/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package se.kth.karamel.backend.running.model.tasks; import java.io.IOException; import java.util.List; import java.util.UUID; import org.apache.log4j.Logger; import se.kth.karamel.backend.ClusterService; import se.kth.karamel.backend.dag.DagTask; import se.kth.karamel.backend.dag.DagTaskCallback; import se.kth.karamel.backend.machines.MachineInterface; import se.kth.karamel.backend.machines.TaskSubmitter; import se.kth.karamel.backend.running.model.Failure; import se.kth.karamel.backend.running.model.MachineRuntime; import se.kth.karamel.common.exception.KaramelException; import se.kth.karamel.common.stats.ClusterStats; import se.kth.karamel.common.stats.TaskStat; /** * * @author kamal */ public abstract class Task implements DagTask, TaskCallback { private static final Logger logger = Logger.getLogger(Task.class); public static enum Status { WAITING, READY, EXIST, ONGOING, DONE, FAILED, SKIPPED; } private Status status = Status.WAITING; private final String name; private final String id; private final String machineId; private final String sshUser; protected List<ShellCommand> commands; private final MachineRuntime machine; private final String uuid; private final boolean idempotent; private DagTaskCallback dagCallback; private final TaskSubmitter submitter; private final ClusterStats clusterStats; private long startTime; private long duration = 0; private boolean markSkip = false; public Task(String name, String id, boolean idempotent, MachineRuntime machine, ClusterStats clusterStats, TaskSubmitter submitter) { this.name = name; this.id = id; this.idempotent = idempotent; this.machineId = machine.getId(); this.sshUser = machine.getSshUser(); this.machine = machine; this.uuid = UUID.randomUUID().toString(); this.clusterStats = clusterStats; this.submitter = submitter; } public void setDuration(long duration) { this.duration = duration; } public long getDuration() { return duration; } public Status getStatus() { return status; } public String getMachineId() { return machineId; } public String getSshUser() { return sshUser; } public String getName() { return name; } public String getId() { return id; } public boolean isIdempotent() { return idempotent; } public void markSkip() { this.markSkip = true; } public boolean isMarkSkip() { return markSkip; } public abstract List<ShellCommand> getCommands() throws IOException; public void setCommands(List<ShellCommand> commands) { this.commands = commands; } @Override public String asJson() { return String.format("\"name\": \"%s\", \"machine\": \"%s\"", name, machineId); } @Override public String toString() { return name + " on " + machineId; } public abstract String uniqueId(); public MachineRuntime getMachine() { return machine; } public String getUuid() { return uuid; } @Override public String dagNodeId() { return uniqueId(); } @Override public void prepareToStart() { try { submitter.prepareToStart(this); } catch (KaramelException ex) { machine.getGroup().getCluster().issueFailure(new Failure(Failure.Type.TASK_FAILED, uuid, ex.getMessage())); logger.error("", ex); dagCallback.failed(ex.getMessage()); } } @Override public void terminate() { try { submitter.terminate(this); } catch (KaramelException ex) { logger.error("", ex); dagCallback.failed(ex.getMessage()); } } @Override public void submit(DagTaskCallback callback) { this.dagCallback = callback; try { submitter.submitTask(this); } catch (KaramelException ex) { machine.getGroup().getCluster().issueFailure(new Failure(Failure.Type.TASK_FAILED, uuid, ex.getMessage())); logger.error("", ex); dagCallback.failed(ex.getMessage()); } } @Override public void queued() { status = Status.READY; dagCallback.queued(); } @Override public void exists() { status = Status.EXIST; dagCallback.exists(); } @Override public void started() { status = Status.ONGOING; startTime = System.currentTimeMillis(); dagCallback.started(); } @Override public void succeed() { status = Status.DONE; addStats(); dagCallback.succeed(); } @Override public void failed(String reason) { this.status = Status.FAILED; machine.setTasksStatus(MachineRuntime.TasksStatus.FAILED, uuid, reason); addStats(); dagCallback.failed(reason); } @Override public void retried() { status = Status.READY; addStats(); } @Override public void skipped() { status = Status.SKIPPED; addStats(); dagCallback.skipped(); } public void collectResults(MachineInterface sshMachine) throws KaramelException { //override it in the subclasses if needed } public boolean isSudoTerminalReqd() { //override it in the subclasses if needed return false; } public void downloadExperimentResults(MachineInterface sshMachine) throws KaramelException { //override it in the subclasses if needed } public String getSudoCommand() { String password = ClusterService.getInstance().getCommonContext().getSudoAccountPassword(); return (password == null || password.isEmpty()) ? "sudo" : "echo \"%password_hidden%\" | sudo -S "; } private void addStats() { duration = System.currentTimeMillis() - startTime; TaskStat taskStat = new TaskStat(getId(), machine.getMachineType(), status.name(), duration); clusterStats.addTask(taskStat); } public void kill() throws KaramelException { submitter.killMe(this); } public void retry() throws KaramelException { submitter.retryMe(this); } public void skip() throws KaramelException { submitter.skipMe(this); } }