This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.20 by this push:
new 199170be433 utils: fix extra slash in Redfish default systems url path
(#10630)
199170be433 is described below
commit 199170be4331f5d1a8e5e4cacf84c7f064502b31
Author: Rohit Yadav <[email protected]>
AuthorDate: Thu Apr 17 20:24:43 2025 +0530
utils: fix extra slash in Redfish default systems url path (#10630)
Signed-off-by: Rohit Yadav <[email protected]>
---
.../cloudstack/utils/redfish/RedfishClient.java | 36 ++++++++++++++--------
.../utils/redfish/RedfishClientTest.java | 12 ++++----
2 files changed, 30 insertions(+), 18 deletions(-)
diff --git
a/utils/src/main/java/org/apache/cloudstack/utils/redfish/RedfishClient.java
b/utils/src/main/java/org/apache/cloudstack/utils/redfish/RedfishClient.java
index e6af2315ba2..f9952b2c03b 100644
--- a/utils/src/main/java/org/apache/cloudstack/utils/redfish/RedfishClient.java
+++ b/utils/src/main/java/org/apache/cloudstack/utils/redfish/RedfishClient.java
@@ -29,6 +29,7 @@ import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
@@ -36,7 +37,9 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
+import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.nio.TrustAllManager;
+import com.google.gson.JsonElement;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
@@ -75,14 +78,15 @@ public class RedfishClient {
private boolean ignoreSsl;
private int redfishRequestMaxRetries;
- private final static String SYSTEMS_URL_PATH = "redfish/v1/Systems/";
- private final static String COMPUTER_SYSTEM_RESET_URL_PATH =
"/Actions/ComputerSystem.Reset";
+ private final static String SYSTEMS_URL_PATH = "redfish/v1/Systems";
+ private final static String COMPUTER_SYSTEM_RESET_URL_PATH =
"Actions/ComputerSystem.Reset";
private final static String REDFISH_RESET_TYPE = "ResetType";
private final static String POWER_STATE = "PowerState";
private final static String APPLICATION_JSON = "application/json";
private final static String ACCEPT = "accept";
private final static String ODATA_ID = "@odata.id";
private final static String MEMBERS = "Members";
+ private final static String LINKS = "Links";
private final static String EXPECTED_HTTP_STATUS = "2XX";
private final static int WAIT_FOR_REQUEST_RETRY = 2;
@@ -265,12 +269,12 @@ public class RedfishClient {
if (StringUtils.isBlank(resourceId)) {
throw new RedfishException(String.format("Command '%s'
requires a valid resource ID '%s'.", cmd, resourceId));
}
- return String.format("%s%s", SYSTEMS_URL_PATH, resourceId);
+ return String.format("%s/%s", SYSTEMS_URL_PATH, resourceId);
case ComputerSystemReset:
if (StringUtils.isBlank(resourceId)) {
throw new RedfishException(String.format("Command '%s'
requires a valid resource ID '%s'.", cmd, resourceId));
}
- return String.format("%s%s%s", SYSTEMS_URL_PATH, resourceId,
COMPUTER_SYSTEM_RESET_URL_PATH);
+ return String.format("%s/%s/%s", SYSTEMS_URL_PATH, resourceId,
COMPUTER_SYSTEM_RESET_URL_PATH);
default:
throw new RedfishException(String.format("Redfish client does not
support command '%s'.", cmd));
}
@@ -305,8 +309,8 @@ public class RedfishClient {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode < HttpStatus.SC_OK || statusCode >=
HttpStatus.SC_MULTIPLE_CHOICES) {
- throw new RedfishException(String.format("Failed to get System
power state for host '%s' with request '%s: %s'. The expected HTTP status code
is '%s' but it got '%s'.",
- HttpGet.METHOD_NAME, url, hostAddress,
EXPECTED_HTTP_STATUS, statusCode));
+ throw new RedfishException(String.format("Failed to execute System
power command for host by performing '%s' request on URL '%s' and host address
'%s'. The expected HTTP status code is '%s' but it got '%s'.",
+ HttpPost.METHOD_NAME, url, hostAddress,
EXPECTED_HTTP_STATUS, statusCode));
}
logger.debug(String.format("Sending ComputerSystem.Reset Command '%s'
to host '%s' with request '%s %s'", resetCommand, hostAddress,
HttpPost.METHOD_NAME, url));
}
@@ -340,16 +344,25 @@ public class RedfishClient {
try {
in = response.getEntity().getContent();
BufferedReader streamReader = new BufferedReader(new
InputStreamReader(in, StandardCharsets.UTF_8));
- jsonString = streamReader.readLine();
+ jsonString = streamReader.lines().collect(Collectors.joining());
} catch (UnsupportedOperationException | IOException e) {
throw new RedfishException("Failed to process system Response", e);
}
// retrieving the system ID (e.g. 'System.Embedded.1') via JsonParser:
// (...)
Members":[{"@odata.id":"/redfish/v1/Systems/System.Embedded.1"}] (...)
- JsonArray jArray = new
JsonParser().parse(jsonString).getAsJsonObject().get(MEMBERS).getAsJsonArray();
- JsonObject jsonnObject = jArray.get(0).getAsJsonObject();
- String jsonObjectAsString = jsonnObject.get(ODATA_ID).getAsString();
+ JsonArray jArray = null;
+ JsonElement jsonElement = new JsonParser().parse(jsonString);
+ if (jsonElement.getAsJsonObject().get(MEMBERS) != null) {
+ jArray =
jsonElement.getAsJsonObject().get(MEMBERS).getAsJsonArray();
+ } else if (jsonElement.getAsJsonObject().get(LINKS) != null){
+ jArray =
jsonElement.getAsJsonObject().get(LINKS).getAsJsonObject().get(MEMBERS).getAsJsonArray();
+ }
+ if (jArray == null || jArray.size() < 1) {
+ throw new CloudRuntimeException("Members not found in the Redfish
Systems JSON, unable to determine Redfish system ID");
+ }
+ JsonObject jsonObject = jArray.get(0).getAsJsonObject();
+ String jsonObjectAsString = jsonObject.get(ODATA_ID).getAsString();
String[] arrayOfStrings = StringUtils.split(jsonObjectAsString, '/');
return arrayOfStrings[arrayOfStrings.length - 1];
@@ -384,8 +397,7 @@ public class RedfishClient {
try {
in = response.getEntity().getContent();
BufferedReader streamReader = new BufferedReader(new
InputStreamReader(in, StandardCharsets.UTF_8));
-
- jsonString = streamReader.readLine();
+ jsonString = streamReader.lines().collect(Collectors.joining());
String powerState = new
JsonParser().parse(jsonString).getAsJsonObject().get(POWER_STATE).getAsString();
return RedfishPowerState.valueOf(powerState);
} catch (UnsupportedOperationException | IOException e) {
diff --git
a/utils/src/test/java/org/apache/cloudstack/utils/redfish/RedfishClientTest.java
b/utils/src/test/java/org/apache/cloudstack/utils/redfish/RedfishClientTest.java
index 58dfbceb66a..83098cabf38 100644
---
a/utils/src/test/java/org/apache/cloudstack/utils/redfish/RedfishClientTest.java
+++
b/utils/src/test/java/org/apache/cloudstack/utils/redfish/RedfishClientTest.java
@@ -41,9 +41,9 @@ public class RedfishClientTest {
private static final String PASSWORD = "password";
private static final String oobAddress = "oob.host.address";
private static final String systemId = "SystemID.1";
- private final static String COMPUTER_SYSTEM_RESET_URL_PATH =
"/Actions/ComputerSystem.Reset";
+ private final static String COMPUTER_SYSTEM_RESET_URL_PATH =
"Actions/ComputerSystem.Reset";
private final static Integer REDFISHT_REQUEST_RETRIES = Integer.valueOf(2);
- private static final String url =
"https://address.system.net/redfish/v1/Systems/";
+ private static final String url =
"https://address.system.net/redfish/v1/Systems";
private static final HttpRequestBase httpReq = new HttpGet(url);
@Mock
@@ -87,7 +87,7 @@ public class RedfishClientTest {
public void buildRequestUrlTestHttpsGetSystemId() {
RedfishClient redfishclient = new RedfishClient(USERNAME, PASSWORD,
true, false, REDFISHT_REQUEST_RETRIES);
String result = redfishclient.buildRequestUrl(oobAddress,
RedfishClient.RedfishCmdType.GetSystemId, systemId);
- String expected = String.format("https://%s/redfish/v1/Systems/",
oobAddress);
+ String expected = String.format("https://%s/redfish/v1/Systems",
oobAddress);
Assert.assertEquals(expected, result);
}
@@ -95,7 +95,7 @@ public class RedfishClientTest {
public void buildRequestUrlTestGetSystemId() {
RedfishClient redfishclient = new RedfishClient(USERNAME, PASSWORD,
false, false, REDFISHT_REQUEST_RETRIES);
String result = redfishclient.buildRequestUrl(oobAddress,
RedfishClient.RedfishCmdType.GetSystemId, systemId);
- String expected = String.format("http://%s/redfish/v1/Systems/",
oobAddress);
+ String expected = String.format("http://%s/redfish/v1/Systems",
oobAddress);
Assert.assertEquals(expected, result);
}
@@ -103,7 +103,7 @@ public class RedfishClientTest {
public void buildRequestUrlTestHttpsComputerSystemReset() {
RedfishClient redfishclient = new RedfishClient(USERNAME, PASSWORD,
true, false, REDFISHT_REQUEST_RETRIES);
String result = redfishclient.buildRequestUrl(oobAddress,
RedfishClient.RedfishCmdType.ComputerSystemReset, systemId);
- String expected = String.format("https://%s/redfish/v1/Systems/%s%s",
oobAddress, systemId, COMPUTER_SYSTEM_RESET_URL_PATH);
+ String expected = String.format("https://%s/redfish/v1/Systems/%s/%s",
oobAddress, systemId, COMPUTER_SYSTEM_RESET_URL_PATH);
Assert.assertEquals(expected, result);
}
@@ -111,7 +111,7 @@ public class RedfishClientTest {
public void buildRequestUrlTestComputerSystemReset() {
RedfishClient redfishclient = new RedfishClient(USERNAME, PASSWORD,
false, false, REDFISHT_REQUEST_RETRIES);
String result = redfishclient.buildRequestUrl(oobAddress,
RedfishClient.RedfishCmdType.ComputerSystemReset, systemId);
- String expected = String.format("http://%s/redfish/v1/Systems/%s%s",
oobAddress, systemId, COMPUTER_SYSTEM_RESET_URL_PATH);
+ String expected = String.format("http://%s/redfish/v1/Systems/%s/%s",
oobAddress, systemId, COMPUTER_SYSTEM_RESET_URL_PATH);
Assert.assertEquals(expected, result);
}