/* * Copyright 2016 Baidu, Inc. * * 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.baidubce.services.batch; import com.baidubce.AbstractBceClient; import com.baidubce.BceClientConfiguration; import com.baidubce.BceClientException; import com.baidubce.auth.SignOptions; import com.baidubce.http.Headers; import com.baidubce.http.HttpMethodName; import com.baidubce.http.handler.BceErrorResponseHandler; import com.baidubce.http.handler.BceJsonResponseHandler; import com.baidubce.http.handler.BceMetadataResponseHandler; import com.baidubce.http.handler.HttpResponseHandler; import com.baidubce.internal.InternalRequest; import com.baidubce.internal.RestartableInputStream; import com.baidubce.model.AbstractBceRequest; import com.baidubce.model.AbstractBceResponse; import com.baidubce.services.batch.model.CancelJobRequest; import com.baidubce.services.batch.model.CreateJobRequest; import com.baidubce.services.batch.model.CreateJobResponse; import com.baidubce.services.batch.model.GetJobRequest; import com.baidubce.services.batch.model.GetJobResponse; import com.baidubce.services.batch.model.ListJobsRequest; import com.baidubce.services.batch.model.ListJobsResponse; import com.baidubce.util.HttpUtils; import com.baidubce.util.JsonUtils; import com.fasterxml.jackson.core.JsonGenerator; import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import static com.baidubce.util.Validate.checkIsTrue; import static com.baidubce.util.Validate.checkStringNotEmpty; import static com.google.common.base.Preconditions.checkNotNull; /** * Provides the client for accessing the Baidu Batch-Compute service. */ public class BatchClient extends AbstractBceClient { private static final String VERSION = "v1"; private static final String JOB = "job"; private static final String[] HEADERS_TO_SIGN = {"host", "x-bce-date"}; /** * Responsible for handling HttpResponse from all Batch-Compute service calls. */ private static final HttpResponseHandler[] BATCH_HANDLERS = new HttpResponseHandler[]{ new BceMetadataResponseHandler(), new BceErrorResponseHandler(), new BceJsonResponseHandler() }; /** * Constructs a new client to invoke service methods on Batch-Compute. */ public BatchClient() { this(new BceClientConfiguration()); } /** * Constructs a new client using the client configuration to access Batch-Compute. * * @param clientConfiguration The BCE client configuration options. */ public BatchClient(BceClientConfiguration clientConfiguration) { super(clientConfiguration, BATCH_HANDLERS); } /** * List Batch-Compute jobs owned by the authenticated user. * <p> * <p> * Users must authenticate with a valid BCE Access Key ID, and the response * contains all the Batch-Compute jobs owned by the user. * * @param request The request containing valid query parameters. * @return The response containing a list of the Batch-Compute jobs owned by the authenticated sender of the request. */ public ListJobsResponse listJobs(ListJobsRequest request) { checkNotNull(request, "request should not be null."); InternalRequest internalRequest = this.createRequest(request, HttpMethodName.GET, JOB); if (request.getMarker() != null) { internalRequest.addParameter("marker", request.getMarker()); } if (request.getMaxKeys() >= 0) { internalRequest.addParameter("maxKeys", String.valueOf(request.getMaxKeys())); } return this.invokeHttpClient(internalRequest, ListJobsResponse.class); } /** * List Batch-Compute jobs owned by the authenticated user. * * @return The response containing a list of the Batch-Compute jobs owned by the authenticated sender of the request. */ public ListJobsResponse listJobs() { return listJobs(new ListJobsRequest()); } /** * List Batch-Compute jobs owned by the authenticated user. * * @param maxKeys The maximum number of jobs returned. * @return The response containing a list of the Batch-Compute jobs owned by the authenticated sender of the request. * And the size of list is limited below maxKeys. */ public ListJobsResponse listJobs(int maxKeys) { return listJobs(new ListJobsRequest().withMaxKeys(maxKeys)); } /** * List Batch-Compute jobs owned by the authenticated user. * * @param marker The start record of jobs. * @param maxKeys The maximum number of jobs returned. * @return The response containing a list of the Batch-Compute jobs owned by the authenticated sender of the request. * The jobs' records start from the marker and the size of list is limited below maxKeys. */ public ListJobsResponse listJobs(String marker, int maxKeys) { return listJobs(new ListJobsRequest().withMaxKeys(maxKeys).withMarker(marker)); } /** * Describe the detail information of the target job. * * @param request The request object containing the ID of the target job. * @return response containing the detail information of the target job. */ public GetJobResponse getJob(GetJobRequest request) { checkNotNull(request, "request should not be null."); checkStringNotEmpty(request.getJobId(), "The parameter jobId should not be null or empty string."); InternalRequest internalRequest = this.createRequest( request, HttpMethodName.GET, JOB, request.getJobId()); return this.invokeHttpClient(internalRequest, GetJobResponse.class); } /** * Describe the detail information of the target job. * * @param jobId The ID of the target job. * @return The response containing the detail information of the target job. */ public GetJobResponse getJob(String jobId) { return getJob(new GetJobRequest().withJobId(jobId)); } /** * Create a Batch-Compute job with the specified options. * * @param request The request containing all options for creating a Batch-Compute job. * @return The response containing the ID of the newly created job. */ public CreateJobResponse createJob(CreateJobRequest request) { checkNotNull(request, "request should not be null."); checkStringNotEmpty(request.getName(), "The name should not be null or empty string."); checkStringNotEmpty(request.getVmType(), "The vmType should not be null or empty string."); checkStringNotEmpty(request.getJobDagJson(), "The jobDagJson should not be null or empty string."); checkIsTrue(request.getVmCount() > 0, "The vmCount should greater than 0"); StringWriter writer = new StringWriter(); try { JsonGenerator jsonGenerator = JsonUtils.jsonGeneratorOf(writer); jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("name", request.getName()); jsonGenerator.writeStringField("vmType", request.getVmType()); jsonGenerator.writeNumberField("vmCount", request.getVmCount()); jsonGenerator.writeStringField("jobDagJson", request.getJobDagJson()); if (request.getJobTimeoutInSeconds() != null) { jsonGenerator.writeNumberField("jobTimeoutInSeconds", request.getJobTimeoutInSeconds()); } if (request.getMemo() != null) { jsonGenerator.writeStringField("memo", request.getMemo()); } jsonGenerator.writeEndObject(); jsonGenerator.close(); } catch (IOException e) { throw new BceClientException("Fail to generate json", e); } byte[] json = null; try { json = writer.toString().getBytes(DEFAULT_ENCODING); } catch (UnsupportedEncodingException e) { throw new BceClientException("Fail to get UTF-8 bytes", e); } InternalRequest internalRequest = this.createRequest(request, HttpMethodName.POST, JOB); internalRequest.addHeader(Headers.CONTENT_LENGTH, String.valueOf(json.length)); internalRequest.addHeader(Headers.CONTENT_TYPE, "application/json"); internalRequest.setContent(RestartableInputStream.wrap(json)); internalRequest.addParameter("run", "immediate"); if (request.getClientToken() != null) { internalRequest.addParameter("clientToken", request.getClientToken()); } return this.invokeHttpClient(internalRequest, CreateJobResponse.class); } /** * Cancel a Batch-Compute job. * * @param request The request containing the ID of the job to be cancelled. */ public void cancelJob(CancelJobRequest request) { checkNotNull(request, "request should not be null."); checkStringNotEmpty(request.getJobId(), "The parameter jobId should not be null or empty string."); InternalRequest internalRequest = this.createRequest( request, HttpMethodName.PUT, JOB, request.getJobId()); internalRequest.addParameter("cancel", null); this.invokeHttpClient(internalRequest, AbstractBceResponse.class); } /** * Cancel a Batch-Compute job. * * @param jobId The ID of the job to be cancelled. */ public void cancelJob(String jobId) { cancelJob(new CancelJobRequest().withJobId(jobId)); } /** * Creates and initializes a new request object for the specified resource. * * @param bceRequest The original BCE request created by the user. * @param httpMethod The HTTP method to use when sending the request. * @param pathVariables The optional variables used in the URI path. * @return A new request object populated with endpoint, resource path and specific * parameters to send. */ private InternalRequest createRequest( AbstractBceRequest bceRequest, HttpMethodName httpMethod, String... pathVariables) { List<String> path = new ArrayList<String>(); path.add(VERSION); if (pathVariables != null) { for (String pathVariable : pathVariables) { path.add(pathVariable); } } URI uri = HttpUtils.appendUri(this.getEndpoint(), path.toArray(new String[path.size()])); InternalRequest request = new InternalRequest(httpMethod, uri); SignOptions signOptions = new SignOptions(); signOptions.setHeadersToSign(new HashSet<String>(Arrays.asList(HEADERS_TO_SIGN))); request.setSignOptions(signOptions); request.setCredentials(bceRequest.getRequestCredentials()); return request; } }