/** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.airavata.gfac.impl.task; import org.apache.airavata.common.exception.ApplicationSettingsException; import org.apache.airavata.common.utils.AiravataUtils; import org.apache.airavata.gfac.core.*; import org.apache.airavata.gfac.core.cluster.JobSubmissionOutput; import org.apache.airavata.gfac.core.cluster.RemoteCluster; import org.apache.airavata.gfac.core.context.ProcessContext; import org.apache.airavata.gfac.core.context.TaskContext; import org.apache.airavata.gfac.core.task.JobSubmissionTask; import org.apache.airavata.gfac.core.task.TaskException; import org.apache.airavata.gfac.impl.Factory; import org.apache.airavata.model.appcatalog.appdeployment.ApplicationDeploymentDescription; import org.apache.airavata.model.appcatalog.appdeployment.SetEnvPaths; import org.apache.airavata.model.appcatalog.computeresource.ResourceJobManager; import org.apache.airavata.model.application.io.InputDataObjectType; import org.apache.airavata.model.commons.ErrorModel; import org.apache.airavata.model.job.JobModel; import org.apache.airavata.model.status.JobState; import org.apache.airavata.model.status.JobStatus; import org.apache.airavata.model.status.TaskState; import org.apache.airavata.model.status.TaskStatus; import org.apache.airavata.model.task.TaskTypes; import org.apache.airavata.registry.cpi.AppCatalogException; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.util.*; public class LocalJobSubmissionTask implements JobSubmissionTask{ private static final Logger log = LoggerFactory.getLogger(LocalJobSubmissionTask.class); private ProcessBuilder builder; @Override public void init(Map<String, String> propertyMap) throws TaskException { } @Override public TaskStatus execute(TaskContext taskContext) { TaskStatus taskStatus = new TaskStatus(TaskState.CREATED); try { ProcessContext processContext = taskContext.getParentProcessContext(); JobModel jobModel = processContext.getJobModel(); jobModel.setTaskId(taskContext.getTaskId()); RemoteCluster remoteCluster = processContext.getJobSubmissionRemoteCluster(); GroovyMap groovyMap = GFacUtils.createGroovyMap(processContext,taskContext); String jobId = AiravataUtils.getId("JOB_ID_"); jobModel.setJobName(groovyMap.get(Script.JOB_NAME).toString()); jobModel.setJobId(jobId); ResourceJobManager resourceJobManager = GFacUtils.getResourceJobManager(processContext); JobManagerConfiguration jConfig = null; if (resourceJobManager != null) { jConfig = Factory.getJobManagerConfiguration(resourceJobManager); } JobStatus jobStatus = new JobStatus(); File jobFile = GFacUtils.createJobFile(groovyMap, taskContext, jConfig); if (jobFile != null && jobFile.exists()) { jobModel.setJobDescription(FileUtils.readFileToString(jobFile)); GFacUtils.saveJobModel(processContext, jobModel); JobSubmissionOutput jobSubmissionOutput = remoteCluster.submitBatchJob(jobFile.getPath(), processContext.getWorkingDir()); jobStatus.setJobState(JobState.SUBMITTED); jobStatus.setReason("Successfully Submitted to " + taskContext.getParentProcessContext() .getComputeResourceDescription().getHostName()); jobStatus.setTimeOfStateChange(AiravataUtils.getCurrentTimestamp().getTime()); jobModel.setJobStatuses(Arrays.asList(jobStatus)); //log job submit status GFacUtils.saveJobStatus(taskContext.getParentProcessContext(), jobModel); //for local, job gets completed synchronously //so changing job status to complete jobModel.setExitCode(jobSubmissionOutput.getExitCode()); jobModel.setStdErr(jobSubmissionOutput.getStdErr()); jobModel.setStdOut(jobSubmissionOutput.getStdOut()); jobModel.setJobId(jobId); jobStatus.setJobState(JobState.COMPLETE); jobStatus.setReason("Successfully Completed " + taskContext.getParentProcessContext() .getComputeResourceDescription().getHostName()); jobStatus.setTimeOfStateChange(AiravataUtils.getCurrentTimestamp().getTime()); jobModel.setJobStatuses(Arrays.asList(jobStatus)); //log job complete status GFacUtils.saveJobStatus(taskContext.getParentProcessContext(), jobModel); taskStatus = new TaskStatus(TaskState.COMPLETED); taskStatus.setReason("Submitted job to compute resource"); } else { taskStatus.setState(TaskState.FAILED); if (jobFile == null) { taskStatus.setReason("JobFile is null"); } else { taskStatus.setReason("Job file doesn't exist"); } } } catch (GFacException | IOException | AppCatalogException | ApplicationSettingsException e) { String msg = "Error occurred while submitting a local job"; log.error(msg, e); taskStatus.setReason(msg); ErrorModel errorModel = new ErrorModel(); errorModel.setActualErrorMessage(e.getMessage()); errorModel.setUserFriendlyMessage(msg); taskContext.getTaskModel().setTaskErrors(Arrays.asList(errorModel)); taskStatus.setState(TaskState.FAILED); } return taskStatus; } @Override public TaskStatus recover(TaskContext taskContext) { return null; } private List<String> buildCommand(ProcessContext processContext) { List<String> cmdList = new ArrayList<>(); cmdList.add(processContext.getApplicationDeploymentDescription().getExecutablePath()); List<InputDataObjectType> processInputs = processContext.getProcessModel().getProcessInputs(); // sort the inputs first and then build the command List Comparator<InputDataObjectType> inputOrderComparator = new Comparator<InputDataObjectType>() { @Override public int compare(InputDataObjectType inputDataObjectType, InputDataObjectType t1) { return inputDataObjectType.getInputOrder() - t1.getInputOrder(); } }; Set<InputDataObjectType> sortedInputSet = new TreeSet<InputDataObjectType>(inputOrderComparator); for (InputDataObjectType input : processInputs) { sortedInputSet.add(input); } for (InputDataObjectType inputDataObjectType : sortedInputSet) { if (inputDataObjectType.getApplicationArgument() != null && !inputDataObjectType.getApplicationArgument().equals("")) { cmdList.add(inputDataObjectType.getApplicationArgument()); } if (inputDataObjectType.getValue() != null && !inputDataObjectType.getValue().equals("")) { cmdList.add(inputDataObjectType.getValue()); } } return cmdList; } private void initProcessBuilder(ApplicationDeploymentDescription app, List<String> cmdList){ builder = new ProcessBuilder(cmdList); List<SetEnvPaths> setEnvironment = app.getSetEnvironment(); if (setEnvironment != null) { for (SetEnvPaths envPath : setEnvironment) { Map<String,String> builderEnv = builder.environment(); builderEnv.put(envPath.getName(), envPath.getValue()); } } } @Override public TaskTypes getType() { return TaskTypes.JOB_SUBMISSION; } @Override public JobStatus cancel(TaskContext taskcontext) { // TODO - implement Local Job cancel return null; } }