/******************************************************************************* * Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved * * 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 org.cloudifysource.restclient; import java.io.File; import java.io.IOException; import java.net.URL; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.impl.client.AbstractHttpClient; import org.apache.http.impl.client.SystemDefaultHttpClient; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.cloudifysource.dsl.internal.CloudifyConstants; import org.cloudifysource.dsl.internal.CloudifyErrorMessages; import org.cloudifysource.dsl.internal.ProcessorTypes; import org.cloudifysource.dsl.rest.AddTemplatesException; import org.cloudifysource.dsl.rest.request.AddTemplatesRequest; import org.cloudifysource.dsl.rest.request.InstallApplicationRequest; import org.cloudifysource.dsl.rest.request.InstallServiceRequest; import org.cloudifysource.dsl.rest.request.InvokeCustomCommandRequest; import org.cloudifysource.dsl.rest.request.SetServiceInstancesRequest; import org.cloudifysource.dsl.rest.response.AddTemplatesResponse; import org.cloudifysource.dsl.rest.response.ApplicationDescription; import org.cloudifysource.dsl.rest.response.DeploymentEvent; import org.cloudifysource.dsl.rest.response.DeploymentEvents; import org.cloudifysource.dsl.rest.response.GetMachineDumpFileResponse; import org.cloudifysource.dsl.rest.response.GetMachinesDumpFileResponse; import org.cloudifysource.dsl.rest.response.GetPUDumpFileResponse; import org.cloudifysource.dsl.rest.response.GetTemplateResponse; import org.cloudifysource.dsl.rest.response.InstallApplicationResponse; import org.cloudifysource.dsl.rest.response.InstallServiceResponse; import org.cloudifysource.dsl.rest.response.InvokeInstanceCommandResponse; import org.cloudifysource.dsl.rest.response.InvokeServiceCommandResponse; import org.cloudifysource.dsl.rest.response.ListTemplatesResponse; import org.cloudifysource.dsl.rest.response.Response; import org.cloudifysource.dsl.rest.response.ServiceDescription; import org.cloudifysource.dsl.rest.response.ShutdownManagementResponse; import org.cloudifysource.dsl.rest.response.UninstallApplicationResponse; import org.cloudifysource.dsl.rest.response.UninstallServiceResponse; import org.cloudifysource.dsl.rest.response.UploadResponse; import org.cloudifysource.restclient.exceptions.RestClientException; import org.cloudifysource.restclient.messages.MessagesUtils; import org.cloudifysource.restclient.messages.RestClientMessageKeys; import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.TypeReference; /** * This class performs all the calls to the REST API, using the {@link RestClientExecutor}. * * @author yael * */ public class RestClient { private static final Logger logger = Logger.getLogger(RestClient.class.getName()); private static final String FAILED_CREATING_CLIENT = "failed_creating_client"; private static final String HTTPS = "https"; private static final String UPLOAD_CONTROLLER_URL = "/upload/"; private static final String DEPLOYMENT_CONTROLLER_URL = "/deployments/"; private static final String TEMPLATES_CONTROLLER_URL = "/templates/"; private static final String SHUTDOWN_MANAGERS_CONTROLLER_URL = "/management/"; private static final String INSTALL_SERVICE_URL_FORMAT = "%s/services/%s"; private static final String INSTALL_APPLICATION_URL_FORMAT = "%s"; private static final String UPLOAD_URL_FORMAT = "%s"; private static final String GET_DEPLOYMENT_EVENTS_URL_FORMAT = "%s/events/?from=%s&to=%s"; private static final String GET_SERVICE_DESCRIPTION_URL_FORMAT = "%s/service/%s/description"; private static final String GET_SERVICES_DESCRIPTION_URL_FORMAT = "%s/description"; private static final String GET_APPLICATION_DESCRIPTION_URL_FORMAT = "applications/%s/description"; private static final String GET_APPLICATION_DESCRIPTIONS_URL_FORMAT = "applications/description"; private static final String ADD_TEMPALTES_URL_FORMAT = ""; private static final String GET_TEMPALTE_URL_FORMAT = "%s"; private static final String LIST_TEMPALTES_URL_FORMAT = ""; private static final String REMOVE_TEMPALTE_URL_FORMAT = "%s"; private static final String INVOKE_SERVICE_COMMAND_URL_FORMAT = "applications/%s/services/%s/invoke"; private static final String INVOKE_INSTANCE_COMMAND_URL_FORMAT = "applications/%s/services/%s/instances/%s/invoke"; private static final String SET_INSTANCES_URL_FORMAT = "%s/services/%s/count"; private static final String GET_LAST_EVENT_URL_FORMAT = "%s/events/last/"; private static final String SHUTDOWN_MANAGERS_URL_FORMAT = "controllers"; private static final String GET_PU_DUMP_FILE_URL_FORMAT = "dump/processing-units/?fileSizeLimit=%s"; private static final String GET_MACHINE_DUMP_FILE_URL_FORMAT = "dump/machine/%s/?processors=%s&fileSizeLimit=%s"; private static final String GET_MACHINES_DUMP_FILE_URL_FORMAT = "dump/machines/?processors=%s&fileSizeLimit=%s"; protected final RestClientExecutor executor; private final String versionedDeploymentControllerUrl; protected String versionedUploadControllerUrl; protected String versionedTemplatesControllerUrl; protected String shutdownManagersControllerUrl; public RestClient(final URL url, final String username, final String password, final String apiVersion) throws RestClientException { versionedDeploymentControllerUrl = apiVersion + DEPLOYMENT_CONTROLLER_URL; versionedUploadControllerUrl = apiVersion + UPLOAD_CONTROLLER_URL; versionedTemplatesControllerUrl = apiVersion + TEMPLATES_CONTROLLER_URL; shutdownManagersControllerUrl = apiVersion + SHUTDOWN_MANAGERS_CONTROLLER_URL; this.executor = createExecutor(url, apiVersion); setCredentials(username, password); } /** * * @throws RestClientException . */ public void connect() throws RestClientException { final String url = versionedDeploymentControllerUrl + "testrest"; log(Level.FINE, "[connect] - sending GET request to REST [" + url + "]"); executor.get(url, new TypeReference<Response<Void>>() { }); } /** * Sets the credentials. * * @param username * . * @param password * . */ public void setCredentials(final String username, final String password) { executor.setCredentials(username, password); } /** * Executes a rest api call to install a specific service. * * @param applicationName * The name of the application. * @param serviceName * The name of the service to install. * @param request * The install service request. * @return The install service response. * @throws RestClientException . */ public InstallServiceResponse installService(final String applicationName, final String serviceName, final InstallServiceRequest request) throws RestClientException { String effAppName = applicationName; if (applicationName == null) { effAppName = CloudifyConstants.DEFAULT_APPLICATION_NAME; } if (serviceName == null) { throw MessagesUtils.createRestClientException(CloudifyErrorMessages.SERVICE_NAME_MISSING.getName()); } if (request == null) { throw MessagesUtils.createRestClientException( CloudifyErrorMessages.INSTALL_SERVICE_REQUEST_MISSING.getName()); } final String installServiceUrl = getFormattedUrl( versionedDeploymentControllerUrl, INSTALL_SERVICE_URL_FORMAT, effAppName, serviceName); log(Level.FINE, "[installService] - sending POST request to REST [" + installServiceUrl + "]"); return executor.postObject(installServiceUrl, request, new TypeReference<Response<InstallServiceResponse>>() { }); } /** * Executes a rest api call to install an application. * * @param applicationName * The name of the application. * @param request * The install service request. * @return The install service response. * @throws RestClientException . */ public InstallApplicationResponse installApplication(final String applicationName, final InstallApplicationRequest request) throws RestClientException { final String installApplicationUrl = getFormattedUrl( versionedDeploymentControllerUrl, INSTALL_APPLICATION_URL_FORMAT, applicationName); log(Level.FINE, "[installApplication] - sending POST request to REST [" + installApplicationUrl + "]"); return executor.postObject(installApplicationUrl, request, new TypeReference<Response<InstallApplicationResponse>>() { }); } /** * Uninstalls the specified service. * * @param applicationName * The application containing the service. * @param serviceName * The service name. * @param timeoutInMinutes * Timeout in minutes. * @return an uninstall service response object. * @throws RestClientException * Indicates the uninstall operation failed. */ public UninstallServiceResponse uninstallService(final String applicationName, final String serviceName, final int timeoutInMinutes) throws RestClientException { final String url = getFormattedUrl( versionedDeploymentControllerUrl, INSTALL_SERVICE_URL_FORMAT, applicationName, serviceName); final Map<String, String> requestParams = new HashMap<String, String>(); requestParams.put(CloudifyConstants.REQ_PARAM_TIMEOUT_IN_MINUTES, String.valueOf(timeoutInMinutes)); log(Level.FINE, "[uninstallService] - sending DELETE request to REST [" + url + "]"); return executor.delete(url, requestParams, new TypeReference<Response<UninstallServiceResponse>>() { }); } /** * Uninstalls the specified application. * * @param applicationName * The application name. * @param timeoutInMinutes * Timeout in minutes. * @return an uninstall application response object. * * @throws RestClientException * Indicates the uninstall operation failed. */ public UninstallApplicationResponse uninstallApplication(final String applicationName, final int timeoutInMinutes) throws RestClientException { final String url = versionedDeploymentControllerUrl + applicationName; final Map<String, String> requestParams = new HashMap<String, String>(); requestParams.put(CloudifyConstants.REQ_PARAM_TIMEOUT_IN_MINUTES, String.valueOf(timeoutInMinutes)); log(Level.FINE, "[uninstallApplication] - sending DELETE request to REST [" + url + "]"); return executor.delete(url, requestParams, new TypeReference<Response<UninstallApplicationResponse>>() { }); } /** * Uploads a file to the repository. * * @param fileName * The name of the file to upload. * @param file * The file to upload. * @return upload response. * @throws RestClientException . */ public UploadResponse upload(final String fileName, final File file) throws RestClientException { validateFile(file); final String finalFileName = fileName == null ? file.getName() : fileName; if (logger.isLoggable(Level.FINE)) { logger.fine("[getDeploymentEvents] - uploading file " + file.getAbsolutePath() + " with name " + finalFileName); } final String uploadUrl = getFormattedUrl( versionedUploadControllerUrl, UPLOAD_URL_FORMAT, finalFileName); log(Level.FINE, "[upload] - sending POST request to REST [" + uploadUrl + "]"); final UploadResponse response = executor.postFile( uploadUrl, file, CloudifyConstants.UPLOAD_FILE_PARAM_NAME, new TypeReference<Response<UploadResponse>>() { }); return response; } /** * Provides access to life cycle events of a service. * * @param deploymentId * The deployment id given at installation time. * @param from * The starting event index. * @param to * The last event index. passing -1 means all events (limit to 100 at a time) * @return The events. * @throws RestClientException . */ public DeploymentEvents getDeploymentEvents(final String deploymentId, final int from, final int to) throws RestClientException { validateDeploymentID(deploymentId, "getDeploymentEvents(String,int,int)"); final String url = getFormattedUrl( versionedDeploymentControllerUrl, GET_DEPLOYMENT_EVENTS_URL_FORMAT, deploymentId, String.valueOf(from), String.valueOf(to)); log(Level.FINE, "[getDeploymentEvents] - sending GET request to REST [" + url + "]"); return executor.get(url, new TypeReference<Response<DeploymentEvents>>() { }); } private void validateDeploymentID(final String deploymentId, final String methodName) throws RestClientException { if (deploymentId == null) { logger.warning("[" + methodName + "] - deployment ID is missing."); throw MessagesUtils.createRestClientException( CloudifyErrorMessages.MISSING_DEPLOYMENT_ID.getName(), methodName); } } /** * * @param appName * . * @param serviceName * . * @return ServiceDescription. * @throws RestClientException . */ public ServiceDescription getServiceDescription(final String appName, final String serviceName) throws RestClientException { final String url = getFormattedUrl( versionedDeploymentControllerUrl, GET_SERVICE_DESCRIPTION_URL_FORMAT, appName, serviceName); log(Level.FINE, "[getServiceDescription] - sending GET request to REST [" + url + "]"); return executor.get(url, new TypeReference<Response<ServiceDescription>>() { }); } /** * Retrieves a list of services description by deployment id. * * @param deploymentId * The deployment id. * @return list of {@link ServiceDescription} * @throws RestClientException */ public List<ServiceDescription> getServiceDescriptions(final String deploymentId) throws RestClientException { validateDeploymentID(deploymentId, "getServiceDescriptions(String)"); final String url = getFormattedUrl( versionedDeploymentControllerUrl, GET_SERVICES_DESCRIPTION_URL_FORMAT, deploymentId); log(Level.FINE, "[getServiceDescriptions] - sending GET request to REST [" + url + "]"); return executor.get(url, new TypeReference<Response<List<ServiceDescription>>>() { }); } /** * * @param appName * . * @return ApplicationDescription. * @throws RestClientException . */ public ApplicationDescription getApplicationDescription(final String appName) throws RestClientException { final String url = getFormattedUrl( versionedDeploymentControllerUrl, GET_APPLICATION_DESCRIPTION_URL_FORMAT, appName); log(Level.FINE, "[getApplicationDescription] - sending GET request to REST [" + url + "]"); return executor.get(url, new TypeReference<Response<ApplicationDescription>>() { }); } /** * * @return List of ApplicationDescription objects. * @throws RestClientException . */ public List<ApplicationDescription> getApplicationDescriptionsList() throws RestClientException { final String url = getFormattedUrl( versionedDeploymentControllerUrl, GET_APPLICATION_DESCRIPTIONS_URL_FORMAT); log(Level.FINE, "[getApplicationDescriptionsList] - sending GET request to REST [" + url + "]"); return executor.get(url, new TypeReference<Response<List<ApplicationDescription>>>() { }); } /** * @param appName * The application the services to be listed are part of. * @return List of service descriptions * @throws RestClientException . */ public List<ServiceDescription> getServicesDescriptionList(final String appName) throws RestClientException { return getApplicationDescription(appName).getServicesDescription(); } /******** * Manually Scales a specific service in/out. * * @param applicationName * the service's application name. * @param serviceName * the service name. * @param request * the scale request details. * @throws RestClientException * in case of an error. */ public void setServiceInstances(final String applicationName, final String serviceName, final SetServiceInstancesRequest request) throws RestClientException { if (request == null) { throw new IllegalArgumentException("request may not be null"); } final String setInstancesUrl = getFormattedUrl( versionedDeploymentControllerUrl, SET_INSTANCES_URL_FORMAT, applicationName, serviceName); log(Level.FINE, "[setServiceInstances] - sending POST request to REST [" + setInstancesUrl + "]"); executor.postObject( setInstancesUrl, request, new TypeReference<Response<Void>>() { } ); } /** * Invokes the command specified in the request on all the instances of the given service. * * @param applicationName * the service's application name. * @param serviceName * the service's name. * @param request * the InvokeCustomCommandRequest containing the command and parameters * @return InvokeServiceCommandResponse the response holding the results of the command invocation per service * @throws RestClientException * when the invocation failed or the service/instance were not found. */ public InvokeServiceCommandResponse invokeServiceCommand(final String applicationName, final String serviceName, final InvokeCustomCommandRequest request) throws RestClientException { if (request == null) { throw new IllegalArgumentException("request may not be null"); } InvokeServiceCommandResponse result = null; final String invokeCommandUrl = getFormattedUrl( versionedDeploymentControllerUrl, INVOKE_SERVICE_COMMAND_URL_FORMAT, applicationName, serviceName); result = executor.postObject( invokeCommandUrl, request, new TypeReference<Response<InvokeServiceCommandResponse>>() { } ); return result; } /** * Invokes the command specified in the request on the specified instance of the given service. * * @param applicationName * the service's application name. * @param serviceName * the service's name. * @param instanceId * the relevant instance id * @param request * the InvokeCustomCommandRequest containing the command and parameters * @return InvokeServiceCommandResponse the response holding the results of the command invocation per service * @throws RestClientException * when the invocation failed or the service/instance were not found. */ public InvokeInstanceCommandResponse invokeInstanceCommand(final String applicationName, final String serviceName, final int instanceId, final InvokeCustomCommandRequest request) throws RestClientException { if (request == null) { throw new IllegalArgumentException("request may not be null"); } final String instanceIdStr = String.valueOf(instanceId); InvokeInstanceCommandResponse result = null; final String invokeCommandUrl = getFormattedUrl( versionedDeploymentControllerUrl, INVOKE_INSTANCE_COMMAND_URL_FORMAT, applicationName, serviceName, instanceIdStr); result = executor.postObject( invokeCommandUrl, request, new TypeReference<Response<InvokeInstanceCommandResponse>>() { } ); return result; } /******** * Retrieves last event indes for this deployment id. * * @param deploymentId * The deploymentId. * @return {@link DeploymentEvents} * @throws RestClientException * in case of an error on the rest server. */ public DeploymentEvent getLastEvent(final String deploymentId) throws RestClientException { validateDeploymentID(deploymentId, "getLastEvent(String)"); final String url = getFormattedUrl( versionedDeploymentControllerUrl, GET_LAST_EVENT_URL_FORMAT, deploymentId); log(Level.FINE, "[getLastEvent] - sending GET request to REST [" + url + "]"); return executor.get(url, new TypeReference<Response<DeploymentEvent>>() { }); } /** * Validate file before uploading. * * @param file * The file to upload. * @throws RestClientException . */ protected void validateFile(final File file) throws RestClientException { if (file == null) { throw MessagesUtils.createRestClientException(RestClientMessageKeys.UPLOAD_FILE_MISSING.getName()); } final String absolutePath = file.getAbsolutePath(); if (!file.exists()) { throw MessagesUtils.createRestClientException(RestClientMessageKeys.UPLOAD_FILE_DOESNT_EXIST.getName(), absolutePath); } if (!file.isFile()) { throw MessagesUtils.createRestClientException(RestClientMessageKeys.UPLOAD_FILE_NOT_FILE.getName(), absolutePath); } final long length = file.length(); if (length > CloudifyConstants.DEFAULT_UPLOAD_SIZE_LIMIT_BYTES) { throw MessagesUtils.createRestClientException( RestClientMessageKeys.UPLOAD_FILE_SIZE_LIMIT_EXCEEDED.getName(), absolutePath, length, CloudifyConstants.DEFAULT_UPLOAD_SIZE_LIMIT_BYTES); } } private RestClientExecutor createExecutor(final URL url, final String apiVersion) throws RestClientException { SystemDefaultHttpClient httpClient; if (HTTPS.equals(url.getProtocol())) { httpClient = getSSLHttpClient(url); } else { httpClient = new SystemDefaultHttpClient(); } final HttpParams httpParams = httpClient.getParams(); HttpConnectionParams.setConnectionTimeout(httpParams, CloudifyConstants.DEFAULT_HTTP_CONNECTION_TIMEOUT); int socketTimeout = getSocketTimeout(); logger.fine("setting rest client socket timeout to: " + socketTimeout); HttpConnectionParams.setSoTimeout(httpParams, socketTimeout); return new RestClientExecutor(httpClient, url); } /** * Returns a HTTP client configured to use SSL. * * @param url * * @return HTTP client configured to use SSL * @throws org.cloudifysource.restclient.exceptions.RestClientException * Reporting different failures while creating the HTTP client */ private SystemDefaultHttpClient getSSLHttpClient(final URL url) throws RestClientException { try { final X509TrustManager trustManager = createTrustManager(); final SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, new TrustManager[] { trustManager }, null); final SSLSocketFactory ssf = new SSLSocketFactory(ctx, createHostnameVerifier()); final AbstractHttpClient base = new SystemDefaultHttpClient(); SystemDefaultHttpClient httpClient = new SystemDefaultHttpClient(base.getParams()); httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme(HTTPS, url.getPort(), ssf)); return httpClient; } catch (final Exception e) { throw new RestClientException(FAILED_CREATING_CLIENT, "Failed creating http client", ExceptionUtils.getFullStackTrace(e)); } } private X509TrustManager createTrustManager() { final X509TrustManager tm = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { } @Override public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException { } }; return tm; } private X509HostnameVerifier createHostnameVerifier() { final X509HostnameVerifier verifier = new X509HostnameVerifier() { @Override public boolean verify(final String arg0, final SSLSession arg1) { return true; } @Override public void verify(final String host, final String[] cns, final String[] subjectAlts) throws SSLException { } @Override public void verify(final String host, final X509Certificate cert) throws SSLException { } @Override public void verify(final String host, final SSLSocket ssl) throws IOException { } }; return verifier; } /** * * @param controllerUrl * . * @param format * . * @param args * . * @return the formatted URL. */ protected String getFormattedUrl(final String controllerUrl, final String format, final String... args) { return controllerUrl + String.format(format, (Object[]) args); } /** * Executes a rest API call to get template. * * @param templateName * the name of the template to get. * @return GetTemplateResponse. * @throws RestClientException . */ public GetTemplateResponse getTemplate(final String templateName) throws RestClientException { final String getTempalteInternalUrl = getFormattedUrl( versionedTemplatesControllerUrl, GET_TEMPALTE_URL_FORMAT, templateName); log(Level.FINE, "[getTemplate] - sending GET request to REST [" + getTempalteInternalUrl + "]"); return executor.get(getTempalteInternalUrl, new TypeReference<Response<GetTemplateResponse>>() { }); } /** * Executes a rest API call to list templates. * * @return ListTemplatesResponse. * @throws RestClientException . */ public ListTemplatesResponse listTemplates() throws RestClientException { final String listTempaltesInternalUrl = getFormattedUrl( versionedTemplatesControllerUrl, LIST_TEMPALTES_URL_FORMAT); log(Level.FINE, "[listTemplates] - sending GET request to REST [" + listTempaltesInternalUrl + "]"); return executor.get(listTempaltesInternalUrl, new TypeReference<Response<ListTemplatesResponse>>() { }); } /** * Executes a rest API call to add templates to all REST instances. * * @param request * contains the templates folder. * @return AddTemplatesResponse. * @throws AddTemplatesException * If failed to add all templates (includes partial failure). * @throws RestClientException . */ public AddTemplatesResponse addTemplates(final AddTemplatesRequest request) throws RestClientException, AddTemplatesException { final String addTempaltesUrl = getFormattedUrl( versionedTemplatesControllerUrl, ADD_TEMPALTES_URL_FORMAT); AddTemplatesResponse response = null; try { log(Level.FINE, "[addTemplates] - sending POST request to REST [" + addTempaltesUrl + "]"); return executor.postObject( addTempaltesUrl, request, new TypeReference<Response<AddTemplatesResponse>>() { }); } catch (final RestClientException e) { final String verbose = e.getVerbose(); // may be partial failure - in this case the verbose contains the AddTemplatesResponse object. log(Level.FINE, "[addTemplates] - caught RestClientException, " + "trying to read the response from the verbose[ " + verbose + "]"); try { response = new ObjectMapper().readValue(verbose, AddTemplatesResponse.class); throw new AddTemplatesException(response); } catch (final JsonProcessingException e1) { // failed to read the response from the verbose => not a partial failure // => throwing the original exception log(Level.FINE, "[addTemplates] - caught JsonProcessingException " + "when tried to read the response from the verbose, " + " throwing the RestClientException that constructed " + "from the original exception"); throw e; } catch (final IOException e1) { // failed to read the response from the verbose => not a partial failure // => throwing the original exception if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "[addTemplates] - caught IOException " + "when tried to read the response from the verbose, " + " throwing the RestClientException that constructed " + "from the original exception", e1); } throw e; } } } /** * Executes a rest API call to remove template from all REST instances. * * @param templateName * the template's name to remove. * @throws RestClientException . */ public void removeTemplate(final String templateName) throws RestClientException { final String removeTempalteUrl = getFormattedUrl( versionedTemplatesControllerUrl, REMOVE_TEMPALTE_URL_FORMAT, templateName); log(Level.FINE, "[removeTemplate] - sending DELETE request to REST [" + removeTempalteUrl + "]"); executor.delete( removeTempalteUrl, new TypeReference<Response<Void>>() { }); } /** * Executes a rest API call to shutdown the managers of the current cloud. * * @return ShutdownManagementResponse * @throws RestClientException */ public ShutdownManagementResponse shutdownManagers() throws RestClientException { final String shutdownManagersUrl = getFormattedUrl( shutdownManagersControllerUrl, SHUTDOWN_MANAGERS_URL_FORMAT); log(Level.FINE, "[shutdownManagers] - sending DELETE request to REST [" + shutdownManagersUrl + "]"); return executor.delete( shutdownManagersUrl, new TypeReference<Response<ShutdownManagementResponse>>() { }); } /** * * @param fileSizeLimit * @return {@link GetPUDumpFileResponse} containing the dump of all the processing units. * @throws RestClientException */ public GetPUDumpFileResponse getPUDumpFile(final long fileSizeLimit) throws RestClientException { long actualFileSizeLimit = fileSizeLimit; if (fileSizeLimit == 0) { actualFileSizeLimit = CloudifyConstants.DEFAULT_DUMP_FILE_SIZE_LIMIT; } final String getPUDumpFileUrl = getFormattedUrl( shutdownManagersControllerUrl, GET_PU_DUMP_FILE_URL_FORMAT, Long.toString(actualFileSizeLimit)); log(Level.FINE, "[getPUDumpFile] - sending GET request to REST [" + getPUDumpFileUrl + "]"); return executor.get( getPUDumpFileUrl, new TypeReference<Response<GetPUDumpFileResponse>>() { }); } /** * @param ip * The machine IP. * @param processors * The list of processors to be used. * @param fileSizeLimit * The dump file size limit. * @return {@link GetMachineDumpFileResponse} containing the dump data of the machine. * @throws RestClientException */ public GetMachineDumpFileResponse getMachineDumpFile( final String ip, final long fileSizeLimit, final String processors) throws RestClientException { if (ip == null) { throw MessagesUtils.createRestClientException(CloudifyErrorMessages.MACHINE_IP_MISSING.getName()); } long actualSizeLimit = fileSizeLimit; if (fileSizeLimit == 0) { actualSizeLimit = CloudifyConstants.DEFAULT_DUMP_FILE_SIZE_LIMIT; } String actualProcessors = processors; if (StringUtils.isBlank(processors)) { actualProcessors = ProcessorTypes.DEFAULT_PROCESSORS; } final String getMachineDumpFileURL = getFormattedUrl( shutdownManagersControllerUrl, GET_MACHINE_DUMP_FILE_URL_FORMAT, ip, actualProcessors, Long.toString(actualSizeLimit)); log(Level.FINE, "[getPUDumpFile] - sending GET request to REST [" + getMachineDumpFileURL + "]"); return executor.get( getMachineDumpFileURL, new TypeReference<Response<GetMachineDumpFileResponse>>() { }); } /** * @param processors * The list of processors to be used. * @param fileSizeLimit * The dump file size limit. * @return {@link GetMachinesDumpFileResponse} containing the dump data of all the machines. * @throws RestClientException */ public GetMachinesDumpFileResponse getMachinesDumpFile(final String processors, final long fileSizeLimit) throws RestClientException { long actualSizeLimit = fileSizeLimit; if (fileSizeLimit == 0) { actualSizeLimit = CloudifyConstants.DEFAULT_DUMP_FILE_SIZE_LIMIT; } String actualProcessors = processors; if (StringUtils.isBlank(processors)) { actualProcessors = ProcessorTypes.DEFAULT_PROCESSORS; } final String getMachinesDumpFileURL = getFormattedUrl( shutdownManagersControllerUrl, GET_MACHINES_DUMP_FILE_URL_FORMAT, actualProcessors, Long.toString(actualSizeLimit)); log(Level.FINE, "[getPUDumpFile] - sending GET request to REST [" + getMachinesDumpFileURL + "]"); return executor.get( getMachinesDumpFileURL, new TypeReference<Response<GetMachinesDumpFileResponse>>() { }); } private void log(final Level level, final String msg) { if (logger.isLoggable(level)) { logger.log(level, msg); } } /********* * Resolves the configured rest client socket timeout or the default * @return the the configured rest client socket timeout or the default */ public int getSocketTimeout() { int restClientSocketTimeout; final String restClientSocketTimeoutSysProp = System.getProperty(CloudifyConstants.SYSTEM_PROPERTY_REST_CLIENT_SOCKET_TIMEOUT_MILLIS); if (StringUtils.isNotBlank(restClientSocketTimeoutSysProp)) { try { restClientSocketTimeout = Integer.parseInt(restClientSocketTimeoutSysProp); } catch (final NumberFormatException nfe) { restClientSocketTimeout = CloudifyConstants.DEFAULT_HTTP_READ_TIMEOUT; logger.severe("Failed to parse integer system property: " + CloudifyConstants.SYSTEM_PROPERTY_REST_CLIENT_SOCKET_TIMEOUT_MILLIS + ". Value was: " + restClientSocketTimeoutSysProp + ". Using default value " + CloudifyConstants.DEFAULT_HTTP_READ_TIMEOUT + " instead"); } } else { // use the default socket timeout restClientSocketTimeout = CloudifyConstants.DEFAULT_HTTP_READ_TIMEOUT; } return restClientSocketTimeout; } }