/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package org.ow2.proactive.scheduler.core; import java.security.KeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.util.ArrayList; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.ow2.proactive.authentication.crypto.CredData; import org.ow2.proactive.authentication.crypto.Credentials; import org.ow2.proactive.authentication.crypto.HybridEncryptionUtil; import org.ow2.proactive.authentication.crypto.HybridEncryptionUtil.HybridEncryptedData; import org.ow2.proactive.scheduler.common.TaskTerminateNotification; import org.ow2.proactive.scheduler.common.job.JobType; import org.ow2.proactive.scheduler.common.task.TaskId; import org.ow2.proactive.scheduler.common.task.TaskResult; import org.ow2.proactive.scheduler.descriptor.TaskDescriptor; import org.ow2.proactive.scheduler.job.InternalJob; import org.ow2.proactive.scheduler.task.TaskLauncher; import org.ow2.proactive.scheduler.task.internal.InternalTask; import org.ow2.proactive.scheduler.task.internal.InternalTaskParentFinder; import org.ow2.proactive.threading.CallableWithTimeoutAction; /** * TimedDoTaskAction is used to start the task execution in parallel. * * @author The ProActive Team * @since ProActive Scheduling 2.0 */ public class TimedDoTaskAction implements CallableWithTimeoutAction<Void> { private static final Logger logger = Logger.getLogger(TimedDoTaskAction.class); private final InternalJob job; private final TaskDescriptor taskDescriptor; private final InternalTask task; private final TaskLauncher launcher; private final SchedulingService schedulingService; private final TaskTerminateNotification terminateNotification; private final PrivateKey corePrivateKey; private boolean taskWasRestarted; private final InternalTaskParentFinder internalTaskParentFinder; /** * Create a new instance of TimedDoTaskAction * * @param launcher the launcher of the task */ public TimedDoTaskAction(InternalJob job, TaskDescriptor taskDescriptor, TaskLauncher launcher, SchedulingService schedulingService, TaskTerminateNotification terminateNotification, PrivateKey corePrivateKey) { this.job = job; this.taskDescriptor = taskDescriptor; this.task = taskDescriptor.getInternal(); this.launcher = launcher; this.schedulingService = schedulingService; this.terminateNotification = terminateNotification; this.corePrivateKey = corePrivateKey; this.internalTaskParentFinder = InternalTaskParentFinder.getInstance(); } /** * {@inheritDoc} */ public Void call() throws Exception { try { // Set to empty array to emulate varargs behavior (i.e. not defined is // equivalent to empty array, not null. TaskResult[] params = new TaskResult[0]; //if job is TASKSFLOW, preparing the list of parameters for this task. int resultSize = taskDescriptor.getParents().size(); if ((job.getType() == JobType.TASKSFLOW) && (resultSize > 0) && task.handleResultsArguments()) { Set<TaskId> parentIds = new HashSet<>(resultSize); for (int i = 0; i < resultSize; i++) { parentIds.addAll(internalTaskParentFinder.getFirstNotSkippedParentTaskIds(taskDescriptor.getParents() .get(i) .getInternal())); } params = new TaskResult[parentIds.size()]; Map<TaskId, TaskResult> taskResults = schedulingService.getInfrastructure() .getDBManager() .loadTasksResults(job.getId(), new ArrayList<>(parentIds)); int i = 0; for (TaskId taskId : parentIds) { params[i] = taskResults.get(taskId); i++; } } // activate loggers for this task if needed schedulingService.getListenJobLogsSupport().activeLogsIfNeeded(job.getId(), launcher); fillContainer(); // try launch the task launcher.doTask(task.getExecutableContainer(), params, terminateNotification); } catch (Throwable e) { logger.warn("Failed to start task: " + e.getMessage(), e); restartTask(); } return null; } protected void fillContainer() throws KeyException, NoSuchAlgorithmException { boolean isRunAsMeEnabled = task.isRunAsMe(); task.getExecutableContainer().setRunAsUser(isRunAsMeEnabled); createAndSetCredentials(); } private void createAndSetCredentials() throws KeyException, NoSuchAlgorithmException { CredData decryptedUserCredentials = job.getCredentials().decrypt(corePrivateKey); enrichWithThirdPartyCredentials(decryptedUserCredentials); PublicKey nodePublicKey = launcher.generatePublicKey(); Credentials nodeEncryptedUserCredentials = Credentials.createCredentials(decryptedUserCredentials, nodePublicKey); task.getExecutableContainer().setCredentials(nodeEncryptedUserCredentials); } protected boolean areThirdPartyCredentialsDefined() { return schedulingService.getInfrastructure() .getDBManager() .hasThirdPartyCredentials(job.getJobInfo().getJobOwner()); } private void enrichWithThirdPartyCredentials(CredData decryptedUserCredentials) throws KeyException { Map<String, HybridEncryptedData> thirdPartyCredentials = schedulingService.getInfrastructure() .getDBManager() .thirdPartyCredentialsMap(job.getJobInfo() .getJobOwner()); for (Map.Entry<String, HybridEncryptedData> thirdPartyCredential : thirdPartyCredentials.entrySet()) { String decryptedValue = HybridEncryptionUtil.decryptString(thirdPartyCredential.getValue(), corePrivateKey); decryptedUserCredentials.addThirdPartyCredential(thirdPartyCredential.getKey(), decryptedValue); } } /** * {@inheritDoc} */ public void timeoutAction() { try { logger.warn("Task start timeout for task '" + task.getId() + "'"); restartTask(); } catch (Throwable e) { logger.warn("Exception during submit timeout handling: " + e.getMessage(), e); } } private synchronized void restartTask() { if (taskWasRestarted) { return; } logger.info("Trying to restart task '" + task.getId() + "'"); schedulingService.restartTaskOnNodeFailure(task); taskWasRestarted = true; } }