HADOOP-15809. ABFS: better exception handling when making getAccessToken call.

Contributed by Da Zhou

(cherry picked from commit 273cc2d4e9)
This commit is contained in:
Steve Loughran 2018-10-05 11:29:43 +01:00
parent a7711073ac
commit 83b9b25c51
No known key found for this signature in database
GPG Key ID: D22CF846DBB162A0
3 changed files with 38 additions and 15 deletions

View File

@ -22,6 +22,7 @@ package org.apache.hadoop.fs.azurebfs.contracts.exceptions;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.fs.azurebfs.contracts.services.AzureServiceErrorCode;
import org.apache.hadoop.fs.azurebfs.oauth2.AzureADAuthenticator.HttpException;
import org.apache.hadoop.fs.azurebfs.services.AbfsHttpOperation;
/**
@ -59,6 +60,14 @@ public class AbfsRestOperationException extends AzureBlobFileSystemException {
this.errorMessage = errorMessage;
}
public AbfsRestOperationException(final HttpException innerException) {
super(innerException.getMessage());
this.statusCode = innerException.getHttpErrorCode();
this.errorCode = AzureServiceErrorCode.UNKNOWN;
this.errorMessage = innerException.getMessage();
}
public int getStatusCode() {
return this.statusCode;
}

View File

@ -161,14 +161,28 @@ public final class AzureADAuthenticator {
return getTokenCall(authEndpoint, qp.serialize(), null, null);
}
private static class HttpException extends IOException {
/**
* This exception class contains the http error code,
* requestId and error message, it is thrown when AzureADAuthenticator
* failed to get the Azure Active Directory token.
*/
public static class HttpException extends IOException {
private int httpErrorCode;
private String requestId;
/**
* Gets Http error status code.
* @return http error code.
*/
public int getHttpErrorCode() {
return this.httpErrorCode;
}
/**
* Gets http request id .
* @return http request id.
*/
public String getRequestId() {
return this.requestId;
}
@ -188,21 +202,17 @@ public final class AzureADAuthenticator {
= new ExponentialRetryPolicy(3, 0, 1000, 2);
int httperror = 0;
String requestId;
String httpExceptionMessage = null;
IOException ex = null;
boolean succeeded = false;
int retryCount = 0;
do {
httperror = 0;
requestId = "";
ex = null;
try {
token = getTokenSingleCall(authEndpoint, body, headers, httpMethod);
} catch (HttpException e) {
httperror = e.httpErrorCode;
requestId = e.requestId;
httpExceptionMessage = e.getMessage();
ex = e;
} catch (IOException e) {
ex = e;
}
@ -210,12 +220,7 @@ public final class AzureADAuthenticator {
retryCount++;
} while (!succeeded && retryPolicy.shouldRetry(retryCount, httperror));
if (!succeeded) {
if (ex != null) {
throw ex;
}
if (httperror != 0) {
throw new IOException(httpExceptionMessage);
}
throw ex;
}
return token;
}
@ -263,7 +268,7 @@ public final class AzureADAuthenticator {
InputStream httpResponseStream = conn.getInputStream();
token = parseTokenFromStream(httpResponseStream);
} else {
String responseBody = consumeInputStream(conn.getInputStream(), 1024);
String responseBody = consumeInputStream(conn.getErrorStream(), 1024);
String proxies = "none";
String httpProxy = System.getProperty("http.proxy");
String httpsProxy = System.getProperty("https.proxy");
@ -273,11 +278,11 @@ public final class AzureADAuthenticator {
String logMessage =
"AADToken: HTTP connection failed for getting token from AzureAD. Http response: "
+ httpResponseCode + " " + conn.getResponseMessage()
+ " Content-Type: " + responseContentType
+ "\nContent-Type: " + responseContentType
+ " Content-Length: " + responseContentLength
+ " Request ID: " + requestId.toString()
+ " Proxies: " + proxies
+ " First 1K of Body: " + responseBody;
+ "\nFirst 1K of Body: " + responseBody;
LOG.debug(logMessage);
throw new HttpException(httpResponseCode, requestId, logMessage);
}

View File

@ -31,6 +31,7 @@ import org.apache.hadoop.fs.azurebfs.contracts.exceptions.AbfsRestOperationExcep
import org.apache.hadoop.fs.azurebfs.contracts.exceptions.AzureBlobFileSystemException;
import org.apache.hadoop.fs.azurebfs.contracts.exceptions.InvalidAbfsRestOperationException;
import org.apache.hadoop.fs.azurebfs.constants.HttpHeaderConfigurations;
import org.apache.hadoop.fs.azurebfs.oauth2.AzureADAuthenticator.HttpException;
/**
* The AbfsRestOperation for Rest AbfsClient.
@ -175,6 +176,14 @@ public class AbfsRestOperation {
if (!client.getRetryPolicy().shouldRetry(retryCount, -1)) {
throw new InvalidAbfsRestOperationException(ex);
}
// once HttpException is thrown by AzureADAuthenticator,
// it indicates the policy in AzureADAuthenticator determined
// retry is not needed
if (ex instanceof HttpException) {
throw new AbfsRestOperationException((HttpException) ex);
}
return false;
} finally {
AbfsClientThrottlingIntercept.updateMetrics(operationType, httpOperation);