Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Cisco UCS Service Profile Discovery #420

Merged
merged 3 commits into from
Mar 13, 2017

Conversation

uppalk1
Copy link
Contributor

@uppalk1 uppalk1 commented Mar 7, 2017

*Create base-task, task and job for a new workflow to
     discover UCS Service Profile

ucsTool,
rackmountData,
rootData,
serverData,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'serverData' is defined but never used.

graphId = uuid.v4(),
ucsJob,
ucsTool,
rackmountData,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'rackmountData' is defined but never used.

throw error;
})
.then(function(data){
return [data, waterline.obms.upsertByNode(data.id,obm)]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.

})
.then(function(data) {
assert.object(data);
return data['ServiceProfile']['members']

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

['ServiceProfile'] is better written in dot notation.
['members'] is better written in dot notation.
Missing semicolon.

urlParse = require('url-parse');

module.exports = UcsServiceProfileDiscoveryJobFactory;
di.annotate(UcsServiceProfileDiscoveryJobFactory, new di.Provide('Job.Ucs.Service.Profile.Discovery'));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line is too long.


return self.getRoot()
.then(function(root) {
return [ root, self.createServiceProfile(root) ];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since root is not used in following spread , so it better to be removed from the array.

protocol: protocol,
username: this.options.username,
password: this.options.password,
ucs: this.options.ucs,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please teach me what's the difference between the setting of ucs and host? Because I see you use the ucs as the host in the query but rather than host

var host = this.settings.ucs;
var url= "/login?host=" + host+ "&user="+ username + "&password=" + password;

My understanding is:

  • host is the ucs-service address, RackHD use the ucs-service to talk with UCS servers.
  • ucs is the target UCS server, the ucs-service proxies the request to UCS server.

Is correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yyscamper that is correct.

properties: {
catalog: {}
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the schema for the new base task.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yyscamper can you point me to one that I could use as a reference ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty simple, just put a JSON schema in the property optionsSchema, this is very alike with the JSON schema in swagger ui.

This is an example: https://github.com/RackHD/on-tasks/blob/master/lib/task-data/base-tasks/provide-catalog-data.js

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yyscamper We will revisit the schema soon for all ucs-service tasks. For now this may not be held as a gate for PR merge.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@uppalk1 : I am OK with your plan.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yyscamper if ok with the plan, can you please help remove the -1 that currently blocks the PR from being merged?

return data['ServiceProfile']['members']
})
.map(function(members){
self.createNode(members, Constants.NodeTypes.Compute);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This promise has to be returned, otherwise this function will return earlier before all nodes are really created.

var node = {
type: type,
name: data.name,
associatedServer: data.associatedServer,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this property? I don't see it is defined in node model (https://github.com/RackHD/on-core/blob/master/lib/models/node.js). If it is not necessary, them remove it; if you think this is necessary, please explain the reason and then we can check whether it is suitable to create a new property.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yyscamper I created a new relation called "associatedTo" instead of creating a new property

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good.

assert.string(data.name);
assert.string(data.path);
var id;
id = [config.ucs, data.path];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the plural of id or change to other better name.

Because when I see the code identifer: id in line 174, I thought the identifer need be array, but you wrongly gave it a single id. So I look back to check the node, and see the id is really an array.

My point is choosing a good variable name and don't bring surprise to other people who read the code.

.then(function(curNode) {
return waterline.nodes.updateOne(
{ id: curNode.id },
node
Copy link
Contributor

@yyscamper yyscamper Mar 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In line 175, the relations is reset to be empty, since this line of code is to update the node document, so whether it is intentionally to reset the relations? And how the relations are built again?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yyscamper Yes, the relation will be rebuilt with the discovery.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, thanks for explanation, could you please add some comment here

});
};

UcsServiceProfileDiscoveryJob.prototype.createNode = function(data, type) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name is not accurate, the code is to "update or create" node, not just "create" node.

@@ -0,0 +1,17 @@
// Copyright 2016, EMC, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect copyright date

injectableName: 'Task.Base.UCS.Service.Profile.Discovery',
runJob: 'Job.Ucs.Service.Profile.Discovery',
requiredOptions: [
'uri'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From your implementation, the username, password, ucs are also required options.

assert.string(this.options.uri);
assert.string(this.options.username);
assert.string(this.options.password);
assert.string(this.options.ucs);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yyscamper this will be refactored as part of https://rackhd.atlassian.net/browse/RAC-4389

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sound good.

requiredProperties: {
},
properties: {
catalog: {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this property used for? I don't see any reason to define such property and I don't see any code is to create the catalog.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yyscamper This is a place holder for follow on stories to create a catalog for UCS logical server (if we deem its necessary)

@@ -0,0 +1,17 @@
// Copyright 2016, EMC, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect copyright date

ucs: this.options.ucs,
verifySSL: this.options.verifySSL || false
};
this.ucs = new UcsTool();
Copy link
Contributor

@yyscamper yyscamper Mar 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.ucs and this.settings.ucs is a little confused here, please rename to another distinguish one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yyscamper I don't understand your confusion. I'm creating an instance and assigning settings to it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the same variable name ucs, but when it is in this.settings it means an IP address, however it is a UCS tool instance if it is in this

username:'user',
password:'pass',
ucs:"1.1.1.1"
}, {}, graphId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is taskId, not graphId, though this doesn't break the unit-test, but don't bring confusion since unit-test is a kind of doc for the code.

ucs:"1.1.1.1"
}, {}, graphId);

sandbox.stub(ucsJob.ucs);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct usage is sandbox.stub(ucsJob, 'ucs')

});

afterEach(function() {
sandbox.restore();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All stubs are created once in before, but all are restored after the first test case finishes. So when the 2nd test case begins to run, actually all stubs are not existing, so what's the purpose to create so many stubs in advance?

Meanwhile, I see a lot stubs are never been used, if so, just remove them.

return ucsJob.logIn()
.then(function(data) {
expect(data).to.deep.equal("cookie");
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, line 140-143 can be short for:

return ucsJob.logIn().to.become('cookie');

Your code is still OK, just for your awareness if you like it.

relations : []
};
// Update existing node or create a new one
return waterline.nodes.needOne({identifiers:data.path})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking of a corner case, since the identifiers is [config.ucs, data.path], here you only find node document by data.path, but how about if the ucs server address is actually changed for the target node, then it means this node's obm service need be updated as well.

});
});
});
});
Copy link
Contributor

