/* * 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 functionaltests.job; import static functionaltests.utils.SchedulerTHelper.log; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.File; import java.net.URL; import org.junit.BeforeClass; import org.junit.Test; import org.ow2.proactive.scheduler.common.exception.TaskAbortedException; import org.ow2.proactive.scheduler.common.exception.TaskPreemptedException; import org.ow2.proactive.scheduler.common.exception.TaskRestartedException; import org.ow2.proactive.scheduler.common.job.JobId; import org.ow2.proactive.scheduler.common.job.JobInfo; import org.ow2.proactive.scheduler.common.job.JobState; import org.ow2.proactive.scheduler.common.job.JobStatus; import org.ow2.proactive.scheduler.common.task.TaskInfo; import org.ow2.proactive.scheduler.common.task.TaskResult; import org.ow2.proactive.scheduler.common.task.TaskState; import org.ow2.proactive.scheduler.common.task.TaskStatus; import functionaltests.utils.SchedulerFunctionalTestWithCustomConfigAndRestart; import functionaltests.utils.SchedulerTHelper; /** * This class tests the preempt task, restart task, and kill task features. * * Submit a taskflow job with 4 tasks. * One has 4 max number of executions * one is failJobOnError * Preempt task must : (test 1) * - stop execution * - restart later without side effect * Restart task must : * - stop execution (ends like a normal termination with TaskRestartedException) * - restart later if possible, fails the job if 'failJobOnError' * Kill task must : * - stop execution * - not restart this task, fails the job if 'failJobOnError' * * * @author The ProActive Team * @since ProActive Scheduling 3.0 */ public class TestPreemptRestartKillTask extends SchedulerFunctionalTestWithCustomConfigAndRestart { private static URL jobDescriptor = TestPreemptRestartKillTask.class.getResource("/functionaltests/descriptors/Job_preempt_restart_kill.xml"); private static URL configFile = TestPreemptRestartKillTask.class.getResource("/functionaltests/config/schedulerPropertiesNoRetry.ini"); @BeforeClass public static void startSchedulerInAnyCase() throws Exception { schedulerHelper.log("Starting a clean scheduler."); schedulerHelper = new SchedulerTHelper(true, configFile.getPath()); } @Test public void testPreemptRestartKillTask() throws Throwable { String jobDescriptorPath = new File(jobDescriptor.toURI()).getAbsolutePath(); TestPreemtRestartKillTask(jobDescriptorPath); } private void TestPreemtRestartKillTask(String jobDescriptorPath) throws Exception { log("Submitting job"); log(schedulerHelper.getSchedulerInterface().getClass().toString()); schedulerHelper.addExtraNodes(3); JobId id = schedulerHelper.submitJob(jobDescriptorPath); log("Wait for event job submitted"); schedulerHelper.waitForEventJobSubmitted(id); log("Wait for event t1 running"); schedulerHelper.waitForEventTaskRunning(id, "t1"); log("Wait for event t2 running"); schedulerHelper.waitForEventTaskRunning(id, "t2"); log("Wait for event t3 running"); schedulerHelper.waitForEventTaskRunning(id, "t3"); log("Wait for event t4 running"); schedulerHelper.waitForEventTaskRunning(id, "t4"); log("Preempt t1"); schedulerHelper.getSchedulerInterface().preemptTask(id, "t1", 1); log("Wait for event t1 waiting for restart"); //running jobs list must have only one job, task t1 must have number of execution to 0 TaskInfo ti1 = schedulerHelper.waitForEventTaskWaitingForRestart(id, "t1"); //task result for t1 must be available with TaskPreemptedException TaskResult tr1 = schedulerHelper.getSchedulerInterface().getTaskResult(id, "t1"); log("Restart t2"); schedulerHelper.getSchedulerInterface().restartTask(id, "t2", 1); log("Wait for event t2 waiting for restart"); //running jobs list must have only one job, task t2 must have number of execution to 1 TaskInfo ti2 = schedulerHelper.waitForEventTaskWaitingForRestart(id, "t2"); //task result for t2 must be available with TaskRestartedException TaskResult tr2 = schedulerHelper.getSchedulerInterface().getTaskResult(id, "t2"); log("Wait for event t2 running"); schedulerHelper.waitForEventTaskRunning(id, "t2"); log("Restart t2 again"); schedulerHelper.getSchedulerInterface().restartTask(id, "t2", 1); log("Wait for event t2 waiting for restart again"); //running jobs list must have only one job, task t2 must have number of execution to 2 TaskInfo ti3 = schedulerHelper.waitForEventTaskWaitingForRestart(id, "t2"); //task result for t2 must be available with TaskRestartedException TaskResult tr3 = schedulerHelper.getSchedulerInterface().getTaskResult(id, "t2"); //ensure every tasks are running at this point schedulerHelper.waitForEventTaskRunning(id, "t1"); schedulerHelper.waitForEventTaskRunning(id, "t2"); log("Kill t3"); schedulerHelper.getSchedulerInterface().killTask(id, "t3"); log("Wait for event t3 finished"); schedulerHelper.waitForEventTaskFinished(id, "t3"); //task result for t3 must be available with TaskRestartedException TaskResult tr4 = schedulerHelper.getSchedulerInterface().getTaskResult(id, "t3"); log("Kill t4"); schedulerHelper.getSchedulerInterface().killTask(id, "t4"); log("Wait for event job finished"); //finished jobs list must have only one job JobInfo ji4 = schedulerHelper.waitForEventJobFinished(id); //task result for t4 must be TaskRestartedException JobState j4 = schedulerHelper.getSchedulerInterface().getJobState(id); TaskResult tr5 = schedulerHelper.getSchedulerInterface().getTaskResult(id, "t4"); //check result j1 assertEquals(2, ti1.getNumberOfExecutionLeft()); assertTrue(tr1.getException() instanceof TaskPreemptedException); //check result j2 assertEquals(3, ti2.getNumberOfExecutionLeft()); assertTrue(tr2.getException() instanceof TaskRestartedException); //check result j3 assertEquals(2, ti3.getNumberOfExecutionLeft()); assertTrue(tr3.getException() instanceof TaskRestartedException); //check result tr4 assertTrue(tr4.getException() instanceof TaskAbortedException); //check result j4 assertEquals(JobStatus.CANCELED, ji4.getStatus()); TaskStatus t1Status = getTask(j4, "t1").getStatus(); assertTrue(t1Status.equals(TaskStatus.ABORTED) || t1Status.equals(TaskStatus.NOT_RESTARTED)); TaskStatus t2Status = getTask(j4, "t2").getStatus(); assertTrue(t2Status.equals(TaskStatus.ABORTED) || t2Status.equals(TaskStatus.NOT_RESTARTED)); assertEquals(TaskStatus.FAULTY, getTask(j4, "t3").getStatus()); assertEquals(TaskStatus.FAULTY, getTask(j4, "t4").getStatus()); //check result tr5 assertTrue(tr5.getException() instanceof Exception);// } private TaskState getTask(JobState job, String taskName) { for (TaskState ts : job.getTasks()) { if (ts.getId().getReadableName().equals(taskName)) { return ts; } } assertFalse("taskName '" + taskName + "' was not found in job", true); return null; } }