Add support to run an ansible playbook
- Add an API to upload a playbook - Add an API to run an ansible playbook on a rackHD node - fix new eslint errors - Add unit tests Change-Id: Ibe623c228c6ac13cab0f2726e267878bec1bdb6e Implements: blueprint shovel-deployment-capability
This commit is contained in:
parent
9449f7a443
commit
50ec0f2000
@ -589,6 +589,40 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/run/ansible-playbook/{identifier}": {
|
||||
"post": {
|
||||
"x-swagger-router-controller": "Shovel",
|
||||
"tags": [ "Nodes Provisionning" ],
|
||||
"operationId": "runAnsible",
|
||||
"summary": "run the uploaded ansible playbook",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "identifier",
|
||||
"in": "path",
|
||||
"description": "rackHD node ID",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "Config",
|
||||
"in": "body",
|
||||
"description": "OS Configuration",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/run-ansible"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Not Implemented"
|
||||
},
|
||||
"default": {
|
||||
"description": "unexpected error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@ -753,7 +787,7 @@
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example":"Graph.InstallCentOS"
|
||||
"example": "Graph.InstallCentOS"
|
||||
},
|
||||
"options": {
|
||||
"type": "object",
|
||||
@ -823,6 +857,25 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"run-ansible": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "runExample"
|
||||
},
|
||||
"vars": {
|
||||
"type": "object"
|
||||
},
|
||||
"playbookPath": {
|
||||
"type": "string",
|
||||
"example": "files/extract/main.yml"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -278,20 +278,20 @@ module.exports.registerpost = function registerpost(req, res) {
|
||||
userEntry = req.body;
|
||||
if (userEntry.driver === 'pxe_ipmitool') {
|
||||
info = {
|
||||
'ipmi_address': userEntry.ipmihost,
|
||||
'ipmi_username': userEntry.ipmiuser,
|
||||
'ipmi_password': userEntry.ipmipass,
|
||||
'deploy_kernel': userEntry.kernel,
|
||||
'deploy_ramdisk': userEntry.ramdisk
|
||||
ipmi_address: userEntry.ipmihost,
|
||||
ipmi_username: userEntry.ipmiuser,
|
||||
ipmi_password: userEntry.ipmipass,
|
||||
deploy_kernel: userEntry.kernel,
|
||||
deploy_ramdisk: userEntry.ramdisk
|
||||
};
|
||||
} else if (userEntry.driver === 'pxe_ssh') {
|
||||
info = {
|
||||
'ssh_address': userEntry.sshhost,
|
||||
'ssh_username': userEntry.sshuser,
|
||||
'ssh_password': userEntry.sshpass,
|
||||
'ssh_port': userEntry.sshport,
|
||||
'deploy_kernel': userEntry.kernel,
|
||||
'deploy_ramdisk': userEntry.ramdisk
|
||||
ssh_address: userEntry.sshhost,
|
||||
ssh_username: userEntry.sshuser,
|
||||
ssh_password: userEntry.sshpass,
|
||||
ssh_port: userEntry.sshport,
|
||||
deploy_kernel: userEntry.kernel,
|
||||
deploy_ramdisk: userEntry.ramdisk
|
||||
};
|
||||
} else {
|
||||
info = {};
|
||||
@ -299,11 +299,11 @@ module.exports.registerpost = function registerpost(req, res) {
|
||||
|
||||
/* Fill in the extra meta data with some failover and event data */
|
||||
extra = {
|
||||
'nodeid': userEntry.uuid,
|
||||
'name': userEntry.name,
|
||||
'lsevents': { 'time': 0 },
|
||||
'eventcnt': 0,
|
||||
'timer': {}
|
||||
nodeid: userEntry.uuid,
|
||||
name: userEntry.name,
|
||||
lsevents: { time: 0 },
|
||||
eventcnt: 0,
|
||||
timer: {}
|
||||
};
|
||||
if (typeof userEntry.failovernode !== 'undefined') {
|
||||
extra.failover = userEntry.failovernode;
|
||||
@ -315,7 +315,7 @@ module.exports.registerpost = function registerpost(req, res) {
|
||||
localGb = 0.0;
|
||||
return monorail.request_node_get(userEntry.uuid).
|
||||
then(function (result) {
|
||||
if (!JSON.parse(result).name) {
|
||||
if (!JSON.parse(result).hasOwnProperty('name')) {
|
||||
var error = { error_message: { message: 'failed to find required node in RackHD' } };
|
||||
logger.error(error);
|
||||
throw error;
|
||||
@ -349,16 +349,16 @@ module.exports.registerpost = function registerpost(req, res) {
|
||||
throw error;
|
||||
}
|
||||
propreties = {
|
||||
'cpus': dmiData.cpus,
|
||||
'memory_mb': dmiData.memory,
|
||||
'local_gb': localGb
|
||||
cpus: dmiData.cpus,
|
||||
memory_mb: dmiData.memory,
|
||||
local_gb: localGb
|
||||
};
|
||||
node = {
|
||||
'name': userEntry.uuid,
|
||||
'driver': userEntry.driver,
|
||||
'driver_info': info,
|
||||
'properties': propreties,
|
||||
'extra': extra
|
||||
name: userEntry.uuid,
|
||||
driver: userEntry.driver,
|
||||
driver_info: info,
|
||||
properties: propreties,
|
||||
extra: extra
|
||||
};
|
||||
return keystone.authenticatePassword(ironicConfig.os_tenant_name, ironicConfig.os_username,
|
||||
ironicConfig.os_password);
|
||||
@ -373,10 +373,13 @@ module.exports.registerpost = function registerpost(req, res) {
|
||||
throw JSON.parse(ret);
|
||||
}
|
||||
ironicNode = JSON.parse(ret);
|
||||
port = { 'address': userEntry.port, 'node_uuid': ironicNode.uuid };
|
||||
return ironic.createPort(ironicToken, JSON.stringify(port));
|
||||
port = { address: userEntry.port, node_uuid: ironicNode.uuid };
|
||||
return ironic.create_port(ironicToken, JSON.stringify(port));
|
||||
}).
|
||||
then(function (createPort) {
|
||||
if (createPort && JSON.parse(createPort).error_message) {
|
||||
throw JSON.parse(createPort);
|
||||
}
|
||||
logger.info('\r\nCreate port:\r\n' + JSON.stringify(createPort));
|
||||
return ironic.set_power_state(ironicToken, ironicNode.uuid, 'on');
|
||||
}).
|
||||
@ -392,7 +395,7 @@ module.exports.registerpost = function registerpost(req, res) {
|
||||
timer.stop = false;
|
||||
timer.timeInterval = 15000;
|
||||
timer.isDone = true;
|
||||
var data = [{ 'path': '/extra/timer', 'value': timer, 'op': 'replace' }];
|
||||
var data = [{ path: '/extra/timer', value: timer, op: 'replace' }];
|
||||
return ironic.patch_node(ironicToken, ironicNode.uuid, JSON.stringify(data));
|
||||
}).
|
||||
then(function (result) {
|
||||
@ -637,8 +640,8 @@ module.exports.deployOS = function deployOS(req, res) {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
return monorail.runWorkFlow(req.swagger.params.identifier.value,
|
||||
req.body.name,req.body)
|
||||
.then(function(data) {
|
||||
res.end(data);
|
||||
.then(function(result) {
|
||||
res.end(result);
|
||||
})
|
||||
.catch(function(err) {
|
||||
res.end(JSON.stringify(err));
|
||||
@ -654,12 +657,79 @@ module.exports.workflowStatus = function workflowStatus(req,res) {
|
||||
return monorail.getWorkFlowActive(req.swagger.params.identifier.value)
|
||||
.then(function(data) {
|
||||
if (data) {
|
||||
res.end(JSON.stringify({'jobStatus':'Running'}));
|
||||
res.end(JSON.stringify({jobStatus:'Running'}));
|
||||
} else {
|
||||
res.end(JSON.stringify({'jobStatus':'Currently there is no job running on this node'}));
|
||||
res.end(JSON.stringify({jobStatus:'Currently there is no job running on this node'}));
|
||||
}
|
||||
})
|
||||
.catch(function(err) {
|
||||
res.end(JSON.stringify(err));
|
||||
});
|
||||
};
|
||||
/*
|
||||
* @api {put} /api/1.1/uploadFiles/filename / PUT /
|
||||
* @apiDescription uploaded ansible playbook in tar form and extract it
|
||||
*/
|
||||
//Code for tar file uploads
|
||||
// module.exports.uploadFiles = function uploadFiles(req, res) {
|
||||
// 'use strict';
|
||||
// res.setHeader('content-type', 'text/plain');
|
||||
// var tar = require('tar');
|
||||
// var extractor = tar.Extract({path: 'files/extract'})
|
||||
// .on('error', function(err) {
|
||||
// logger.error(err);
|
||||
// res.status(500);
|
||||
// res.end('error');
|
||||
// })
|
||||
// .on('end', function() {
|
||||
// res.status(202);
|
||||
// res.end('success');
|
||||
// });
|
||||
// var stream = require('stream');
|
||||
// var bufferStream = new stream.PassThrough();
|
||||
// bufferStream.end(new Buffer(req.swagger.params.playbook.value.buffer));
|
||||
// bufferStream.pipe(extractor);
|
||||
// };
|
||||
|
||||
/*
|
||||
* @api {post} /api/1.1/runAnsible/{identifier} / POST /
|
||||
* @apiDescription run uploaded ansible playbook in tar form and extract it
|
||||
*/
|
||||
module.exports.runAnsible = function runAnsible(req, res) {
|
||||
'use strict';
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
var ansibleTask = {
|
||||
friendlyName: req.body.name,
|
||||
injectableName: 'Task.Ansible.' + req.body.name,
|
||||
implementsTask: 'Task.Base.Ansible',
|
||||
options: {
|
||||
playbook: req.body.playbookPath,
|
||||
vars : req.body.vars
|
||||
},
|
||||
properties: { }
|
||||
};
|
||||
var ansibleWorkflow = {
|
||||
friendlyName: 'Graph ' + req.body.name,
|
||||
injectableName: 'Graph.Ansible.' + req.body.name,
|
||||
tasks : [
|
||||
{
|
||||
label: 'ansible-job',
|
||||
taskName: 'Task.Ansible.' + req.body.name
|
||||
}
|
||||
]
|
||||
};
|
||||
return monorail.createTask(ansibleTask)
|
||||
.then(function() {
|
||||
return monorail.createWorkflow(ansibleWorkflow);
|
||||
})
|
||||
.then(function() {
|
||||
return monorail.runWorkFlow(req.swagger.params.identifier.value,
|
||||
'Graph.Ansible.' + req.body.name,null);
|
||||
})
|
||||
.then(function(result) {
|
||||
res.end(result);
|
||||
})
|
||||
.catch(function(err) {
|
||||
res.end(JSON.stringify(err));
|
||||
});
|
||||
};
|
||||
|
2
index.js
2
index.js
@ -1,7 +1,7 @@
|
||||
/* global process */
|
||||
'use strict';
|
||||
|
||||
var app = require('connect')();
|
||||
var app = require('express')();
|
||||
var http = require('http');
|
||||
var swaggerTools = require('swagger-tools');
|
||||
var config = require('./config.json');
|
||||
|
@ -50,7 +50,7 @@ var HttpClient = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
Accept: 'application/json',
|
||||
'Content-Length': Buffer.byteLength(msg.data),
|
||||
'User-Agent': 'shovel-client'
|
||||
}
|
||||
@ -140,16 +140,16 @@ var HttpClient = {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
Accept: 'application/json',
|
||||
'Content-Length': Buffer.byteLength(msg.data),
|
||||
'User-Agent': 'shovel-client'
|
||||
}
|
||||
};
|
||||
|
||||
/*Update the request header with special fields*/
|
||||
if (Buffer.byteLength(msg.token)) {
|
||||
options.headers['X-Auth-Token'] = msg.token;
|
||||
}
|
||||
|
||||
if (Buffer.byteLength(JSON.stringify(msg.api))) {
|
||||
options.headers[msg.api.name] = msg.api.version;
|
||||
}
|
||||
@ -159,8 +159,8 @@ var HttpClient = {
|
||||
response.on('data', function (chunk) {
|
||||
body += chunk;
|
||||
});
|
||||
response.on('error', function (err) {
|
||||
var errorMessage = { errorMessage: { hostname: msg.host, message: err } };
|
||||
response.on('error', function (e) {
|
||||
var errorMessage = { errorMessage: { hostname: msg.host, message: e } };
|
||||
output(errorMessage);
|
||||
});
|
||||
response.on('end', function () {
|
||||
@ -174,7 +174,9 @@ var HttpClient = {
|
||||
output(errorMessage);
|
||||
});
|
||||
|
||||
request.write(msg.data);
|
||||
if (Buffer.byteLength(msg.data)) {
|
||||
request.write(msg.data);
|
||||
}
|
||||
request.end();
|
||||
},
|
||||
Patch: function (msg, output) {
|
||||
@ -187,7 +189,7 @@ var HttpClient = {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
Accept: 'application/json',
|
||||
'Content-Length': Buffer.byteLength(msg.data),
|
||||
'User-Agent': 'shovel-client'
|
||||
}
|
||||
|
@ -149,7 +149,9 @@ var MonorailWrapper = {
|
||||
runWorkFlow: function runWorkFlow(hwaddr,graphName,content) {
|
||||
'use strict';
|
||||
request.path = pfx + '/nodes/' + hwaddr + '/workflows/?name=' + graphName;
|
||||
request.data = JSON.stringify(content);
|
||||
if (content !== null) {
|
||||
request.data = JSON.stringify(content);
|
||||
}
|
||||
return client.PostAsync(request);
|
||||
},
|
||||
getWorkFlowActive: function getWorkFlowActive(hwaddr) {
|
||||
@ -161,6 +163,18 @@ var MonorailWrapper = {
|
||||
'use strict';
|
||||
request.path = pfx + '/nodes/' + hwaddr + '/workflows/active';
|
||||
return client.DeleteAsync(request);
|
||||
},
|
||||
createTask: function createTask(content) {
|
||||
'use strict';
|
||||
request.path = pfx + '/workflows/tasks/';
|
||||
request.data = JSON.stringify(content);
|
||||
return client.PutAsync(request);
|
||||
},
|
||||
createWorkflow: function createWorkflow(content) {
|
||||
'use strict';
|
||||
request.path = pfx + '/workflows';
|
||||
request.data = JSON.stringify(content);
|
||||
return client.PutAsync(request);
|
||||
}
|
||||
};
|
||||
module.exports = Object.create(MonorailWrapper);
|
||||
|
@ -13,8 +13,8 @@ var request = {
|
||||
token: '',
|
||||
data: '',
|
||||
api: {
|
||||
'name': 'X-OpenStack-Ironic-API-Version',
|
||||
'version': '1.6'
|
||||
name: 'X-OpenStack-Ironic-API-Version',
|
||||
version: '1.6'
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -33,11 +33,11 @@ var KeystoneAuthentication = {
|
||||
}
|
||||
request.data = JSON.stringify(
|
||||
{
|
||||
'auth': {
|
||||
'tenantName': tenantName,
|
||||
'passwordCredentials': {
|
||||
'username': username,
|
||||
'password': decrypted
|
||||
auth: {
|
||||
tenantName: tenantName,
|
||||
passwordCredentials: {
|
||||
username: username,
|
||||
password: decrypted
|
||||
|
||||
}
|
||||
}
|
||||
@ -49,10 +49,10 @@ var KeystoneAuthentication = {
|
||||
'use strict';
|
||||
request.data = JSON.stringify(
|
||||
{
|
||||
'auth': {
|
||||
'tenantName': tenantName,
|
||||
'token': {
|
||||
'id': token
|
||||
auth: {
|
||||
tenantName: tenantName,
|
||||
token: {
|
||||
id: token
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -135,9 +135,9 @@ function Poller(timeInterval) {
|
||||
nodeData.extra.events = lastEvent;
|
||||
var data = [
|
||||
{
|
||||
'path': '/extra',
|
||||
'value': nodeData.extra,
|
||||
'op': 'replace'
|
||||
path: '/extra',
|
||||
value: nodeData.extra,
|
||||
op: 'replace'
|
||||
}];
|
||||
return data;
|
||||
})
|
||||
|
@ -9,7 +9,6 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"bluebird": "3.1.1",
|
||||
"connect": "^3.2.0",
|
||||
"swagger-tools": "0.8.*",
|
||||
"should": "~7.0.1",
|
||||
"mocha": "^2.1.0",
|
||||
@ -23,7 +22,9 @@
|
||||
"istanbul": "0.4.1",
|
||||
"nock": "3.6.0",
|
||||
"eslint-config-openstack": "~1.2.3",
|
||||
"eslint": "~1.10.3"
|
||||
"eslint": "~1.10.3",
|
||||
"express": "~4.13.4",
|
||||
"tar": "~2.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "start shovel",
|
||||
|
@ -185,5 +185,19 @@ describe('****Monorail Lib****',function(){
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('monorail.createWorkflow return data from monorail', function (done) {
|
||||
return monorail.createWorkflow({})
|
||||
.then(function (result) {
|
||||
result.should.have.property('data');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('monorail.createTask return data from monorail', function (done) {
|
||||
return monorail.createTask({})
|
||||
.then(function (result) {
|
||||
result.should.have.property('data');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -56,6 +56,8 @@ describe('****SHOVEL API Interface****', function () {
|
||||
sinon.stub(monorail, 'get_catalog_data_by_source').returns(Promise.resolve(JSON.stringify(catalogSource[0])));
|
||||
sinon.stub(monorail, 'runWorkFlow').returns(Promise.resolve('{"definition":{}}'));
|
||||
getWorkflow = sinon.stub(monorail,'getWorkFlowActive');
|
||||
sinon.stub(monorail, 'createTask').returns(Promise.resolve());
|
||||
sinon.stub(monorail, 'createWorkflow').returns(Promise.resolve());
|
||||
//glance
|
||||
sinon.stub(glance, 'get_images').returns(Promise.resolve(JSON.stringify(glanceImages)));
|
||||
//keystone
|
||||
@ -83,6 +85,8 @@ describe('****SHOVEL API Interface****', function () {
|
||||
monorail['get_catalog_data_by_source'].restore();
|
||||
monorail['runWorkFlow'].restore();
|
||||
monorail['getWorkFlowActive'].restore();
|
||||
monorail['createTask'].restore();
|
||||
monorail['createWorkflow'].restore();
|
||||
//ironic
|
||||
ironic['patch_node'].restore();
|
||||
ironic['get_node_list'].restore();
|
||||
@ -334,10 +338,8 @@ describe('****SHOVEL API Interface****', function () {
|
||||
.send({"name": "Graph.InstallCentOS","options": { "defaults": {"obmServiceName": "ipmi-obm-service"}}})
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
console.log('hey yo');
|
||||
throw err;
|
||||
}
|
||||
console.log('hello' + res.text)
|
||||
JSON.parse(res.text).should.have.property('definition');
|
||||
done();
|
||||
});
|
||||
@ -350,11 +352,22 @@ describe('****SHOVEL API Interface****', function () {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
console.log(res.text);
|
||||
JSON.parse(res.text).should.have.property('jobStatus');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('/api/1.1/run/ansible-playbook/{id} should return property definition', function (done) {
|
||||
request(url)
|
||||
.post('/api/1.1/run/ansible-playbook/123')
|
||||
.send({"name": "Graph.Example","options": {}})
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
JSON.parse(res.text).should.have.property('definition');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('/api/1.1/worflow-status/{identifier} should return property jobStatus even if no job is running', function (done) {
|
||||
getWorkflow.returns(Promise.resolve());
|
||||
request(url)
|
||||
@ -379,10 +392,12 @@ describe('****SHOVEL API Interface****', function () {
|
||||
var output = ({ error: 'error_message' });
|
||||
sinon.stub(client, 'GetAsync').returns(Promise.reject(output));
|
||||
sinon.stub(client, 'PostAsync').returns(Promise.reject(output));
|
||||
sinon.stub(client, 'PutAsync').returns(Promise.reject(output));
|
||||
});
|
||||
after('teardown mocks', function () {
|
||||
client['GetAsync'].restore();
|
||||
client['PostAsync'].restore();
|
||||
client['PutAsync'].restore();
|
||||
});
|
||||
|
||||
it('/api/1.1/nodes/identifier should return error message', function (done) {
|
||||
@ -558,34 +573,92 @@ describe('****SHOVEL API Interface****', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('api/1.1/run/ansible-playbook/{id} should return error message', function (done) {
|
||||
request(url)
|
||||
.post('/api/1.1/run/ansible-playbook/123')
|
||||
.send({name: 'runExample',vars: {},
|
||||
playbookPath: 'main.yml'
|
||||
})
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
JSON.parse(res.text).should.have.property('error');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Shovel api unit test for register', function () {
|
||||
var error_message = '{"error_message": "{\\"debuginfo\\": null, \\"faultcode\\": \\"Client\\", \\"faultstring\\": \\"A node with name 5668b42d8bee16a10989e4e4 already exists.\\"}"}';
|
||||
var error_message = '{"error_message": "{\\"debuginfo\\": null, \\"faultcode\\": \\"Client\\", \\"faultstring\\": \\"some error\\"}"}';
|
||||
var body = { "id": identifier, "driver": "string", "ipmihost": "string", "ipmiusername": "string", "ipmipasswd": "string" };
|
||||
|
||||
var getNode, diskSize, memoryCpu, ironicNodeCreate,
|
||||
ironicCreatePort, ironicPowerState, ironicPatch;
|
||||
beforeEach('set up mocks', function () {
|
||||
//monorail
|
||||
getNode = sinon.stub(monorail, 'request_node_get');
|
||||
diskSize = sinon.stub(monorail, 'nodeDiskSize');
|
||||
memoryCpu = sinon.stub(monorail, 'getNodeMemoryCpu');
|
||||
monorailWhiteList = sinon.stub(monorail,'request_whitelist_set');
|
||||
//keystone
|
||||
sinon.stub(keystone, 'authenticatePassword').returns(Promise.resolve(JSON.stringify(keyToken)));
|
||||
//ironic
|
||||
sinon.stub(ironic, 'create_node').returns(Promise.resolve(error_message));
|
||||
ironicNodeCreate = sinon.stub(ironic, 'create_node');
|
||||
ironicCreatePort = sinon.stub(ironic,'create_port');
|
||||
ironicPowerState = sinon.stub(ironic,'set_power_state');
|
||||
ironicPatch = sinon.stub(ironic, 'patch_node');
|
||||
});
|
||||
afterEach('teardown mocks', function () {
|
||||
//monorail
|
||||
monorail['nodeDiskSize'].restore();
|
||||
monorail['getNodeMemoryCpu'].restore();
|
||||
monorail['request_node_get'].restore();
|
||||
monorail['request_whitelist_set'].restore();
|
||||
//keystone
|
||||
keystone['authenticatePassword'].restore();
|
||||
//ironic
|
||||
ironic['create_node'].restore();
|
||||
|
||||
ironic['create_port'].restore();
|
||||
ironic['set_power_state'].restore();
|
||||
ironic['patch_node'].restore();
|
||||
});
|
||||
it('response in register should have property error_message when node returns empty ', function (done) {
|
||||
getNode.returns(Promise.resolve('{}'));
|
||||
request(url)
|
||||
.post('/api/1.1/register')
|
||||
.send(body)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
JSON.parse(res.text).should.have.property('error_message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('response in register should have property error_message when diskSize has an exception ', function (done) {
|
||||
var output = {error_message: { message: 'failed to get compute node Disk Size' }};
|
||||
getNode.returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
|
||||
diskSize.returns(Promise.reject(output));
|
||||
request(url)
|
||||
.post('/api/1.1/register')
|
||||
.send(body)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
JSON.parse(res.text).should.have.property('error_message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
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, 'getNodeMemoryCpu').returns(Promise.resolve({ cpus: 0, memory: 0 }));
|
||||
getNode.returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
|
||||
diskSize.returns(Promise.resolve(0));
|
||||
memoryCpu.returns(Promise.resolve({ cpus: 0, memory: 0 }));
|
||||
|
||||
request(url)
|
||||
.post('/api/1.1/register')
|
||||
@ -601,10 +674,10 @@ describe('****SHOVEL API Interface****', function () {
|
||||
});
|
||||
});
|
||||
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, 'getNodeMemoryCpu').returns(Promise.resolve({ cpus: 1, memory: 1 }));
|
||||
|
||||
getNode.returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
|
||||
diskSize.returns(Promise.resolve(1));
|
||||
memoryCpu.returns(Promise.resolve({ cpus: 1, memory: 1 }));
|
||||
ironicNodeCreate.returns(Promise.resolve(error_message));
|
||||
request(url)
|
||||
.post('/api/1.1/register')
|
||||
.send(body)
|
||||
@ -618,5 +691,86 @@ describe('****SHOVEL API Interface****', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('response in register should have property error_message create port return error in ironic', function (done) {
|
||||
getNode.returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
|
||||
diskSize.returns(Promise.resolve(1));
|
||||
memoryCpu.returns(Promise.resolve({ cpus: 1, memory: 1 }));
|
||||
ironicNodeCreate.returns(Promise.resolve(JSON.stringify(ironic_node_list[0])));
|
||||
ironicCreatePort.returns(Promise.resolve(error_message));
|
||||
request(url)
|
||||
.post('/api/1.1/register')
|
||||
.send(body)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
JSON.parse(res.text).should.have.property('error_message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('response in register should have property error_message set power state return error in ironic', function (done) {
|
||||
getNode.returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
|
||||
diskSize.returns(Promise.resolve(1));
|
||||
memoryCpu.returns(Promise.resolve({ cpus: 1, memory: 1 }));
|
||||
ironicNodeCreate.returns(Promise.resolve(JSON.stringify(ironic_node_list[0])));
|
||||
ironicCreatePort.returns(Promise.resolve());
|
||||
ironicPowerState.returns(Promise.resolve(error_message));
|
||||
request(url)
|
||||
.post('/api/1.1/register')
|
||||
.send(body)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
JSON.parse(res.text).should.have.property('error_message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('response in register should have property error_message ironic patch node return error in ironic', function (done) {
|
||||
getNode.returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
|
||||
diskSize.returns(Promise.resolve(1));
|
||||
memoryCpu.returns(Promise.resolve({ cpus: 1, memory: 1 }));
|
||||
ironicNodeCreate.returns(Promise.resolve(JSON.stringify(ironic_node_list[0])));
|
||||
ironicCreatePort.returns(Promise.resolve());
|
||||
ironicPowerState.returns(Promise.resolve());
|
||||
ironicPatch.returns(Promise.reject({error_message:'some error'}));
|
||||
request(url)
|
||||
.post('/api/1.1/register')
|
||||
.send(body)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
JSON.parse(res.text).should.have.property('error_message');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('response in register should have property result on success', function (done) {
|
||||
getNode.returns(Promise.resolve(JSON.stringify(rackhdNode[0])));
|
||||
diskSize.returns(Promise.resolve(1));
|
||||
memoryCpu.returns(Promise.resolve({ cpus: 1, memory: 1 }));
|
||||
ironicNodeCreate.returns(Promise.resolve(JSON.stringify(ironic_node_list[0])));
|
||||
ironicCreatePort.returns(Promise.resolve());
|
||||
ironicPowerState.returns(Promise.resolve());
|
||||
ironicPatch.returns(Promise.resolve());
|
||||
request(url)
|
||||
.post('/api/1.1/register')
|
||||
.send(body)
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
JSON.parse(res.text).should.have.property('result');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright 2015, EMC, Inc.
|
||||
|
||||
var app = require('connect')();
|
||||
var app = require('express')();
|
||||
var http = require('http');
|
||||
var swaggerTools = require('swagger-tools');
|
||||
var sinon = require('sinon');
|
||||
|
Loading…
Reference in New Issue
Block a user