/*
* Copyright 2015 EMC Corporation
* Copyright 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.emc.storageos.keystone.restapi;
import java.net.URI;
import javax.ws.rs.core.MediaType;
import com.emc.storageos.keystone.restapi.model.request.CreateEndpointRequest;
import com.emc.storageos.keystone.restapi.model.response.*;
import com.emc.storageos.svcs.errorhandling.resources.APIException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.keystone.KeystoneConstants;
import com.emc.storageos.keystone.restapi.errorhandling.KeystoneApiException;
import com.emc.storageos.keystone.restapi.model.request.AuthTokenRequest;
import com.emc.storageos.keystone.restapi.model.request.PassWordCredentials;
import com.emc.storageos.services.restutil.StandardRestClient;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
/**
* Keystone API client to execute rest APIs on
* keystone service.
*
*/
public class KeystoneApiClient extends StandardRestClient {
private static Logger log = LoggerFactory.getLogger(KeystoneApiClient.class);
private String _tenantName;
/**
* Constructor
*
* @param client
* A reference to a Jersey Apache HTTP client.
* @param username
* The user to be authenticated.
* @param password
* The user password for authentication.
*/
public KeystoneApiClient(URI baseURI, String username,
String password, Client client) {
_client = client;
_base = baseURI;
_username = username;
_password = password;
_authToken = "";
}
@Override
protected Builder setResourceHeaders(WebResource resource) {
log.info("Setting the resource header " + _authToken);
return resource.header(KeystoneConstants.AUTH_TOKEN, _authToken);
}
@Override
protected void authenticate() throws KeystoneApiException {
// Construct the Java pojo request object
AuthTokenRequest tokenRequest = new AuthTokenRequest();
tokenRequest.auth.setTenantName(_tenantName);
PassWordCredentials creds = new PassWordCredentials();
creds.setUsername(_username);
creds.setPassword(_password);
tokenRequest.auth.setPasswordCreds(creds);
String body = "";
try {
// Convert java pojo to json request body
body = getJsonForEntity(tokenRequest);
} catch (Exception e) {
throw KeystoneApiException.exceptions.requestJsonPayloadParseFailure(tokenRequest.toString());
}
// invoke the API to authenticate
URI requestURI = _base.resolve(URI.create(KeystoneConstants.URI_TOKENS));
ClientResponse response = _client.resource(requestURI).type(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, body);
if (response.getClientResponseStatus() != ClientResponse.Status.OK
&& response.getClientResponseStatus() != ClientResponse.Status.CREATED) {
throw KeystoneApiException.exceptions.authenticationFailure(requestURI.toString());
}
AuthTokenResponse responseBody = getAuthTokenResponce(response);
_authToken = responseBody.getAccess().getToken().getId();
}
/**
* Retrieves Keystone endpoints from the Keystone API.
*
* @return EndpointResponse object filled with Keystone endpoints data.
*/
public EndpointResponse getKeystoneEndpoints() throws KeystoneApiException {
log.debug("START - getKeystoneEndpoints");
// Send a request to Keystone API.
URI requestURI = _base.resolve(URI.create(KeystoneConstants.URI_ENDPOINTS));
ClientResponse response = get(requestURI);
// Throw an exception when response code is other than OK
if (response.getClientResponseStatus() != ClientResponse.Status.OK) {
throw KeystoneApiException.exceptions.apiExecutionFailed(response.toString());
}
// Parse response to Java object.
EndpointResponse endpointResponse;
log.debug("Parsing endpoint request results to Java object");
try {
endpointResponse = getResponseObject(EndpointResponse.class, response);
} catch (Exception e) {
log.error("Failed to parse the endpoint validation response");
throw KeystoneApiException.exceptions.responseJsonParseFailure(response.toString());
}
log.debug("END - getKeystoneEndpoints");
return endpointResponse;
}
/**
* Get Keystone services from the Keystone API.
*
* @return ServiceResponse object filled with Keystone services data.
*/
public ServiceResponse getKeystoneServices() throws KeystoneApiException {
log.debug("START - getKeystoneServices");
// Send a request to Keystone API.
URI requestURI = _base.resolve(URI.create(KeystoneConstants.URI_SERVICES));
ClientResponse response = get(requestURI);
// Throw an exception when response code is other than OK.
if (response.getClientResponseStatus() != ClientResponse.Status.OK) {
throw KeystoneApiException.exceptions.apiExecutionFailed(response.toString());
}
// Parse response to Java object.
ServiceResponse serviceResponse;
log.debug("Parsing service request results to Java object");
try {
serviceResponse = getResponseObject(ServiceResponse.class, response);
} catch (Exception e) {
log.error("Failed to parse the service validation response");
throw KeystoneApiException.exceptions.responseJsonParseFailure(response.toString());
}
log.debug("END - getKeystoneServices");
return serviceResponse;
}
/**
* Deletes Keystone endpoint with given ID.
*
* @param endpointId Keystone endpoint ID to delete.
*/
public void deleteKeystoneEndpoint(String endpointId) {
log.debug("START - deleteKeystoneEndpoint");
if (endpointId == null) {
log.error("endpointId is null");
throw APIException.internalServerErrors.targetIsNullOrEmpty("Endpoint id");
}
// Create correct delete URI.
String uri = KeystoneConstants.URI_ENDPOINTS + "/" + endpointId;
URI requestURI = _base.resolve(URI.create(uri));
// Send a delete request to Keystone API.
ClientResponse response = delete(requestURI);
// Throw an exception when response code is other than NO_CONTENT.
if (response.getClientResponseStatus() != ClientResponse.Status.NO_CONTENT) {
throw KeystoneApiException.exceptions.apiExecutionFailed(response.toString());
}
log.debug("END - deleteKeystoneEndpoint");
}
/**
* Creates a new Keystone endpoint.
*
* @param endpoint A new endpoint to create filled with information.
* @return CreateEndpointResponse object with created Keystone endpoint.
*/
public CreateEndpointResponse createKeystoneEndpoint(EndpointV2 endpoint) {
log.debug("START - createKeystoneEndpoint");
if (endpoint == null) {
log.error("endpoint is null");
throw APIException.internalServerErrors.targetIsNullOrEmpty("Endpoint object");
}
// Construct the Java pojo request object
CreateEndpointRequest endpointRequest = new CreateEndpointRequest();
endpointRequest.setEndpoint(endpoint);
String body = "";
try {
// Convert java pojo to json request body
body = getJsonForEntity(endpointRequest);
} catch (Exception e) {
throw KeystoneApiException.exceptions.requestJsonPayloadParseFailure(endpointRequest.toString());
}
// Create a new URI for endpoint creation.
String uri = KeystoneConstants.URI_ENDPOINTS;
URI requestURI = _base.resolve(URI.create(uri));
// Send a create request to Keystone API.
ClientResponse response = post(requestURI, body);
// Throw an exception when response code is other than OK or CREATED.
if (response.getClientResponseStatus() != ClientResponse.Status.OK
&& response.getClientResponseStatus() != ClientResponse.Status.CREATED) {
throw KeystoneApiException.exceptions.apiExecutionFailed(response.toString());
}
// Parse response to Java object.
CreateEndpointResponse createEndpointResponse;
log.debug("Parsing service request results to Java object");
try {
createEndpointResponse = getResponseObject(CreateEndpointResponse.class, response);
} catch (Exception e) {
log.error("Failed to parse the endpoint validation response");
throw KeystoneApiException.exceptions.responseJsonParseFailure(response.toString());
}
log.debug("END - createKeystoneEndpoint");
return createEndpointResponse;
}
/**
* Creates a new Keystone service.
*
* @param service A new service to create filled with information.
* @return CreateServiceResponse object with created Keystone service.
*/
public CreateServiceResponse createKeystoneService(ServiceV2 service) {
log.debug("START - createKeystoneService");
if (service == null) {
log.error("service is null");
throw APIException.internalServerErrors.targetIsNullOrEmpty("Service object");
}
// Construct the Java pojo request object
CreateServiceResponse serviceResponse = new CreateServiceResponse();
serviceResponse.setService(service);
String body = "";
try {
// Convert java pojo to json request body
body = getJsonForEntity(serviceResponse);
} catch (Exception e) {
throw KeystoneApiException.exceptions.requestJsonPayloadParseFailure(serviceResponse.toString());
}
// Create a new URI for service creation.
String uri = KeystoneConstants.URI_SERVICES;
URI requestURI = _base.resolve(URI.create(uri));
// Send a create request to Keystone API.
ClientResponse response = post(requestURI, body);
// Throw an exception when response code is other than OK or CREATED.
if (response.getClientResponseStatus() != ClientResponse.Status.OK
&& response.getClientResponseStatus() != ClientResponse.Status.CREATED) {
throw KeystoneApiException.exceptions.apiExecutionFailed(response.toString());
}
// Parse response to Java object.
CreateServiceResponse createServiceResponse;
log.debug("Parsing service request results to Java object");
try {
createServiceResponse = getResponseObject(CreateServiceResponse.class, response);
} catch (Exception e) {
log.error("Failed to parse the endpoint validation response");
throw KeystoneApiException.exceptions.responseJsonParseFailure(response.toString());
}
log.debug("END - createKeystoneService");
return createServiceResponse;
}
/**
* Get Keystone tenants from the Keystone API.
*
* @return TenantResponse object filled with Keystone tenants data.
*/
public TenantResponse getKeystoneTenants() throws KeystoneApiException {
log.debug("START - getKeystoneTenants");
// Send a request to Keystone API.
URI requestURI = _base.resolve(URI.create(KeystoneConstants.URI_TENANTS));
ClientResponse response = get(requestURI);
// Throw an exception when response code is other than OK.
if (response.getClientResponseStatus() != ClientResponse.Status.OK) {
throw KeystoneApiException.exceptions.apiExecutionFailed(response.toString());
}
// Parse response to Java object.
TenantResponse tenantResponse;
log.debug("Parsing service request results to Java object");
try {
tenantResponse = getResponseObject(TenantResponse.class, response);
} catch (Exception e) {
log.error("Failed to parse the tenant validation response");
throw KeystoneApiException.exceptions.responseJsonParseFailure(response.toString());
}
log.debug("END - getKeystoneTenants");
return tenantResponse;
}
private AuthTokenResponse getAuthTokenResponce(ClientResponse response) {
log.debug("START - getAuthTokenResponce");
// Read the response and get the auth token
AuthTokenResponse responseBody = null;
try {
responseBody = getResponseObject(AuthTokenResponse.class, response);
} catch (Exception e) {
log.error("Failed to parse the token validation response");
throw KeystoneApiException.exceptions.responseJsonParseFailure(response.toString());
}
log.debug("END - getAuthTokenResponce");
return responseBody;
}
public void authenticate_keystone() {
authenticate();
}
public String getTenantName() {
return _tenantName;
}
public void setTenantName(String _tenantName) {
this._tenantName = _tenantName;
}
public String getAuthToken() {
return _authToken;
}
public void setAuthToken(String token) {
this._authToken = token;
}
/**
* Validates the token
* If valid - returns the token response
*
* @param userToken
* @return
*/
public AuthTokenResponse validateUserToken(String userToken) {
String tokenValidateUri = String.format(KeystoneConstants.VALIDATE_TOKEN,
new Object[] { userToken });
log.info("Invoking token validation api " + _base.resolve(URI.create(tokenValidateUri)).toString());
ClientResponse response = get(_base.resolve(URI.create(tokenValidateUri)));
AuthTokenResponse responseBody = getAuthTokenResponce(response);
log.debug("Got the response -" + responseBody.toString());
return responseBody;
}
@Override
protected int checkResponse(URI uri, ClientResponse response) {
log.debug("START - checkresponse");
ClientResponse.Status status = response.getClientResponseStatus();
int responseCode = 0;
if (status != ClientResponse.Status.OK
&& status != ClientResponse.Status.ACCEPTED
&& status != ClientResponse.Status.CREATED
&& status != ClientResponse.Status.NO_CONTENT) {
log.error("Keystone API failed to execute");
throw KeystoneApiException.exceptions.apiExecutionFailed(response.toString());
} else {
responseCode = status.getStatusCode();
}
log.info("The response code is - " + String.valueOf(responseCode));
log.debug("END - checkresponse");
return responseCode;
}
}