UNPKG

decentralized-internet

Version:

An NPM library of programs to create decentralized web and distributed computing projects

279 lines (216 loc) 5.45 kB
module.exports = function (conf) { var fs = require('fs'); var Promise = require('bluebird'); var _ = require("underscore"); var spawn = require('child_process').spawn; var path = require('path'); var Joi = require('@hapi/joi'); var executionmethods = require('./executionserver.methods')(conf); var clustermodel = require('clusterpost-model'); var parseString = require('xml2js').parseString; var handler = {}; const getXmlJs = function(xml){ return new Promise(function(resolve, reject){ parseString(xml, function(err, result){ if(err){ reject(err) }else{ resolve(result); } }) }) } handler.submitJob = function(doc, cwd){ Joi.assert(doc, clustermodel.job); return new Promise(function(resolve, reject){ var command = "qsub"; var parameters = doc.parameters; var scriptfilename = "script.pbs"; var params = []; if(doc.jobparameters){ params = _.clone(doc.jobparameters); } params.push({ flag: "-V" }); params.push({ flag: "-d", name: cwd }); params.push({ flag: "-e", name: "stderr.err" }); params.push({ flag: "-o", name: "stdout.out" }); params.push({ flag: "-M", name: doc.userEmail }); var jobname; if(doc.name){ jobname = doc.name; }else{ jobname = doc.userEmail; } params.push({ flag: "-N", name: jobname }); var preamble = _.map(params, function(param){ return _.compact([param.flag, param.name]).join(" "); }).join("\n#PBS "); var script = "#!/bin/bash\n#### PBS preamble\n"; script += "#PBS " + preamble + "\n"; script += "#### End PBS preamble\n"; script += '\nif [ -n "$PBS_O_WORKDIR" ]; then cd $PBS_O_WORKDIR; fi\n\n' var executableparams = ""; if(parameters){ executableparams = " " + _.map(parameters, function(param){ return _.compact([param.flag, param.name]).join(" "); }).join(" "); } script += doc.executable + executableparams; try{ var scriptpath = path.join(cwd, scriptfilename); fs.writeFileSync(scriptpath, script); const runcommand = spawn(command, [scriptpath]); var allerror = ""; runcommand.stderr.on('data', function(data){ allerror += data; }); var alldata = ""; runcommand.stdout.on('data', function(data){ alldata += data; }); //"sample: Job <898104> is submitted to default queue <day>" runcommand.on('close', function(code){ if(code){ resolve({ status: 'FAIL', error: allerror + alldata }); }else{ try{ var jobid = alldata.split('.')[0]; resolve({ jobid : Number.parseInt(jobid), status: 'RUN' }); }catch(e){ reject({ status: 'FAIL', error: allerror, stat: alldata }); } } }); }catch(e){ reject({ status: "FAIL", error: e }); } }); } handler.getJobStatus = function(doc){ Joi.assert(doc.jobstatus, clustermodel.jobstatus); Joi.assert(doc.jobstatus.jobid, Joi.number().required(), "Please execute the job first."); return new Promise(function(resolve, reject){ try{ var jobid = doc.jobstatus.jobid; var params = ["-x", jobid]; const ps = spawn('qstat', params); var allerror = ""; ps.stderr.on('data', function(data){ allerror += data; }); var alldata = ""; ps.stdout.on('data', function(data){ alldata += data; }); ps.on('close', function(code){ if(alldata.indexOf("Unknown Job Id Error") !== -1){ return { status: 'DONE', stat: alldata } }else{ getXmlJs(alldata) .then(function(jsonstat){ if(jsonstat && jsonstat.Data && jsonstat.Data.Job && _.isArray(jsonstat.Data.Job) && jsonstat.Data.Job.length === 1){ var job = jsonstat.Data.Job[0]; var isdone = false; if(_.isArray(job.job_state)){ isdone = _.findIndex(job.job_state, function(state){ return state === "C" || state === "E"; }) !== -1; }else{ isdone = job.job_state === "C" || job.job_state === "E"; } if(isdone){ return { status: 'DONE', stat: jsonstat }; }else{ return { jobid: jobid, status: 'RUN', stat: jsonstat }; } }else{ return { status: 'FAIL', stat: jsonstat }; } }) .catch(function(e){ return { status: 'FAIL', error: e, stat: alldata } }) .then(resolve) .catch(reject); } }); }catch(e){ reject(e); } }); } handler.killJob = function(doc){ Joi.assert(doc.jobstatus, clustermodel.jobstatus); return new Promise(function(resolve, reject){ try{ var jobid = doc.jobstatus.jobid; var params = [jobid]; const kill = spawn('qdel', params); var allerror = ""; kill.stderr.on('data', function(data){ allerror += data; }); var alldata = ""; kill.stdout.on('data', function(data){ alldata += data; }); kill.on('close', function(code){ resolve({ status: 'EXIT', stat: allerror + alldata }); }); }catch(e){ reject(e); } }); } return handler; }