Fix Script to Create CI's on Assets

NFGDom
Mega Sage

Hello!

I'm trying to create a fix script that will create CI records on assets (alm_asset) that do not have a CI.

I'm using this Business Rule and Script Include to aid me in actually creating the CI.

https://<instance-name>.service-now.com/nav_to.do?uri=sys_script.do?sys_id=26ebfeef1b3210002502fbcd2c07136f https://<instance-name>.service-now.com/nav_to.do?uri=sys_script_include.do?sys_id=19c0f3603703100044e0bfc8bcbe5d9b

Here is my script below. I'm basically searching for all of my assets then going to loop though each calling the script include to create the CI for each.

var queryStr = 'ciISEMPTY^model_category!=fed01818db93ff00c0ede66505961962^ORmodel_category=NULL^model_category!=996b568ec3102000b959fd251eba8f19^model_category!=218323293743100044e0bfc8bcbe5d61^model_category!=35bf2d4137101000deeabfc8bcbe5dbd^model_category!=c9d5bc50c3031000b959fd251eba8fbc^model_category!=83c92540732623008b516cb63cf6a7b1^model_category!=58fdb454c3031000b959fd251eba8ff0';
var assets_no_ci = new GlideRecord('alm_asset');
//assets_no_ci.addEncodedQuery(queryStr); //Commented to test with a single record
assets_no_ci.addQuery('serial_number', '1234567890'); //test this script with a single record
assets_no_ci.orderBy('model_category');
assets_no_ci.query();

while (assets_no_ci.next()) {
   (new AssetandCI()).createCI(assets_no_ci);
    gs.log("Adding CI to Asset: " + assets_no_ci.display_name);
}

However when I run the script it gives me an error:

*** Script: Asset count: 1
Evaluator: org.mozilla.javascript.EvaluatorException: GlideRecord.insert() - invalid table name: null (sys_script_include.19c0f3603703100044e0bfc8bcbe5d9b.script; line 180)
   EvaluatorException(JavaScript evaluation error on:
var queryStr = 'ciISEMPTY^model_category!=fed01818db93ff00c0ede66505961962^ORmodel_category=NULL^model_category!=996b568ec3102000b959fd251eba8f19^model_category!=218323293743100044e0bfc8bcbe5d61^model_category!=35bf2d4137101000deeabfc8bcbe5dbd^model_category!=c9d5bc50c3031000b959fd251eba8fbc^model_category!=83c92540732623008b516cb63cf6a7b1^model_category!=58fdb454c3031000b959fd251eba8ff0';
var assets_no_ci = new GlideRecord('alm_asset');
//assets_no_ci.addEncodedQuery(queryStr); //Commented to test with a single record
assets_no_ci.addQuery('serial_number', '1234567890'); //test this script with a single template
assets_no_ci.orderBy('model_category');
assets_no_ci.query();

while (assets_no_ci.next()) {
   (new AssetandCI()).createCI(assets_no_ci);
    gs.log("Adding CI to Asset: " + assets_no_ci.display_name);
}
)
[0:00:00.055] Total Time

Any thoughts or help would be appreciated.

Thanks!

Dom

1 ACCEPTED SOLUTION

so that's the issue, it doesn't know on what cmdb_ci table to create the CI's. This value should be stored in the model category and is what the following does. it dot walks to the value

ciClass = asset.model_category.cmdb_ci_class.toString();

find_real_file.png

 

View solution in original post

21 REPLIES 21

Dang, helps if I copy and paste properly!

var queryStr = 'ciISEMPTY^model_category!=fed01818db93ff00c0ede66505961962^ORmodel_category=NULL^model_category!=996b568ec3102000b959fd251eba8f19^model_category!=218323293743100044e0bfc8bcbe5d61^model_category!=35bf2d4137101000deeabfc8bcbe5dbd^model_category!=c9d5bc50c3031000b959fd251eba8fbc^model_category!=83c92540732623008b516cb63cf6a7b1^model_category!=58fdb454c3031000b959fd251eba8ff0';
var assets_no_ci = new GlideRecord('alm_asset');
//assets_no_ci.addEncodedQuery(queryStr); //Commented to test with a single record
assets_no_ci.addQuery('serial_number', '1234567890'); //test this script with a single record
assets_no_ci.orderBy('model_category');
assets_no_ci.query();

