Name

sn_itom_licensing.ITOMDEXLicenseCounterStore

Description

Script Include to calculate license usage of DEX

Script

var ITOMDEXLicenseCounterStore = Class.create();
ITOMDEXLicenseCounterStore.prototype = {
  initialize: function(enableLog) {
      this.metaDataUtils = new ITOMLicensingMetaDataStore();
      this.batchUtil = new global.BatchCommandUtilScript();
      this.pluginManager = new GlidePluginManager();
      this.utils = new ITOMLicensingUtilsStore();
      this.globalUtils = new global.UtilScript();
      this.ITOM_LU_CI_COUNTS = "itom_lu_ci_counts";
      this.LICENSE_EXCLUSION_LIST = "license_exclusion_list";
      this.ITOM_LU_LICENSABLE_CIS = "itom_lu_licensable_cis";
      this.ITOM_LU_DEX_CIS = "sn_itom_licensing_itom_lu_dex_ci";
      this.DX_MENU_APP = "sn_dex_systray_desktop_exp";
      this.DX_CHROME_PLUGIN = "dem_ci_browser_extension";
      this.DEM_CONTENT_PLUGIN = "sn_dem_content";
      this.SYS_OBJECT_SOURCE = "sys_object_source";
      this.CMDB_CI_COMPUTER = "cmdb_ci_computer";
      this.CHROME_PLUGIN = "sn_dem";
      this.MENU_APP_PLUGIN = "sn_dex_systray";
      this.DEX_DISCOVERY_SOURCE = "ServiceNow DEX";
      this.DATE_FILTER = 'Last 90 days@javascript:gs.beginningOfLast90Days()@javascript:gs.endOfLast90Days()';
      this.CATEGORY = 'enduser_devices';
      this.valueStream = "DEX";
      this.enableLog = enableLog;
      this.ciTableCategoryMap = {};
      this.domainsMap = this.utils.getDomainsMap();
  },

  process: function(skuTypeGr) {
  	var start = new Date().getTime();
  	this._logMessage("Process Started");
  	this.skuId = skuTypeGr.getValue("sys_id");
  	this.skuType = skuTypeGr.getValue("sku");

      //Step1: delete all previous records
      this._deletePreviousCIs();

  	//Step2: populated CIs to central table
  	if (this._isPluginActive(this.CHROME_PLUGIN)) 
  		this._populateCisToCentralTable(this.DX_CHROME_PLUGIN);
  	if (this._isPluginActive(this.MENU_APP_PLUGIN))
  		this._populateCisToCentralTable(this.DX_MENU_APP);
  	if(this._isPluginActive(this.DEM_CONTENT_PLUGIN))
  		this._populateCisToCentralTable(this.CMDB_CI_COMPUTER);


      //Step3: calculate usage
      this._calculateLicenseUsgae();
      this._logMessage("Process ended");
      var end = new Date().getTime();
      gs.debug("ITOMDEXLicenseCounter - Total Time taken :- " + Math.abs(end - start));
      
  },

  populateReportTable: function(skuTypeGr) {
      var start = new Date().getTime();
      this._logMessage("Listing process started");
      var skuType = skuTypeGr.getValue('sku');
      var skuTypeSysId = skuTypeGr.getValue('sys_id');

      var counter = 0;
      var total = 0;
      var jsonArr = [];
      var bulkSize = parseInt(gs.getProperty("dex.batchInsert.bulk_size", 5000));
      var suRatio = this.utils.getCategory2Ratio();
      var ciConditions = this.globalUtils.getAdditionalFiltersQuery(this.ITOM_LU_DEX_CIS, 'cmdb_ci', this.valueStream);
      var maxRecords = this.utils.getMaxResultsFor(this.valueStream, skuType);
      var gr = new GlideRecord(this.ITOM_LU_DEX_CIS);
      if (!gs.nil(ciConditions))
          gr.addEncodedQuery(ciConditions);
      gr.addQuery('sku_type', skuTypeSysId);
      gr.query();
      while (gr.next()) {
          var jsonObj = {};
          if (!gs.nil(gr.cmdb_ci)) 
              jsonObj.configuration_item = '' + gr.cmdb_ci;
          var category = gr.category;
          var su_ratio = suRatio[category];
          jsonObj.sys_domain = '' + gr.domain;
          jsonObj.value_stream = '' + this.valueStream;
          jsonObj.category = '' + category;
          jsonObj.su_ratio = '' + su_ratio + ':1';
          jsonObj.sku = '' + skuTypeSysId;
          jsonArr.push(jsonObj);
          counter++;
          total++;
          if (total >= maxRecords)
              break;
          if (counter >= bulkSize) {
              if (this.utils.isDEXJobCanceled())
                  return;
              this._logMessage("Going to insert CIs:- " + JSON.stringify(jsonArr));
              this.batchUtil.batchInsertMultiple(JSON.stringify(jsonArr), this.ITOM_LU_LICENSABLE_CIS, '');
              counter = 0;
              jsonArr = [];
          }
      }
      if (counter > 0) {
          if (this.utils.isDEXJobCanceled())
              return;
          this._logMessage("Going to insert CIs:- " + JSON.stringify(jsonArr));
          this.batchUtil.batchInsertMultiple(JSON.stringify(jsonArr), this.ITOM_LU_LICENSABLE_CIS, '');
      }
      this._logMessage("Listing process ended");
      var end = new Date().getTime();
      gs.debug("ITOMDEXLicenseCounter - Time taken in listing CIs :- " + Math.abs(end - start));
  },

  _calculateLicenseUsgae: function() {
      this._logMessage("In calculateUsage function");
      var categoriesHashMap = this._getCategoriesHashMap();
      var ga = new GlideAggregate(this.ITOM_LU_DEX_CIS);
      ga.addAggregate('COUNT');
      ga.addQuery('sku_type', this.skuId);
      ga.groupBy('category');
      ga.groupBy('domain');
      ga.query();
      var jsonArr = [];
      var counter = 0;
      var bulkSize = parseInt(gs.getProperty("dex.batchInsert.bulk_size", 5000));
      while (ga.next()) {
          var category = ga.getValue('category');
          this._addJsonObjToJsonArr(jsonArr, ga.getValue('domain'), category, ga.getAggregate('COUNT'));
          ++counter;
          if (categoriesHashMap[category])
              delete categoriesHashMap[category];
          if (counter >= bulkSize) {
              this._logMessage("Before insertion 1 :: " + JSON.stringify(jsonArr));
              this.batchUtil.batchInsertMultiple(JSON.stringify(jsonArr), this.ITOM_LU_CI_COUNTS, '');
              jsonArr = [];
              counter = 0;
          }
      }

      if (Object.keys(categoriesHashMap).length > 0) {
          for (var category in categoriesHashMap) {
              this._addJsonObjToJsonArr(jsonArr, 'global', category, 0);
              ++counter;
          }
      }


      if (counter > 0) {
          this._logMessage("Before insertion 2 :: " + JSON.stringify(jsonArr));
          this.batchUtil.batchInsertMultiple(JSON.stringify(jsonArr), this.ITOM_LU_CI_COUNTS, '');
      }
      this._logMessage("Done calculation");
  },

  _getCategoriesHashMap: function() {
      var categoriesHashMap = [];
      var categories = this.metaDataUtils.getCategoryNamesBasedonValueStream(this.valueStream.toLowerCase(), this.skuType);
      for (var i = 0; i < categories.length; i++)
          categoriesHashMap[categories[i]] = 1;
      return categoriesHashMap;
  },

  _logMessage: function(message) {
  	if (this.enableLog)
  		gs.info("ITOMDEXLicenseCounterStore - " + message);
  },

  _isPluginActive: function(plugin) {
  	return this.pluginManager.isActive(plugin);
  },

  _addJsonObjToJsonArr: function(jsonArr, domain, category, count) {
      var jsonObj = {};
      jsonObj.value_stream = '' + this.valueStream;
      jsonObj.is_aggregated = '' + false;
      jsonObj.sku = '' + this.skuId;
      jsonObj.sys_domain = '' + domain;
      jsonObj.category = '' + category;
      jsonObj.count = '' + count;
      jsonArr.push(jsonObj);
  },

  _deletePreviousCIs: function() {
      this._logMessage("Deleting records from " + this.ITOM_LU_DEX_CIS + " table for sku " + this.skuType);
      var cleanupGr = new GlideRecord(this.ITOM_LU_DEX_CIS);
      cleanupGr.addQuery("sku_type", this.skuId);
      cleanupGr.deleteMultiple();
  },

  _populateCisToCentralTable: function(tableName) {
      if(!gs.tableExists(tableName))
          return;
      this._logMessage("Populating CIs from table");
      var totalRecords = 0;
      var bulkSize = parseInt(gs.getProperty("dex.batchInsert.bulk_size", 5000));
      totalRecords += this._saveData(this._queryForNotNullCis(tableName), bulkSize, tableName);
      this._logMessage("DEX processed total records: " + totalRecords);
  },

  _queryForNotNullCis: function(table) {
      var start = new Date().getTime();
      var gr = new GlideRecord(table);
  	if(table == this.DX_CHROME_PLUGIN) {
  		gr.addNotNullQuery("ci_id");
  		gr.addNullQuery("ci_id.duplicate_of")
  		this.utils.addCiStatusQuery(gr, "ci_id.install_status");
  	} else if (table == this.DX_MENU_APP) {
  		gr.addNotNullQuery("installed_on");
          gr.addNullQuery("installed_on.duplicate_of");
          this.utils.addCiStatusQuery(gr, "installed_on.install_status");
  	} else if (table == this.CMDB_CI_COMPUTER) {
  		gr.addQuery('duplicate_of', 'NULL');
  		this.utils.addCiStatusQuery(gr, "install_status");
  		this._addConditionForDEX(gr, 'sys_id', this.DEX_DISCOVERY_SOURCE);
  	}
      gr.query();
      var end = new Date().getTime();
      gs.debug("ITOMDEXLicenseCounter - Time taken to query cmdb CIs :- " + Math.abs(end - start));
      return gr;
  },

  _addConditionForDEX: function(gr, ref, dex_discovery_source) {
      var sourceQuery = gr.addJoinQuery('sys_object_source', ref, 'target_sys_id');
      sourceQuery.addCondition('name', dex_discovery_source);
  },

  _saveData: function(gr, bulkSize, tableName) {
      var counter = 0;
      var total = 0;
      var jsonArr = [];
  	var computerGR = new GlideRecord(this.CMDB_CI_COMPUTER);
      while (gr.next()) {
          var jsonObj = {};
  		if(tableName == this.DX_CHROME_PLUGIN) {
              jsonObj.cmdb_ci = this._validateAndGetValue('ci_id', gr);
  			jsonObj.domain = '' + this._getDomainFromCITable(gr.getValue('ci_id'), computerGR);
  		} else if (tableName == this.DX_MENU_APP) {
  			jsonObj.cmdb_ci = this._validateAndGetValue('installed_on', gr);
  			jsonObj.domain = '' + this._getDomainFromCITable(gr.getValue('installed_on'), computerGR);
  		} else if (tableName == this.CMDB_CI_COMPUTER) {
  			jsonObj.cmdb_ci = this._validateAndGetValue('sys_id', gr);
  			jsonObj.domain = '' + this._getDomain(gr.sys_domain);
  		}
          jsonObj.table_name = tableName;
          jsonObj.category = this.CATEGORY;
          jsonObj.sku_type = '' + this.skuId;
          jsonArr.push(jsonObj);
          counter++;
          total++;
          if (counter >= bulkSize) {
              this._logMessage("Before calling _insertRecord function 1 :: " + JSON.stringify(jsonArr));
              this._insertRecords(jsonArr);
              counter = 0;
              jsonArr = [];
          }
      }
      if (counter > 0) {
          this._logMessage("Before calling _insertRecord function 2 :: " + JSON.stringify(jsonArr));
          this._insertRecords(jsonArr);
      }
      return total;
  },

  _validateAndGetValue: function(field, gr) {
      var value = gr.getValue(field);
      if (!value) {
          gs.error("ITOMDEXLicenseCounter - getting undefined value for " + field);
          return '';
      }
      return '' + value;
  },

  _insertRecords: function(jsonArr) {
      jsonArr = this._deDuplicateCis(jsonArr);
      this._logMessage("After deduplication :: " + JSON.stringify(jsonArr));
      jsonArr = this._removeExcludedCis(jsonArr);
      this._logMessage("After removing excluded cis :: " + JSON.stringify(jsonArr));
      var start = new Date().getTime();
      this.batchUtil.batchInsertMultiple(JSON.stringify(jsonArr), this.ITOM_LU_DEX_CIS, '');
      var end = new Date().getTime();
      gs.debug("ITOMDEXLicenseCounter - Time taken to insert " + jsonArr.length + " records in " + this.ITOM_LU_DEX_CIS + " table :- " + Math.abs(end - start));
  },

  _getDomainFromCITable: function(ciColumn, computerGR) {
      computerGR.initialize();
      computerGR.addQuery('sys_id', ciColumn);
      computerGR.query();
      var domain;
      if(computerGR.next())
          domain = computerGR.getValue('sys_domain');
      if (!domain || domain == "" || !this.pluginManager.isActive("com.glide.domain.msp_extensions.installer") || !this.domainsMap[domain])
          return "global";
      return domain;
  },

  _getDomain: function(domain) {
      if (!domain || domain == "" || !this.pluginManager.isActive("com.glide.domain.msp_extensions.installer") || !this.domainsMap[domain])
          return "global";
      return domain;
  },

  _removeExcludedCis: function(jsonArr) {
      var start = new Date().getTime();
      var ciHashMap = {};
      var finalCiList = [];
      for (var i = 0; i < jsonArr.length; i++)
          ciHashMap[jsonArr[i].cmdb_ci] = jsonArr[i];
      var excludeGr = new GlideRecord(this.LICENSE_EXCLUSION_LIST);
      excludeGr.addQuery('ci', 'IN', Object.keys(ciHashMap).join(','));
      excludeGr.addQuery('exclusion_reason.value_stream', this.valueStream).addOrCondition('exclusion_reason.value_stream', 'All');
      excludeGr.query();
      while (excludeGr.next())
          delete ciHashMap[excludeGr.getValue('ci')];
      for (var ciHash in ciHashMap)
          finalCiList.push(ciHashMap[ciHash]);
      var end = new Date().getTime();
      gs.debug("ITOMDEXLicenseCounter - Time taken to exclude CIs :- " + Math.abs(end - start));
      return finalCiList;
  },

  _deDuplicateCis: function(jsonArr) {
      var start = new Date().getTime();
      var ciHashMap = {};
      var dedupedCiList = [];
      var column = 'cmdb_ci';
      for (var i = 0; i < jsonArr.length; i++)
          ciHashMap[jsonArr[i][column]] = jsonArr[i];
      var dedupGr = new GlideRecord(this.ITOM_LU_DEX_CIS);
      dedupGr.addQuery(column, 'IN', Object.keys(ciHashMap).join(','));
      dedupGr.query();
      while (dedupGr.next())
          delete ciHashMap[dedupGr.getValue(column)];
      for (var ciHash in ciHashMap)
          dedupedCiList.push(ciHashMap[ciHash]);
      var end = new Date().getTime();
      gs.debug("ITOMDEXLicenseCounter - Time taken to deduplicate CIs :- " + Math.abs(end - start));
      return dedupedCiList;
  },

  type: 'ITOMDEXLicenseCounterStore'
};

Sys ID

fc2871f2875d619010f08519dabb35da

Offical Documentation

Official Docs: