Skip to content

Commit 2983a10

Browse files
author
Eugenio Grosso
committed
flasharray: extract login() helpers and drop redundant execute() casts
Address winterhazel review on PR #13060: - Extract the api-version discovery block into fetchApiVersionFromPurity(client). Reduces indentation and line count of login(). - Extract the legacy username/password auth block into getApiTokenUsingUserPass(client). Handles response close via a proper try/finally so the caller no longer needs the manual response.close() + response = null dance. - Drop redundant (CloseableHttpResponse) casts on client.execute(...). CloseableHttpClient.execute() already returns CloseableHttpResponse. Cleaned up all four occurrences in the file, not just the two winterhazel flagged, for consistency. No functional change. Signed-off-by: Eugenio Grosso <eugenio.grosso@gmail.com>
1 parent e49809f commit 2983a10

1 file changed

Lines changed: 91 additions & 67 deletions

File tree

  • plugins/storage/volume/flasharray/src/main/java/org/apache/cloudstack/storage/datastore/adapter/flasharray

plugins/storage/volume/flasharray/src/main/java/org/apache/cloudstack/storage/datastore/adapter/flasharray/FlashArrayAdapter.java

Lines changed: 91 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,91 @@ private String getAccessToken() {
524524
return accessToken;
525525
}
526526

