From ec565c2803fe97f8f9f09a518052c427613c7cb4 Mon Sep 17 00:00:00 2001 From: william mantly Date: Wed, 20 Jul 2016 15:36:07 -0400 Subject: [PATCH] done --- doapi.js | 42 +++++++++---- lxc.js | 2 +- routes/api.js | 149 +++++++++++++++++++++++++++++--------------- routes/workers.json | 2 +- testAPI.py | 5 +- 5 files changed, 135 insertions(+), 65 deletions(-) diff --git a/doapi.js b/doapi.js index cda8088..a91177d 100644 --- a/doapi.js +++ b/doapi.js @@ -34,6 +34,7 @@ api = function(key){ }; this.dropletSetTag = function(tag, dropletID, callback) { + callback = callback || function(){}; var data = { resources: [ { @@ -55,6 +56,8 @@ api = function(key){ }; this.dropletCreate = function(args, callback){ + callback = callback || function(){}; + var data = { name: args.name, // || return false, region: args.region || 'nyc3', @@ -79,27 +82,30 @@ api = function(key){ this.dropletToActive = function(args){ var doapi = this; + args.onCreated = args.onCreate || function(){}; + this.dropletCreate(args, function(data){ data = JSON.parse(data); - setTimeout(function(id, args, doapi){ + args.onCreate(data, args); + setTimeout(function check(id, args, doapi){ time = args.time || 10000; - - doapi.dropletInfo(id, function check(data){ + doapi.dropletInfo(id, function (data){ var droplet = JSON.parse(data)['droplet']; if(droplet.status == 'active'){ - return args.onActive(worker); + return args.onActive(droplet, args); }else{ - setTimeout(function(check){ - checkDroplet(id); - }, time, check, .droplet.id); + setTimeout(function(check, id){ + check(id, args, doapi); + }, time, check, droplet.id); } - }, 70000, data.droplet.id, args, doapi); - }); + }); + }, 70000, data.droplet.id, args, doapi); }); - } + }; this.dropletDestroy = function(dropletID, callback){ + callback = callback || function(){}; var options = { url: this.BASEURL+'droplets/'+dropletID, headers: this.headers @@ -123,6 +129,20 @@ api = function(key){ }); }; + this.tagCreate = function(tag, callback){ + callback = callback || function(){}; + var options = { + url: this.BASEURL+'tags', + headers: this.headers, + body: JSON.stringify({name: tag}) + }; + this.calls++; + + return request.post(options, function(error, response, body){ + return callback(body, response, error); + }); + }; + this.tagsList = function(callback){ var options = { url: this.BASEURL+'tags', @@ -136,7 +156,7 @@ api = function(key){ }; this.domianAddRecord = function(args, callback){ - + callback = callback || function(){}; var options = { url: this.BASEURL+'domains/'+ args.domain +'/records', headers: this.headers, diff --git a/lxc.js b/lxc.js index 9bf3796..dbd9ec0 100644 --- a/lxc.js +++ b/lxc.js @@ -4,7 +4,7 @@ var exec = require('child_process').exec; function sysExec(command, ip, callback){ ip = ip || '104.236.77.157'; command = new Buffer(command).toString('base64') - command = 'ssh -o StrictHostKeyChecking=no virt@'+ ip + ' "echo ' + command + '|base64 --decode|bash"'; + command = 'ssh -i ~/.ssh/clw_rsa -o StrictHostKeyChecking=no virt@'+ ip + ' "echo ' + command + '|base64 --decode|bash"'; // command = 'unset XDG_SESSION_ID XDG_RUNTIME_DIR; cgm movepid all virt $$; ' + command; return exec(command, (function(callback){ diff --git a/routes/api.js b/routes/api.js index f8769c3..a2b8dc2 100644 --- a/routes/api.js +++ b/routes/api.js @@ -11,29 +11,35 @@ var label2runner = {}; var workers = (function(){ var workers = []; - var worker.settings = require('./workers.json'); + workers.settings = require('./workers.json'); workers.currentCreating = 0; workers.create = function(){ - if(workers.currentCreating > workers.settins.max ) return false; + if(workers.currentCreating > workers.settings.max ) return false; workers.currentCreating++; - return doapi.dropletToActive({ - name: 'clw'+workerSnapID+'-'+(Math.random()*100).toString().slice(-4), - image: '18473675', - size: '2gb', - onActive = function(worker){ - doapi.domianAddRecord({ - domain: "codeland.us", - type: "A", - name: "*."+args.worker.name+".workers", - data: args.worker.publicIP - }, function(){}); - + return doapi.dropletToActive({ + name: 'clw'+workers.settings.version+'-'+(Math.random()*100).toString().slice(-4), + image: workers.settings.image, + size: workers.settings.size, + onCreate: function(data){ + doapi.dropletSetTag('clw'+workers.settings.version, data.droplet.id); + }, + onActive: function(worker, args){ workers.startRunners({ worker: workers.makeWorkerObj(worker), - onDone: function(worker){ - workers.push(args.worker) + onStart: function(runner, args){ + workers.push(args.worker); + doapi.domianAddRecord({ + domain: "codeland.us", + type: "A", + name: "*."+worker.name+".workers", + data: worker.publicIP + }); + args.onStart = function(){}; + }, + onDone: function(args){ + console.log("done with workers"); } }), workers.currentCreating--; @@ -48,10 +54,9 @@ var workers = (function(){ }); worker.availrunners = []; - worker.ip = worker.privateIP; + worker.ip = worker.publicIP; worker.usedrunner = 0; worker.index = workers.length; - worker.snapShotId = worker.settings.snapShotId; worker.getRunner = function(){ if(this.availrunners.length === 0) return false; @@ -64,6 +69,10 @@ var workers = (function(){ return runner; } + worker.freeAll = function(){ + this.availrunners.forEach(runnerFree); + } + return worker; }; @@ -82,18 +91,15 @@ var workers = (function(){ }; workers.destroyOld = function(tag){ - if(droplets.length === 0) return true; - var droplet = droplets.pop(); - tag = tag || 'clworker'; + tag = tag || 'clw'+workers.settings.version; var currentIDs = workers.__workersId(); - var deleteDroplets = function(droplets){ - console.log('checking', droplet.name, droplet.id); + if(droplets.length === 0) return true; + var droplet = droplets.pop(); if(~currentIDs.indexOf(droplet.id)) return deleteDroplets(droplets); doapi.dropletDestroy(droplet.id, function(body){ - console.log('delete body', body); - setTimeout(deleteDroplets(droplets)); + setTimeout(deleteDroplets, 1000, droplets); }); } @@ -101,7 +107,7 @@ var workers = (function(){ data = JSON.parse(data); console.log('current worker ids', currentIDs); console.log('do droplets', data['droplets'].length, data['droplets'].map(function(item){ - return item.name+'| '+item.id; + return item.name+' | '+item.id; })); deleteDroplets(data['droplets']); @@ -109,35 +115,38 @@ var workers = (function(){ }; workers.startRunners = function(args){ - // console.log('starting runners on', worker.name, worker.ip) - args.stopPercent = stopPercent || 80; + // console.log('starting runners on', args.worker.name, args.worker.ip) + args.stopPercent = args.stopPercent || 80; args.onStart = args.onStart || function(){}; args.onDone = args.onDone || function(){}; ramPercentUsed(args.worker.ip, function(usedMemPercent){ - if(usedMemPercent > stopPercent ){ + if(usedMemPercent > args.stopPercent ){ console.log('using', String(usedMemPercent), 'percent memory, stopping runner creation!', args.worker.availrunners.length, 'created on ', args.worker.name ); - args.onDone(worker) + args.onDone(args) return ; } var name = 'crunner-'+(Math.random()*100).toString().slice(-4); + // console.log('Free ram check passed!') lxc.startEphemeral(name, 'crunner0', args.worker.ip, function(data){ - if(!data.ip) return setTimeout(workers.startRunners,0, args); + if(!data.ip) return setTimeout(workers.startRunners, 0, args); // console.log('started runner on', args.worker.name) - args.onStart(args.worker.availrunners[args.worker.availrunners.length-1]) - args.worker.availrunners.push({ + var runner = { ip: data.ip, name: name, - worker: worker, + worker: args.worker, label: args.worker.name + ':' + name - }); + }; + args.onStart(runner, args) - setTimeout(workers.startRunners(args), 0); + args.worker.availrunners.push(runner); + + setTimeout(workers.startRunners, 0, args); }); }); }; @@ -151,7 +160,7 @@ var workers = (function(){ return ; } - if(minAvail > 0) return ; + if(workers.settings.minAvail > 0) return ; var lastMinAval for(let worker of workers.slice(-wokers.settings.minAvail)){ @@ -176,6 +185,11 @@ var workers = (function(){ } }; + workers.concat = function(newWorkers){ + newWorkers.forEach(workers.push) + } + + doapi.tagCreate('clw'+workers.settings.version) return workers; })(); @@ -196,9 +210,7 @@ var runnerTimeout = function(runner, time){ clearTimeout(runner.timeout); } - return runner.timeout = setTimeout(function(){ - runnerFree(runner); - }, time); + return runner.timeout = setTimeout(runnerFree, time, runner); }; var runnerFree = function(runner){ @@ -209,7 +221,7 @@ var runnerFree = function(runner){ } delete label2runner[runner.label]; - workers.startRunners(runner.worker); + workers.startRunners({worker: runner.worker}); }; var getAvailrunner = function(runner){ @@ -234,10 +246,9 @@ var run = function(req, res, runner, count){ return res.json({error: 'No runners, try again soon.'}); } - if(count > 3){ + if(count > 2){ console.log('to many reties on runner'); - res.status(400); - return res.json({error: 'Runner restarted to many times'}); + return res.status(400).json({error: 'Runner restarted to many times'}); } var httpOptions = { @@ -250,19 +261,22 @@ var run = function(req, res, runner, count){ }) }; - return request.post(httpOptions, function(error, response, body){ // console.log('runner response:', arguments) if(error || response.statusCode !== 200) return run(req, res, getAvailrunner(), ++count); body = JSON.parse(body); - res.json(body); - - if(req.params.once) return runnerFree(runner); + + if(req.query.once){ + res.json(body); + return runnerFree(runner, 0); + } label2runner[runner.label] = runner; body['ip'] = runner.label; body['rname'] = runner.name; body['wname'] = runner.worker.name; + res.json(body); + runnerTimeout(runner); }); }; @@ -270,7 +284,7 @@ var run = function(req, res, runner, count){ setTimeout(function(){ // console.log('Starting balance checking in 30 seconds') setInterval(workers.checkBalance, 15000); -}, 180000); +}, 600000); workers.destroyOld(); workers.checkBalance(); @@ -292,7 +306,42 @@ router.get('/destroyOld', function(req, res, next) { }); router.post('/updateID', function(req, res, next){ + var newWorkers = []; + var newWorkersTarget = workers.length; + var newWokerImage = req.query.image; + for(var i = 0; iWorkers
"+obj+"

label2runner

"+util.inspect(label2runner)+'

DO calls

'+doapi.calls); }); -runner.get('/ping/:runner', function(req, res, next){ +router.get('/ping/:runner', function(req, res, next){ runnerTimeout(runner); res.json({res:''}); }); diff --git a/routes/workers.json b/routes/workers.json index 15eec4b..fea18f4 100644 --- a/routes/workers.json +++ b/routes/workers.json @@ -1 +1 @@ -{"snapShotId":"18473675","version":5,"lastSnapShotId":"0","size":"2gb","max":100,"min":1,"minAvail":1} \ No newline at end of file +{"image":"18473675","version":5,"lastSnapShotId":"0","size":"2gb","max":100,"min":1,"minAvail":1} \ No newline at end of file diff --git a/testAPI.py b/testAPI.py index e507afd..ac507f9 100644 --- a/testAPI.py +++ b/testAPI.py @@ -7,8 +7,9 @@ def testAPI(times=100, sleep=2): for i in range(times): try: res = r.post( - 'http://codeland.bytedev.co:2000/api/run', - data={'code': 'pwd'} + 'http://127.0.0.1:2000/api/run', + data={'code': 'pwd'}, + params={'once': True} ) if res.status_code != 200: errors += 1 print(i, res.status_code, res.content)