Make Monasca-API recover from Keystone failures

Fixes JAH-1987.

Fixes "API is failing keystone authentication and never recovering".

Make Monasca-API release HTTP connection in finally clause for Keystone
requests.

Change-Id: Ia4c9899a311794cad8f2fa538fce11bcc265a7e2
This commit is contained in:
Deklan Dieterly 2015-08-10 13:06:23 -06:00
parent de87b63c9b
commit 908bd87609
1 changed files with 78 additions and 58 deletions

View File

@ -50,6 +50,7 @@ public class HttpAuthClient implements AuthClient {
private static final Logger logger = LoggerFactory.getLogger(HttpAuthClient.class); private static final Logger logger = LoggerFactory.getLogger(HttpAuthClient.class);
private static final int DELTA_TIME_IN_SEC = 30; private static final int DELTA_TIME_IN_SEC = 30;
private static final String APPLICATION_JSON = "application/json";
private static SimpleDateFormat expiryFormat; private static SimpleDateFormat expiryFormat;
static { static {
@ -72,53 +73,67 @@ public class HttpAuthClient implements AuthClient {
@Override @Override
public String validateTokenForServiceEndpointV3(String token) throws ClientProtocolException { public String validateTokenForServiceEndpointV3(String token) throws ClientProtocolException {
String newUri = uri.toString() + "/v3/auth/tokens/"; String newUri = uri.toString() + "/v3/auth/tokens/";
Header[] header = new Header[1]; Header[] header = new Header[]{new BasicHeader(AUTH_SUBJECT_TOKEN, token)};
header[0] = new BasicHeader(AUTH_SUBJECT_TOKEN, token);
return verifyUUIDToken(token, newUri, header); return verifyUUIDToken(token, newUri, header);
} }
private String verifyUUIDToken(String token, String newUri, private String verifyUUIDToken(String token, String newUri,
Header[] header) Header[] headers)
throws ClientProtocolException { throws ClientProtocolException {
HttpResponse response = sendGet(newUri, header);
HttpEntity entity = response.getEntity(); HttpGet httpGet = new HttpGet(newUri);
int code = response.getStatusLine().getStatusCode();
InputStream instream = null;
try { try {
if (code == 404) {
instream = entity.getContent(); httpGet.setHeader("Accept", APPLICATION_JSON);
instream.close(); httpGet.setHeader("Content-Type", APPLICATION_JSON);
throw new AuthException("Authorization failed for user token: " + token);
if (headers != null) {
for (Header header : headers) {
httpGet.setHeader(header);
}
} }
if (code != 200) { HttpResponse response = sendGet(httpGet);
adminToken = null;
instream = entity.getContent();
instream.close();
String reasonPhrase = response.getStatusLine().getReasonPhrase();
throw new AuthException("Failed to validate via HTTP " + code HttpEntity entity = response.getEntity();
+ " " + reasonPhrase); int code = response.getStatusLine().getStatusCode();
InputStream instream;
try {
if (code == 404) {
instream = entity.getContent();
instream.close();
throw new AuthException("Authorization failed for user token: " + token);
}
if (code != 200) {
adminToken = null;
instream = entity.getContent();
instream.close();
String reasonPhrase = response.getStatusLine().getReasonPhrase();
throw new AuthException("Failed to validate via HTTP " + code + " " + reasonPhrase);
}
} catch (IOException e) {
throw new ClientProtocolException("IO Exception: problem closing stream ", e);
} }
} catch (IOException e) {
throw new ClientProtocolException( return parseResponse(response);
"IO Exception: problem closing stream ", e);
} finally {
httpGet.releaseConnection();
} }
return parseResponse(response);
} }
private HttpResponse sendPost(String uri, StringEntity body) private HttpResponse sendPost(HttpPost httpPost)
throws ClientProtocolException { throws ClientProtocolException {
HttpResponse response = null; HttpResponse response;
HttpPost post = new HttpPost(uri);
post.setHeader("Accept", "application/json");
post.setHeader("Content-Type", "application/json");
try { try {
post.setEntity(body); response = client.execute(httpPost);
response = client.execute(post);
int code = response.getStatusLine().getStatusCode(); int code = response.getStatusLine().getStatusCode();
if (!(code == 201 || code == 200 || code == 203)) { if (!(code == 201 || code == 200 || code == 203)) {
adminToken = null; adminToken = null;
@ -134,41 +149,32 @@ public class HttpAuthClient implements AuthClient {
message = e.getMessage(); message = e.getMessage();
} }
logger.error("Failure authenticating adminUser: {}", message); logger.error("Failure authenticating adminUser: {}", message);
post.abort(); httpPost.abort();
throw new AdminAuthException( throw new AdminAuthException(
"Failure authenticating adminUser :" + message, e); "Failure authenticating adminUser :" + message, e);
} }
return response; return response;
} }
private HttpResponse sendGet(String newUri, Header[] headers) private HttpResponse sendGet(HttpGet httpGet)
throws ClientProtocolException { throws ClientProtocolException {
HttpResponse response = null; HttpResponse response;
HttpGet get = null;
get = new HttpGet(newUri);
get.setHeader("Accept", "application/json");
get.setHeader("Content-Type", "application/json");
if (headers != null) {
for (Header header : headers) {
get.setHeader(header);
}
}
if (appConfig.getAdminAuthMethod().equalsIgnoreCase(Config.TOKEN)) { if (appConfig.getAdminAuthMethod().equalsIgnoreCase(Config.TOKEN)) {
get.setHeader(new BasicHeader(TOKEN, appConfig.getAdminToken())); httpGet.setHeader(new BasicHeader(TOKEN, appConfig.getAdminToken()));
} else { } else {
get.setHeader(new BasicHeader(TOKEN, getAdminToken())); httpGet.setHeader(new BasicHeader(TOKEN, getAdminToken()));
} }
try { try {
response = client.execute(get);
response = client.execute(httpGet);
} catch (ConnectException c) { } catch (ConnectException c) {
get.abort(); httpGet.abort();
throw new ServiceUnavailableException(c.getMessage()); throw new ServiceUnavailableException(c.getMessage());
} catch (IOException e) { } catch (IOException e) {
get.abort(); httpGet.abort();
throw new ClientProtocolException( throw new ClientProtocolException(
"IO Exception during GET request ", e); "IO Exception during GET request ", e);
@ -202,23 +208,37 @@ public class HttpAuthClient implements AuthClient {
} }
private String getAdminToken() throws ClientProtocolException { private String getAdminToken() throws ClientProtocolException {
HttpResponse response;
String json;
JsonParser jp = new JsonParser();
if (adminTokenExpiry != null) { if (adminTokenExpiry != null) {
if (isExpired(adminTokenExpiry)) { if (isExpired(adminTokenExpiry)) {
adminToken = null; adminToken = null;
} }
} }
if (adminToken == null) { if (adminToken == null) {
StringEntity params = getUnscopedV3AdminTokenRequest();
String authUri = uri + "/v3/auth/tokens"; String authUri = uri + "/v3/auth/tokens";
response = sendPost(authUri, params); HttpPost httpPost = new HttpPost(authUri);
adminToken = response.getFirstHeader(AUTH_SUBJECT_TOKEN).getValue();
json = parseResponse(response); try {
JsonObject token = jp.parse(json).getAsJsonObject().get("token").getAsJsonObject();
adminTokenExpiry = token.get("expires_at").getAsString(); StringEntity params = getUnscopedV3AdminTokenRequest();
httpPost.setHeader("Accept", APPLICATION_JSON);
httpPost.setHeader("Content-Type", APPLICATION_JSON);
httpPost.setEntity(params);
HttpResponse response = sendPost(httpPost);
adminToken = response.getFirstHeader(AUTH_SUBJECT_TOKEN).getValue();
String json = parseResponse(response);
JsonObject
token =
new JsonParser().parse(json).getAsJsonObject().get("token").getAsJsonObject();
adminTokenExpiry = token.get("expires_at").getAsString();
} finally {
httpPost.releaseConnection();
}
} }
return adminToken; return adminToken;
} }
@ -289,7 +309,7 @@ public class HttpAuthClient implements AuthClient {
} }
private boolean isExpired(String expires) { private boolean isExpired(String expires) {
Date tokenExpiryDate = null; Date tokenExpiryDate;
try { try {
// The date looks like: 2014-11-13T02:34:59.953729Z // The date looks like: 2014-11-13T02:34:59.953729Z
// SimpleDateFormat can't handle the microseconds so take them off // SimpleDateFormat can't handle the microseconds so take them off