Skip to content

Commit

Permalink
ZAPI-662: Add changefeed support
Browse files Browse the repository at this point in the history
ZAPI-684: Replace common.objectDiff with deep-diff
ZAPI-687: Allow VM creation via PUT /vms
  • Loading branch information
richardkiene committed Nov 27, 2015
1 parent 6289dd6 commit 58f775d
Show file tree
Hide file tree
Showing 17 changed files with 924 additions and 114 deletions.
30 changes: 30 additions & 0 deletions lib/apis/moray.js
Expand Up @@ -197,6 +197,7 @@ Moray.prototype.getVm = function (params, cb) {
filter = '(&' + filter + ')';
}


var vm;
var req = this.connection.findObjects(VMS_BUCKET_NAME, filter);

Expand Down Expand Up @@ -456,7 +457,36 @@ Moray.prototype._createSearch = function (params, cb) {
});
};

/**
* List all VMs for a given server from the VM bucket.
* @param {string} uuid uuid of the server whos vms should be fetched.
* @param {Function} cb function of the form function(err, vms) {...}
*/
Moray.prototype.listVmsForServer = function listVmsForServer(uuid, cb) {
var self = this;
var vms = {};
var vm;
var filter = sprintf(PARAM_FILTER, 'server_uuid', uuid);
filter += sprintf(PARAM_FILTER_NE, 'state', 'destroyed');
filter = '(&' + filter + ')';

var req = self.connection.findObjects(VMS_BUCKET_NAME, filter);

req.once('error', function (error) {
return cb(error);
});

req.on('record', function (object) {
if (object && object.value) {
vm = common.translateVm(object.value, false);
vms[vm.uuid] = vm;
}
});

return req.once('end', function () {
return cb(null, vms);
});
};

/*
* List VMs
Expand Down
73 changes: 25 additions & 48 deletions lib/common/util.js
Expand Up @@ -91,54 +91,6 @@ exports.shallowEqual = function (a, b, ignoreKeys) {



/*
* Gets the diff between two objects. The idea is that A is the outdated object
* so we want to check which properties that both objects share are different
* and which properties that B has and A does not, need to be added to A.
*
* Consider these 2 examples:
*
* - Machine running status changes. zone_state will appear in the object B,
* meaning that A has an old value for running status compared to B
* - Machine alias has been added. alias doesn't exist in A but it is present
* in the B object, so it will appear in the diff object as well
*/
function objectDiff(old, newObj) {
var result = {};
var i = 0;

for (i in newObj) {
// Any object
if (typeof (old[i]) == 'object' && typeof (newObj[i]) == 'object') {

// If date objects
if (old[i].getTime && newObj[i].getTime &&
(old[i].getTime() != newObj[i].getTime())) {
result[i] = newObj[i];

// Any other object should be fine for our case
} else {
result[i] = objectDiff(old[i], newObj[i]);
if (!result[i]) delete result[i];
}

// string, number
} else if (old[i] != newObj[i]) {
result[i] = newObj[i];
}
}

if (Object.keys(result).length === 0) {
return undefined;
} else {
return result;
}
}

exports.objectDiff = objectDiff;



/*
* Creates a YYYYMMDD date string
*/
Expand All @@ -160,6 +112,31 @@ exports.timestamp = function (aDate) {
};



/**
* Publishes a change feed item with the provided Publisher.
* @param {Publisher} publisher Publisher module via changefeed
* @param {string} resource Identifies the resource e.g. 'vms'
* @param {array} subResources Strings of resource properties e.g ['nics']
* @param {string} uuid UUID of the changed resource
* @param {function} cb callback function which takes err param
*/
function publishChange(publisher, resource, subResources, uuid, cb) {
var changeItem = {
changeKind: {
resource: resource,
subResources: subResources
},
changedResourceId: uuid
};

publisher.publish(changeItem, cb);
}

exports.publishChange = publishChange;



/*
* Poll a job until it reaches either the succeeded or failed state.
*
Expand Down
13 changes: 7 additions & 6 deletions lib/endpoints/jobs.js
Expand Up @@ -16,6 +16,7 @@ var restify = require('restify');
var assert = require('assert');

var common = require('../common');
var interceptors = require('../interceptors');



Expand Down Expand Up @@ -100,15 +101,15 @@ function jobResults(req, res, next) {
/*
* Mounts job actions as server routes
*/
function mount(server, before) {
function mount(server) {
server.get({ path: '/vms/:uuid/jobs', name: 'ListVmJobs' },
before, listJobs);
server.get({ path: '/jobs', name: 'ListJobs' }, before, listJobs);
server.get({ path: '/jobs/:job_uuid', name: 'GetJob' }, before, getJob);
interceptors.loadVm,
listJobs);
server.get({ path: '/jobs', name: 'ListJobs' }, listJobs);
server.get({ path: '/jobs/:job_uuid', name: 'GetJob' }, getJob);

// Post back URL for provision job results
server.post({ path: '/job_results', name: 'JobResults' },
before, jobResults);
server.post({ path: '/job_results', name: 'JobResults' }, jobResults);
}


Expand Down
31 changes: 24 additions & 7 deletions lib/endpoints/metadata.js
Expand Up @@ -16,6 +16,7 @@ var restify = require('restify');
var assert = require('assert');
var common = require('../common');
var errors = require('../errors');
var interceptors = require('../interceptors');

var METADATA_TYPES = [
'customer_metadata',
Expand Down Expand Up @@ -250,24 +251,40 @@ function deleteAllMetadata(req, res, next) {
/*
* Mounts metadata actions as server routes
*/
function mount(server, before) {
function mount(server) {
server.get({ path: '/vms/:uuid/:metadata', name: 'ListMetadata' },
before, setMetadataType, listMetadata);
interceptors.loadVm,
setMetadataType,
listMetadata);

server.get({ path: '/vms/:uuid/:metadata/:key', name: 'GetMetadata' },
before, setMetadataType, getMetadata);
interceptors.loadVm,
setMetadataType,
getMetadata);

server.post({ path: '/vms/:uuid/:metadata', name: 'AddMetadata' },
before, setMetadataType, addMetadata);
interceptors.checkWfapi,
interceptors.loadVm,
setMetadataType,
addMetadata);

server.put({ path: '/vms/:uuid/:metadata', name: 'SetMetadata' },
before, setMetadataType, setMetadata);
interceptors.checkWfapi,
interceptors.loadVm,
setMetadataType,
setMetadata);

server.del({ path: '/vms/:uuid/:metadata/:key', name: 'DeleteMetadata' },
before, setMetadataType, deleteMetadata);
interceptors.checkWfapi,
interceptors.loadVm,
setMetadataType,
deleteMetadata);

server.del({ path: '/vms/:uuid/:metadata', name: 'DeleteAllMetadata' },
before, setMetadataType, deleteAllMetadata);
interceptors.checkWfapi,
interceptors.loadVm,
setMetadataType,
deleteAllMetadata);
}


Expand Down
4 changes: 2 additions & 2 deletions lib/endpoints/ping.js
Expand Up @@ -86,8 +86,8 @@ function ping(req, res, next) {
/*
* Mounts job actions as server routes
*/
function mount(server, before) {
server.get({ path: '/ping', name: 'Ping' }, before, ping);
function mount(server) {
server.get({ path: '/ping', name: 'Ping' }, ping);
}


Expand Down
21 changes: 16 additions & 5 deletions lib/endpoints/role-tags.js
Expand Up @@ -16,6 +16,7 @@ var restify = require('restify');
var assert = require('assert');
var common = require('../common');
var errors = require('../errors');
var interceptors = require('../interceptors');


/*
Expand Down Expand Up @@ -160,17 +161,27 @@ function deleteAllRoleTags(req, res, next) {
*/
function mount(server, before) {
server.post({ path: '/vms/:uuid/role_tags', name: 'AddRoleTags' },
before, getVmRoleTags, addRoleTags);
interceptors.checkWfapi,
interceptors.loadVm,
getVmRoleTags,
addRoleTags);

server.put({ path: '/vms/:uuid/role_tags', name: 'SetRoleTags' },
before, setRoleTags);
interceptors.checkWfapi,
interceptors.loadVm,
setRoleTags);

server.del({ path: '/vms/:uuid/role_tags/:role_tag',
name: 'DeleteRoleTag' },
before, getVmRoleTags, deleteRoleTag);
name: 'DeleteRoleTag' },
interceptors.checkWfapi,
interceptors.loadVm,
getVmRoleTags,
deleteRoleTag);

server.del({ path: '/vms/:uuid/role_tags', name: 'DeleteAllRoleTags' },
before, deleteAllRoleTags);
interceptors.checkWfapi,
interceptors.loadVm,
deleteAllRoleTags);
}


Expand Down
5 changes: 2 additions & 3 deletions lib/endpoints/statuses.js
Expand Up @@ -46,9 +46,8 @@ function listStatuses(req, res, next) {
/*
* Mounts job actions as server routes
*/
function mount(server, before) {
server.get({ path: '/statuses', name: 'ListStatuses' },
before, listStatuses);
function mount(server) {
server.get({ path: '/statuses', name: 'ListStatuses' }, listStatuses);
}


Expand Down

0 comments on commit 58f775d

Please sign in to comment.