while (assets_no_ci.next()) {
 createAsset(assets_no_ci);
  gs.log("Adding CI to Asset: " + assets_no_ci.display_name);
}

var ciClass = '';
		if ('leave_to_category' == asset.model.asset_tracking_strategy
			.toString())
		ciClass = asset.model_category.cmdb_ci_class.toString();

function createAsset(asset){

  if (ciClass != '') {
    var ciSysId;
    var ci = new GlideRecord(ciClass);
    ci.initialize();
    ci.asset = asset.sys_id;
    ci.name = asset.model.name;
    // Populate manufacturer
    ci.manufacturer = asset.model.manufacturer;
   
    var sync = new AssetAndCISynchronizer();
    sync.syncRecordsWithoutUpdate(asset, ci, 'cmdb_ci', false);
   
    var assetCMDBUtil = new AssetCMDBUtil();
    if (asset.install_status != 2
      && !gs.nil(asset.serial_number)
      && assetCMDBUtil.isSerialNumberMandatory(asset.model_category)) {
      ci.name = asset.serial_number + ' - ' + asset.model.name;
      ciSysId = assetCMDBUtil.createCIUsingIRE(ci);
    } else {
      ciSysId = ci.insert();
    }
    asset.ci = ciSysId;
  }
}

lol no worries! Here is what I get - no success yet:

Evaluator: org.mozilla.javascript.EcmaError: "AssetCMDBUtil" is not defined.
   Caused by error in script at line 49

     46:     var sync = new AssetAndCISynchronizer();
     47:     sync.syncRecordsWithoutUpdate(asset, ci, 'cmdb_ci', false);
     48:    
