diff --git a/lib/jobs/general-redfish-catalog.js b/lib/jobs/general-redfish-catalog.js index 6ad75f37..220a8723 100644 --- a/lib/jobs/general-redfish-catalog.js +++ b/lib/jobs/general-redfish-catalog.js @@ -235,7 +235,6 @@ function GeneralRedfishCatalogJobFactory( }) .catch(function (err) { logger.info(JSON.stringify(err, null,4)); - self._done(err); }); }; diff --git a/lib/jobs/redfish-update-lookups.js b/lib/jobs/redfish-update-lookups.js new file mode 100644 index 00000000..e22b6057 --- /dev/null +++ b/lib/jobs/redfish-update-lookups.js @@ -0,0 +1,87 @@ +// Copyright © 2018 Dell Inc. or its subsidiaries. All Rights Reserved. + +'use strict'; + +module.exports = RedfishUpdateLookupsJobFactory; + +var di = require('di'); +di.annotate(RedfishUpdateLookupsJobFactory, new di.Provide('Job.Redfish.Update.Lookups')); +di.annotate(RedfishUpdateLookupsJobFactory, new di.Inject( + 'Job.Base', + 'Assert', + 'Logger', + 'Util', + 'Promise', + 'Services.Waterline', + '_' +)); + +function RedfishUpdateLookupsJobFactory( + BaseJob, + assert, + Logger, + util, + Promise, + waterline, + _ +) { + var logger = Logger.initialize(RedfishUpdateLookupsJobFactory); + + function RedfishUpdateLookupsJob(options, context, taskId) { + RedfishUpdateLookupsJob.super_.call(this, logger, options, context, taskId); + this.chassis = this.context.chassis || []; + this.systems = this.context.systems || []; + this.cooling = this.context.cooling || []; + this.power = this.context.power || []; + this.networks = this.context.networks || []; + this.allEndpoints = _.union( + this.systems, + this.power, + this.cooling, + this.networks, + this.chassis + ); + } + + util.inherits(RedfishUpdateLookupsJob, BaseJob); + + RedfishUpdateLookupsJob.prototype._run = function() { + var self = this; + return Promise.resolve(self.allEndpoints) + .map(self.updateLookups.bind(self), {concurrency: 128}) + .then(function() { + return self._done(); + }) + .catch(function(err) { + return self._done(err); + }); + }; + + RedfishUpdateLookupsJob.prototype.updateLookups = function(nodeId) { + var ethernetInterfacesSource = '/redfish/v1/Systems/' + nodeId + '/EthernetInterfaces'; + return waterline.catalogs.findLatestCatalogOfSource(nodeId, ethernetInterfacesSource) + .then(function(ethernetInterfacesCatalog){ + if(!_.has(ethernetInterfacesCatalog, 'data.Members')) { + throw new Error('Could not find Members in EthernetInterfaces catalog!'); + } + return _.map(ethernetInterfacesCatalog.data.Members, function(member){ + return _.last(_.get(member, "@odata_id").split('/')); + }); + }) + .map(function(nicId){ + var nicSource = ethernetInterfacesSource + '/' + nicId; + return waterline.catalogs.findLatestCatalogOfSource(nodeId, nicSource) + .then(function(nicCatalog) { + if(!nicCatalog || !nicCatalog.data || !nicCatalog.data.MacAddress) { + throw new Error('Could not find MacAddress in NIC catalog!'); + } + return waterline.lookups.upsertNodeToMacAddress( + nodeId, + nicCatalog.data.MacAddress + ); + }); + }); + }; + + return RedfishUpdateLookupsJob; +} diff --git a/lib/task-data/base-tasks/redfish-update-lookups.js b/lib/task-data/base-tasks/redfish-update-lookups.js new file mode 100644 index 00000000..45b5e47a --- /dev/null +++ b/lib/task-data/base-tasks/redfish-update-lookups.js @@ -0,0 +1,12 @@ +// Copyright © 2018 Dell Inc. or its subsidiaries. All Rights Reserved. + +'use strict'; + +module.exports = { + friendlyName: 'Redfish Update Lookups', + injectableName: 'Task.Base.Redfish.Update.Lookups', + runJob: 'Job.Redfish.Update.Lookups', + requiredOptions: [], + requiredProperties: {}, + properties: {} +}; diff --git a/lib/task-data/tasks/redfish-update-lookups.js b/lib/task-data/tasks/redfish-update-lookups.js new file mode 100644 index 00000000..30f2bf77 --- /dev/null +++ b/lib/task-data/tasks/redfish-update-lookups.js @@ -0,0 +1,11 @@ +// Copyright © 2018 Dell Inc. or its subsidiaries. All Rights Reserved. + +'use strict'; + +module.exports = { + friendlyName: 'Redfish Update Lookups', + injectableName: 'Task.Redfish.Update.Lookups', + implementsTask: 'Task.Base.Redfish.Update.Lookups', + options: {}, + properties: {} +}; diff --git a/spec/lib/jobs/redfish-update-lookups-spec.js b/spec/lib/jobs/redfish-update-lookups-spec.js new file mode 100644 index 00000000..7f8fcb76 --- /dev/null +++ b/spec/lib/jobs/redfish-update-lookups-spec.js @@ -0,0 +1,142 @@ +// Copyright © 2018 Dell Inc. or its subsidiaries. All Rights Reserved. + +'use strict'; +var uuid = require('node-uuid'); + +describe('redfish-update-lookups-job', function() { + var waterline = { catalogs: {}, lookups: {} }, + RedfishUpdateLookupsJob, + job; + + var ethernetInterfacesCatalog = { + "id": "abf88cc8-ea5c-4db8-961c-5faf39bec1b9", + "node": "/api/2.0/nodes/5afbe4080ff1d4bb0e2c0232", + "createdAt": "2018-05-16T07:56:23.785Z", + "updatedAt": "2018-05-16T07:56:23.785Z", + "source": "/redfish/v1/Systems/5afbe4080ff1d4bb0e2c0232/EthernetInterfaces", + "data": { + "@odata_context": "/redfish/v1/$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection", + "@odata_id": "/redfish/v1/Systems/18D2182-CN7475158B0188/EthernetInterfaces", + "@odata_type": "#EthernetInterfaceCollection.EthernetInterfaceCollection", + "Description": "Collection of Ethernet Interfaces for this System", + "Members": [ + { + "@odata_id": "/redfish/v1/Systems/18D2182-CN7475158B0188/EthernetInterfaces/NIC.Embedded.1-1-1" + } + ], + "Members@odata_count": 1, + "Name": "System Ethernet Interface Collection" + } + }; + var nicCatalog = { + "id": "7fab2fdb-0e7a-4348-b600-15ce532c7ced", + "node": "/api/2.0/nodes/5afbe4080ff1d4bb0e2c0232", + "createdAt": "2018-05-16T07:56:27.744Z", + "updatedAt": "2018-05-16T07:56:27.744Z", + "source": "/redfish/v1/Systems/5afbe4080ff1d4bb0e2c0232/EthernetInterfaces/NIC.Embedded.1-1-1", + "data": { + "@odata_context": "/redfish/v1/$metadata#EthernetInterface.EthernetInterface", + "@odata_id": "/redfish/v1/Systems/18D2182-CN7475158B0188/EthernetInterfaces/NIC.Embedded.1-1-1", + "@odata_type": "#EthernetInterface.v1_0_2.EthernetInterface", + "AutoNeg": false, + "Description": "Embedded NIC 1 Port 1 Partition 1", + "FQDN": null, + "FullDuplex": true, + "HostName": null, + "IPV6DefaultGateway": null, + "IPv4Addresses": [], + "IPv4Addresses@odata_count": 0, + "IPv6AddressPolicyTable": [], + "IPv6AddressPolicyTable@odata_count": 0, + "IPv6Addresses": [], + "IPv6Addresses@odata_count": 0, + "IPv6StaticAddresses": [], + "IPv6StaticAddresses@odata_count": 0, + "Id": "NIC.Embedded.1-1-1", + "InterfaceEnabled": null, + "MTUSize": null, + "MacAddress": "00:8C:FA:F3:78:18", + "MaxIPv6StaticAddresses": null, + "Name": "System Ethernet Interface", + "NameServers": [], + "NameServers@odata_count": 0, + "PermanentMACAddress": "00:8C:FA:F3:78:18", + "SpeedMbps": 10240, + "Status": { + "Health": "Ok", + "State": "Enabled" + }, + "UefiDevicePath": "PciRoot(0x1)/Pci(0x1,0x0)/Pci(0x0,0x0)", + "VLAN": null + } + }; + + before(function() { + helper.setupInjector([ + helper.require('/lib/jobs/base-job.js'), + helper.require('/lib/jobs/redfish-update-lookups.js'), + helper.di.simpleWrapper(waterline, 'Services.Waterline') + ]); + this.sandbox = sinon.sandbox.create(); + RedfishUpdateLookupsJob = helper.injector.get('Job.Redfish.Update.Lookups'); + }); + + beforeEach(function() { + waterline.catalogs.findLatestCatalogOfSource = this.sandbox.stub(); + waterline.lookups.upsertNodeToMacAddress = this.sandbox.stub(); + job = new RedfishUpdateLookupsJob({}, { systems: ['someNodeId']}, uuid.v4()); + }); + + afterEach(function() { + this.sandbox.restore(); + }); + + it('should update lookups from catalog', function() { + waterline.catalogs.findLatestCatalogOfSource.withArgs( + 'someNodeId', + '/redfish/v1/Systems/someNodeId/EthernetInterfaces' + ).resolves(ethernetInterfacesCatalog); + waterline.catalogs.findLatestCatalogOfSource.withArgs( + 'someNodeId', + '/redfish/v1/Systems/someNodeId/EthernetInterfaces/NIC.Embedded.1-1-1' + ).resolves(nicCatalog); + return job._run() + .then(function() { + expect(waterline.lookups.upsertNodeToMacAddress).to.be.calledOnce; + expect(waterline.lookups.upsertNodeToMacAddress).to.be + .calledWith('someNodeId', '00:8C:FA:F3:78:18'); + }); + }); + + it('should fail if lookups insertion fails', function() { + var error = new Error('some Waterline error'); + waterline.lookups.upsertNodeToMacAddress.rejects(error); + waterline.catalogs.findLatestCatalogOfSource.withArgs( + 'someNodeId', + '/redfish/v1/Systems/someNodeId/EthernetInterfaces' + ).resolves(ethernetInterfacesCatalog); + waterline.catalogs.findLatestCatalogOfSource.withArgs( + 'someNodeId', + '/redfish/v1/Systems/someNodeId/EthernetInterfaces/NIC.Embedded.1-1-1' + ).resolves(nicCatalog); + return expect(job._run()).to.be.rejectedWith('some Waterline error'); + }); + + it('should fail if EthernetInterfaces data is unavailable in catalog', function() { + waterline.catalogs.findLatestCatalogOfSource.resolves(undefined); + return expect(job._run()) + .to.be.rejectedWith('Could not find Members in EthernetInterfaces catalog!'); + }); + + it('should fail if NIC data is unavailable in catalog', function() { + waterline.catalogs.findLatestCatalogOfSource.withArgs( + 'someNodeId', + '/redfish/v1/Systems/someNodeId/EthernetInterfaces' + ).resolves(ethernetInterfacesCatalog); + waterline.catalogs.findLatestCatalogOfSource.withArgs( + 'someNodeId', + '/redfish/v1/Systems/someNodeId/EthernetInterfaces/NIC.Embedded.1-1-1' + ).resolves(undefined); + return expect(job._run()).to.be.rejectedWith('Could not find MacAddress in NIC catalog!'); + }); +}); diff --git a/spec/lib/task-data/base-tasks/redfish-update-lookups-spec.js b/spec/lib/task-data/base-tasks/redfish-update-lookups-spec.js new file mode 100644 index 00000000..4b484ce7 --- /dev/null +++ b/spec/lib/task-data/base-tasks/redfish-update-lookups-spec.js @@ -0,0 +1,16 @@ +// Copyright © 2018 Dell Inc. or its subsidiaries. All Rights Reserved. + +'use strict'; + +describe(require('path').basename(__filename), function () { + var base = require('./base-task-data-spec'); + + base.before(function (context) { + context.taskdefinition = helper.require('/lib/task-data/base-tasks/redfish-update-lookups.js'); + }); + + describe('task-data', function () { + base.examples(); + }); +}); + diff --git a/spec/lib/task-data/tasks/redfish-update-lookups-spec.js b/spec/lib/task-data/tasks/redfish-update-lookups-spec.js new file mode 100644 index 00000000..877fe105 --- /dev/null +++ b/spec/lib/task-data/tasks/redfish-update-lookups-spec.js @@ -0,0 +1,16 @@ +// Copyright © 2018 Dell Inc. or its subsidiaries. All Rights Reserved. + +'use strict'; + +describe(require('path').basename(__filename), function () { + var base = require('./base-tasks-spec'); + + base.before(function (context) { + context.taskdefinition = helper.require('/lib/task-data/tasks/redfish-update-lookups.js'); + }); + + describe('task-data', function () { + base.examples(); + }); +}); +