Add more untit test in Shovel.js

Statements   : 45.76% ( 302/660 )
Branches     : 35.81% ( 53/148 )
Functions    : 40.7% ( 70/172 )
Lines        : 45.76% ( 302/660 )
This commit is contained in:
andre keedy 2015-12-18 10:08:48 -05:00
parent c32d56976e
commit ad9ad93053
6 changed files with 825 additions and 267 deletions

View File

@ -9,8 +9,8 @@ var keystone = require('./../lib/api/openstack/keystone');
var logger = require('./../lib/services/logger').Logger; var logger = require('./../lib/services/logger').Logger;
var encryption = require('./../lib/services/encryption'); var encryption = require('./../lib/services/encryption');
var jsonfile = require('jsonfile'); var jsonfile = require('jsonfile');
var Promise = require('bluebird');
var _ = require('underscore'); var _ = require('underscore');
var Promise = require('bluebird');
var ironicConfig = config.ironic; var ironicConfig = config.ironic;
var glanceConfig = config.glance; var glanceConfig = config.glance;
@ -51,8 +51,8 @@ module.exports.driversGet = function driversGet(req, res, next) {
else else
res.end(); res.end();
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -78,8 +78,8 @@ module.exports.ironicnodesGet = function ironicnodesGet(req, res, next) {
else else
res.end(); res.end();
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -105,8 +105,8 @@ module.exports.ironicchassisGet = function ironicchassisGet(req, res, next) {
else else
res.end(); res.end();
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -122,7 +122,7 @@ module.exports.ironicnodeGet = function ironicnodeGet(req, res, next) {
ironicConfig.os_password). ironicConfig.os_password).
then(function (token) { then(function (token) {
token = JSON.parse(token).access.token.id; token = JSON.parse(token).access.token.id;
return ironic.get_nodeAsync(token, req.swagger.params.identifier.value); return ironic.get_node(token, req.swagger.params.identifier.value);
}). }).
then(function (result) { then(function (result) {
if (typeof result !== 'undefined') { if (typeof result !== 'undefined') {
@ -132,8 +132,8 @@ module.exports.ironicnodeGet = function ironicnodeGet(req, res, next) {
else else
res.end(); res.end();
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -158,8 +158,8 @@ module.exports.ironicnodePatch = function ironicnodePatch(req, res, next) {
res.end(result); res.end(result);
} }
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -180,8 +180,8 @@ module.exports.catalogsGet = function catalogsGet(req, res, next) {
else else
res.end(); res.end();
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -203,8 +203,8 @@ module.exports.catalogsbysourceGet = function catalogsbysourceGet(req, res, next
else else
res.end(); res.end();
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -225,8 +225,8 @@ module.exports.nodeGet = function nodeGet(req, res, next) {
else else
res.end(); res.end();
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -241,7 +241,7 @@ module.exports.nodesGet = function nodesGet(req, res, next) {
return monorail.request_nodes_get(). return monorail.request_nodes_get().
then(function (nodes) { then(function (nodes) {
Promise.filter(JSON.parse(nodes), function (node) { Promise.filter(JSON.parse(nodes), function (node) {
return lookupCatalog(node); return monorail.lookupCatalog(node);
}) })
.then(function (discoveredNodes) { .then(function (discoveredNodes) {
if (typeof discoveredNodes !== 'undefined') { if (typeof discoveredNodes !== 'undefined') {
@ -259,38 +259,6 @@ module.exports.nodesGet = function nodesGet(req, res, next) {
}); });
}; };
function lookupCatalog(node) {
return monorail.get_catalog_data_by_source(node.id, 'dmi')
.then(function (dmi) {
if (!_.has(JSON.parse(dmi), 'data')) {
return false;
}
})
.then(function () {
return monorail.get_catalog_data_by_source(node.id, 'lsscsi')
})
.then(function (lsscsi) {
if (!_.has(JSON.parse(lsscsi), 'data')) {
return false;
}
})
.then(function () {
return monorail.get_catalog_data_by_source(node.id, 'bmc')
})
.then(function (bmc) {
if (!_.has(JSON.parse(bmc), 'data')) {
return false;
}
else {
return true;
}
})
.catch(function (err) {
logger.error(err);
return false;
})
}
/* /*
* @api {get} /api/1.1/nodes/identifier/sel / GET / * @api {get} /api/1.1/nodes/identifier/sel / GET /
* @apiDescription get specific node by id * @apiDescription get specific node by id
@ -315,8 +283,8 @@ module.exports.getSeldata = function getSeldata(req, res, next) {
res.end(); res.end();
} }
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -361,57 +329,43 @@ module.exports.registerpost = function registerpost(req, res, next) {
return monorail.request_node_get(user_entry.uuid). return monorail.request_node_get(user_entry.uuid).
then(function (result) { then(function (result) {
if (!JSON.parse(result).name) { if (!JSON.parse(result).name) {
res.setHeader('Content-Type', 'application/json'); var error = { error_message: { message: 'failed to find required node in RackHD' } };
res.end(result); logger.error(err);
throw error;
} }
onrack_node = JSON.parse(result); onrack_node = JSON.parse(result);
}).then(function () { return monorail.nodeDiskSize(onrack_node)
return monorail.get_catalog_data_by_source(user_entry.uuid, 'lsscsi'). .catch(function (err) {
then(function (scsi) { var error = { error_message: { message: 'failed to get compute node Disk Size' } };
scsi = JSON.parse(scsi); logger.error(err);
if (scsi.data) { throw error;
for (var elem in scsi.data) {
var item = (scsi.data[elem]);
if (item['peripheralType'] == 'disk') {
local_gb += parseFloat(item['size'].replace('GB', '').trim());
}
}
}
}); });
}).then(function () { }).then(function (localDisk) {
monorail.get_catalog_data_by_source(user_entry.uuid, 'dmi'). local_gb = localDisk;
then(function (dmi) { return monorail.get_node_memory_cpu(onrack_node)
dmi = JSON.parse(dmi); .catch(function (err) {
if (dmi.data) { var error = { error_message: { message: 'failed to get compute node memory size' } };
var dmi_total = 0; logger.error(err);
if (dmi.data['Memory Device']) { throw error;
var memory_device = dmi.data['Memory Device'];
for (var elem in memory_device) {
var item = memory_device[elem];
//logger.info(item['Size']);
if (item['Size'].indexOf('GB') > -1) {
dmi_total += parseFloat(item['Size'].replace('GB', '').trim()) * 1000;
}
if (item['Size'].indexOf('MB') > -1) {
dmi_total += parseFloat(item['Size'].replace('MB', '').trim());
}
}
}
propreties = {
'cpus': dmi['data']['Processor Information'].length,
'memory_mb': dmi_total,
'local_gb': local_gb
};
}
node = {
'name': user_entry.uuid,
'driver': user_entry.driver,
'driver_info': info,
'properties': propreties,
'extra': extra
};
}); });
}).then(function () { }).then(function (dmiData) {
if (local_gb == 0 || dmiData.cpus == 0 || dmiData.memory == 0) {
var error = { error_message: { message: 'failed to get compute node data', nodeDisk: local_gb, memorySize: dmiData.memory, cpuCount: dmiData.cpus } };
throw (error);
}
propreties = {
'cpus': dmiData.cpus,
'memory_mb': dmiData.memory,
'local_gb': local_gb
};
node = {
'name': user_entry.uuid,
'driver': user_entry.driver,
'driver_info': info,
'properties': propreties,
'extra': extra
};
return (keystone.authenticatePassword(ironicConfig.os_tenant_name, ironicConfig.os_username, return (keystone.authenticatePassword(ironicConfig.os_tenant_name, ironicConfig.os_username,
ironicConfig.os_password)); ironicConfig.os_password));
}). }).
@ -420,10 +374,9 @@ module.exports.registerpost = function registerpost(req, res, next) {
return ironic.create_node(ironicToken, JSON.stringify(node)); return ironic.create_node(ironicToken, JSON.stringify(node));
}). }).
then(function (ret) { then(function (ret) {
logger.info('\r\ncreate node:\r\n' + ret); logger.debug('\r\ncreate node:\r\n' + ret);
if (ret && JSON.parse(ret).error_message) { if (ret && JSON.parse(ret).error_message) {
res.setHeader('Content-Type', 'application/json'); throw (JSON.parse(ret));
res.end(ret);
} }
ironic_node = JSON.parse(ret); ironic_node = JSON.parse(ret);
port = { 'address': user_entry.port, 'node_uuid': ironic_node.uuid }; port = { 'address': user_entry.port, 'node_uuid': ironic_node.uuid };
@ -436,9 +389,7 @@ module.exports.registerpost = function registerpost(req, res, next) {
then(function (pwr_state) { then(function (pwr_state) {
logger.info('\r\npwr_state: on'); logger.info('\r\npwr_state: on');
if (pwr_state && JSON.parse(pwr_state).error_message) { if (pwr_state && JSON.parse(pwr_state).error_message) {
console.error(JSON.parse(pwr_state).error_message); throw (JSON.parse(pwr_state));
res.setHeader('Content-Type', 'application/json');
res.end(pwr_state);
} }
}).then(function () { }).then(function () {
var timer = {}; var timer = {};
@ -452,7 +403,8 @@ module.exports.registerpost = function registerpost(req, res, next) {
}). }).
then(function (result) { then(function (result) {
logger.info('\r\patched node:\r\n' + result); logger.info('\r\patched node:\r\n' + result);
}).then(function () { }).
then(function () {
return monorail.request_whitelist_set(user_entry.port) return monorail.request_whitelist_set(user_entry.port)
}). }).
then(function (whitelist) { then(function (whitelist) {
@ -460,8 +412,8 @@ module.exports.registerpost = function registerpost(req, res, next) {
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(whitelist); res.end(whitelist);
}) })
.catch(function(err){ .catch(function (err) {
logger.error({message:err,path:req.url}); logger.error({ message: err, path: req.url });
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(err)); res.end(JSON.stringify(err));
}); });
@ -472,36 +424,36 @@ module.exports.registerpost = function registerpost(req, res, next) {
* @apiVersion 1.1.0 * @apiVersion 1.1.0
*/ */
module.exports.unregisterdel = function unregisterdel(req, res, next) { module.exports.unregisterdel = function unregisterdel(req, res, next) {
var ironicToken;
return keystone.authenticatePassword(ironicConfig.os_tenant_name, ironicConfig.os_username, return keystone.authenticatePassword(ironicConfig.os_tenant_name, ironicConfig.os_username,
ironicConfig.os_password). ironicConfig.os_password).
then(function (token) { then(function (token) {
token = JSON.parse(token).access.token.id;; ironicToken = JSON.parse(token).access.token.id;
return ironic.delete_node(token, req.swagger.params.identifier.value); return ironic.get_node(ironicToken, req.swagger.params.identifier.value);
}).
then(function (ironicNode) {
if (JSON.parse(ironicNode).hasOwnProperty('extra')) {
return monorail.request_whitelist_del(JSON.parse(ironicNode).extra.nodeid);
}
else {
throw { error_message: 'Node is not registered with Shovel' };
}
}).
then(function () {
return ironic.delete_node(ironicToken, req.swagger.params.identifier.value);
}). }).
then(function (del_node) { then(function (del_node) {
if (del_node && JSON.parse(del_node).error_message) { if (del_node && JSON.parse(del_node).error_message) {
logger.info(del_node); throw (del_node);
res.setHeader('Content-Type', 'application/json');
res.end(del_node);
return;
} }
return monorail.request_node_get(req.swagger.params.identifier.value); else {
}). logger.debug('ironicNode: ' + req.swagger.params.identifier.value + ' is been deleted susccessfully');
then(function (onrack_node) {
if (onrack_node && !JSON.parse(onrack_node).name) {
logger.info(onrack_node);
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.end(onrack_node); var success = {
return; result: 'success'
};
res.end(JSON.stringify(success));
} }
return monorail.request_whitelist_del(JSON.parse(onrack_node).name);
}).
then(function (whitelist) {
res.setHeader('Content-Type', 'application/json');
var success = {
result: 'success'
};
res.end(JSON.stringify(success));
}) })
.catch(function (err) { .catch(function (err) {
logger.error({ message: err, path: req.url }); logger.error({ message: err, path: req.url });
@ -551,14 +503,14 @@ module.exports.configsetironic = function configsetironic(req, res, next) {
if (req.body.hasOwnProperty('os_password')) { if (req.body.hasOwnProperty('os_password')) {
var password = req.body.os_password; var password = req.body.os_password;
//replace password with encrypted value //replace password with encrypted value
try{ try {
req.body.os_password = encryption.encrypt(password); req.body.os_password = encryption.encrypt(password);
} }
catch (err) { catch (err) {
logger.error(err); logger.error(err);
res.end('failed to update ironic config'); res.end('failed to update ironic config');
} }
} }
if (setConfig('ironic', req.body)) { if (setConfig('ironic', req.body)) {
res.end('success'); res.end('success');
} }
@ -599,19 +551,19 @@ module.exports.configsetglance = function configsetglance(req, res, next) {
* @apiVersion 1.1.0 * @apiVersion 1.1.0
*/ */
module.exports.configset = function configset(req, res, next) { module.exports.configset = function configset(req, res, next) {
res.setHeader('content-type', 'text/plain'); res.setHeader('content-type', 'text/plain');
if (setConfig('shovel', req.body) == true) { if (setConfig('shovel', req.body) == true) {
res.end('success'); res.end('success');
} }
else { else {
res.end('failed to update shovel config'); res.end('failed to update shovel config');
}; };
}; };
function setConfig(keyValue, entry) { function setConfig(keyValue, entry) {
var filename = require('path').dirname(require.main.filename) + '/config.json'; var filename = 'config.json';
try { jsonfile.readFile(filename, function (err, output) {
jsonfile.readFile(filename, function (err, output) { try {
var content = (keyValue == null) ? output : output[keyValue]; var content = (keyValue == null) ? output : output[keyValue];
var filteredList = _.pick(content, Object.keys(entry)); var filteredList = _.pick(content, Object.keys(entry));
_.each(Object.keys(filteredList), function (key) { _.each(Object.keys(filteredList), function (key) {
@ -621,14 +573,15 @@ function setConfig(keyValue, entry) {
}); });
output[keyValue] = content; output[keyValue] = content;
jsonfile.writeFile(filename, output, { spaces: 2 }, function (err) { jsonfile.writeFile(filename, output, { spaces: 2 }, function (err) {
logger.info(content); logger.debug(content);
}); });
}); }
} catch (err) {
catch (err) { logger.error(err);
logger.error(err); return false;
return false; }
} });
return true; return true;
} }
@ -638,29 +591,34 @@ function setConfig(keyValue, entry) {
* @apiVersion 1.1.0 * @apiVersion 1.1.0
*/ */
module.exports.configget = function configget(req, res, next) { module.exports.configget = function configget(req, res, next) {
var fs = require('fs'); var filename = 'config.json';
var path = require('path'); jsonfile.readFile(filename, function (err, content) {
var appDir = path.dirname(require.main.filename); try {
var file_content = fs.readFileSync(appDir + '/config.json');
var content = JSON.parse(file_content); delete content['key'];
delete content['key']; if (content.ironic.hasOwnProperty("os_password")) {
if (content.ironic.hasOwnProperty("os_password")){ content.ironic.os_password = '[REDACTED]';
content.ironic.os_password = '[REDACTED]'; }
} if (content.glance.hasOwnProperty("os_password")) {
if (content.glance.hasOwnProperty("os_password")) { content.glance.os_password = '[REDACTED]';
content.glance.os_password = '[REDACTED]'; }
} res.setHeader('Content-Type', 'application/json');
res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(content));
res.end(JSON.stringify(content)); }
}; catch (err) {
logger.error(err);
res.end();
};
});
};
/* /*
* @api {get} /api/1.1/glance/images / GET / * @api {get} /api/1.1/glance/images / GET /
* @apiDescription get glance images * @apiDescription get glance images
*/ */
module.exports.imagesGet = function imagesGet(req, res, next) { module.exports.imagesGet = function imagesGet(req, res, next) {
return keystone.authenticatePassword(glanceConfig.os_tenant_name,glanceConfig.os_username, return keystone.authenticatePassword(glanceConfig.os_tenant_name, glanceConfig.os_username,
glanceConfig.os_password ). glanceConfig.os_password).
then(function (token) { then(function (token) {
token = JSON.parse(token).access.token.id; token = JSON.parse(token).access.token.id;
return glance.get_images(token); return glance.get_images(token);

View File

@ -1,6 +1,7 @@
var config = require('./../../../config.json'); var config = require('./../../../config.json');
var client = require('./../client'); var client = require('./../client');
var Promise = require('bluebird'); var Promise = require('bluebird');
var _ = require('underscore');
Promise.promisifyAll(client); Promise.promisifyAll(client);
var pfx = '/api/' + config.monorail.version; var pfx = '/api/' + config.monorail.version;
@ -48,6 +49,90 @@ var MonorailWrapper = {
request_poller_data_get: function (identifier, ret) { request_poller_data_get: function (identifier, ret) {
request.path = pfx + '/pollers/' + identifier + '/data/current'; request.path = pfx + '/pollers/' + identifier + '/data/current';
return client.GetAsync(request); return client.GetAsync(request);
},
lookupCatalog: function lookupCatalog(node) {
var self = this;
return self.get_catalog_data_by_source(node.id, 'dmi')
.then(function (dmi) {
if (!_.has(JSON.parse(dmi), 'data')) {
return false;
}
})
.then(function () {
return self.get_catalog_data_by_source(node.id, 'lsscsi')
})
.then(function (lsscsi) {
if (!_.has(JSON.parse(lsscsi), 'data')) {
return false;
}
})
.then(function () {
return self.get_catalog_data_by_source(node.id, 'bmc')
})
.then(function (bmc) {
if (!_.has(JSON.parse(bmc), 'data')) {
return false;
}
else {
return true;
}
})
.catch(function (err) {
return false;
})
},
nodeDiskSize: function nodeDiskSize(node) {
var local_gb = 0;
var self = this;
return self.get_catalog_data_by_source(node.id, 'lsscsi').
then(function (scsi) {
scsi = JSON.parse(scsi);
if (scsi.data) {
for (var elem in scsi.data) {
var item = (scsi.data[elem]);
if (item['peripheralType'] == 'disk') {
local_gb += parseFloat(item['size'].replace('GB', '').trim());
}
}
}
return Promise.resolve(local_gb);
})
.catch(function (err) {
throw err;
})
},
get_node_memory_cpu: function get_node_memory_cpu(computeNode) {
var self = this;
var dmiData = { cpus: 0, memory: 0 };
return self.get_catalog_data_by_source(computeNode.id, 'dmi').
then(function (dmi) {
dmi = JSON.parse(dmi);
if (dmi.data) {
var dmi_total = 0;
if (dmi.data['Memory Device']) {
var memory_device = dmi.data['Memory Device'];
for (var elem in memory_device) {
var item = memory_device[elem];
//logger.info(item['Size']);
if (item['Size'].indexOf('GB') > -1) {
dmi_total += parseFloat(item['Size'].replace('GB', '').trim()) * 1000;
}
if (item['Size'].indexOf('MB') > -1) {
dmi_total += parseFloat(item['Size'].replace('MB', '').trim());
}
}
dmiData.memory = dmi_total;
}
if (dmi['data'].hasOwnProperty('Processor Information')) {
dmiData.cpus = dmi['data']['Processor Information'].length;
}
}
return Promise.resolve(dmiData);
})
.catch(function (err) {
throw err;
})
} }
}; };
module.exports = Object.create(MonorailWrapper); module.exports = Object.create(MonorailWrapper);

View File

@ -1,33 +1,35 @@
{ {
"name": "", "name": "",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"keywords": [ "keywords": [
"swagger" "swagger"
], ],
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"dependencies": { "dependencies": {
"connect": "^3.2.0", "connect": "^3.2.0",
"swagger-tools": "0.8.*", "swagger-tools": "0.8.*",
"bluebird": "" "bluebird": ""
}, },
"devDependencies": { "devDependencies": {
"should": "~7.0.1", "should": "~7.0.1",
"mocha": "^2.1.0", "mocha": "^2.1.0",
"sinon": "1.16.1", "sinon": "1.16.1",
"sinon-as-promised": "^2.0.3", "sinon-as-promised": "^2.0.3",
"sinon-chai": "^2.7.0", "sinon-chai": "^2.7.0",
"supertest": "^0.15.0", "supertest": "^0.15.0",
"underscore": "^1.8.3", "underscore": "^1.8.3",
"xunit-file": "0.0.6", "xunit-file": "0.0.6",
"winston": "2.1.1", "winston": "2.1.1",
"jsonfile": "2.2.3", "jsonfile": "2.2.3",
"crypto": "0.0.3" "crypto": "0.0.3",
}, "istanbul": "0.4.1"
"scripts" :{ },
"postinstall": "scripts/post-install.sh", "scripts": {
"start" : "start shovel" "postinstall": "scripts/post-install.sh",
} "start": "start shovel",
"test": "istanbul cover -x '**/test/**' ./node_modules/.bin/_mocha test/* && istanbul report cobertura"
}
} }

119
Shovel/test/api/monorail.js Normal file
View File

@ -0,0 +1,119 @@
var request = require('supertest');
var should = require('should');
var assert = require('assert');
var sinon = require('sinon');
var monorail = require('./../../lib/api/monorail/monorail');
var Promise = require('bluebird');
var _ = require('underscore');
var rackhdNode = [{ workflows: [], autoDiscover: false, identifiers: ["2c:60:0c:83:f5:d1"], name: "2c:60:0c:83:f5:d1", sku: null, type: "compute", id: "5668b6ad8bee16a10989e4e5" }];
var catalogSource = [{ source: 'dmi', data: {'Memory Device': [{ Size: '1 GB' }, { Size: '1 GB' }],
'Processor Information': [{}, {}] }}, { source: 'lsscsi', data: [{ peripheralType: 'disk', size: '1GB' }] }];
var rackhdNode =[ { workflows: [], autoDiscover: false, identifiers: ["2c:60:0c:83:f5:d1"], name: "2c:60:0c:83:f5:d1", sku: null, type: "compute", id: "5668b6ad8bee16a10989e4e5" }];
var identifier = '123456789';
describe('monorail nodeDiskSize', function () {
beforeEach('set up mocks', function () {
//monorail
sinon.stub(monorail, 'get_catalog_data_by_source').returns(Promise.resolve(JSON.stringify(catalogSource[1])));
});
afterEach('teardown mocks', function () {
//monorail
monorail['get_catalog_data_by_source'].restore();
});
describe('nodeDiskSize', function () {
it('response should returns an integer with value equal to disk size 1GB', function (done) {
return monorail.nodeDiskSize(rackhdNode).
then(function (result) {
result.should.be.exactly(1);
done();
});
});
});
});
describe('monorail get_node_memory_cpu', function () {
beforeEach('set up mocks', function () {
//monorail
sinon.stub(monorail, 'get_catalog_data_by_source').returns(Promise.resolve(JSON.stringify(catalogSource[0])));
});
afterEach('teardown mocks', function () {
//monorail
monorail['get_catalog_data_by_source'].restore();
});
describe('get_node_memory_cpu', function () {
it('response should returns an integer with value equal to memory size 2000MB and cpus=2', function (done) {
return monorail.get_node_memory_cpu(rackhdNode).
then(function (result) {
result.cpus.should.be.exactly(2);
result.memory.should.be.exactly(2000);
done();
})
});
});
});
describe('lookupCatalog true', function () {
beforeEach('set up mocks', function () {
//monorail
sinon.stub(monorail, 'get_catalog_data_by_source').returns(Promise.resolve(JSON.stringify(catalogSource[0])));
});
afterEach('teardown mocks', function () {
//monorail
monorail['get_catalog_data_by_source'].restore();
});
describe('lookupCatalog', function () {
it('lookupCatalog response should be equal to true', function (done) {
return monorail.lookupCatalog(rackhdNode[0]).
then(function (result) {
console.log(result);
JSON.parse(result).should.be.exactly(true);
done();
})
.catch(function (err) {
throw err;
})
});
});
});
describe('lookupCatalog false', function () {
beforeEach('set up mocks', function () {
//monorail
sinon.stub(monorail, 'get_catalog_data_by_source').returns(Promise.resolve(JSON.stringify({})));
});
afterEach('teardown mocks', function () {
//monorail
monorail['get_catalog_data_by_source'].restore();
});
describe('lookupCatalog', function () {
it('lookupCatalog response should be equal to fasle if catalog does not have property data', function (done) {
return monorail.lookupCatalog(rackhdNode[0]).
then(function (result) {
console.log(result);
JSON.parse(result).should.be.exactly(false);
done();
})
.catch(function (err) {
throw err;
})
});
});
});

View File

@ -0,0 +1,442 @@
var request = require('supertest');
var should = require('should');
var assert = require('assert');
var sinon = require('sinon');
var monorail = require('./../../lib/api/monorail/monorail');
var ironic = require('./../../lib/api/openstack/ironic');
var keystone = require('./../../lib/api/openstack/keystone');
var Promise = require('bluebird');
var _ = require('underscore');
var helper = require('./../helper');
var url = 'http://localhost:9008';
var rackhdNode =[ { workflows: [], autoDiscover: false, identifiers: ["2c:60:0c:83:f5:d1"], name: "2c:60:0c:83:f5:d1", sku: null, type: "compute", id: "5668b6ad8bee16a10989e4e5" }];
var identifier = '9a761508-4eee-4065-b47b-45c22dff54c2';
var ironic_node_list = [ { uuid: "9a761508-4eee-4065-b47b-45c22dff54c2", extra: { name: "D51B-2U (dual 10G LoM)", eventre: "", nodeid: "564cefa014ee77be18e48efd",
timer: { start: "2015-11-30T21:14:11.753Z", finish: "2015-11-30T21:14:11.772Z", stop: false, isDone: true, timeInteval: 5000 }, eventcnt: 0 } }];
var nodePollers = [{ config: { command: "sel" }, id: "564dd86285fb1e7c72721543" }];
var _sel = { sel:[ { logId: "1", date: "12/03/2015", time: "08:54:11", sensorType: "Memory", sensorNumber: "#0x53", event: "Correctable ECC", value: "Asserted"} ] };
var keyToken = { access:{ token:{id:'123456'} } };
var selEvent = { message: "There is no cache record for the poller with ID 564cf02a4978dadc187976f5.Perhaps it has not been run yet?" };
var extraPatch = {extra: {name: "QuantaPlex T41S-2U", eventre: "Correctable ECC",nodeid: "565f3f3b4c95bce26f35c6a0",
timer: {timeInterval: 15000, start: "2015-12-03T17:38:20.569Z",finish: "2015-12-03T17:38:20.604Z",stop: false,isDone: true} } };
var patchedData = [{ 'path': '/extra', 'value': extraPatch.extra, 'op': 'replace' }];
var catalog = [{ node: "9a761508-4eee-4065-b47b-45c22dff54c2", source: "dmi", data: {} }];
var ironicDrivers = { drivers: [{ "hosts": ["localhost"], "name": "pxe_ssh", "links": [] }] };
var ironicChassis = { uuid: "1ac07daf-264e-4bd5-b0c4-d53095c217ac", link: [], extra: {}, created_at: "", "nodes": [], description: "ironic test chassis" };
var catalogSource = [{ source: 'dmi', data: {'Memory Device': [{ Size: '1 GB' }, { Size: '1 GB' }],
'Processor Information': [{}, {}] }}, { source: 'lsscsi', data: [{ peripheralType: 'disk', size: '1GB' }] }];
describe('Shovel api unit testing', function () {
var dmiData = { cpus: 1, memory: 1 };
before('start HTTP server', function () {
helper.startServer();
});
beforeEach('set up mocks', function () {
//monorail
sinon.stub(monorail, 'request_node_get').returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
sinon.stub(monorail, 'request_nodes_get').returns(Promise.resolve(JSON.stringify(rackhdNode)));
sinon.stub(monorail, 'lookupCatalog').returns(Promise.resolve(true));
sinon.stub(monorail, 'request_catalogs_get').returns(Promise.resolve(JSON.stringify(catalog)));
sinon.stub(monorail, 'request_poller_get').returns(Promise.resolve(JSON.stringify(nodePollers)));
sinon.stub(monorail, 'request_poller_data_get').returns(Promise.resolve(JSON.stringify(_sel)));
sinon.stub(monorail, 'request_whitelist_del').returns(Promise.resolve(''));
sinon.stub(monorail, 'nodeDiskSize').returns(Promise.resolve(0));
sinon.stub(monorail, 'get_node_memory_cpu').returns(Promise.resolve(dmiData));
sinon.stub(monorail, 'get_catalog_data_by_source').returns(Promise.resolve(JSON.stringify(catalogSource[0])));
//keystone
sinon.stub(keystone, 'authenticatePassword').returns(Promise.resolve(JSON.stringify(keyToken)));
//ironic
sinon.stub(ironic, 'get_driver_list').returns(Promise.resolve(JSON.stringify(ironicDrivers)));
sinon.stub(ironic, 'get_chassis_by_id').returns(Promise.resolve(JSON.stringify(ironicChassis)));
sinon.stub(ironic, 'patch_node').returns(Promise.resolve(JSON.stringify(extraPatch)));
sinon.stub(ironic, 'get_node_list').returns(Promise.resolve(JSON.stringify(ironic_node_list)));
sinon.stub(ironic, 'get_node').returns(Promise.resolve(JSON.stringify(ironic_node_list[0])));
sinon.stub(ironic, 'delete_node').returns(Promise.resolve(''));
});
afterEach('teardown mocks', function () {
//monorail
monorail['request_node_get'].restore();
monorail['request_nodes_get'].restore();
monorail['request_poller_get'].restore();
monorail['request_poller_data_get'].restore();
monorail['request_catalogs_get'].restore();
monorail['lookupCatalog'].restore();
monorail['request_whitelist_del'].restore();
monorail['nodeDiskSize'].restore();
monorail['get_node_memory_cpu'].restore();
monorail['get_catalog_data_by_source'].restore();
//ironic
ironic['patch_node'].restore();
ironic['get_node_list'].restore();
ironic['get_node'].restore();
ironic['get_chassis_by_id'].restore();
ironic['get_driver_list'].restore();
ironic['delete_node'].restore();
//keystone
keystone['authenticatePassword'].restore();
});
after('stop HTTP server', function () {
helper.stopServer();
});
describe('shovel-info', function () {
it('response should have property \'name\': \'shovel\'', function (done) {
request(url)
.get('/api/1.1/info')
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).should.have.property('name', 'shovel');
done();
});
});
});
describe('shovel-catalogs/{identifier}', function () {
it('in case of a correct rackHD id, response should include property node, source and data', function (done) {
request(url)
.get('/api/1.1/catalogs/' + identifier)
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text)[0].should.have.property('node', identifier);
JSON.parse(res.text)[0].should.have.property('data');
JSON.parse(res.text)[0].should.have.property('source');
done();
});
});
});
describe('shovel-catalogs/{identifier}/source', function () {
it('in case of a correct rackHD id, response should include property source and data', function (done) {
request(url)
.get('/api/1.1/catalogs/' + identifier + '/dmi')
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).should.have.property('data');
JSON.parse(res.text).should.have.property('source');
done();
});
});
});
describe('shovel-nodes/{identifier}', function () {
it('in case of correct id, response should include property: id,identifiers', function (done) {
request(url)
.get('/api/1.1/nodes/' + identifier)
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).should.have.property('id');
JSON.parse(res.text).should.have.property('identifiers');
done();
});
});
});
describe('shovel-ironic/chassis/{identifier}', function () {
it('in case of a correct id, response should include property: uuid , description ', function (done) {
request(url)
.get('/api/1.1/ironic/chassis/' + identifier)
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).should.have.property('uuid');
JSON.parse(res.text).should.have.property('description');
done();
});
});
});
describe('shovel-ironic/drivers', function () {
it('response should have property \'drivers\'', function (done) {
request(url)
.get('/api/1.1/ironic/drivers')
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).should.have.property('drivers');
done();
});
});
});
describe('shovel-ironic/nodes', function () {
it('response should have property \'uuid\'', function (done) {
request(url)
.get('/api/1.1/ironic/nodes')
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text)[0].should.have.property('uuid');
done();
});
});
});
describe('shovel-ironic/nodes/identifier', function () {
it('response should have property \'uuid\'', function (done) {
request(url)
.get('/api/1.1/ironic/nodes/' + identifier)
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).should.have.property('uuid');
done();
});
});
});
describe('shovel-ironic/patch', function () {
it('response should have property nodeid timer', function (done) {
var body = {};
request(url)
.patch('/api/1.1/ironic/node/' + identifier)
.send(body)
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).extra.should.have.property('nodeid');
JSON.parse(res.text).extra.should.have.property('timer');
done();
});
});
});
describe('shovel-nodes', function () {
it('response should have property "identifiers"', function (done) {
request(url)
.get('/api/1.1/nodes')
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
for (item in JSON.parse(res.text)) {
JSON.parse(res.text)[item].should.have.property('identifiers');
}
done();
});
});
});
describe('shovel-unregister/{identifier}', function () {
it('if ironic id exist, response should include property: result: success', function (done) {
request(url)
.delete('/api/1.1/unregister/' + identifier)
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).result.should.be.equal('success');
done();
});
});
});
describe('shovel-getconfig', function () {
it('', function (done) {
request(url)
.get('/api/1.1/shovel/config')
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
JSON.parse(res.text).should.have.property('shovel');
JSON.parse(res.text).should.have.property('ironic');
JSON.parse(res.text).should.have.property('glance');
JSON.parse(res.text).should.have.property('keystone')
done();
});
});
});
describe('shovel-set ironic config', function () {
it('', function (done) {
var body = { httpHost: "localhost" };
request(url)
.post('/api/1.1/shovel/ironic/set-config')
.send(body)
.expect('Content-Type', /text/)
.expect(200) //Status code
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
res.text.should.be.exactly('success');
done();
});
});
});
describe('shovel-set monorail config', function () {
it('', function (done) {
var body = { httpHost: "localhost" };
request(url)
.post('/api/1.1/shovel/monorail/set-config')
.send(body)
.expect('Content-Type', /text/)
.expect(200) //Status code
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
res.text.should.be.exactly('success');
done();
});
});
});
describe('shovel-set glance config', function () {
it('', function (done) {
var body = { httpHost: "localhost" };
request(url)
.post('/api/1.1/shovel/glance/set-config')
.send(body)
.expect('Content-Type', /text/)
.expect(200) //Status code
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
res.text.should.be.exactly('success');
done();
});
});
});
describe('shovel-set keystone config', function () {
it('', function (done) {
var body = { httpHost: "localhost" };
request(url)
.post('/api/1.1/shovel/keystone/set-config')
.send(body)
.expect('Content-Type', /text/)
.expect(200) //Status code
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
res.text.should.be.exactly('success');
done();
});
});
});
});
describe('Shovel api register', function () {
var error_message = '{"error_message": "{\\"debuginfo\\": null, \\"faultcode\\": \\"Client\\", \\"faultstring\\": \\"A node with name 5668b42d8bee16a10989e4e4 already exists.\\"}"}';
var body = { "id": identifier, "driver": "string", "ipmihost": "string", "ipmiusername": "string", "ipmipasswd": "string" };
beforeEach('set up mocks', function () {
//monorail
//keystone
sinon.stub(keystone, 'authenticatePassword').returns(Promise.resolve(JSON.stringify(keyToken)));
//ironic
sinon.stub(ironic, 'create_node').returns(Promise.resolve(error_message));
});
afterEach('teardown mocks', function () {
//monorail
monorail['nodeDiskSize'].restore();
monorail['get_node_memory_cpu'].restore();
monorail['request_node_get'].restore();
//keystone
keystone['authenticatePassword'].restore();
//ironic
ironic['create_node'].restore();
});
describe('shovel-resgister', function () {
it('response in register should have property error_message when any of node info equal to 0 ', function (done) {
sinon.stub(monorail, 'request_node_get').returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
sinon.stub(monorail, 'nodeDiskSize').returns(Promise.resolve(0));
sinon.stub(monorail, 'get_node_memory_cpu').returns(Promise.resolve({ cpus: 0, memory: 0 }));
request(url)
.post('/api/1.1/register')
.send(body)
.expect('Content-Type', /json/)
.expect(200) //Status code
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).should.have.property('error_message');
done();
});
});
it('response in register should have property error_message create node return error in ironic', function (done) {
sinon.stub(monorail, 'request_node_get').returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
sinon.stub(monorail, 'nodeDiskSize').returns(Promise.resolve(1));
sinon.stub(monorail, 'get_node_memory_cpu').returns(Promise.resolve({ cpus: 1, memory: 1 }));
request(url)
.post('/api/1.1/register')
.send(body)
.expect('Content-Type', /json/)
.expect(200) //Status code
// end handles the response
.end(function (err, res) {
if (err) {
throw err;
}
// this is should.js syntax, very clear
JSON.parse(res.text).should.have.property('error_message');
done();
});
});
});
});

