From 10edf58bf917667cdd01b9101533c8dc01efb2ac Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Wed, 2 Oct 2013 18:18:34 +0200 Subject: [PATCH] Various updates. --- package.json | 2 +- src/api.js | 35 +++++++++++++------ src/xapi.js | 94 ++++++++++++++++++++++++++++++++++------------------ src/xo.js | 40 +++++++++------------- 4 files changed, 102 insertions(+), 69 deletions(-) diff --git a/package.json b/package.json index 6787b13..03466bf 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "q": ">=0.9.6", "sync": ">=0.2.2", "then-redis": ">=0.3.8", - "underscore": ">=1.4.4", + "underscore": ">=1.5.2", "validator": ">=1.2.1", "ws": ">=0.4.27", "xmlrpc": ">=1.1.0" diff --git a/src/api.js b/src/api.js index 9b3dfbe..ae0939f 100644 --- a/src/api.js +++ b/src/api.js @@ -535,14 +535,21 @@ Api.fn.xo = { // (and possibly heavy) computing. var xo = this.xo; + var xobjs = xo.xobjs; return Q.all([ - xo.hosts.get(), - xo.vms.get({ + xobjs.host.get(), + xobjs.host_metrics.get().then(function (metrics) { + return _.indexBy(metrics, 'id'); + }), + xobjs.VM.get({ 'is_a_template': false, 'is_control_domain': false, }), - xo.srs.count(), - ]).spread(function (hosts, vms, n_srs) { + xobjs.VM_metrics.get().then(function (metrics) { + return _.indexBy(metrics, 'id'); + }), + xobjs.SR.count(), + ]).spread(function (hosts, host_metrics, vms, vms_metrics, n_srs) { var running_vms = _.where(vms, { 'power_state': 'Running', }); @@ -551,16 +558,18 @@ Api.fn.xo = { var total_memory = 0; _.each(hosts, function (host) { n_cpus += host.host_CPUs.length; - total_memory += +host.metrics.memory_total; + total_memory += +host_metrics[host.metrics].memory_total; }); var n_vifs = 0; var n_vcpus = 0; var used_memory = 0; _.each(vms, function (vm) { + var metrics = vms_metrics[vm.metrics]; + n_vifs += vm.VIFs.length; - n_vcpus += +vm.metrics.VCPUs_number; - used_memory += +vm.metrics.memory_actual; + n_vcpus += +metrics.VCPUs_number; + used_memory += +metrics.memory_actual; }); return { @@ -584,7 +593,7 @@ Api.fn.xo = { throw Api.err.INVALID_PARAMS; } - return this.xo.pools.first(p_pool_id).then(function (pool) { + return this.xobjs.pool.first(p_pool_id).then(function (pool) { return pool.get('sessionId'); }); }, @@ -599,7 +608,10 @@ Api.fn.xapi = { throw Api.err.INVALID_METHOD; } - return this.xo[match[1] +'s'].get(); + var xobjs = this.xo.xobjs; + var collection = xobjs[match[1]] || xobjs[match[1].toUpperCase()]; + + return collection.get(); }, 'vm': { @@ -611,9 +623,10 @@ Api.fn.xapi = { } var xo = this.xo; + var xobjs = xo.xobjs; var vm; return this.checkPermission(session, 'write').then(function () { - return xo.vms.first(p_id); + return xobjs.VM.first(p_id); }).then(function (tmp) { vm = tmp; @@ -622,7 +635,7 @@ Api.fn.xapi = { throw Api.err.NO_SUCH_OBJECT; } - return xo.pools.first(vm.get('pool_uuid')); + return xobjs.pool.first(vm.get('pool_uuid')); }).then(function (pool) { var xapi = xo.connections[pool.get('uuid')]; diff --git a/src/xapi.js b/src/xapi.js index 43ec909..58cb346 100644 --- a/src/xapi.js +++ b/src/xapi.js @@ -5,51 +5,79 @@ Q.longStackSupport = true; ////////////////////////////////////////////////////////////////////// -function Xapi(host) +function Xapi(host, username, password) { // Parent constructor. Xapi.super_.call(this); + this.username = username; + this.password = password; + + this.changeHost(host); +} +require('util').inherits(Xapi, require('events').EventEmitter); + +Xapi.prototype.call = function (method) { + var args = arguments; + var params = Array.prototype.slice.call(arguments, 1); + + var self = this; + return Q(self.sessionId).then(function (session_id) { + if (session_id) + { + params.unshift(session_id); + } + + return Q.ninvoke(self.xmlrpc, 'methodCall', method, params); + }).then(function (value) { + if ('Success' !== value.Status) + { + if ('Failure' === value.Status) + { + throw value.ErrorDescription; + } + + throw value; + } + + return value.Value; + }).fail(function (error) { + if ('HOST_IS_SLAVE' !== error[0]) + { + throw error; + } + + self.changeHost(error[1]); + return self.call.apply(self, args); + }); +}; + +Xapi.prototype.changeHost = function (host) { + if (this.host === host) + { + return; + } + + this.host = host; this.xmlrpc = xmlrpc.createSecureClient({ hostname: host, port: '443', rejectUnauthorized: false, }); // @todo Handle connection success/error. -} -require('util').inherits(Xapi, require('events').EventEmitter); -Xapi.prototype.call = function (method) { - var params = Array.prototype.slice.call(arguments, 1); - - if (this.sessionId) - { - params.unshift(this.sessionId); - } - - return Q.ninvoke(this.xmlrpc, 'methodCall', method, params) - .then(function (value) { - if ('Success' !== value.Status) - { - if ('Failure' === value.Status) - { - throw value.ErrorDescription; - } - - throw value; - } - - return value.Value; - }); -}; - -Xapi.prototype.connect = function (username, password) { var self = this; + self.sessionId = undefined; + self.sessionId = self.call( + 'session.login_with_password', + self.username, + self.password + ).then(function (session_id) { + self.sessionId = session_id; - return this.call('session.login_with_password', username, password) - .then(function (session_id) { - console.log(self.xmlrpc.options, session_id); - self.sessionId = session_id; - }); + return session_id; + }); + + return self.sessionId; }; ////////////////////////////////////////////////////////////////////// diff --git a/src/xo.js b/src/xo.js index cb781d0..7c3ed9d 100644 --- a/src/xo.js +++ b/src/xo.js @@ -230,35 +230,27 @@ Xo.prototype.start = function (cfg) { // When a server is added we should connect to it and fetch data. var connect = function (server) { var pool_id = server.id; - var xapi = new Xapi(server.host); + var xapi = new Xapi(server.host, server.username, server.password); - xapi.connect(server.username, server.password).then(function () { - var xclasses = xo.xclasses; - var xobjs = xo.xobjs; + var xclasses = xo.xclasses; + var xobjs = xo.xobjs; - return _.map(xclasses, function (xclass) { - var collection = xo.xobjs[xclass]; - var helper = function () { - return xapi.call(xclass +'.get_all_records').then(function (records) { - _.each(records, function (record) { - record.pool = pool_id; - }); + return Q.all(_.map(xclasses, function (xclass) { + var collection = xobjs[xclass]; - return collection.add(records, { - 'update': true, - }); - }).fail(function (error) { - if ('HOST_IS_SLAVE' === error[0]) - { - server.host = error[1]; - } + return xapi.call(xclass +'.get_all_records').then(function (records) { + records = _.map(records, function (record, ref) { + record.id = ref; + record.pool = pool_id; + return record; + }); - throw error; - }); - } + return collection.add(records, { + 'replace': true, + }); }); - }).fail(function (error) { - console.log(error); + })).fail(function (error) { + console.error(error); }); }; // Connect existing servers.