==>  49:     var assetCMDBUtil = new AssetCMDBUtil();
     50:     if (asset.install_status != 2
     51:       && !gs.nil(asset.serial_number)
     52:       && assetCMDBUtil.isSerialNumberMandatory(asset.model_category)) {

Evaluator: org.mozilla.javascript.EcmaError: "AssetCMDBUtil" is not defined.
   Caused by error in script at line 26

     23: assets_no_ci.query();
     24: 
     25: while (assets_no_ci.next()) {
==>  26:  createAsset(assets_no_ci);
     27:   gs.log("Adding CI to Asset: " + assets_no_ci.display_name);
     28: }
     29: 

[0:00:00.078] Total Time

Ah we're getting there,

can you check your script include table and look for a record called AssetCMDBUtil. Looks like it currently doesn't exist as servicenow isn't able to find it, possible someone accidentally renamed it?

find_real_file.png

 

If you can't find it, create a new script include and call it AssetCMDBUtil and ensure you're in the global scope. copy the following script into the file and save it

var AssetCMDBUtil = Class.create();
AssetCMDBUtil.prototype = {
	initialize: function() {
		this.jsonApi = new global.JSON();
		this.cmdbApi = SNC.IdentificationEngineScriptableApi;
	},

	isSerialNumberMandatory: function(modelCategory) {
		if (gs.getProperty(AssetCMDBUtil.ASSET_IRE_PROPERTY) === 'true') {
			var modelCategoryGr = new GlideRecord('cmdb_model_category');
			if (modelCategoryGr.get(modelCategory)) {
				var ciClass = modelCategoryGr.getValue('cmdb_ci_class');
				if (!gs.nil(ciClass)) {
					var res = SNC.CmdbMetadataScriptableApi.hasSerialNumberRuleWithNoRelationship(ciClass);
					return res;
				}
			}
		}
		return false;
	},

	getMatchRuleInfo: function(attempts) {
		var matchRuleInfo = {};
		var attempt;
		if (gs.nil(attempts)) {
			return matchRuleInfo;
		}
		for (var element in attempts) {
			attempt = attempts[element];
			if (attempt.attemptResult === 'MATCHED') {
				matchRuleInfo.identifier = !gs.nil(attempt.identifierName) ? attempt.identifierName : '';
				matchRuleInfo.table = !gs.nil(attempt.searchOnTable) ? attempt.searchOnTable : '';
				matchRuleInfo.attributes = !gs.nil(attempt.attributes) ? attempt.attributes.join(', ') : '';
				break;
			}
		}
		return matchRuleInfo;
	},

	parseIDResult: function(result) {
		var idResultObj = {
			success: false,
			insert: false,
			sysId: null,
			className: null,
			attempts: [],
			matchedRule: {},
			errors: [],
		};

		if (JSUtil.nil(result) || JSUtil.nil(result.items) || !result.items.length || result.items.length > 1) {
			return idResultObj;
		}

		// There should be only one item returned
		var item = result.items[0];

		if (item.errors) {
			idResultObj.errors = item.errors;
			return idResultObj;
		}

		idResultObj.success = true;
		idResultObj.insert = item.operation === 'INSERT';
		idResultObj.matchedRule = this.getMatchRuleInfo(item.identificationAttempts);
		idResultObj.sysId = !gs.nil(item.sysId) ? item.sysId : null;
		idResultObj.className = item.className;
		idResultObj.attempts = item.identificationAttempts;

		return idResultObj;
	},

	checkInsertOrUpdate: function(input) {
		var result = this.jsonApi.decode(this.cmdbApi.identifyCI(input));
		return this.parseIDResult(result);
	},

	insertOrUpdate: function(source, input) {
		var result = this.jsonApi.decode(this.cmdbApi.createOrUpdateCI(source, input));
		return this.parseIDResult(result);
	},

	createCIUsingIRE: function(ci) {
		var ciJSON = {};
		var columnName;
		var fields = ci.getFields();
		for (var num = 0; num < fields.size(); num++) {
			columnName = fields.get(num).getName();
			if (columnName.indexOf('sys_') !== 0 && ci[columnName].changes()) {
				ciJSON[columnName] = ci.getValue(columnName);
			}
		}

		var payload = {
			items: [{
				className: ci.getTableName(),
				values: ciJSON,
			}],
		};
		var input = this.jsonApi.encode(payload);

		var ciSysId;
		var checkResult = this.checkInsertOrUpdate(input);
		if (!checkResult.success) {
			throw new Error(gs.getMessage('CMDB Identification Error occured during creation of CI'));
		}
		if (checkResult.success && !checkResult.insert && checkResult.sysId) {
			var link = '<a href=/cmdb_ci.do?sys_id=' + checkResult.sysId + '>Configuration Item</a>';
			var msg = gs.getMessage('Duplicate Entry - Matching {0} found', link);
			throw new Error(msg);
		} else {
			var insertOrUpdateResult = this.insertOrUpdate(AssetCMDBUtil.DISCOVERY_SOURCE, input);
			if (!insertOrUpdateResult.success) {
				throw new Error(gs.getMessage('CMDB Identification Error occured during creation of CI'));
			}
			if (insertOrUpdateResult.success && JSUtil.notNil(insertOrUpdateResult.sysId)) {
				ciSysId = insertOrUpdateResult.sysId;
			}
		}
		return ciSysId;
	},

	type: 'AssetCMDBUtil',
};
AssetCMDBUtil.ASSET_IRE_PROPERTY = 'glide.asset.create_ci_with_ire';
AssetCMDBUtil.DISCOVERY_SOURCE = 'SNAssetManagement';

 

It didn't seem to exist in our instance and I wasn't able to find anything similar.

After creating it, this is what I got:

Evaluator: org.mozilla.javascript.EvaluatorException: GlideRecord.insert() - invalid table name: null (<refname>; line 39)
   Line(39)
	} else {
evaluateString(JavaScript evaluation error on:
var queryStr = 'ciISEMPTY^model_category!=fed01818db93ff00c0ede66505961962^ORmodel_category=NULL^model_category!=996b568ec3102000b959fd251eba8f19^model_category!=218323293743100044e0bfc8bcbe5d61^model_category!=35bf2d4137101000deeabfc8bcbe5dbd^model_category!=c9d5bc50c3031000b959fd251eba8fbc^model_category!=83c92540732623008b516cb63cf6a7b1^model_category!=58fdb454c3031000b959fd251eba8ff0';
var assets_no_ci = new GlideRecord('alm_asset');
//assets_no_ci.addEncodedQuery(queryStr); //Commented to test with a single record
assets_no_ci.addQuery('serial_number', '041804401557'); //test this script with a single record
assets_no_ci.orderBy('model_category');
assets_no_ci.query();

while (assets_no_ci.next()) {
 createAsset(assets_no_ci);
  gs.log("Adding CI to Asset: " + assets_no_ci.display_name);
}

var ciClass = '';
		if ('leave_to_category' == asset.model.asset_tracking_strategy
			.toString())
		ciClass = asset.model_category.cmdb_ci_class.toString();

function createAsset(asset){

  if (ciClass != '') {
    var ciSysId;
    var ci = new GlideRecord(ciClass);
    ci.initialize();
    ci.asset = asset.sys_id;
    ci.name = asset.model.name;
    // Populate manufacturer
    ci.manufacturer = asset.model.manufacturer;
   
    var sync = new AssetAndCISynchronizer();
    sync.syncRecordsWithoutUpdate(asset, ci, 'cmdb_ci', false);
   
    var assetCMDBUtil = new AssetCMDBUtil();
    if (asset.install_status != 2
      && !gs.nil(asset.serial_number)
      && assetCMDBUtil.isSerialNumberMandatory(asset.model_category)) {
      ci.name = asset.serial_number + ' - ' + asset.model.name;
      ciSysId = assetCMDBUtil.createCIUsingIRE(ci);
    } else {
      ciSysId = ci.insert();
    }
    asset.ci = ciSysId;
  }
}
)
[0:00:00.055] Total Time

Added a few logging statements to get a bit more detail other than ci.insert failure.

var queryStr = 'ciISEMPTY^model_category!=fed01818db93ff00c0ede66505961962^ORmodel_category=NULL^model_category!=996b568ec3102000b959fd251eba8f19^model_category!=218323293743100044e0bfc8bcbe5d61^model_category!=35bf2d4137101000deeabfc8bcbe5dbd^model_category!=c9d5bc50c3031000b959fd251eba8fbc^model_category!=83c92540732623008b516cb63cf6a7b1^model_category!=58fdb454c3031000b959fd251eba8ff0';
var assets_no_ci = new GlideRecord('alm_asset');
//assets_no_ci.addEncodedQuery(queryStr); //Commented to test with a single record
assets_no_ci.addQuery('serial_number', '1234567890'); //test this script with a single record
assets_no_ci.orderBy('model_category');
assets_no_ci.query();

while (assets_no_ci.next()) {
 createAsset(assets_no_ci);
  gs.log("Adding CI to Asset: " + assets_no_ci.display_name);
}

function createAsset(asset){
  
  
  var ciClass = '';
		if ('leave_to_category' == asset.model.asset_tracking_strategy
			.toString())
		ciClass = asset.model_category.cmdb_ci_class.toString();

  gs.print("Class being used as reference table value is: " + ciClass");

  if (ciClass != '') {
    var ciSysId;
    var ci = new GlideRecord(ciClass);
    ci.initialize();
    ci.asset = asset.sys_id;
    ci.name = asset.model.name;
    // Populate manufacturer
    ci.manufacturer = asset.model.manufacturer;
   
    var sync = new AssetAndCISynchronizer();
    sync.syncRecordsWithoutUpdate(asset, ci, 'cmdb_ci', false);
   
    var assetCMDBUtil = new AssetCMDBUtil();
    if (asset.install_status != 2
      && !gs.nil(asset.serial_number)
      && assetCMDBUtil.isSerialNumberMandatory(asset.model_category)) {
      ci.name = asset.serial_number + ' - ' + asset.model.name;
      ciSysId = assetCMDBUtil.createCIUsingIRE(ci);
    } else {
      ciSysId = ci.insert();
    }
    asset.ci = ciSysId;
  }
}