From 426dbf4fffe43c0a231371380582127b8febf9f6 Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Tue, 1 Oct 2013 17:52:52 +0200 Subject: [PATCH] Various updates. --- src/xapi.js | 7 +- src/xo.js | 435 ++++++++-------------------------------------------- 2 files changed, 68 insertions(+), 374 deletions(-) diff --git a/src/xapi.js b/src/xapi.js index 06c7dc8..43ec909 100644 --- a/src/xapi.js +++ b/src/xapi.js @@ -26,11 +26,15 @@ Xapi.prototype.call = function (method) { params.unshift(this.sessionId); } - var self = this; return Q.ninvoke(this.xmlrpc, 'methodCall', method, params) .then(function (value) { if ('Success' !== value.Status) { + if ('Failure' === value.Status) + { + throw value.ErrorDescription; + } + throw value; } @@ -43,6 +47,7 @@ Xapi.prototype.connect = function (username, password) { return this.call('session.login_with_password', username, password) .then(function (session_id) { + console.log(self.xmlrpc.options, session_id); self.sessionId = session_id; }); }; diff --git a/src/xo.js b/src/xo.js index f99e2d5..cb781d0 100644 --- a/src/xo.js +++ b/src/xo.js @@ -157,352 +157,6 @@ var Users = RedisCollection.extend({ //-------------------------------------------------------------------- -var Pool = Model.extend({}); - -var Pools = MemoryCollection.extend({ - 'model': Pool, -}); - -//-------------------------------------------------------------------- - -var Host = Model.extend({}); - -var Hosts = MemoryCollection.extend({ - 'model': Host, -}); - -//-------------------------------------------------------------------- - -var VM = Model.extend({}); - -var VMs = MemoryCollection.extend({ - 'model': VM, -}); - -//-------------------------------------------------------------------- - -var Network = Model.extend({}); - -var Networks = MemoryCollection.extend({ - 'model': Network, -}); - -//-------------------------------------------------------------------- - -var SR = Model.extend({}); - -var SRs = MemoryCollection.extend({ - 'model': SR, -}); - -//-------------------------------------------------------------------- - -var VDI = Model.extend({}); - -var VDIs = MemoryCollection.extend({ - 'model': VDI, -}); - -//-------------------------------------------------------------------- - -var PIF = Model.extend({}); - -var PIFs = MemoryCollection.extend({ - 'model': PIF, -}); - -//-------------------------------------------------------------------- - -var VIF = Model.extend({}); - -var VIFs = MemoryCollection.extend({ - 'model': VIF, -}); - -////////////////////////////////////////////////////////////////////// -// Collections -////////////////////////////////////////////////////////////////////// - -var VDIs = MemoryCollection.extend({ - 'model': VDI, -}); - -////////////////////////////////////////////////////////////////////// - -// @todo Really ugly. -function refresh(xo, xapi) -{ - var get_records = function (classes) { - var promises = []; - for (var i = 0, n = classes.length; i < n; i++) - { - !function (klass) { - promises.push( - xapi.call(klass +'.get_all_records') - .fail(function (error) { - console.error(klass, error); - return {}; - }) - ); - }(classes[i]); - } - return Q.all(promises); - }; - - return get_records([ - // Main classes. - 'pool', - 'host', - 'VM', - - 'network', - 'SR', - 'VDI', - - 'PIF', - 'VIF', - - // Associated classes (e.g. metrics). - 'console', - 'crashdump', - 'DR_task', - 'host_cpu', - 'host_crashdump', - 'host_metrics', - 'host_patch', - 'message', - 'PBD', - 'PCI', - 'PGPU', - 'PIF_metrics', - 'VBD', - 'VGPU', - 'VIF_metrics', - 'VM_appliance', - 'VM_metrics', - 'VM_guest_metrics', - //'VMPP', - //'VTPM', - ]).spread(function ( - pools, - hosts, - vms, - - networks, - srs, - vdis, - - pifs, - vifs, - - consoles, - crashdumps, - dr_tasks, - host_cpus, - host_crashdumps, - host_metrics, - host_patches, - messages, - pbds, - pcis, - pgpus, - pif_metrics, - vbds, - vgpus, - vif_metrics, - vm_appliances, - vm_metrics, - vm_guest_metrics - //vmpps - //vtpms - ) { - // Special case for pools. - pools = _.values(pools); - var pool_uuid = pools[0].id = pools[0].uuid; - - xo.connections[pool_uuid] = xapi; - - // @todo Remove: security concerns. - pools[0].sessionId = xapi.sessionId; - - var resolve = function (model, collection, props, include) { - /* jshint laxbreak: true */ - - if (!_.isArray(props)) - { - props = [props]; - } - - var helper; - if (include) - { - helper = function (ref) { - return collection[ref] || null; - }; - } - else - { - helper = function (ref) { - var model = collection[ref]; - return model && model.uuid || null; - }; - } - - var map = function (list, iterator) { - var result = _.isArray(list) ? [] : {}; - _.each(list, function (value, key) { - result[key] = iterator(value); - }); - return result; - }; - - for (var i = 0, n = props.length; i < n; ++i) - { - var prop = props[i]; - var ref = model[prop]; - - model[prop] = _.isArray(ref) - ? map(ref, helper) - : helper(ref); - } - }; - - // @todo Messages are linked differently. - messages = _.groupBy(messages, 'obj_uuid'); - - // @todo Cast numerical/boolean properties to correct types. - - // Resolves dependencies. - // - // 1. Associated objects are included. - // 2. Linked objects are relinked using their uuid instead of - // their reference. - _.each(pools, function (pool) { - // @todo Blobs? - - resolve(pool, srs, [ - 'crash_dump_SR', - 'default_SR', - 'suspend_image_SR', - ]); - resolve(pool, hosts, 'master'); - resolve(pool, vdis, [ - 'metadata_VDIs', - 'redo_log_vdi', - ]); - }); - _.each(hosts, function (host) { - // @todo Blobs? - - resolve(host, srs, [ - 'crash_dump_sr', - 'local_cache_sr', - 'suspend_image_SR', - ]); - resolve(host, host_crashdumps, 'host_crashdumps', true); - resolve(host, host_cpus, 'host_CPUs', true); - resolve(host, host_metrics, 'metrics', true); - resolve(host, host_patches, 'patches', true); - resolve(host, pbds, 'PBDs', true); - resolve(host, pcis, 'PCIs', true); - resolve(host, pgpus, 'PGPUs', true); - resolve(host, pifs, 'PIFs'); - resolve(host, vms, 'resident_VMs'); - }); - _.each(vms, function (vm) { - // @todo Blobs? - - resolve(vm, hosts, [ - 'affinity', - 'resident_on', - ]); - resolve(vm, vm_appliances, 'appliance', true); - resolve(vm, pcis, 'attached_PCIs', true); - resolve(vm, vms, [ - 'children', // Snapshots? - 'parent', - 'snapshot_of', - ]); - resolve(vm, consoles, 'consoles', true); - resolve(vm, crashdumps, 'crash_dumps', true); - resolve(vm, vm_guest_metrics, 'guest_metrics', true); - vm.messages = messages[vm.uuid] || []; // @todo - resolve(vm, vm_metrics, 'metrics', true); - //resolve(vm, vmpps, 'protection_policy', true); - resolve(vm, srs, 'suspend_SR'); - resolve(vm, vdis, 'suspend_VDI'); - resolve(vm, vbds, 'VBDs'); - resolve(vm, vgpus, 'VGPUs'); - resolve(vm, vifs, 'VIFs', true); // @todo - //resolve(vm, vtpms, 'VTPMs'); - }); - _.each(networks, function (network) { - // @todo Blobs? - - resolve(network, pifs, 'PIFs'); - resolve(network, vifs, 'VIFs'); - }); - _.each(srs, function (sr) { - // @todo Blobs? - - resolve(sr, dr_tasks, 'introduced_by'); // @todo. - resolve(sr, pbds, 'PBDs'); - resolve(sr, vdis, 'VDIs'); - }); - _.each(vdis, function (vdi) { - resolve(vdi, crashdumps, 'crash_dumps', true); - resolve(vdi, pools, 'metadata_of_pool'); - resolve(vdi, vdis, [ - 'parent', - 'snapshot_of', - 'snapshots', - ]); - resolve(vdi, srs, 'SR'); - resolve(vdi, vbds, 'VBDs'); - }); - _.each(pifs, function (pif) { - // @todo Bonds, tunnels & VLANs. - - resolve(pif, hosts, 'host'); - resolve(pif, pif_metrics, 'metrics'); - resolve(pif, networks, 'network'); - }); - _.each(vifs, function (vif) { - resolve(vif, vif_metrics, 'metrics'); - resolve(vif, networks, 'network'); - resolve(vif, vms, 'VM'); - }); - - // Normalizes the collections. - // - // 1. The collection is converted to an array. - // 2. For each object, an identifier based on its uuid is - // created. - var normalize = function (items) { - return _.map(items, function (item, ref) { - item.id = item.uuid; - item.pool_uuid = pool_uuid; - item.ref = ref; - return item; - }); - }; - - var opts = { - 'replace': true, - }; - - return Q.all([ - xo.pools.add(pools, opts), // Special case. - xo.hosts.add(normalize(hosts), opts), - xo.vms.add(normalize(vms), opts), - - xo.networks.add(normalize(networks), opts), - xo.srs.add(normalize(srs), opts), - xo.vdis.add(normalize(vdis), opts), - ]); - }); -} - function Xo() { if ( !(this instanceof Xo) ) @@ -510,27 +164,8 @@ function Xo() return new Xo(); } - var xo = this; - - - // Connections to Xen pools/servers. - xo.connections = {}; - - //-------------------------------------- - // Xen objects. - - xo.pools = new Pools(); - xo.hosts = new Hosts(); - xo.vms = new VMs(); - - xo.networks = new Networks(); - xo.srs = new SRs(); - xo.vdis = new VDIs(); - - // Connecting classes. (@todo VBD & SR). - xo.vifs = new VIFs(); - xo.pifs = new PIFs(); + this.connections = {}; } require('util').inherits(Xo, require('events').EventEmitter); @@ -557,20 +192,74 @@ Xo.prototype.start = function (cfg) { 'indexes': ['email'], }); + xo.xclasses = [ + 'console', + 'crashdump', + 'DR_task', + 'host', + 'host_cpu', + 'host_crashdump', + 'host_metrics', + 'host_patch', + 'message', + 'network', + 'PBD', + 'PCI', + 'PGPU', + 'PIF', + 'PIF_metrics', + 'pool', + 'SR', + 'VBD', + 'VDI', + 'VGPU', + 'VIF', + 'VIF_metrics', + 'VM', + 'VM_appliance', + 'VM_guest_metrics', + 'VM_metrics', + // 'VMPP', + // 'VTPM', + ]; + xo.xobjs = {}; + _.each(xo.xclasses, function (xclass) { + xo.xobjs[xclass] = new MemoryCollection(); + }); + // 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); xapi.connect(server.username, server.password).then(function () { - // @todo Use events. - !function helper() { - refresh(xo, xapi).then(function () { - setTimeout(helper, 5000); - }).done(); - }(); + 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 collection.add(records, { + 'update': true, + }); + }).fail(function (error) { + if ('HOST_IS_SLAVE' === error[0]) + { + server.host = error[1]; + } + + throw error; + }); + } + }); }).fail(function (error) { console.log(error); - }).done(); + }); }; // Connect existing servers. xo.servers.get().then(function (servers) {