RackHD/on-tasks

View on GitHub
lib/jobs/ucs-catalog.js

Summary

Maintainability
C
1 day
Test Coverage
// Copyright 2016-2017 Dell Inc. or its subsidiaries. All Rights Reserved.

'use strict';

var di = require('di');
module.exports = UcsCatalogJobFactory;
di.annotate(UcsCatalogJobFactory, new di.Provide('Job.Ucs.Catalog'));
di.annotate(UcsCatalogJobFactory, new di.Inject(
    'Job.Ucs.Base',
    'Logger',
    'Promise',
    'Assert',
    'Util',
    'Services.Waterline',
    'Services.Encryption',
    '_',
    'uuid'
));

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


    /**
     * @param {Object} options task options object
     * @param {Object} context graph context object
     * @param {String} taskId running task identifier
     * @constructor
     */
    function UcsCatalogJob(options, context, taskId) {
        UcsCatalogJob.super_.call(this,
            logger,
            options,
            context,
            taskId);
        this.nodes = _.union( this.context.physicalNodeList, this.context.logicalNodeList);
        if(_.isEmpty(this.nodes)) {
            this.nodes = [ this.context.target ];
        }
        this._obmsCollection = {};
        this.boardChildrenToExtend = [
            //"disk-collection",
            "memarray-collection"
        ];
    }

    util.inherits(UcsCatalogJob, BaseJob);

    /**
     * @memberOf UcsCatalogJob
     */
    UcsCatalogJob.prototype._run = function() {
        var self = this;
        return Promise.map(this.nodes, function(node) {
            return self.catalogServers(node);
        })
        .then(function() {
            self._done();
        })
        .catch(function(err) {
            self._done(err);
        });
    };

    /**
     * @memberOf UcsCatalogJob
     * @param {string} nodeId: node ID
     */
    UcsCatalogJob.prototype._getObmsByNodeId = function (nodeId) {
        var self = this;
        var obms = self._obmsCollection[nodeId];
        if (!obms) {
            return waterline.obms.findByNode(nodeId, 'ucs-obm-service', true)
                .then(function(obmSetting) {
                    if (obmSetting) {
                        self._obmsCollection[nodeId] = {
                            obmSetting: obmSetting
                        };
                        return self._obmsCollection[nodeId];
                    } else {
                        return Promise.reject(
                            new Error("No ucs-obm-service found for id: %s".format(nodeId)));
                    }
                });
        } else {
            return Promise.resolve(self._obmsCollection[nodeId]);
        }
    };

    /**
     * @memberOf UcsCatalogJob
     * @param {String} dn: distinguished name of ucs managed object
     * @param {Boolean} withSelfData: boolean value to indicate if to include self data of dn
     * @return {Object}: JSON data got from ucs service
     */
    UcsCatalogJob.prototype._getCatalogByDN = function (dn, nodeId, withSelfData) {
        var self = this;
        var groupingPattern = /^(.*)-\d{1,2}$/;
        var callbackId = uuid.v4();
        var url = "/catalog/async?identifier=%s&callbackId=%s"
            .format(dn, callbackId);
        var result = {};
        return self._getObmsByNodeId(nodeId)
            .then(function(entity){
                var settings = entity.obmSetting.config;
                return self._ucsRequestAsync(url, settings, callbackId)
                    .then(function(res) {
                        return res.body;
                    });
            })
            .map(function(data) {
                var matched;
                matched = data.rn.match(groupingPattern);
                if(dn === data.dn){
                    if(!withSelfData) {
                        return;
                    } else {
                        result[data.rn] = data;
                    }
                } else {
                    if(matched) {
                        var name = matched[1] + "-collection";
                        result[name] = result[name] || [];
                        result[name].push(data);
                    } else {
                        result[data.rn] = data;
                    }
                }
            })
            .then(function() {
                return result;
            });
    };

    /**
     * @memberOf UcsCatalogJob
     * @param {Object | arrayOfObject} collection: board children object data
     * @return {Object}: JSON data got from ucs service
     */
    UcsCatalogJob.prototype._extendBoardChildCatalog = function(collection, nodeId) {
        var self = this;
        var _collection;
        if (!_.isArray(collection)) {
            _collection = [collection];
        } else {
            _collection = collection;
        }
        return Promise.map(_collection, function(item) {
            return self._getCatalogByDN(item.dn, nodeId)
            .then(function(result) {
                item.children = result;
            });
        });
    };

    /**
     * @memberOf UcsCatalogJob
     * @param {Object} board: board object data
     * @return {Promise}
     */
    UcsCatalogJob.prototype._extendBoardCatalog = function(board, nodeId) {
        var self = this;
        var extendPromiseList = [];
        var boardKeys = _.keys(board);
        return Promise.try(function(){
            var boardChildrenToExtend = _.cloneDeep(self.boardChildrenToExtend);
            _.forEach(boardKeys, function(key){
                if (_.startsWith(key, "storage-")) {
                    boardChildrenToExtend.push(key);
                }
            });
            _.forEach(boardChildrenToExtend, function(boardChild){
                var boardChildData = board[boardChild];
                extendPromiseList.push(self._extendBoardChildCatalog(boardChildData, nodeId));
            });
            return Promise.all(extendPromiseList);
        });
    };

    /**
     * @memberOf UcsCatalogJob
     * @param {string} nodeId: node ID
     * @return {Promise}
     */
    UcsCatalogJob.prototype.catalogServers = function(nodeId) {
        var self = this;
        var nodeName = '';
        return waterline.nodes.getNodeById(nodeId)
        .then(function(node){
            nodeName = node.name;
            var isChassis = _.startsWith(_.last(nodeName.split('/')), 'chassis');
            return Promise.all([
                self._getCatalogByDN(nodeName, nodeId, true),
                isChassis ?
                new Promise.resolve() : self._getCatalogByDN(nodeName + '/board', nodeId)
            ])
            .spread(function(nodeResult, boardResult) {
                if(boardResult && nodeResult.board) {
                    // Get more details under rn="board" as hardware info like memory,
                    // disk, cpu are under rn="board"
                    nodeResult.board.children = boardResult;
                    return self._extendBoardCatalog(boardResult, nodeId)
                    .then(function() {
                        return nodeResult;
                    });
                }
                return nodeResult;
            });
        })
        .then(function(data) {
            return _.map(data, function(value, key) {
                return waterline.catalogs.create({
                    node: nodeId,
                    source: (value.dn === nodeName) ? 'UCS' : 'UCS:' + key,
                    data: value
                });
            });
        })
        .all(function() {
            return nodeId;
        })
        .catch(function(err) {
            logger.error('Ucs Servers', { error:err });
            if(err.message !== 'No Servers Members') {
                throw err;
            }
            return nodeId; // allow
        });
    };
    return UcsCatalogJob;
}