RackHD/on-tasks

View on GitHub
lib/jobs/emc-redfish-catalog.js

Summary

Maintainability
F
1 wk
Test Coverage

// Copyright 2016, EMC, Inc.

'use strict';

var di = require('di');
module.exports = EmcRedfishCatalogJobFactory;
di.annotate(EmcRedfishCatalogJobFactory, new di.Provide('Job.Emc.Redfish.Catalog'));
di.annotate(EmcRedfishCatalogJobFactory, new di.Inject(
    'Job.Base',
    'Logger',
    'Promise',
    'Assert',
    'Util',
    'Services.Waterline',
    'Services.Encryption',
    '_',
    'JobUtils.RedfishTool'
));

function EmcRedfishCatalogJobFactory(
    BaseJob,
    Logger,
    Promise,
    assert,
    util,
    waterline,
    encryption,
    _,
    RedfishTool
) {
    var logger = Logger.initialize(EmcRedfishCatalogJobFactory);
    

    /**
     * @param {Object} options task options object
     * @param {Object} context graph context object
     * @param {String} taskId running task identifier
     * @constructor
     */
    function EmcRedfishCatalogJob(options, context, taskId) {
        EmcRedfishCatalogJob.super_.call(this,
                                   logger,
                                   options,
                                   context,
                                   taskId);
        this.chassis = this.context.chassis || [];
        if(_.isEmpty(this.chassis)) {
            this.chassis = [ this.context.target ]
        }
        this.redfish = new RedfishTool();
    }

    util.inherits(EmcRedfishCatalogJob, BaseJob);

    /**
     * @memberOf EmcRedfishCatalogJob
     */
    EmcRedfishCatalogJob.prototype._run = function() {
        var self = this;
        return Promise.resolve(self.chassis)
        .each(self.catalogElements.bind(self))
        .each(self.catalogHbas.bind(self))
        .each(self.catalogAggregators.bind(self))
        .each(self.catalogSpine.bind(self))
        .then(function() {
            self._done();
        })
        .catch(function(err) {
            self._done(err);
        });
    };
    
    EmcRedfishCatalogJob.prototype.catalogSpine = Promise.method(function(nodeId) {
        var self = this;
        var catalogData = [];
        return self.redfish.setup(nodeId)
        .then(function() {
            return self.redfish.clientRequest(self.redfish.settings.root);
        })
        .then(function(res) {
            assert.object(res, 'Chassis Resource Object');
            var spineModId = _.get(res.body, 'Oem.Emc.SpineModules', {})['@odata.id'];
            if (_.isUndefined(spineModId)) {
                throw new Error('Missing SpineModules Resource');
            }
            return self.redfish.clientRequest(spineModId)
            .then(function(res) {
                var members = _.get(res, 'body.Members', []);
                assert.notEqual(members.length, 0, 'No SpineModules Members');
                return members;
            });
        })
        .map(function(member) {
            return self.redfish.clientRequest(member['@odata.id']);
        })
        .map(function(res) {
            assert.object(res.body, 'SpineModule Data');
            var data = {
                Id: res.body.Id,
                Name: res.body.Name,
                Type: res.body.Type,
                Manufacturer: res.body.Manufacturer,
                Model: res.body.Model,
                PartNumber: res.body.PartNumber,
                SerialNumber: res.body.SerialNumber,
                Controllers: [],
                Switches: [],
                Vpd: {}
            };
            return Promise.each([
                self.redfish.clientRequest(_.get(res.body, 'Controllers', {})['@odata.id']),
                self.redfish.clientRequest(_.get(res.body, 'Switches', {})['@odata.id'])
            ], function(resList) {
                return Promise.map(_.get(resList.body, 'Members', []), function(member) {
                    var id = member['@odata.id'];
                    return self.redfish.clientRequest(id)
                    .then(function(res) {
                        data[id.match(/Controllers/g) ? 'Controllers' : 'Switches'].push(res.body);
                    });
                });
            })
            .then(function() {
                return self.redfish.clientRequest(_.get(res.body, 'Vpd', {})['@odata.id'])
                .then(function(res) {
                    data['Vpd'] = res.body;
                    catalogData.push(data);
                });
            });
        })
        .then(function() {
            return waterline.catalogs.create({
                node: nodeId,
                source: 'SpineModules',
                data: _.flattenDeep(catalogData)
            }).then(function() {
                return nodeId;
            });
        })
        .catch(function(err) {
            logger.error('SpineModules', {
                error: err
            });
            if(err.message !== 'Missing SpineModules Resource' &&
               err.message !== 'No SpineModules Members') {
                throw err;
            }
            return nodeId;
        });
    });
    
    EmcRedfishCatalogJob.prototype.catalogHbas = Promise.method(function(nodeId) {
        var self = this;
        var catalogData = [];
        return self.redfish.setup(nodeId)
        .then(function() {
            return self.redfish.clientRequest(self.redfish.settings.root);
        })
        .then(function(res) {
            assert.object(res, 'Chassis Resource Object');
            var hbaId = _.get(res.body, 'Oem.Emc.Hbas', {})['@odata.id'];
            if(_.isUndefined(hbaId)) {
                throw new Error('Missing HBA Resource');
            }
            return self.redfish.clientRequest(hbaId);
        })
        .then(function(res) {
            var members = _.get(res, 'body.Members', []);
            assert.notEqual(members.length, 0, 'No HBA Members');
            return members;
        })
        .map(function(member) {
            return self.redfish.clientRequest(member['@odata.id']);
        })
        .map(function(res) {
            assert.object(res.body, 'HBA Data');
            var ctrlId = _.get(res.body, 'Controllers', {})['@odata.id'];
            var data = {
                Id: res.body.Id,
                Name: res.body.Name,
                Manufacturer: res.body.Manufacturer,
                Model: res.body.Model,
                PartNumber: res.body.PartNumber,
                SerialNumber: res.body.SerialNumber,
                Controllers: []
            };
            return self.redfish.clientRequest(ctrlId).then(function(ctrlRes) {
                var members = _.get(ctrlRes.body, 'Members', []);
                return Promise.each(members, function(member) {
                    return self.redfish.clientRequest(member['@odata.id'])
                    .then(function(hbaRes) {
                        data.Controllers.push(hbaRes.body);
                        catalogData.push(data);
                    });
                });
            });
        })
        .then(function() {
            return waterline.catalogs.create({
                node: nodeId,
                source: 'Hbas',
                data: _.flattenDeep(catalogData)
            }).then(function() {
                return nodeId;
            });            
        })
        .catch(function(err) {
            logger.error('HBA', { error:err });
            if(err.message !== 'Missing HBA Resource' &&
               err.message !== 'No HBA Members') {
                throw err;
            }
            return nodeId; // allow
        });
    });

    EmcRedfishCatalogJob.prototype.catalogAggregators = Promise.method(function(nodeId) {
        var self = this;
        var catalogData = [];
        return self.redfish.setup(nodeId)
        .then(function() {
            return self.redfish.clientRequest(self.redfish.settings.root);
        })
        .then(function(res) {
            assert.object(res, 'Chassis Resource Object');
            var aggrId = _.get(res.body, 'Oem.Emc.Aggregators', {})['@odata.id'];
            if(_.isUndefined(aggrId)) {
                throw new Error('Missing Aggregators Resource');
            }
            return self.redfish.clientRequest(aggrId);
        })
        .then(function(res) {
            var members = _.get(res, 'body.Members', []);
            assert.notEqual(members.length, 0, 'No Aggregators Members');
            return members;
        })
        .map(function(member) {
            return self.redfish.clientRequest(member['@odata.id']);
        })
        .map(function(res) {
            assert.object(res.body, 'Aggregators Data');
            var data = {
                Id: res.body.Id,
                Name: res.body.Name,
                Type: res.body.Type,
                Manufacturer: res.body.Manufacturer,
                Model: res.body.Model,
                PartNumber: res.body.PartNumber,
                SerialNumber: res.body.SerialNumber,
                Controllers: [],
                Switches: []
            };         
            return Promise.each([
                self.redfish.clientRequest(_.get(res.body, 'Controllers', {})['@odata.id']),
                self.redfish.clientRequest(_.get(res.body, 'Switches', {})['@odata.id'])
            ], function(aggRes) {   
                return Promise.map(_.get(aggRes.body, 'Members', []), function(member) {
                    var id = member['@odata.id']; 
                    return self.redfish.clientRequest(id)
                    .then(function(res) {
                        data[(id.match(/Controllers/g))?'Controllers':'Switches'].push(res.body);
                        catalogData.push(data);
                    });
                });
            });
        })
        .then(function() {
            return waterline.catalogs.create({
                node: nodeId,
                source: 'Aggregators',
                data: _.flattenDeep(catalogData)
            }).then(function() {
                return nodeId;
            });            
        })
        .catch(function(err) {
            logger.error('Aggregators', { error:err });
            if(err.message !== 'Missing Aggregators Resource' &&
               err.message !== 'No Aggregators Members') {
                throw err;
            }
            return nodeId; // allow
        });
    });

    /**
     * @memberOf EmcRedfishCatalogJob
     */
    EmcRedfishCatalogJob.prototype.catalogElements = Promise.method(function(nodeId) {
        var self = this;
        return self.redfish.setup(nodeId)
        .then(function() {
            return self.redfish.clientRequest(self.redfish.settings.root);
        })
        .then(function(res) {
            assert.object(res, 'Chassis Resource Object');
            var elements = _.get(res.body, 'Oem.Emc.Elements');
            if (!elements) {
                throw new Error('Missing Emc Element Data');
            }
            return elements['@odata.id'];
        })
        .then(function(id) {
            assert.string(id, 'Element Identifier');
            return self.redfish.clientRequest(id);
        })
        .then(function(res) {
            var elements = _.get(res, 'body.Members');
            assert.notEqual(elements.length, 0, 'No Element Members');
            return elements;
        })
        .map(function(element) {
            return self.redfish.clientRequest(element['@odata.id']);
        })
        .map(function(element) {
            assert.object(element, 'Element Resource Object');
            assert.object(element.body);
            return element.body;
        })
        .map(function(element) {
            return self.redfish.clientRequest(element['@odata.id'])
                .then (function(element){
                    return element;
                });
        })
        .map(function(element) {
            assert.object(element, 'Element Resource Object');
            assert.object(element.body);
            return element.body;
        })
        .map(function(element){
            var newElement = {};
            _.forEach(element,function(value,key){
                if(key === "Processors" || key === "Vpd" || key === "Dimms" || key === "Drives") {
                    if(value instanceof Array){
                        newElement [key]=   self.updatingComponentsArray(element,key);
                    }
                    else {
                        newElement [key]=   self.updatingComponents(element,key);
                    }
                }
                else {
                    newElement[key] = element[key];
                }
            });
            return Promise.props(newElement);
        })
        .then(function(data) {
            assert.ok(Array.isArray(data), 'Element Data');
            return waterline.catalogs.create({
                node: nodeId,
                source: 'Elements',
                data: data
            }).then(function() {
                return nodeId;
            });
        })
        .catch(function(err) {
            logger.error('Elements', { error:err });
            if(err.message !== 'No Element Members') {
                throw err;
            }
            return nodeId; // allow
        });
    });

    EmcRedfishCatalogJob.prototype.updatingComponents = function (element, property) {
        var self = this;
        return self.redfish.clientRequest(element[property]['@odata.id'])
            .then (function(data){
                return data.body;
            })
            .then (function(element){
                if (element.hasOwnProperty("Members")){
                    var subElement = _(element.Members).map(function(arr){
                        return self.redfish.clientRequest(arr['@odata.id'])
                            .then(function(res){
                                return res.body;
                            });
                    }).value();
                    return Promise.all(subElement)
                }
                else {
                    return element;
                }
            });
    };

    EmcRedfishCatalogJob.prototype.updatingComponentsArray = function (element, property) {
        var self = this;
        var subElement = _(element[property]).map(function(arr){
            return self.redfish.clientRequest(arr['@odata.id'])
                .then(function(res){
                    return res.body;
                });
        }).value();
        return Promise.all(subElement)

    };
    return EmcRedfishCatalogJob;
}