Name

global.CSDMCMDBUtil

Description

Generic utilities for CSDM specific interactions with CMDB

Script

var CSDMCMDBUtil = Class.create();
CSDMCMDBUtil.prototype = {
  initialize: function() {
  },
  
  getDynamicCIGroupsFromTSO: function (TSOSysId) {
  	var groups = [];
  	
  	if(!this.isTechnicalService(TSOSysId))
  		return groups;
  	
  	var grRel = new GlideRecord('cmdb_rel_ci');
  	grRel.addEncodedQuery('parent.sys_class_name=service_offering^child.sys_class_name=cmdb_ci_query_based_service^parent=' + TSOSysId);
  	grRel.query();
  	while (grRel.next()) {
  		if (this.isTechnicalService(grRel.getValue('child')))
  			groups.push(grRel.getValue('child'));
  	}
  	return groups;
  },
  
  // Dynamic ci groups are mapped to their associated technical service offering
  // Mapping is one to many
  getAssocTSOsFromDCG : function (dcgIds) {
  	var grRel = new GlideRecord("cmdb_rel_ci");
  	grRel.addQuery("child", "IN", dcgIds);
  	grRel.addQuery("parent.sys_class_name", "service_offering");
  	grRel.query();
  	var groupsMappedToTso = {};
  	while (grRel.next()) {
  		var serviceId = grRel.getValue("parent");
  		if (!groupsMappedToTso[serviceId]) {
  			groupsMappedToTso[serviceId] = [];
  		}
  		groupsMappedToTso[serviceId].push(grRel.getValue("child"));
  	}
  	return groupsMappedToTso;
  },
  
  // Gets a gliderecord of technical service offerings, sorting by create date from most recent created to last
  getTSOs : function (tsoIds) {
  	var grTso = new GlideRecord("service_offering");
  	grTso.addQuery("service_classification", "Technical Service");
  	grTso.addQuery("sys_id", "IN", tsoIds);
  	grTso.orderByDesc("sys_created_on");
  	grTso.query();
  	return grTso;
  },
  
  getCIsFromDCG: function(dcgSysIds) {
  	var cis = {};
  	var ciArr = [];
  	if (JSUtil.nil(dcgSysIds))
  		return cis;
  	var grAssoc = new GlideRecord('svc_ci_assoc');
  	grAssoc.addQuery('service_id','IN', dcgSysIds);
  	grAssoc.addQuery("service_id.service_classification", "Technical Service");
  	grAssoc.query();
  	while(grAssoc.next()) {
  		ciArr.push(grAssoc.getValue('ci_id'));
  	}
  	var grCiCmdb = new GlideRecord("cmdb_ci");
  	grCiCmdb.addQuery('sys_id', 'IN', ciArr);
  	grCiCmdb.query();
  	while (grCiCmdb.next()) {
  		var className = grCiCmdb.getValue("sys_class_name");
  		if (!cis[className]) {
  			cis[className] = [];
  		}
  		cis[className].push(grCiCmdb.getValue('sys_id'));
  	}
  	return cis;
  },
  
  // Queries for associated dynamic CI groups given a list of CIs and returns an object
  // such that each DCG -> array of associated CIs
  getCisMappedToDCG : function (ciSysIds) {
  	if (JSUtil.nil(ciSysIds)) 
  		return {};
  	var grAssoc = new GlideRecord("svc_ci_assoc");
  	grAssoc.addQuery("ci_id","IN", ciSysIds);
  	grAssoc.addQuery("service_id.service_classification", "Technical Service");
  	grAssoc.query();
  	var cisMappedToGroup = {};
  	while(grAssoc.next()) {
  		var dcgId = grAssoc.getValue("service_id");
  		if (!cisMappedToGroup[dcgId]) {
  			cisMappedToGroup[dcgId] = [];
  		}
  		cisMappedToGroup[dcgId].push(grAssoc.getValue("ci_id"));
  	}
  	return cisMappedToGroup;
  },
  
  // Updates a list of sysIds using an updates object containing the column -> value mapping
  updateRecords: function(tableName, sysIds, updates) {
  	if(JSUtil.nil(sysIds) || JSUtil.nil(updates) || Object.keys(updates).length == 0 || JSUtil.nil(tableName))
  		return;
  	var gr = new GlideRecord(tableName);
  	gr.addQuery('sys_id', 'IN', sysIds);
  	gr.query();
  	for(var columnName in updates) {
  		if (updates.hasOwnProperty(columnName) && GlideTableDescriptor.fieldExists(tableName, columnName))
  			gr.setValue(columnName, JSUtil.nil(updates[columnName])? 'NULL' : updates[columnName]);
  	}
  	
  	gr.updateMultiple();
  },
  
  // service_classification is at cmdb_ci_service level so it would be generic function 
  // that works for all classes inherited from cmdb_ci_service
  isTechnicalService: function(sysId) {
  	var grTech = new GlideRecord('cmdb_ci_service');
  	return (grTech.get(sysId) && grTech.getValue('service_classification') == 'Technical Service');
  },
  
  isDynamicCiGroup: function(sysId) {
  	var grDcg = new GlideRecord('cmdb_ci_query_based_service');
  	return grDcg.get(sysId) && grDcg.getValue('service_classification') == 'Technical Service';
  },
  
  // Gets CIs for a specific class and ignores inherited CIs
  getCisForClass : function(className) {
  	var ciRecords = new GlideRecord(className);
  	ciRecords.addQuery("sys_class_name", className);
  	ciRecords.query();
  
  	if (ciRecords.getRowCount() == 0) {
  		// The CI Class has no individual CIs
  		return {};
  	}
  	var ciSysIds = {};
  	while (ciRecords.next()) {
  		ciSysIds[ciRecords.getValue("sys_id")] = "";
  	}
  	return ciSysIds;
  },
  
  // expects a map of ciClass to many ci sys_ids, optional second parameter is a managed_by_group value to apply to all cis
  revertMBGToClassValueOrNull : function(cis, tsoMbgValue) {
  	var newMbgValue = "NULL";
  	if (!Object.keys(cis) || Object.keys(cis).length == 0)
  		return;
  	Object.keys(cis).forEach(function (ciClass) {
  		if (!new TableUtils(ciClass).tableExists())
  			return; 
  		var grUpdate = new GlideRecord(ciClass);
  		grUpdate.addQuery("sys_id", "IN", cis[ciClass]);
  		grUpdate.query();
  		if (!tsoMbgValue || tsoMbgValue === "NULL") {
  			var grCci = new GlideRecord("cmdb_class_info");
  			grCci.addQuery("class", ciClass);
  			grCci.query();
  			if (grCci.next() && grCci.getValue("managed_by_group")) {
  				// set managed by group to the cmdb class info value
  				newMbgValue = grCci.getValue("managed_by_group");
  			} 
  		} else {
  			newMbgValue = tsoMbgValue;
  		}
  		grUpdate.setValue("managed_by_group", newMbgValue);
  		gs.log("Reverting Managed by group to " + newMbgValue + " for " + cis[ciClass].length + " CIs from class " + ciClass, "CSDMCMDBUtil");
  		grUpdate.updateMultiple();
  	});
  	
  },
  
  // expects a dynamic ci group sys_id 
  updateOnTsoRelDelete : function(dcgString) {
  	var startTime = new GlideTime();
  	if (!dcgString || dcgString.length == 0)
  		return;
  	// revert DCG back to another TSOs values if still has a relationship or null if not
  	var tsoMbgValue;
  	var groupTsoMap = this.getAssocTSOsFromDCG(dcgString);
  	if (Object.keys(groupTsoMap).length > 0) {
  		var soArray = [];
  		Object.keys(groupTsoMap).forEach(function (serviceOffering) {
  			soArray.push(serviceOffering);
  		});
  		var tsos = this.getTSOs(soArray);

  		while (tsos.next()) {
  			if (tsos.getValue("managed_by_group")) {
  				// the most recently created technical service offering with a relationship to this dcg has a managed by group value
  				tsoMbgValue = tsos.getValue("managed_by_group");
  				break;
  			}
  		}
  	}

  	// update the dcg to the new mbg value from another tso or set to empty
  	var grDcg = new GlideRecord("cmdb_ci_query_based_service");
  	if (!grDcg.get(dcgString))
  		return;
  	grDcg.setValue("managed_by_group", tsoMbgValue ? tsoMbgValue : "NULL");
  	grDcg.update();
  	gs.log("Updated Dynamic CI group with Managed by group: " + grDcg.getValue("managed_by_group"), "CSDMCMDBUtil");

  	// get the CIs from the DCG and revert mbg to class manager or to new tso value
  	cis = this.getCIsFromDCG(dcgString);
  	this.revertMBGToClassValueOrNull(cis, tsoMbgValue);

  	var dur = GlideDate.subtract(startTime, new GlideTime());
  	gs.log("Completed reverting Managed by group values for CIs in " + dur.getDurationValue(), "CSDMCMDBUtil");
  },
  
  // reverts a string comma separated list of CIs to MBG values. Optional "::" is used to pass a dcg sys id to exclude from searches
  updateCiOnAssocDelete : function(ciSysIds) {
  	var startTime = new GlideTime();
  	if (!ciSysIds || ciSysIds.length == 0)
  		return;
  	var dcgToExclude;
  	var ciSysIdArr;
  	if (ciSysIds.indexOf("::") > 0) {
  		var temp = ciSysIds.split("::");
  		ciSysIdArr = temp[0].split(",");
  		dcgToExclude = temp[1];
  	} else {
  		ciSysIdArr = ciSysIds.split(",");
  	}
  	// check if ci is still associated to another dcg
  	var grAssoc = new GlideRecord("svc_ci_assoc");
  	grAssoc.addQuery("ci_id", "IN", ciSysIdArr);
  	grAssoc.addQuery("service_id.service_classification", "Technical Service");
  	grAssoc.addQuery("service_id.sys_class_name", "cmdb_ci_query_based_service");
  	if (dcgToExclude) {
  		grAssoc.addQuery("service_id", "!=", dcgToExclude);
  	}
  	grAssoc.query();
  	var dcgs = {};
  	while (grAssoc.next()) {
  		if (!dcgs[grAssoc.getValue("service_id")]) {
  			dcgs[grAssoc.getValue("service_id")] = [];
  		}
  		dcgs[grAssoc.getValue("service_id")].push(grAssoc.getValue("ci_id"));
  		ciSysIdArr = ciSysIdArr.filter(function (sysId) {
  			return sysId != grAssoc.getValue("ci_id");
  		});
  	}
  	
  	// check to see if a TSO has a MBG value
  	if (Object.keys(dcgs).length > 0) {
  		Object.keys(dcgs).forEach(function(dcg) {
  			var sos = this.getAssocTSOsFromDCG([dcg]);
  			if (Object.keys(sos).length > 0) {
  				var grTso = this.getTSOs(Object.keys(sos));
  				while (grTso.next()) {
  					if (grTso.getValue("managed_by_group")) {
  						this.revertMBGToClassValueOrNull(dcgs[dcg], grTso.getValue("managed_by_group"));
  						delete dcgs[dcg];
  						break;
  					}
  				}
  			}
  		});
  	}
  	// combine all CIs not reverted to a TSO value
  	Object.keys(dcgs).forEach(function(dcg) {
  		ciSysIdArr = ciSysIdArr.concat(dcgs[dcg]);
  	});
  	// get all classes associated with the CIs
  	var grCiCmdb = new GlideRecord("cmdb_ci");
  	var cisAndClass = {};
  	grCiCmdb.addQuery('sys_id', 'IN', ciSysIdArr);
  	grCiCmdb.query();
  	while (grCiCmdb.next()) {
  		var className = grCiCmdb.getValue("sys_class_name");
  		if (!cisAndClass[className]) {
  			cisAndClass[className] = [];
  		}
  		cisAndClass[className].push(grCiCmdb.getValue('sys_id'));
  	}
  	this.revertMBGToClassValueOrNull(cisAndClass);
  	var dur = GlideDate.subtract(startTime, new GlideTime());
  	gs.log("Completed reverting Managed by group values for CIs in " + dur.getDurationValue(), "CSDMCMDBUtil");
  },
  type: 'CSDMCMDBUtil'
};

Sys ID

1bafe8897382101061b79c0c6df6a738

Offical Documentation

Official Docs: