|
29 | 29 | import java.security.NoSuchAlgorithmException; |
30 | 30 | import java.util.Base64; |
31 | 31 | import java.util.concurrent.TimeUnit; |
| 32 | +import java.util.stream.Collectors; |
32 | 33 |
|
33 | 34 | import javax.net.ssl.HostnameVerifier; |
34 | 35 | import javax.net.ssl.HttpsURLConnection; |
35 | 36 | import javax.net.ssl.SSLContext; |
36 | 37 | import javax.net.ssl.SSLSession; |
37 | 38 | import javax.net.ssl.TrustManager; |
38 | 39 |
|
| 40 | +import com.cloud.utils.exception.CloudRuntimeException; |
39 | 41 | import com.cloud.utils.nio.TrustAllManager; |
| 42 | +import com.google.gson.JsonElement; |
40 | 43 | import org.apache.commons.httpclient.HttpStatus; |
41 | 44 | import org.apache.commons.lang3.StringUtils; |
42 | 45 | import org.apache.http.HttpResponse; |
@@ -75,14 +78,15 @@ public class RedfishClient { |
75 | 78 | private boolean ignoreSsl; |
76 | 79 | private int redfishRequestMaxRetries; |
77 | 80 |
|
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"; |
80 | 83 | private final static String REDFISH_RESET_TYPE = "ResetType"; |
81 | 84 | private final static String POWER_STATE = "PowerState"; |
82 | 85 | private final static String APPLICATION_JSON = "application/json"; |
83 | 86 | private final static String ACCEPT = "accept"; |
84 | 87 | private final static String ODATA_ID = "@odata.id"; |
85 | 88 | private final static String MEMBERS = "Members"; |
| 89 | + private final static String LINKS = "Links"; |
86 | 90 | private final static String EXPECTED_HTTP_STATUS = "2XX"; |
87 | 91 | private final static int WAIT_FOR_REQUEST_RETRY = 2; |
88 | 92 |
|
@@ -265,12 +269,12 @@ private String getRequestPathForCommand(RedfishCmdType cmd, String resourceId) { |
265 | 269 | if (StringUtils.isBlank(resourceId)) { |
266 | 270 | throw new RedfishException(String.format("Command '%s' requires a valid resource ID '%s'.", cmd, resourceId)); |
267 | 271 | } |
268 | | - return String.format("%s%s", SYSTEMS_URL_PATH, resourceId); |
| 272 | + return String.format("%s/%s", SYSTEMS_URL_PATH, resourceId); |
269 | 273 | case ComputerSystemReset: |
270 | 274 | if (StringUtils.isBlank(resourceId)) { |
271 | 275 | throw new RedfishException(String.format("Command '%s' requires a valid resource ID '%s'.", cmd, resourceId)); |
272 | 276 | } |
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); |
274 | 278 | default: |
275 | 279 | throw new RedfishException(String.format("Redfish client does not support command '%s'.", cmd)); |
276 | 280 | } |
@@ -305,8 +309,8 @@ public void executeComputerSystemReset(String hostAddress, RedfishResetCmd reset |
305 | 309 |
|
306 | 310 | int statusCode = response.getStatusLine().getStatusCode(); |
307 | 311 | 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)); |
310 | 314 | } |
311 | 315 | logger.debug(String.format("Sending ComputerSystem.Reset Command '%s' to host '%s' with request '%s %s'", resetCommand, hostAddress, HttpPost.METHOD_NAME, url)); |
312 | 316 | } |
@@ -340,16 +344,25 @@ protected String processGetSystemIdResponse(CloseableHttpResponse response) { |
340 | 344 | try { |
341 | 345 | in = response.getEntity().getContent(); |
342 | 346 | BufferedReader streamReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); |
343 | | - jsonString = streamReader.readLine(); |
| 347 | + jsonString = streamReader.lines().collect(Collectors.joining()); |
344 | 348 | } catch (UnsupportedOperationException | IOException e) { |
345 | 349 | throw new RedfishException("Failed to process system Response", e); |
346 | 350 | } |
347 | 351 |
|
348 | 352 | // retrieving the system ID (e.g. 'System.Embedded.1') via JsonParser: |
349 | 353 | // (...) 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(); |
353 | 366 | String[] arrayOfStrings = StringUtils.split(jsonObjectAsString, '/'); |
354 | 367 |
|
355 | 368 | return arrayOfStrings[arrayOfStrings.length - 1]; |
@@ -384,8 +397,7 @@ protected RedfishPowerState processGetSystemRequestResponse(CloseableHttpRespons |
384 | 397 | try { |
385 | 398 | in = response.getEntity().getContent(); |
386 | 399 | BufferedReader streamReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); |
387 | | - |
388 | | - jsonString = streamReader.readLine(); |
| 400 | + jsonString = streamReader.lines().collect(Collectors.joining()); |
389 | 401 | String powerState = new JsonParser().parse(jsonString).getAsJsonObject().get(POWER_STATE).getAsString(); |
390 | 402 | return RedfishPowerState.valueOf(powerState); |
391 | 403 | } catch (UnsupportedOperationException | IOException e) { |
|
0 commit comments