var Job = exports.Job= declare([JobBase], { constructor: function(sessionName,jobTemplate,jobId){ this.state="UNDETERMINED"; var _self=this; this._jobDefer = new defer(); if (jobTemplate && !jobId) { var opts = this.getSBatchOpts(jobTemplate,sessionName); when(slurm.sbatch.apply(this,opts), function(results){ _self.jobId = results.stdout.split(" job ")[1].trim(); if (!_self.jobId){ console.log("Error getting job id", results); } when(_self.getState(), function(){ _self._jobDefer.resolve(_self); console.log("Started Job " + _self.jobId); }); }); }else if(jobId){ this.jobId=jobId; when(this.getState(), function(){ _self._jobDefer.resolve(_self); }); } when(this._jobDefer, function(){ _self.emit("ready", _self.jobId); }); this.interval=2000; //this.startMonitor(); }, startMonitor: function(){ var _self=this; this._monitor = setTimeout(function(){ when(_self.getState(), function(state){ _self.state = state; if (state=="DONE" || state == "FAILED"){ _self.stopMonitor(); }else if (state=="QUEUED" || state=="REQUEUED"){ _self.interval=="5000"; }else if (state=="QUEUED_HELD" || state == "REQUEUED_HELD"){ _self.interval=10000; } if (!_self._disableMonitor) { _self.startMonitor(); } }); },this.interval); }, stopMonitor: function(){ this._disableMonitor=true; clearTimeout(this._monitor); }, getSBatchOpts: function(jobTemplate, sessionName){ var opts = [] var command = null; var cmdArgs = []; var hasEmail=false; Object.keys(jobTemplate).forEach(function(key){ console.log("Check Key: ", key, jobTemplate[key]); if (!jobTemplate[key]) { return; } switch(key) { case "workingDirectory": opts.push("--workdir=" + jobTemplate[key]); break; case "submitAsHold": opts.push("-H"); break; case "rerunnable": if (!jobTemplate[key]){ opts.push("--no-requeue"); } break; case "jobEnvironment": Object.keys(jobTemplate[key]).forEach(function(envvar){ opts.push("--export=" + envvar + "=" + jobTemplate[key][envar]); }); break; case "email": jobTemplate[key].forEach(function(addr){ opts.push("--mail-user="******"emailOnTerminated": case "emailOnStarted": if (!hasEmail){ opts.push("--mail-type=ALL"); hasEmail=true; } break; case "jobName": opts.push("-J"); opts.push(jobTemplate[key]); break; case "inputPath": opts.push("--input=" + jobTemplate[key]); break; case "outputPath": opts.push("--output=" + jobTemplate[key]); break; case "errorPath": opts.push("--error=" + jobTemplate[key]); break; case "reservationId": opts.push("--reservation=" + jobTemplate[key]); break; case "queueName": opts.push("--partition=" + jobTemplate[key]); break; case "remoteCommand": case "args": case "minSlots": case "maxSlots": break; case "priority": opts.push("--nice=" + jobTemplate[key]); break; case "candidateMachines": break; case "minPhysMemory": opts.push("--mem-per-cpu=" + jobTemplate[key]); break; case "startTime": opts.push("--begin=" + jobTemplate[key]); break; case "deadlineTime": opts.push("--time=" + jobTemplate[key]); break; case "accountingId": opts.push("--account=" + jobTemplate[key]); break; case "nativeParams": jobTemplate[key].split(" ").forEach(function(i){ opts.push(i); }); default: console.log("Ignoring Template Property: ", key); } }); console.log("opts: ", opts); return [opts.join(' '),jobTemplate.remoteCommand,jobTemplate.args]; }, suspend: function(){ console.log("Suspending DRMAA Job " + this.jobId); return when(slurm.scontrol.suspend(this.jobId), function(results){ console.log("Suspend Results: ", results.stdout, results.stderr); if (results.stderr) { throw new Error(results.stderr); } return true; }); }, resume: function(){ return when(slurm.scontrol.resume(this.jobId), function(results){ console.log("Resume Results: ", results.stdout, results.stderr); if (results.stderr) { throw new Error(results.stderr); } return true; }); }, hold: function(){ return when(slurm.scontrol.suspend(this.jobId), function(results){ console.log("hold Results: ", results.stdout, results.stderr); if (results.stderr) { throw new Error(results.stderr); } return true; }); }, release: function(){ return when(slurm.scontrol.release(this.jobId), function(results){ console.log("release Results: ", results.stdout, results.stderr); if (results.stderr) { throw new Error(results.stderr); } return true; }); }, terminate: function(){ return when(slurm.scontrol.suspend(this.jobId), function(results){ if (results.stderr) { throw new Error(results.stderr); } return true; }); }, getState: function(jobSubState){ var _self=this; if (this.state=="DONE") { return this.state; } return when(this.getInfo(), function(){ return _self.state; }); }, setState: function(state){ var _self=this; // if (this.state != state){ var orig = this.state; console.log("Set State for: ", state," Refresh JobInfo"); return when(_self.getInfo(), function(info){ _self.emit(_self.state, {job: info}); _self.emit("StateChanged",{oldState: orig, newState: _self.state, job: info}); }); // } return state; }, getInfo: function(){ console.log("this.jobId: ", this.jobId); var _self=this; if (this.state=="DONE") { return this.jobInfo; } return when(this.jobId || this._jobDefer, function(){ return when(slurm.scontrol.show("job " + _self.jobId), function(jobInfo){ _self.jobInfo = new JobInfo(jobInfo); _self.state = _self.jobInfo.jobState; console.log("Updated jobInfo: ", _self.jobInfo, _self.state); return _self.jobInfo; }); }); }, waitStarted: function(timeout){ }, waitTerminated: function(timeout){ } });
var MonitoringSession = exports.MonitoringSession = declare([MonitoringSessionBase], { constructor: function(sessionManager){ this.interval=1000; this.sessionManager = sessionManager; this._stateMap = {}; this.startMonitor(); console.log("Slurm MonitoringSession Startup"); }, startMonitor: function(){ var _self=this; this._monitor = setTimeout(function(){ when(_self._getSlurmJobs(), function(jobs){ if (!jobs){ console.log("No Slurm Jobs Found"); return; } //console.log("Found ", jobs.length, " Slurm Jobs"); //console.log("jobs[0]: ", jobs[0]); if (!_self._disableMonitor) { _self.startMonitor(); } }); },this.interval); }, _getSlurmJobs: function(){ //console.log("_getSlurmJobs()"); var _self=this; return when(slurm.squeue({"states":"all"}), function(sjobs){ var map={} sjobs.forEach(function(job){ var initialState=false; if (_self._stateMap[job.jobid]!=new JobInfo(job).jobState){ if (!_self._stateMap[job.jobid]){ console.log("Found New Job in Slurm: ", job.jobid, new JobInfo(job).jobState); var msg = {type: "JobDiscovered", job: new JobInfo(job).jobState}; _self.emit("JobDiscovered", msg); initialState=true; } var curState = _self._stateMap[job.jobid]; _self._stateMap[job.jobid]=new JobInfo(job).jobState; if (!initialState){ var msg = {type:"MonitoredJobStateChange", jobId: job.jobid, oldState: curState, newState: _self._stateMap[job.jobid]} console.log("EMIT Message: ", msg); _self.emit("MonitoredJobStateChange", msg); } } }); return sjobs.map(function(j) { return new JobInfo(j); }); }); }, getAllJobs: function(){ }, stopMonitor: function(){ this._disableMonitor=true; clearTimeout(this._monitor); }, });
var Job = exports.Job= declare([EventEmitter], { jobId: "", sessionName: "", jobTemplate: "", constructor: function(sessionName,jobTemplate,jobId){ this.jobId=jobId; this.sessionName = sessionName; this.jobTemplate = jobTemplate; }, suspend: function(){ throw new UnsupportedOperationException("suspend() must be implemented in subclass"); }, resume: function(){ throw new UnsupportedOperationException("resume() must be implemented in subclass"); }, hold: function(){ throw new UnsupportedOperationException("hold() must be implemented in subclass"); }, release: function(){ throw new UnsupportedOperationException("release() must be implemented in subclass"); }, terminate: function(){ throw new UnsupportedOperationException("terminate() must be implemented in subclass"); }, getState: function(jobSubState){ throw new UnsupportedOperationException("getState() must be implemented in subclass"); }, getInfo: function(){ throw new UnsupportedOperationException("getInfo() must be implemented in subclass"); }, waitStarted: function(timeout){ throw new UnsupportedOperationException("waitStarted() must be implemented in subclass"); }, waitTerminated: function(timeout){ throw new UnsupportedOperationException("waitTerminated() must be implemented in subclass"); } });
var jobIdIndex=1; var JobSession = exports.JobSession= declare([JobSessionBase], { runJob: function(jobTemplate){ if (!(jobTemplate instanceof JobTemplate)){ throw new exceptions.InvalidArgumentExcpetion("Job Template must be an instance of JobTemplate"); } var job = new Job(this.sessionName,jobTemplate); this.jobs.push(job); return job; }, reattachJob: function(jobId){ var _self=this; return when(this.getJobs(), function(jobs){ var job; jobs.some(function(sjob){ if (sjob.jobId==jobId){ job=sjob; } }) if (!job){ job = new Job(this.sessionName,null,jobId); _self.jobs.push(job); } return job; }); } });
var declare = require("dojo-declare/declare"); var drmaa = require("./drmaa"); var ReservationInfo = exports.ReservationInfo= declare([], { reservationId: "", reservationName: "", reservedStartTime: null, reservedEndTime: null, usersACL:[], reservedSlots: null, reservedMachines: [], constructor: function(params){ params = params || {} for (var prop in params){ this[prop]=params[prop]; } } });
var declare = require("dojo-declare/declare"); var drmaa = require("./drmaa"); var SlotInfo = exports.SlotInfo = declare([], { machineName: "", slots: null, constructor: function(params){ params = params || {} for (var prop in params){ this[prop]=params[prop]; } } });