View File

@ -11,68 +11,20 @@ var _ = require('underscore');
describe('Shovel poller unit testing', function () { describe('Shovel poller unit testing', function () {
var rackhdNode =[ { workflows: [], autoDiscover: false, identifiers: ["2c:60:0c:83:f5:d1"], name: "2c:60:0c:83:f5:d1", sku: null, type: "compute", id: "5668b6ad8bee16a10989e4e5" }];
var identifier = '9a761508-4eee-4065-b47b-45c22dff54c2'; var identifier = '9a761508-4eee-4065-b47b-45c22dff54c2';
var ironic_node_list = [ var ironic_node_list = [ { uuid: "9a761508-4eee-4065-b47b-45c22dff54c2", extra: { name: "D51B-2U (dual 10G LoM)", eventre: "", nodeid: "564cefa014ee77be18e48efd",
{ timer: { start: "2015-11-30T21:14:11.753Z", finish: "2015-11-30T21:14:11.772Z", stop: false, isDone: true, timeInteval: 5000 }, eventcnt: 0 } }];
uuid: "9a761508-4eee-4065-b47b-45c22dff54c2", var nodePollers = [{ config: { command: "sel" }, id: "564dd86285fb1e7c72721543" }];
extra: { var _sel = { sel:[ { logId: "1", date: "12/03/2015", time: "08:54:11", sensorType: "Memory", sensorNumber: "#0x53", event: "Correctable ECC", value: "Asserted"} ] };
name: "D51B-2U (dual 10G LoM)", var keyToken = { access:{ token:{id:'123456'} } };
eventre: "",
nodeid: "564cefa014ee77be18e48efd",
timer: {
start: "2015-11-30T21:14:11.753Z",
finish: "2015-11-30T21:14:11.772Z",
stop: false,
isDone: true,
timeInteval: 5000
},
eventcnt: 0
}
}
]
var nodePollers = [{
config: {
command: "sel"
},
id: "564dd86285fb1e7c72721543"
}]
var _sel = {
sel:[
{
logId: "1",
date: "12/03/2015",
time: "08:54:11",
sensorType: "Memory",
sensorNumber: "#0x53",
event: "Correctable ECC",
value: "Asserted"
}
]
};
var keyToken = {
access:{
token:{id:'123456'}
}
};
var selEvent = { message: "There is no cache record for the poller with ID 564cf02a4978dadc187976f5.Perhaps it has not been run yet?" }; var selEvent = { message: "There is no cache record for the poller with ID 564cf02a4978dadc187976f5.Perhaps it has not been run yet?" };
var extraPatch = { var extraPatch = {extra: {name: "QuantaPlex T41S-2U", eventre: "Correctable ECC",nodeid: "565f3f3b4c95bce26f35c6a0",
extra: { timer: {timeInterval: 15000, start: "2015-12-03T17:38:20.569Z",finish: "2015-12-03T17:38:20.604Z",stop: false,isDone: true} } };
name: "QuantaPlex T41S-2U",
eventre: "Correctable ECC",
nodeid: "565f3f3b4c95bce26f35c6a0",
timer: {
timeInterval: 15000,
start: "2015-12-03T17:38:20.569Z",
finish: "2015-12-03T17:38:20.604Z",
stop: false,
isDone: true
}
}
};
var patchedData = [{ 'path': '/extra', 'value': extraPatch.extra, 'op': 'replace' }]; var patchedData = [{ 'path': '/extra', 'value': extraPatch.extra, 'op': 'replace' }];
var pollerInstance; var pollerInstance;
before('start HTTP server', function () { before('start Poller service', function () {
pollerInstance = new Poller(5000);//timeInterval to 5s pollerInstance = new Poller(5000);//timeInterval to 5s
}); });
@ -80,15 +32,15 @@ describe('Shovel poller unit testing', function () {
sinon.stub(monorail, 'request_poller_get').returns(Promise.resolve(JSON.stringify(nodePollers))); sinon.stub(monorail, 'request_poller_get').returns(Promise.resolve(JSON.stringify(nodePollers)));
sinon.stub(monorail, 'request_poller_data_get').returns(Promise.resolve(JSON.stringify(_sel))); sinon.stub(monorail, 'request_poller_data_get').returns(Promise.resolve(JSON.stringify(_sel)));
sinon.stub(ironic,'patch_node').returns(Promise.resolve(JSON.stringify(extraPatch))); sinon.stub(ironic,'patch_node').returns(Promise.resolve(JSON.stringify(extraPatch)));
sinon.stub(keystone,'authenticate').returns(Promise.resolve(JSON.stringify(keyToken))); sinon.stub(keystone,'authenticatePassword').returns(Promise.resolve(JSON.stringify(keyToken)));
sinon.stub(ironic,'get_node_list').returns(Promise.resolve(JSON.stringify(ironic_node_list))) sinon.stub(ironic,'get_node_list').returns(Promise.resolve(JSON.stringify(ironic_node_list)));
}); });
afterEach('teardown mocks', function () { afterEach('teardown mocks', function () {
monorail['request_poller_get'].restore(); monorail['request_poller_get'].restore();
monorail['request_poller_data_get'].restore(); monorail['request_poller_data_get'].restore();
ironic['patch_node'].restore(); ironic['patch_node'].restore();
keystone['authenticate'].restore(); keystone['authenticatePassword'].restore();
ironic['get_node_list'].restore(); ironic['get_node_list'].restore();
}); });
@ -104,8 +56,8 @@ describe('Shovel poller unit testing', function () {
item.should.have.property('event'); item.should.have.property('event');
}); });
done(); done();
}). })
catch (function(err){ .catch (function(err){
throw(err); throw(err);
}); });
}); });
@ -119,8 +71,8 @@ describe('Shovel poller unit testing', function () {
item.should.have.property('value'); item.should.have.property('value');
}); });
done(); done();
}). })
catch(function(err){ .catch(function(err){
throw err; throw err;
}); });
}); });
@ -131,8 +83,8 @@ describe('Shovel poller unit testing', function () {
data.should.have.property('nodeid'); data.should.have.property('nodeid');
data.should.have.property('timer'); data.should.have.property('timer');
done(); done();
}). })
catch(function(err){ .catch(function(err){
throw(err); throw(err);
done(); done();
}); });
@ -146,8 +98,8 @@ describe('Shovel poller unit testing', function () {
item.should.have.property('extra'); item.should.have.property('extra');
}); });
done(); done();
}). })
catch(function(err){ .catch(function(err){
throw(err); throw(err);
}); });
}); });
@ -157,8 +109,8 @@ describe('Shovel poller unit testing', function () {
then(function(token){ then(function(token){
token.should.be.equal('123456'); token.should.be.equal('123456');
done(); done();
}). })
catch(function(err){ .catch(function(err){
throw err; throw err;
}); });