Name

sn_em_ai.EvtMgmtGetServicesRelationsForCsdm

Description

No description available

Script

var EvtMgmtGetServicesRelationsForCsdm = Class.create();
EvtMgmtGetServicesRelationsForCsdm.prototype = {
  initialize: function() {
      this.slowStepManager = new global.SlowStepJSManager();
      this.evtMgmtCommons = new global.EvtMgmtCommons();
      this.debugLog = this.type + " script include: \n";
      this.TABLES = {
          PORTFOLIO: "spm_service_portfolio",
          TAXONOMY_NODE: "spm_taxonomy_node",
          TECHNICAL: "cmdb_ci_service_technical",
          BUSINESS: "cmdb_ci_service_business",
          OFFERING: "service_offering",
          APP_SERVICE: "cmdb_ci_service_auto",
          CI_RELATIONSHIPS: "cmdb_rel_ci"
      };
      this.FIELDS = {
          PARENT: "parent",
          SYS_ID: "sys_id",
          NAME: "name",
          SERVICE_CLASSIFICATION: "service_classification",
          CHILD: "child",
          TYPE: "type",
          TAXONOMY: "spm_taxonomy_node",
          PORTFOLIO: "spm_service_portfolio",
          SERVICE_CLASS: "service_classification"
      };
      this.TYPES = {
          ALL: "ROOT",
          SERVICE_PORTFOLIO: "PO",
          TAXONOMY_NODE: "TX",
          BUSINESS_SERVICE: "BS",
          TECHNICAL_SERVICE: "TS",
          OFFERING: "OFFER",
          APP_SERVICE: "APP"
      };
      this.RELATION_TYPES = {
          DEPENDS_ON_USED_BY: "1a9cb166f1571100a92eb60da2bce5c5",
          CONTAINS_CONTAINED_BY: "55c95bf6c0a8010e0118ec7056ebc54d"
      };
      this.taxonomyNodes = {};
      this.portfolioNodes = {};
  },

  /*
  	returns the portfolios tree as object
  */
  getPortfoliosTree: function() {
      this.slowStepManager.setTopic("CSDM: Get Portfolios Tree");
      this.getServices();
      this.slowStepManager.startStep(this.type + ": getPortfoliosTree");
      var output = this.createNode('0', gs.getMessage("All"), this.TYPES.ALL, []);
      for (var key in this.portfolioNodes) {
          if (this.portfolioNodes.hasOwnProperty(key)) {
              output.children.push(this.portfolioNodes[key]);
          }
      }
      this.slowStepManager.report();
      return output;
  },

  getServices: function() {
      this.slowStepManager.startStep(this.type + ": getServices");
      var tables = [this.TABLES.TECHNICAL, this.TABLES.BUSINESS];
      for (var table in tables) {
          if (!tables.hasOwnProperty(table)) {
              continue;
          }
          var serviceGr = new GlideRecord(tables[table]);
  		// if there isn't a taxonomy node then there is no service portfolio and the service shouldn't be displayed.
  		serviceGr.addNotNullQuery(this.FIELDS.TAXONOMY);
          serviceGr.query();
          while (serviceGr.next()) {
              var serviceTaxonomyID = serviceGr.getValue(this.FIELDS.TAXONOMY);
              var serviceId = serviceGr.getValue(this.FIELDS.SYS_ID);
              var serviceName = serviceGr.getValue(this.FIELDS.NAME);
              var serviceClass = serviceGr.getValue(this.FIELDS.SERVICE_CLASS);
              var serviceType = (serviceClass == 'Business Service') ? this.TYPES.BUSINESS_SERVICE : this.TYPES.TECHNICAL_SERVICE;
              var serviceNode = this.createNode(
                  serviceId,
                  serviceName,
                  serviceType,
                  this.getOfferings(serviceId, serviceType));
              this.getTaxonomy(serviceTaxonomyID, serviceNode);
          }
      }
  },

  getOfferings: function(parent, parentType) {
      this.slowStepManager.startStep(this.type + ": getOfferings");
      var offerings = [];
      var offeringGr = new GlideRecord(this.TABLES.OFFERING);
      offeringGr.addQuery(this.FIELDS.PARENT, parent);
      offeringGr.query();
      while (offeringGr.next()) {
          var offeringID = offeringGr.getValue(this.FIELDS.SYS_ID);
          var offeringName = offeringGr.getValue(this.FIELDS.NAME);
          offerings.push(this.createNode(
              offeringID,
              offeringName,
              this.TYPES.OFFERING,
              this.getApplicationServices(offeringID, parentType)));
      }
      return offerings;
  },

  getApplicationServices: function(parent, offeringClassification) {
      this.slowStepManager.startStep(this.type + ": getApplicationServices");
      var appServices = [];
      var ciRelationsGr = new GlideRecord(this.TABLES.CI_RELATIONSHIPS);
      ciRelationsGr.addQuery(this.FIELDS.PARENT, parent);
      if (offeringClassification == this.TYPES.BUSINESS_SERVICE) {
          ciRelationsGr.addQuery(this.FIELDS.TYPE, this.RELATION_TYPES.DEPENDS_ON_USED_BY);
      } else { // must be technical service
          ciRelationsGr.addQuery(this.FIELDS.TYPE, this.RELATION_TYPES.CONTAINS_CONTAINED_BY);
      }
      ciRelationsGr.query();
      var childrenIds = [];
      while (ciRelationsGr.next())
          childrenIds.push(ciRelationsGr.getValue(this.FIELDS.CHILD));
      var applicationGr = new GlideRecord(this.TABLES.APP_SERVICE);
      applicationGr.addQuery(this.FIELDS.SYS_ID, "IN", childrenIds);
  	applicationGr.query();
      while (applicationGr.next()) {
          var applicationID = applicationGr.getValue(this.FIELDS.SYS_ID);
          var applicationName = applicationGr.getValue(this.FIELDS.NAME);
          appServices.push(this.createNode(
              applicationID,
              applicationName,
              this.TYPES.APP_SERVICE,
              []));
      }
      return appServices;
  },

  // there is an assumption that the caller checked the correctness of taxonomyId and therefore the taxonomyGr will be nexted.
  getTaxonomy: function(taxonomyId, childNode) {
      this.slowStepManager.startStep(this.type + ": getTaxonomy");
      var taxonomyGr = new GlideRecord(this.TABLES.TAXONOMY_NODE);
      while (taxonomyId) {
          var taxonomyNode = this.taxonomyNodes[taxonomyId];
          if (!taxonomyNode) {
              taxonomyGr.get(taxonomyId);
              var taxonomyName = taxonomyGr.getValue(this.FIELDS.NAME);
              childNode = this.createNode(taxonomyId, taxonomyName, this.TYPES.TAXONOMY_NODE, [childNode]);
              this.taxonomyNodes[taxonomyId] = childNode;
              taxonomyId = taxonomyGr.getValue(this.FIELDS.PARENT);
          } else {
              taxonomyNode.children.push(childNode);
              return; // parent already inserted into the tree, no need to continue iterating over the tree
          }
      }
      var portfolioId = taxonomyGr.getValue(this.FIELDS.PORTFOLIO);
      this.getPortfolio(portfolioId, childNode);
      return;
  },

  getPortfolio: function(portfolioId, childNode) {
      this.slowStepManager.startStep(this.type + ": getPortfolio");
      var portfolioNode = this.portfolioNodes[portfolioId];
      if (!portfolioNode) {
          var portfolioGr = new GlideRecord(this.TABLES.PORTFOLIO);
          portfolioGr.get(portfolioId);
          var portfolioName = portfolioGr.getValue(this.FIELDS.NAME);
          this.portfolioNodes[portfolioId] = this.createNode(portfolioId, portfolioName, this.TYPES.SERVICE_PORTFOLIO, [childNode]);
          return;
      }
      portfolioNode.children.push(childNode);
      return;
  },

  createNode: function(sysId, name, type, children) {
      return {
          "data": {
              "id": sysId,
              "name": name,
              "type": type,
          },
          "children": children
      };
  },

  /*
  	returns object with services and/or offerings associated with the given alert 
  	services: if false then don't return the impacted services
  	offerings: if false then don't return the impacted services
  */
  getImpactedServicesAndOffering: function(alertId, services, offerings) {
      var output = {
          "alertId": alertId
      };

      var alertsInGroup = new global.EvtMgmtAlertsInGroupAPI();
      var impactedServices = alertsInGroup.getImpactedServicesForAlert(alertId);
      if (impactedServices) {
          impactedServices = impactedServices.split(',');
          if (offerings)
              var impactedOfferings = this.getOfferingsForServices(impactedServices);
      }
      if (services)
          output["services"] = impactedServices ? impactedServices : [];
      if (offerings)
          output["offerings"] = impactedOfferings ? impactedOfferings : [];
      return output;
  },

  /* 	
  	returns the service offerings of the given serviceIds
  	servicesIds - array of sys_ids
  */
  getOfferingsForServices: function(serviceIds) {
      var startTime = new GlideDateTime().getNumericValue();
      var servicesLimit = gs.getProperty('sn_em_ai.evt_mgmt.offerings_for_services.services_limit', 100);
      var offerings = {};
      if (!serviceIds)
          return [];

      if (serviceIds.length <= servicesLimit)
          this.offeringsForServicesQuery(offerings, serviceIds);
      else {
          var iteration = 0;
          do {
              var services = serviceIds.slice(0, servicesLimit);
              this.offeringsForServicesQuery(offerings, serviceIds);
              serviceIds = serviceIds.slice(servicesLimit);
              iteration = iteration + 1;
          }
          while (serviceIds.length > 0 && iteration < 100);
      }
      var output = [];
      for (offering in offerings)
          output.push(offering);

      var endTime = new GlideDateTime().getNumericValue();
      this.evtMgmtCommons.addDebugMessage(this.debugLog + "getOfferingsForServices time: " + String(endTime - startTime) + " ms");

      return output;
  },

  offeringsForServicesQuery: function(curOfferings, services) {
      var offeringsLimit = gs.getProperty('sn_em_ai.evt_mgmt.offerings_for_services.fetch_limit', 100000);
      var relationGr = new GlideAggregate("cmdb_rel_ci");
      relationGr.addQuery("child", "IN", services);
      relationGr.addQuery("type", this.RELATION_TYPES.DEPENDS_ON_USED_BY)
          .addOrCondition("type", this.RELATION_TYPES.CONTAINS_CONTAINED_BY);
      relationGr.groupBy("parent"); // get unique offerings
      relationGr.setLimit(offeringsLimit);
      relationGr.query();
      if (relationGr.getRowCount() >= offeringsLimit)
          gs.info(this.type + 'The number of fetched service offerings is equal to the limit, more service offerings may exist.');

      while (relationGr.next()) {
          var parent = relationGr.parent.getRefRecord();
          if (parent.isValidRecord()) {
              if (parent.getValue("sys_class_name") == "service_offering")
                  curOfferings[parent.getUniqueValue()] = '';
          }
      }
  },



  type: 'EvtMgmtGetServicesRelationsForCsdm'
};

Sys ID

1180e74107120110a8b38c14dfd30051

Offical Documentation

Official Docs: