decentralized-internet
Version:
An NPM library of programs to create decentralized web and distributed computing projects
1 lines • 7.32 kB
JavaScript
var request=require("request"),_=require("underscore"),Promise=require("bluebird"),Boom=require("boom"),spawn=require("child_process").spawn,fs=require("fs"),os=require("os"),path=require("path");module.exports=function(e,t){var n={},o=new(require("linkedlist"));const r=function(t,n){var o=e.methods.executionserver.getExecutionServer(n.executionserver);return o?(o.scope=["executionserver"],Promise.resolve(o)):Promise.reject(Boom.unauthorized(o))};if(!e.methods.jwtauth)throw"Please update hapi-jwt-couch to version >= 3.0.0";e.methods.jwtauth.addValidationFunction(r);e.method({name:"executionserver.startExecutionServers",method:function(){return Promise.map(_.keys(t.executionservers),function(n){return new Promise(function(o,r){var s=e.methods.jwtauth.sign({executionserver:n},t.algorithm),i=path.join(os.tmpdir(),"."+n);fs.writeFile(i,JSON.stringify(s),function(e){e?r(e):o(i)})}).then(function(e){return new Promise(function(o,r){var s=t.executionservers[n];if(s&&!s.remote){var i=path.join(s.sourcedir,".token");const t=spawn("scp",["-i",s.identityfile,e,s.user+"@"+s.hostname+":"+i]);t.stdout.on("data",function(e){});var u="";t.stderr.on("data",function(e){u+=e}),t.on("close",function(t){0!=t&&""!==u?r(Boom.badImplementation(u)):o(e)})}})}).then(function(e){try{fs.statSync(e)&&fs.unlinkSync(e)}catch(e){console.error(e)}}).catch(function(e){console.error(e)})})},options:{}});const s=function(e){if(e.tunnel){var t=_.flatten(_.map(e.tunnel,function(e,t){return[t,e]}));e.identityfile&&(t=t.concat("-i",e.identityfile));t=t.concat(["-q",e.user+"@"+e.hostname]);const r=spawn("ssh",t);var n="";r.stdout.on("data",function(e){n+=e});var o="";return r.stderr.on("data",function(e){o+=e}),r.on("close",function(e){console.log(n),console.error(o)}),r.unref(),r.pid?Promise.resolve(r):Promise.reject(Boom.badImplementation("Create tunnel failed"))}return Promise.resolve(null)};e.method({name:"executionserver.startTunnel",method:s,options:{}});e.method({name:"executionserver.startTunnels",method:function(){return e.app.tunnels||(e.app.tunnels={}),Promise.map(_.keys(t.executionservers),function(n){var o=t.executionservers[n];return s(o).then(function(t){t&&(e.app.tunnels[n]=t,console.log("Tunnel started:",n))})})},options:{}}),n.getExecutionServers=function(e,n){var o=[];return _.each(t.executionservers,function(e,t){var n={name:t,info:e.info};e.queues&&(n.queues=e.queues),o.push(n)}),o};e.method({name:"executionserver.getExecutionServer",method:function(e){return t.executionservers[e]},options:{}});e.method({name:"executionserver.submitJob",method:function(n){var o=t.executionservers[n.executionserver];return o?o.remote?Promise.resolve(!0):new Promise(function(t,r){try{var s=["-q","-i",o.identityfile,o.user+"@"+o.hostname,"node",o.sourcedir+"/index.js","-j",n._id,"--submit"];n.force&&s.push("-f");const c=spawn("ssh",s);var i="";c.stdout.on("data",function(e){i+=e});var u="";c.stderr.on("data",function(e){u+=e}),c.on("close",function(o){if(0!==o||""!==u)console.error(u),console.log(i),r(Boom.badImplementation(u));else{var s="_design/getJob/_view/status?key="+JSON.stringify(n._id);e.methods.clusterprovider.getView(s).then(function(e){t(_.pluck(e,"value")[0])}).catch(function(e){r(Boom.badImplementation(e))})}})}catch(e){r(e)}}):Promise.reject("No execution server configured",n.executionserver)},options:{}}),n.submitJob=function(t,n){return e.methods.clusterprovider.getDocument(t.params.id).then(function(n){return e.methods.clusterprovider.validateJobOwnership(n,t.auth.credentials)}).then(function(n){return n.jobstatus.status="QUEUE",e.methods.clusterprovider.uploadDocuments(n).then(function(o){return e.methods.cronprovider.addJobToSubmitQueue(n,t.payload.force)}).then(function(){return n.jobstatus})}).catch(function(e){return Boom.badImplementation(e)})};e.method({name:"executionserver.jobStatus",method:function(n){var o=t.executionservers[n.executionserver];return o?o.remote?Promise.resolve(!0):new Promise(function(t,r){try{const s=spawn("ssh",["-q","-i",o.identityfile,o.user+"@"+o.hostname,"node",o.sourcedir+"/index.js","-j",n._id,"--status"]);s.stdout.on("data",function(e){});s.stderr.on("data",function(e){e}),s.on("close",function(o){var s="_design/getJob/_view/status?key="+JSON.stringify(n._id);e.methods.clusterprovider.getView(s).then(function(e){t(_.pluck(e,"value")[0])}).catch(r)})}catch(e){r(e)}}):Promise.reject("No execution server configured",n.executionserver)},options:{}}),n.jobStatus=function(t,n){return e.methods.clusterprovider.getDocument(t.params.id).then(function(n){return e.methods.clusterprovider.validateJobOwnership(n,t.auth.credentials)}).then(function(t){return"RUN"===t.jobstatus.status||"UPLOADING"===t.jobstatus.status||"DONE"===t.jobstatus.status?e.methods.cronprovider.addJobToUpdateQueue(t).then(function(){return t.jobstatus}):t.jobstatus}).catch(function(e){return Boom.wrap(e)})};e.method({name:"executionserver.jobKill",method:function(n){var o=t.executionservers[n.executionserver];return o?o.remote?Promise.resolve(!0):new Promise(function(t,r){try{const s=spawn("ssh",["-q","-i",o.identityfile,o.user+"@"+o.hostname,"node",o.sourcedir+"/index.js","-j",n._id,"--kill"]);s.stdout.on("data",function(e){});s.stderr.on("data",function(e){e}),s.on("close",function(o){var s="_design/getJob/_view/status?key="+JSON.stringify(n._id);e.methods.clusterprovider.getView(s).then(function(e){t(_.pluck(e,"value")[0])}).catch(r)})}catch(e){r(e)}}):Promise.reject("No execution server configured",n.executionserver)},options:{}}),n.killJob=function(t,n){return e.methods.clusterprovider.getDocument(t.params.id).then(function(n){return e.methods.clusterprovider.validateJobOwnership(n,t.auth.credentials)}).then(function(t){return t.jobstatus.status="KILL",e.methods.clusterprovider.uploadDocuments(t).then(function(n){return e.methods.cronprovider.addJobToKillQueue(t)}).then(function(){return t.jobstatus})}).catch(function(e){return Boom.badImplementation(e)})};return e.method({name:"executionserver.jobDelete",method:function(n){var r=t.executionservers[n.executionserver];return r?r.remote?(o.push(n),Promise.resolve(!0)):new Promise(function(t,o){try{const i=spawn("ssh",["-q","-i",r.identityfile,r.user+"@"+r.hostname,"node",r.sourcedir+"/index.js","-j",n._id,"--delete"]);i.stdout.on("data",function(e){});var s="";i.stderr.on("data",function(e){s+=e}),i.on("close",function(r){if(""!==s)o(Boom.badImplementation(s));else{var i="_design/getJob/_view/status?key="+JSON.stringify(n._id);e.methods.clusterprovider.getView(i).then(function(e){t(_.pluck(e,"value")[0])}).catch(function(e){o(Boom.badImplementation(e))})}})}catch(e){console.error(e),o(e)}}):Promise.reject("No execution server configured",n.executionserver)},options:{}}),n.getDeleteQueue=function(e,t){for(var n=[];o.length;)n.push(o.shift());return n},n.getExecutionServerTokens=function(n,o){if(n.query&&n.query.executionserver){if(t.executionservers[n.query.executionserver]){var r=e.methods.jwtauth.sign({executionserver:n.query.executionserver},t.algorithm);return r.executionserver=n.query.executionserver,[r]}return Boom.notFound("The executionserver was not found in the server configuration")}var s=_.map(t.executionservers,function(n,o){var r=e.methods.jwtauth.sign({executionserver:o},t.algorithm);return r.executionserver=o,r});return _.compact(s)},n};