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);
     }
 

Reply via email to