527+
/**
528+
* Discover the latest supported Purity REST API version by hitting the unauthenticated
529+
* {@code /api/api_version} endpoint (returns {@code {"version":["1.0",...,"2.36"]}}).
530+
* The discovered version is stored on {@link #apiVersion}; on failure the caller-configured
531+
* default remains in place.
532+
*/
533+
private void fetchApiVersionFromPurity(CloseableHttpClient client) {
534+
HttpGet vReq = new HttpGet(url + "/api_version");
535+
CloseableHttpResponse vResp = null;
536+
try {
537+
vResp = client.execute(vReq);
538+
if (vResp.getStatusLine().getStatusCode() == 200) {
539+
JsonNode root = mapper.readTree(vResp.getEntity().getContent());
540+
JsonNode versions = root.get("version");
541+
if (versions != null && versions.isArray() && versions.size() > 0) {
542+
apiVersion = versions.get(versions.size() - 1).asText();
543+
}
544+
} else {
545+
logger.warn("Unexpected HTTP " + vResp.getStatusLine().getStatusCode()
546+
+ " from FlashArray [" + url + "] /api_version, falling back to default "
547+
+ API_VERSION_DEFAULT);
548+
}
549+
} catch (Exception e) {
550+
logger.warn("Failed to discover Purity REST API version from " + url
551+
+ "/api_version, falling back to default " + API_VERSION_DEFAULT, e);
552+
} finally {
553+
if (vResp != null) {
554+
try {
555+
vResp.close();
556+
} catch (IOException e) {
557+
logger.debug("Error closing /api_version response from FlashArray [" + url + "]", e);
558+
}
559+
}
560+
}
561+
}
562+
563+
/**
564+
* Exchange the operator-configured username/password for a long-lived Purity api-token
565+
* via REST 1.x {@code /auth/apitoken}. Emits the once-per-URL deprecation WARN.
566+
* @return the api-token to feed into the REST 2.x /login exchange.
567+
*/
568+
private String getApiTokenUsingUserPass(CloseableHttpClient client) throws IOException {
569+
if (WARNED_LEGACY_URLS.add(url)) {
570+
logger.warn("FlashArray adapter at [" + url + "] is using deprecated username/password "
571+
+ "login against Purity REST 1.x. Replace with a pre-minted "
572+
+ ProviderAdapter.API_TOKEN_KEY + " detail; the username/password code path will be "
573+
+ "removed in a future release.");
574+
}
575+
HttpPost request = new HttpPost(url + "/" + apiLoginVersion + "/auth/apitoken");
576+
ArrayList<NameValuePair> postParms = new ArrayList<NameValuePair>();
577+
postParms.add(new BasicNameValuePair("username", username));
578+
postParms.add(new BasicNameValuePair("password", password));
579+
request.setEntity(new UrlEncodedFormEntity(postParms, "UTF-8"));
580+
CloseableHttpResponse response = null;
581+
try {
582+
response = client.execute(request);
583+
int statusCode = response.getStatusLine().getStatusCode();
584+
if (statusCode == 200 || statusCode == 201) {
585+
FlashArrayApiToken legacyToken = mapper.readValue(response.getEntity().getContent(),
586+
FlashArrayApiToken.class);
587+
if (legacyToken == null || legacyToken.getApiToken() == null) {
588+
throw new CloudRuntimeException(
589+
"Authentication responded successfully but no api token was returned");
590+
}
591+
return legacyToken.getApiToken();
592+
} else if (statusCode == 401 || statusCode == 403) {
593+
throw new CloudRuntimeException(
594+
"Authentication or Authorization to FlashArray [" + url + "] with user [" + username
595+
+ "] failed, unable to retrieve session token");
596+
} else {
597+
throw new CloudRuntimeException(
598+
"Unexpected HTTP response code from FlashArray [" + url + "] - [" + statusCode
599+
+ "] - " + response.getStatusLine().getReasonPhrase());
600+
}
601+
} finally {
602+
if (response != null) {
603+
try {
604+
response.close();
605+
} catch (IOException e) {
606+
logger.debug("Error closing legacy auth/apitoken response from FlashArray [" + url + "]", e);
607+
}
608+
}
609+
}
610+
}
611+
527612
private synchronized void refreshSession(boolean force) {
528613
try {
529614
if (force || keyExpiration < System.currentTimeMillis()) {
@@ -688,78 +773,17 @@ private void login() {
688773
// Discover the latest supported API version from the array unless one was explicitly configured.
689774
// GET /api/api_version is unauthenticated and returns {"version":["1.0",...,"2.36"]}.
690775
if (!apiVersionExplicit) {
691-
HttpGet vReq = new HttpGet(url + "/api_version");
692-
CloseableHttpResponse vResp = null;
693-
try {
694-
vResp = (CloseableHttpResponse) client.execute(vReq);
695-
if (vResp.getStatusLine().getStatusCode() == 200) {
696-
JsonNode root = mapper.readTree(vResp.getEntity().getContent());
697-
JsonNode versions = root.get("version");
698-
if (versions != null && versions.isArray() && versions.size() > 0) {
699-
apiVersion = versions.get(versions.size() - 1).asText();
700-
}
701-
} else {
702-
logger.warn("Unexpected HTTP " + vResp.getStatusLine().getStatusCode()
703-
+ " from FlashArray [" + url + "] /api_version, falling back to default "
704-
+ API_VERSION_DEFAULT);
705-
}
706-
} catch (Exception e) {
707-
logger.warn("Failed to discover Purity REST API version from " + url
708-
+ "/api_version, falling back to default " + API_VERSION_DEFAULT, e);
709-
} finally {
710-
if (vResp != null) {
711-
try {
712-
vResp.close();
713-
} catch (IOException e) {
714-
logger.debug("Error closing /api_version response from FlashArray [" + url + "]", e);
715-
}
716-
}
717-
}
776+
fetchApiVersionFromPurity(client);
718777
}
719778

720779
if (usingLegacyUserPass) {
721-
if (WARNED_LEGACY_URLS.add(url)) {
722-
logger.warn("FlashArray adapter at [" + url + "] is using deprecated username/password "
723-
+ "login against Purity REST 1.x. Replace with a pre-minted "
724-
+ ProviderAdapter.API_TOKEN_KEY + " detail; the username/password code path will be "
725-
+ "removed in a future release.");
726-
}
727-
HttpPost request = new HttpPost(url + "/" + apiLoginVersion + "/auth/apitoken");
728-
ArrayList<NameValuePair> postParms = new ArrayList<NameValuePair>();
729-
postParms.add(new BasicNameValuePair("username", username));
730-
postParms.add(new BasicNameValuePair("password", password));
731-
request.setEntity(new UrlEncodedFormEntity(postParms, "UTF-8"));
732-
response = (CloseableHttpResponse) client.execute(request);
733-
int statusCode = response.getStatusLine().getStatusCode();
734-
if (statusCode == 200 || statusCode == 201) {
735-
FlashArrayApiToken legacyToken = mapper.readValue(response.getEntity().getContent(),
736-
FlashArrayApiToken.class);
737-
if (legacyToken == null || legacyToken.getApiToken() == null) {
738-
throw new CloudRuntimeException(
739-
"Authentication responded successfully but no api token was returned");
740-
}
741-
apiToken = legacyToken.getApiToken();
742-
} else if (statusCode == 401 || statusCode == 403) {
743-
throw new CloudRuntimeException(
744-
"Authentication or Authorization to FlashArray [" + url + "] with user [" + username
745-
+ "] failed, unable to retrieve session token");
746-
} else {
747-
throw new CloudRuntimeException(
748-
"Unexpected HTTP response code from FlashArray [" + url + "] - [" + statusCode
749-
+ "] - " + response.getStatusLine().getReasonPhrase());
750-
}
751-
try {
752-
response.close();
753-
} catch (IOException e) {
754-
logger.debug("Error closing legacy auth/apitoken response from FlashArray [" + url + "]", e);
755-
}
756-
response = null;
780+
apiToken = getApiTokenUsingUserPass(client);
757781
}
758782

759783
// Exchange the long-lived api-token for a short-lived x-auth-token (REST 2.x).
760784
HttpPost request = new HttpPost(url + "/" + apiVersion + "/login");
761785
request.addHeader("api-token", apiToken);
762-
response = (CloseableHttpResponse) client.execute(request);
786+
response = client.execute(request);
763787
int statusCode = response.getStatusLine().getStatusCode();
764788
if (statusCode == 200 || statusCode == 201) {
765789
Header[] headers = response.getHeaders("x-auth-token");
@@ -957,7 +981,7 @@ private <T> T PATCH(String path, Object input, final TypeReference<T> type) {
957981
request.setEntity(new StringEntity(data));
958982

959983
CloseableHttpClient client = getClient();
960-
response = (CloseableHttpResponse) client.execute(request);
984+
response = client.execute(request);
961985

962986
final int statusCode = response.getStatusLine().getStatusCode();
963987
if (statusCode == 200 || statusCode == 201) {
@@ -1012,7 +1036,7 @@ private <T> T GET(String path, final TypeReference<T> type) {
10121036
request.addHeader("X-auth-token", getAccessToken());
10131037

10141038
CloseableHttpClient client = getClient();
1015-
response = (CloseableHttpResponse) client.execute(request);
1039+
response = client.execute(request);
10161040
final int statusCode = response.getStatusLine().getStatusCode();
10171041
if (statusCode == 200) {
10181042
try {
@@ -1054,7 +1078,7 @@ private void DELETE(String path) {
10541078
request.addHeader("X-auth-token", getAccessToken());
10551079

10561080
CloseableHttpClient client = getClient();
1057-
response = (CloseableHttpResponse) client.execute(request);
1081+
response = client.execute(request);
10581082
final int statusCode = response.getStatusLine().getStatusCode();
10591083
if (statusCode == 200 || statusCode == 404 || statusCode == 400) {
10601084
// this means the volume was deleted successfully, or doesn't exist (effective

0 commit comments

Comments
 (0)