From 3361da177a0a5e759f6faeeaf9031428377d2d8e Mon Sep 17 00:00:00 2001 From: Jonathan Lee Date: Fri, 15 Oct 2010 11:38:14 -0400 Subject: [PATCH] Add all master/slave nodes when a node is added to console --- console/js/console.ui.js | 52 +++++++++++++++++++++++++--------------- lib/nodeloadlib.js | 10 ++++---- src/remote.js | 27 +++++++++++++++++---- 3 files changed, 62 insertions(+), 27 deletions(-) diff --git a/console/js/console.ui.js b/console/js/console.ui.js index 582f6eb..fa74199 100644 --- a/console/js/console.ui.js +++ b/console/js/console.ui.js @@ -86,12 +86,12 @@ function initShortcuts() { next.find('input').button().click(); optNodes.buttonset('refresh'); }); - doc.bind('keydown', 'p', function() { + doc.bind('keydown', 'h', function() { if (!selectedNode) return; var selected = selectedNode.tabs.tabs('option', 'selected'); selectedNode.tabs.tabs('select', selected-1); }); - doc.bind('keydown', 'n', function() { + doc.bind('keydown', 'l', function() { if (!selectedNode) return; var selected = selectedNode.tabs.tabs('option', 'selected'); selectedNode.tabs.tabs('select', selected+1); @@ -125,14 +125,22 @@ function hideAddNodeDialog() { function addNode(name) { var node = getNodeObject(name); - node.button = addNodeButton(node); - node.tabs = addNodeTabs(node); - node.graphs = {}; - node.selectNode = function() { - node.button.click(); - } - node.selectReportGraph = function(index) { - node.tabs.tabs('select', index); + if (!node.uiloaded) { + node.uiloaded = true; + node.button = addNodeButton(node); + node.tabs = addNodeTabs(node); + node.graphs = {}; + node.selectNode = function() { + node.button.click(); + optNodes.buttonset('refresh'); + } + node.selectReportGraph = function(index) { + node.tabs.tabs('select', index); + } + + $.getJSON('http://' + node.name + '/remote/hosts', function(hosts, status) { + if (hosts) hosts.forEach(function(name) { addNode(name) }); + }); } refreshReportsData(node); @@ -154,6 +162,14 @@ function removeNode(node) { node.tabs.remove(); deleteNodeObject(node); } +function selectNode(node) { + if (selectedNode === node) return; + if (selectedNode) selectedNode.tabs.hide(); + selectedNode = node; + selectedNode.tabs.show(); + refreshReportGraphs(node); + resizeReportGraphs(); +} function addNodeButton(node) { optNodes.append( '\ @@ -163,11 +179,7 @@ function addNodeButton(node) { $('#' + node.id ).button({ icons: { secondary: 'ui-icon-squaresmall-close' } }).click(function() { - if (selectedNode === node) return; - if (selectedNode) selectedNode.tabs.hide(); - selectedNode = node; - selectedNode.tabs.show(); - refreshReportGraphs(node); + selectNode(node); }); $('#cmd-' + node.id + ' span.ui-icon-squaresmall-close').click(function(){ removeNode(node); @@ -177,14 +189,11 @@ function addNodeButton(node) { } function addNodeTabs(node) { var tabs = $('
\ -
< p    n >
\ +
< h    l >
\
    \
    '); tabs.appendTo(pnlCharts).tabs(); tabs.tabs('add', '#tab-console-' + node.id, 'Console: ' + node.name); - tabs.bind('tabsselect', function(event, ui) { - refreshReportGraphs(node); - }); tabs.hide(); return tabs; } @@ -247,6 +256,11 @@ function refreshReportGraphs(node) { } pnlSummary.html(jsonToTable(summary)); + + if (!node.graphsloaded && node.tabs.tabs('length') > 1) { + node.graphsloaded = true; + node.tabs.tabs('select', 0); + } } // --------------- diff --git a/lib/nodeloadlib.js b/lib/nodeloadlib.js index 176a62f..e0909bc 100644 --- a/lib/nodeloadlib.js +++ b/lib/nodeloadlib.js @@ -51,11 +51,11 @@ REMOTE_TESTS[report.spec.name]=localtest;TEST_MONITOR.addTest(localtest);}} function receiveTestProgress(report){if(WORKER_POOL.slaves[report.slaveId]===undefined){return;} WORKER_POOL.slaves[report.slaveId].state="running";for(var testname in report.data){var localtest=REMOTE_TESTS[testname];var remotetest=report.data[testname];if(localtest){for(var s in remotetest.stats){var remotestat=remotetest.stats[s];var localstat=localtest.stats[s];if(localstat===undefined){var backend=statsClassFromString(remotestat.interval.type);localstat=new Reportable([backend,remotestat.interval.params],remotestat.name,remotestat.trend);localtest.stats[s]=localstat;} localstat.merge(remotestat.interval);}}else{qputs("WARN: received remote progress report from '"+report.slaveId+"' for unknown test: "+testname);}}} -function RemoteSlave(id,master){this.id=id;this.tests=[];if(master){master=master.split(':');this.masterhost=master[0];this.master=http.createClient(master[1],master[0]);}} +function RemoteSlave(id,master){this.id=id;this.tests=[];if(master){master=master.split(':');this.master={host:master[0],port:master[1],client:http.createClient(master[1],master[0])};}} RemoteSlave.prototype={addTest:function(test){this.tests.push(test);this.sendReport_('/remote/newTest',{slaveId:this.id,spec:test.spec});},clearTests:function(){this.tests=[];},reportProgress:function(){var reports={};for(var i in this.tests){var test=this.tests[i];var stats={};for(var s in test.stats){stats[s]={name:test.stats[s].name,trend:test.stats[s].trend,interval:test.stats[s].interval}} reports[test.spec.name]={stats:stats};} -this.sendReport_('/remote/progress',{slaveId:this.id,data:reports});},sendReport_:function(url,object){if(this.master){var s=JSON.stringify(object);var req=this.master.request('POST',url,{'host':this.masterhost,'content-length':s.length});req.write(s);req.end();}}} -function RemoteWorkerPool(master,slaves,fun){this.master=master;this.slaves={};this.fun=fun;this.callback=null;this.pingId=null;this.progressId=null;for(var i in slaves){var slave=slaves[i].split(":");this.slaves[slaves[i]]={id:slaves[i],state:"notstarted",host:slave[0],client:http.createClient(slave[1],slave[0])};}} +this.sendReport_('/remote/progress',{slaveId:this.id,data:reports});},sendReport_:function(url,object){if(this.master.client){var s=JSON.stringify(object);var req=this.master.client.request('POST',url,{'host':this.master.host,'content-length':s.length});req.write(s);req.end();}}} +function RemoteWorkerPool(master,slaves,fun){this.master=master;this.slaves={};this.fun=fun;this.callback=null;this.pingId=null;this.progressId=null;for(var i in slaves){var slave=slaves[i].split(":");this.slaves[slaves[i]]={id:slaves[i],state:"notstarted",host:slave[0],port:slave[1],client:http.createClient(slave[1],slave[0])};}} RemoteWorkerPool.prototype={start:function(callback,stayAliveAfterDone){var fun="(function() {"+this.fun+"})();";for(var i in this.slaves){var slave=this.slaves[i],slaveFun='';if(this.master){slaveFun="registerSlave('"+i+"','"+this.master+"');\n"+fun;}else{slaveFun="registerSlave('"+i+"');\n"+fun;} var r=slave.client.request('POST','/remote',{'host':slave.host,'content-length':slaveFun.length});r.write(slaveFun);r.end();slave.state="running";} var worker=this;this.pingId=setInterval(function(){worker.sendPings()},NODELOAD_CONFIG.SLAVE_PING_INTERVAL_MS);this.callback=callback;},checkFinished_:function(){for(var i in this.slaves){if(this.slaves[i].state!="done"&&this.slaves[i].state!="error"){return;}} @@ -65,7 +65,9 @@ for(var i in this.slaves){if(this.slaves[i].state=="ping"){qprint("\nWARN: slave this.checkFinished_();}} function serveRemote(url,req,res){var readBody=function(req,callback){var body='';req.on('data',function(chunk){body+=chunk});req.on('end',function(){callback(body)});} var sendStatus=function(status){res.writeHead(status,{"Content-Length":0});res.end();} -if(req.method=="POST"&&url=="/remote"){readBody(req,function(remoteFun){qputs("\nReceived remote command:\n"+remoteFun);eval(remoteFun);sendStatus(200);});}else if(req.method=="GET"&&req.url=="/remote/state"){if(SCHEDULER.running==true){sendStatus(200);}else{sendStatus(410);} +if(req.method=="POST"&&url=="/remote"){readBody(req,function(remoteFun){qputs("\nReceived remote command:\n"+remoteFun);eval(remoteFun);sendStatus(200);});}else if(req.method=="GET"&&req.url=="/remote/hosts"){var hosts=[];if(SLAVE_CONFIG){hosts.push(SLAVE_CONFIG.master.host+':'+SLAVE_CONFIG.master.port);} +if(WORKER_POOL){hosts.push(WORKER_POOL.master);for(var i in WORKER_POOL.slaves){hosts.push(i);}} +var body=JSON.stringify(hosts);res.writeHead(200,{"Content-Type":"application/json","Access-Control-Allow-Origin":"*","Content-Length":body.length});res.write(body);res.end();}else if(req.method=="GET"&&req.url=="/remote/state"){if(SCHEDULER.running==true){sendStatus(200);}else{sendStatus(410);} res.end();}else if(req.method=="POST"&&url=="/remote/newTest"){readBody(req,function(data){receiveTestCreate(JSON.parse(data));sendStatus(200);});}else if(req.method=="POST"&&url=="/remote/progress"){readBody(req,function(data){receiveTestProgress(JSON.parse(data));sendStatus(200);});}else{sendStatus(405);}} var Histogram=exports.Histogram=function(params){var numBuckets=3000;var percentiles=[0.95,0.99];if(params!=null&¶ms.numBuckets!=null) numBuckets=params.buckets;if(params!=null&¶ms.percentiles!=null) diff --git a/src/remote.js b/src/remote.js index ba060e6..8d20610 100644 --- a/src/remote.js +++ b/src/remote.js @@ -147,8 +147,11 @@ function RemoteSlave(id, master) { this.tests = []; if (master) { master = master.split(':'); - this.masterhost = master[0]; - this.master = http.createClient(master[1], master[0]); + this.master = { + host: master[0], + port: master[1], + client: http.createClient(master[1], master[0]) + }; } } RemoteSlave.prototype = { @@ -176,9 +179,9 @@ RemoteSlave.prototype = { this.sendReport_('/remote/progress', {slaveId: this.id, data: reports}); }, sendReport_: function(url, object) { - if (this.master) { + if (this.master.client) { var s = JSON.stringify(object); - var req = this.master.request('POST', url, {'host': this.masterhost, 'content-length': s.length}); + var req = this.master.client.request('POST', url, {'host': this.master.host, 'content-length': s.length}); req.write(s); req.end(); } @@ -204,6 +207,7 @@ function RemoteWorkerPool(master, slaves, fun) { id: slaves[i], state: "notstarted", host: slave[0], + port: slave[1], client: http.createClient(slave[1], slave[0]) }; } @@ -315,6 +319,21 @@ function serveRemote(url, req, res) { eval(remoteFun); sendStatus(200); }); + } else if (req.method == "GET" && req.url == "/remote/hosts") { + var hosts = []; + if (SLAVE_CONFIG) { + hosts.push(SLAVE_CONFIG.master.host + ':' + SLAVE_CONFIG.master.port); + } + if (WORKER_POOL) { + hosts.push(WORKER_POOL.master); + for (var i in WORKER_POOL.slaves) { + hosts.push(i); + } + } + var body = JSON.stringify(hosts); + res.writeHead(200, {"Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Content-Length": body.length}); + res.write(body); + res.end(); } else if (req.method == "GET" && req.url == "/remote/state") { if (SCHEDULER.running == true) { sendStatus(200);