@yyscamper yyscamper Mar 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the test coverage is good enough (this should be one of the reason why the coverage decrease a lot), I see a lot logic is actually not tested, for example:
(1) If ucs request error, then the job should fail.
(2) If input any invalid option, the job should fail.
(3) If ucs request returns multiple servers, then multiple nodes should be updated or created.
(4) The obm service should be created (or updated) when the node is created (or updated)

Copy link
Contributor

@yyscamper yyscamper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix my comment and improve the test coverage.

var obm = {
config: {
uri: "http://10.240.19.220:7080/sys",
host: "10.240.19.220",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use a faked IP

}
],
"type": "compute"
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.

"associatedServer": "test",
"name": "ls-test",
"path": "org-root/ls-test"
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.

"associatedServer": "test",
"name": "ls-test",
"path": "org-root/ls-test"
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.

relationType: 'associatedTo',
targets: [newNode.associatedServer]
}];
return self.updateRelations(newNode.id, relations)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.

})
.then(function(data) {
assert.object(data);
return data['ServiceProfile']['members'];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

['ServiceProfile'] is better written in dot notation.
['members'] is better written in dot notation.

"associatedServer": "test",
"name": "ls-test",
"path": "org-root/ls-test"
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.

@JenkinsRHD
Copy link
Contributor

BUILD on-tasks #2136 : ABORTED

BUILD unit-tests #12504 Error Logs ▼Test Name: ucs-service-profile-discovery-spec.js task-data expected properties should have valid default option values Error Details: Task.Ucs.Service.Profile.Discovery: JSON schema validation failed - data.uri should be string Stack Trace: Error: Task.Ucs.Service.Profile.Discovery: JSON schema validation failed - data.uri should be string at TaskOptionValidator.JsonSchemaValidator.validatePatternsSkipped (node_modules/on-core/lib/common/json-schema-validator.js:95:23) at TaskOptionValidator.validateContextSkipped (lib/utils/task-option-validator.js:9:2054) at lib/task.js:9:29334 at arrayEach (node_modules/lodash/index.js:1289:13) at Function.<anonymous> (node_modules/lodash/index.js:3345:13) at Function.Task.validateOptions (lib/task.js:9:28969) at lib/task.js:9:20104 at tryCatcher (node_modules/on-core/node_modules/bluebird/js/main/util.js:26:23) at Promise._settlePromiseFromHandler (node_modules/on-core/node_modules/bluebird/js/main/promise.js:510:31) at Promise._settlePromiseAt (node_modules/on-core/node_modules/bluebird/js/main/promise.js:584:18) at Promise._settlePromises (node_modules/on-core/node_modules/bluebird/js/main/promise.js:700:14) at Async._drainQueue (node_modules/on-core/node_modules/bluebird/js/main/async.js:123:16) at Async._drainQueues (node_modules/on-core/node_modules/bluebird/js/main/async.js:133:10) at Immediate.Async.drainQueues [as _onImmediate] (node_modules/on-core/node_modules/bluebird/js/main/async.js:15:14)

@JenkinsRHD
Copy link
Contributor

BUILD on-tasks #2137 : ABORTED

	*Create base-task, task and job for a new workflow to
         discover UCS Service Profile

Clean up ucs-service-profile-discovery test

Address PR comments and improve unit test coverage

Schema reference as a future enhancement
"associatedServer": "test",
"name": "ls-test",
"path": "org-root/ls-test"
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing semicolon.

@JenkinsRHD
Copy link
Contributor

BUILD on-tasks #2138 : ABORTED

@geoff-reid
Copy link
Contributor

It look like the coveralls decreased coverage is due to a change in the way node-coveralls calculates the coverage percentage. See nickmerwin/node-coveralls#158

The actual coverage as reported by istanbul has increased.

from master: https://travis-ci.org/RackHD/on-tasks/jobs/206278092

=============================== Coverage summary ===============================
Statements   : 89.1% ( 6352/7129 )
Branches     : 73.79% ( 1681/2278 )
Functions    : 86.14% ( 1578/1832 )
Lines        : 89.15% ( 6343/7115 )
================================================================================

from this PR: https://travis-ci.org/RackHD/on-tasks/jobs/209488312

=============================== Coverage summary ===============================
Statements   : 89.19% ( 6422/7200 )
Branches     : 73.82% ( 1686/2284 )
Functions    : 86.29% ( 1598/1852 )
Lines        : 89.24% ( 6413/7186 )
================================================================================

@geoff-reid
Copy link
Contributor

test this please

Copy link
Contributor

@geoff-reid geoff-reid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, 👍

verifySSL: this.options.verifySSL || false
};
this.ucs = new UcsTool();
this.ucs.settings = this.settings;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's even more confusing between this.settings.ucs and this.ucs.settings

ucsTool.clientRequest.onCall(1).resolves(rootData);
return ucsJob._run()
.then(function() {
expect(waterline.nodes.updateOne).to.be.called.twice;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no called.twice or called.once, you should use calledTwice and calledOnce.

The twice or once actually has no assertion effect, actually you could append any arbitrary words after called. For example:
expect(xxxx).to.be.called.notexisting or expect(xxx).to.be.called.foobar will always make the mocha happy. so the mocha success doesn't reflect such error.

Copy link
Contributor

@yyscamper yyscamper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 after at least fix the called.once and called.twice

@geoff-reid geoff-reid merged commit 0ebf95a into RackHD:master Mar 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants