Skip to content

Commit 199170b

Browse files
utils: fix extra slash in Redfish default systems url path (#10630)
Signed-off-by: Rohit Yadav <[email protected]>
1 parent d776534 commit 199170b

File tree

2 files changed

+30
-18
lines changed

2 files changed

+30
-18
lines changed

utils/src/main/java/org/apache/cloudstack/utils/redfish/RedfishClient.java

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,17 @@
2929
import java.security.NoSuchAlgorithmException;
3030
import java.util.Base64;
3131
import java.util.concurrent.TimeUnit;
32+
import java.util.stream.Collectors;
3233

3334
import javax.net.ssl.HostnameVerifier;
3435
import javax.net.ssl.HttpsURLConnection;
3536
import javax.net.ssl.SSLContext;
3637
import javax.net.ssl.SSLSession;
3738
import javax.net.ssl.TrustManager;
3839

40+
import com.cloud.utils.exception.CloudRuntimeException;
3941
import com.cloud.utils.nio.TrustAllManager;
42+
import com.google.gson.JsonElement;
4043
import org.apache.commons.httpclient.HttpStatus;
4144
import org.apache.commons.lang3.StringUtils;
4245
import org.apache.http.HttpResponse;
@@ -75,14 +78,15 @@ public class RedfishClient {
7578
private boolean ignoreSsl;
7679
private int redfishRequestMaxRetries;
7780

78-
private final static String SYSTEMS_URL_PATH = "redfish/v1/Systems/";
79-
private final static String COMPUTER_SYSTEM_RESET_URL_PATH = "/Actions/ComputerSystem.Reset";
81+
private final static String SYSTEMS_URL_PATH = "redfish/v1/Systems";
82+
private final static String COMPUTER_SYSTEM_RESET_URL_PATH = "Actions/ComputerSystem.Reset";
8083
private final static String REDFISH_RESET_TYPE = "ResetType";
8184
private final static String POWER_STATE = "PowerState";
8285
private final static String APPLICATION_JSON = "application/json";
8386
private final static String ACCEPT = "accept";
8487
private final static String ODATA_ID = "@odata.id";
8588
private final static String MEMBERS = "Members";
89+
private final static String LINKS = "Links";
8690
private final static String EXPECTED_HTTP_STATUS = "2XX";
8791
private final static int WAIT_FOR_REQUEST_RETRY = 2;
8892

@@ -265,12 +269,12 @@ private String getRequestPathForCommand(RedfishCmdType cmd, String resourceId) {
265269
if (StringUtils.isBlank(resourceId)) {
266270
throw new RedfishException(String.format("Command '%s' requires a valid resource ID '%s'.", cmd, resourceId));
267271
}
268-
return String.format("%s%s", SYSTEMS_URL_PATH, resourceId);
272+
return String.format("%s/%s", SYSTEMS_URL_PATH, resourceId);
269273
case ComputerSystemReset:
270274
if (StringUtils.isBlank(resourceId)) {
271275
throw new RedfishException(String.format("Command '%s' requires a valid resource ID '%s'.", cmd, resourceId));
272276
}
273-
return String.format("%s%s%s", SYSTEMS_URL_PATH, resourceId, COMPUTER_SYSTEM_RESET_URL_PATH);
277+
return String.format("%s/%s/%s", SYSTEMS_URL_PATH, resourceId, COMPUTER_SYSTEM_RESET_URL_PATH);
274278
default:
275279
throw new RedfishException(String.format("Redfish client does not support command '%s'.", cmd));
276280
}
@@ -305,8 +309,8 @@ public void executeComputerSystemReset(String hostAddress, RedfishResetCmd reset
305309

306310
int statusCode = response.getStatusLine().getStatusCode();
307311
if (statusCode < HttpStatus.SC_OK || statusCode >= HttpStatus.SC_MULTIPLE_CHOICES) {
308-
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'.",
309-
HttpGet.METHOD_NAME, url, hostAddress, EXPECTED_HTTP_STATUS, statusCode));
312+
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'.",
313+
HttpPost.METHOD_NAME, url, hostAddress, EXPECTED_HTTP_STATUS, statusCode));
310314
}
311315
logger.debug(String.format("Sending ComputerSystem.Reset Command '%s' to host '%s' with request '%s %s'", resetCommand, hostAddress, HttpPost.METHOD_NAME, url));
312316
}
@@ -340,16 +344,25 @@ protected String processGetSystemIdResponse(CloseableHttpResponse response) {
340344
try {
341345
in = response.getEntity().getContent();
342346
BufferedReader streamReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
343-
jsonString = streamReader.readLine();
347+
jsonString = streamReader.lines().collect(Collectors.joining());
344348
} catch (UnsupportedOperationException | IOException e) {
345349
throw new RedfishException("Failed to process system Response", e);
346350
}
347351

348352
// retrieving the system ID (e.g. 'System.Embedded.1') via JsonParser:
349353
// (...) Members":[{"@odata.id":"/redfish/v1/Systems/System.Embedded.1"}] (...)
350-
JsonArray jArray = new JsonParser().parse(jsonString).getAsJsonObject().get(MEMBERS).getAsJsonArray();
351-
JsonObject jsonnObject = jArray.get(0).getAsJsonObject();
352-
String jsonObjectAsString = jsonnObject.get(ODATA_ID).getAsString();
354+
JsonArray jArray = null;
355+
JsonElement jsonElement = new JsonParser().parse(jsonString);
356+
if (jsonElement.getAsJsonObject().get(MEMBERS) != null) {
357+
jArray = jsonElement.getAsJsonObject().get(MEMBERS).getAsJsonArray();
358+
} else if (jsonElement.getAsJsonObject().get(LINKS) != null){
359+
jArray = jsonElement.getAsJsonObject().get(LINKS).getAsJsonObject().get(MEMBERS).getAsJsonArray();
360+
}
361+
if (jArray == null || jArray.size() < 1) {
362+
throw new CloudRuntimeException("Members not found in the Redfish Systems JSON, unable to determine Redfish system ID");
363+
}
364+
JsonObject jsonObject = jArray.get(0).getAsJsonObject();
365+
String jsonObjectAsString = jsonObject.get(ODATA_ID).getAsString();
353366
String[] arrayOfStrings = StringUtils.split(jsonObjectAsString, '/');
354367

355368
return arrayOfStrings[arrayOfStrings.length - 1];
@@ -384,8 +397,7 @@ protected RedfishPowerState processGetSystemRequestResponse(CloseableHttpRespons
384397
try {
385398
in = response.getEntity().getContent();
386399
BufferedReader streamReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
387-
388-
jsonString = streamReader.readLine();
400+
jsonString = streamReader.lines().collect(Collectors.joining());
389401
String powerState = new JsonParser().parse(jsonString).getAsJsonObject().get(POWER_STATE).getAsString();
390402
return RedfishPowerState.valueOf(powerState);
391403
} catch (UnsupportedOperationException | IOException e) {

utils/src/test/java/org/apache/cloudstack/utils/redfish/RedfishClientTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ public class RedfishClientTest {
4141
private static final String PASSWORD = "password";
4242
private static final String oobAddress = "oob.host.address";
4343
private static final String systemId = "SystemID.1";
44-
private final static String COMPUTER_SYSTEM_RESET_URL_PATH = "/Actions/ComputerSystem.Reset";
44+
private final static String COMPUTER_SYSTEM_RESET_URL_PATH = "Actions/ComputerSystem.Reset";
4545
private final static Integer REDFISHT_REQUEST_RETRIES = Integer.valueOf(2);
46-
private static final String url = "https://address.system.net/redfish/v1/Systems/";
46+
private static final String url = "https://address.system.net/redfish/v1/Systems";
4747
private static final HttpRequestBase httpReq = new HttpGet(url);
4848

4949
@Mock
@@ -87,31 +87,31 @@ public void validateAddressAndPrepareForUrlTestIpv6() {
8787
public void buildRequestUrlTestHttpsGetSystemId() {
8888
RedfishClient redfishclient = new RedfishClient(USERNAME, PASSWORD, true, false, REDFISHT_REQUEST_RETRIES);
8989
String result = redfishclient.buildRequestUrl(oobAddress, RedfishClient.RedfishCmdType.GetSystemId, systemId);
90-
String expected = String.format("https://%s/redfish/v1/Systems/", oobAddress);
90+
String expected = String.format("https://%s/redfish/v1/Systems", oobAddress);
9191
Assert.assertEquals(expected, result);
9292
}
9393

9494
@Test
9595
public void buildRequestUrlTestGetSystemId() {
9696
RedfishClient redfishclient = new RedfishClient(USERNAME, PASSWORD, false, false, REDFISHT_REQUEST_RETRIES);
9797
String result = redfishclient.buildRequestUrl(oobAddress, RedfishClient.RedfishCmdType.GetSystemId, systemId);
98-
String expected = String.format("http://%s/redfish/v1/Systems/", oobAddress);
98+
String expected = String.format("http://%s/redfish/v1/Systems", oobAddress);
9999
Assert.assertEquals(expected, result);
100100
}
101101

102102
@Test
103103
public void buildRequestUrlTestHttpsComputerSystemReset() {
104104
RedfishClient redfishclient = new RedfishClient(USERNAME, PASSWORD, true, false, REDFISHT_REQUEST_RETRIES);
105105
String result = redfishclient.buildRequestUrl(oobAddress, RedfishClient.RedfishCmdType.ComputerSystemReset, systemId);
106-
String expected = String.format("https://%s/redfish/v1/Systems/%s%s", oobAddress, systemId, COMPUTER_SYSTEM_RESET_URL_PATH);
106+
String expected = String.format("https://%s/redfish/v1/Systems/%s/%s", oobAddress, systemId, COMPUTER_SYSTEM_RESET_URL_PATH);
107107
Assert.assertEquals(expected, result);
108108
}
109109

110110
@Test
111111
public void buildRequestUrlTestComputerSystemReset() {
112112
RedfishClient redfishclient = new RedfishClient(USERNAME, PASSWORD, false, false, REDFISHT_REQUEST_RETRIES);
113113
String result = redfishclient.buildRequestUrl(oobAddress, RedfishClient.RedfishCmdType.ComputerSystemReset, systemId);
114-
String expected = String.format("http://%s/redfish/v1/Systems/%s%s", oobAddress, systemId, COMPUTER_SYSTEM_RESET_URL_PATH);
114+
String expected = String.format("http://%s/redfish/v1/Systems/%s/%s", oobAddress, systemId, COMPUTER_SYSTEM_RESET_URL_PATH);
115115
Assert.assertEquals(expected, result);
116116
}
117117

0 commit comments

Comments
 (0)