Name

global.CloudWizardDiscovery

Description

This class contains all common methods that are used for the Discovery scheduler Wizard Configuration

Script

var CloudWizardDiscovery = Class.create();
CloudWizardDiscovery.prototype = Object.extendsObject(CloudDiscovery, {
  initialize: function() {
  	this._isAllowed(this.type); 
  }, 

  validateAccount: function(obj,midServer) {
  	this._debug("validateAccount-> Start configObj-" , obj);
  	var configObj = this._createEmptyConfigObj();
  	configObj.service_account.name = String(obj.accountName);
  	configObj.service_account.account_id = String(obj.accountId);
  	configObj.service_account.discovery_credentials = String(obj.accountCredentialsId);
  	configObj.service_account.datacenter_url = String(obj.accountUrl);
  	configObj.service_account.datacenter_type = String(obj.accountType);
  	configObj.service_account.parent_account = String(obj.parentAccount);
  	configObj.service_account.accessor_account = String(obj.accessorAccount);
  	configObj.service_account.existing_access_role_name = String(obj.existingAccessRoleName);
  	configObj.service_account.existing_accessor_account_ref = String(obj.existingAccessorAccountRef);
  	configObj.service_account.existing_credentials_ref = String(obj.existingCredentialsRef);
  	
  	var probeParams = {};
  	var probeValues = {"ecc_high_priority" : true};
  	var nextPatternId = this._getPatternId( obj.accountType, this.SPECIAL_PATTERNS.ACCOUNT_VALIDATION);
  	var invocationContext = {};
  	invocationContext['service_account_id'] = configObj.service_account.account_id;
  	var midName = midServer ? midServer : this._getAutoMid(configObj.service_account.datacenter_type, JSON.stringify(invocationContext));
  	
  	//Create dummay service account table(just for validation)
  	var SA = {
  		"discovery_credentials": String(obj.accountCredentialsId),
  		"discovery_source": "ServiceNow",
  		"datacenter_url": String(obj.accountUrl),
  		"object_id": String(obj.accountId),
  		"name": String(obj.accountName),
  		"sys_class_name": "cmdb_ci_cloud_service_account",
  		"datacenter_type": String(obj.accountType),
  		"account_id": String(obj.accountId),
  		"is_master_account": "false", //Should be changed if needed by validation
  		"parent_account": String(obj.parentAccount),
  		"accessor_account": String(obj.accessorAccount),
  		"existing_access_role_name": String(obj.existingAccessRoleName),
  		"existing_accessor_account_ref": String(obj.existingAccessorAccountRef),
  		"existing_credentials_ref": String(obj.existingCredentialsRef)
  	};

  	// Before we trigger pattern lets check if user has provided any form fields data.
  	// Form Fields data is something which is a fixed data which cloud resources discovery pattern(s) needs them
  	// and each field is the field in cloud service account needs so we pass that data to the patterns as they're
  	// responsible for inserting/updating cloud service account
  	if (obj.hasOwnProperty('formFieldsData'))
  		SA['formFieldsData'] = obj['formFieldsData'];

  	var ppe = new SNC.PrePatternExecutionData();
  	ppe.addTableEntry('service_account', SA);
  	
  	//In case of Validation don't create auto relations
  	ppe.addString('build_relation_from_host_sys_id','false'); // Don't take the host from the real CI table instead of the computerSystem
  	ppe.addString('no_relation','true'); //Refrain of creating auto relation (all the relation will be done by the pattern itself)
  	
  	this.statusId = this._createDiscoveryStatus("Perform validation account-"+obj.accountId, this.type);
  	this._invokePhase(configObj, nextPatternId, midName, probeParams, probeValues, ppe, 'Account Validation');
  	
  	this._debug("validateAccount->invoke validateAccount Phase end-" ,  configObj);
  	return this.statusId;
  },
  
  refreshMemberAccounts: function(accountSysId, midServer) {
  	this._debug("refreshMemberAccounts-> Start accountSysId" , accountSysId);
  	var res = this._refreshData(accountSysId, this.SPECIAL_PATTERNS.ACCOUNTS_DISCOVERY, midServer);
  	this._debug("refreshMemberAccounts-> End accountSysId" , accountSysId);
  	return res;
  },
  
  refreshDatacenters: function(accountSysId,midServer, memberAccounts) {
  	this._debug("refreshDatacenters-> Start accountSysId" , accountSysId);
  	var SA = this._getAccountGR(String(accountSysId)),
  		serviceAccountGR = new GlideRecord("cmdb_ci_cloud_service_account"),
  		masterAndMembersAccount = {};
  		masterAndMembersAccount[String(accountSysId)] = true;
  	if(typeof memberAccounts !== 'undefined') {
  		 memberAccounts.forEach(function(o){
  			masterAndMembersAccount[String(o.sysId)] = true;
  		});
  	} else {
  		if (String(SA.datacenter_type) == 'cmdb_ci_google_datacenter' && SA.organization_id) {
  			serviceAccountGR.addQuery("organization_id", String(SA.organization_id));
  			serviceAccountGR.addQuery("sys_id","!=", String(accountSysId));
  		} else
  			serviceAccountGR.addQuery("parent_account", accountSysId);
  		serviceAccountGR.addQuery('install_status','!=','7'); // We should only add those member accounts whose install_status is not retiered
  		serviceAccountGR.query();
  		while (serviceAccountGR.next()) {
  			masterAndMembersAccount[String(serviceAccountGR.getUniqueValue())] = true;
  		}
  	}
  	var res = this._refreshDataCenter(masterAndMembersAccount, this.SPECIAL_PATTERNS.LDCS_DISCOVERY, midServer);
  	this._debug("refreshDatacenters-> End accountSysId" , accountSysId);
  	return res;
  },
  
  getDiscoveryResult: function(statusSysId) {
  	var myError = new sn_ws_err.ServiceError();
  	var obj = {
  		"state": "processing",
  		"message" : "",
  		"ci_list" : []
  	};

  	if (gs.nil(statusSysId)){
  		gs.error("getDiscoveryResult- Missing mandatory input statusSysId");
  		myError.setStatus(500);
  		myError.setMessage("getDiscoveryResult- Missing mandatory input statusSysId parameters" );
  		myError.setDetail("Here are the details of the arguments passed to this script " + JSON.stringify(statusSysId, null, 2));
  		return myError;				
  	}
  	
  	var statsGr = new GlideRecord('discovery_status');
  	if (!statsGr.get( String(statusSysId) )) {
  		gs.error("getDiscoveryResult- can't find statusSysId[{0}]", statusSysId);
  		myError.setStatus(500);
  		myError.setMessage("Can't find statusSysId-" + statusSysId);
  		return myError;
  	}
  	var state = statsGr.getValue("state");
  	if (state != "Completed"){
  		return obj; //Meaning still processing ...
  	}

  	var gr = new GlideRecord("discovery_device_history");
  	gr.addQuery("status", statusSysId);                                             
  	gr.query();               

  	var ciSysIdList=[];
  	while (gr.next()){
  		if (!gs.nil(gr.getValue("cmdb_ci")))
  			ciSysIdList.push(gr.getValue("cmdb_ci"));
  	}  

  	gr = new GlideRecord("cmdb_ci");
  	gr.addQuery("sys_id", "IN", ciSysIdList);                                             
  	gr.query();
  	var tmpl = {};
  	while (gr.next()){
  		tmpl = {
  			"sys_id": gr.getValue("sys_id"),
  			"sys_class_name": gr.getValue("sys_class_name"),
  			"name": gr.getValue("name")
  		};

  		var grSA = new GlideRecord(tmpl.sys_class_name);
  		grSA.get(tmpl.sys_id);
  		tmpl.object_id =  grSA.getValue("object_id");
  			
  		if (tmpl.sys_class_name == "cmdb_ci_cloud_service_account"){	
  			tmpl.is_master_account =  JSUtil.getBooleanValue(grSA, "is_master_account");
  			tmpl.datacenter_url =  grSA.getValue("datacenter_url");
  			tmpl.datacenter_type = grSA.getValue("datacenter_type");
  			tmpl.parent_account = grSA.getValue("parent_account");
  			tmpl.account_id  = grSA.getValue("account_id");
  			tmpl.discovery_credentials =  grSA.getValue("discovery_credentials");
  			tmpl.sys_updated_on =  grSA.getValue("sys_updated_on");
  			tmpl.organization_id =  grSA.getValue("organization_id");
  			tmpl.exclude_from_discovery = (grSA.getValue("exclude_from_discovery") == 1);
  		}
  		obj.ci_list.push(tmpl);
  	} 

  	if (ciSysIdList.length > 0 ){
  		obj.state = "success";
  	} else {
  		//Grab the error if exists
  		
  		//Pick up the error message from automation_error_instance_msg based on the discovery status if exists.
  		var errorMessage = '';
  		var errInstanceGr = new GlideRecord('automation_error_instance_msg');
  		errInstanceGr.query('instance_key', statusSysId);

  		if (errInstanceGr.next())
  			errorMessage = String(errInstanceGr.err_msg.message);
  		else {
  			//Pick up the error message from discovery_log only if automation_error_instance_msg doesn't exist for the status. This happens when cmdb_ci is empty in the device_history.
  			errorMessage = this._getErrorOrInfoForDiscoveryStatusFromDiscoveryLog(statusSysId,2);  // check for errors in discovery_log table
              		if (!errorMessage)
              			errorMessage = this._getErrorOrInfoForDiscoveryStatusFromDiscoveryLog(statusSysId,0);   // check for information in discovery_log table

              		//Send this error message if we can't figure out the exact message based on the above two tables.
  			if (!errorMessage)
              			errorMessage = "An error occurred while trying to discover";
  		}

  		obj.message = errorMessage;
  		obj.state = "error";
  	}  	

  	return obj;	
  },

  _getErrorOrInfoForDiscoveryStatusFromDiscoveryLog: function(statusSysId, logLevel) {
      	if (!statusSysId)
  		return;
  	var discoveryLogGr = new GlideRecord('discovery_log');
  	discoveryLogGr.addQuery('status', statusSysId);
  	discoveryLogGr.setLimit(1);
  	if (logLevel == 2) {               //check for error
  		discoveryLogGr.addQuery('level', 2);
  		discoveryLogGr.query();
  		if (!discoveryLogGr.next())
  			return;
  		if (!discoveryLogGr.message)
  			return;
  		var errorMsg = discoveryLogGr.message + '';
  		var isThisNotPatternErrorMsg = (errorMsg.indexOf('To Check Pattern Log Press') == -1);
  		return isThisNotPatternErrorMsg ? errorMsg : this._extractHTMLTagsFromPatternErrorMsg(errorMsg);
  	}
  	discoveryLogGr.addQuery('level', 0);
  	discoveryLogGr.addQuery('message', 'CONTAINS', 'To Check Pattern Log Press');
  	discoveryLogGr.addQuery('source', 'DiscoverySensor');
  	discoveryLogGr.query();
  	if (!discoveryLogGr.next())
  		return;
  	return this._extractHTMLTagsFromPatternErrorMsg(discoveryLogGr.message + '');
  },

  _extractHTMLTagsFromPatternErrorMsg: function (errorMessage) {
  	var regexToRemoveHTMLTags = /(<|\[)(.|\n)*?(>|\])/g;
  	var message = errorMessage.split(',');
  	if (message[0] && message[1])
  		return (message[0].replace(regexToRemoveHTMLTags, "") + " " + message[1].replace(regexToRemoveHTMLTags, ""));
  	return null;
  },

  _refreshData: function( accountSysId, patternType, midServer) {
  	var msg = (patternType === this.SPECIAL_PATTERNS.LDCS_DISCOVERY) ? 'Refresh Datacenters' : 'Refresh Member Accounts' ;
  	this._debug("_refreshData-> Start -"+ msg , accountSysId);
  	
  	var SA = this._getAccountGR(String(accountSysId));
  	var configObj = this._createEmptyConfigObj();
  	configObj.service_account.sys_id = String(accountSysId);
  	configObj.service_account.datacenter_type = String(SA.datacenter_type);
  	configObj.service_account.account_id	=  String(SA.account_id);
  	configObj.service_account.is_master_account = SA.getValue("is_master_account");

  	this.statusId = this._createDiscoveryStatus("Perform "+ msg + " for account-"+configObj.service_account.account_id, this.type);

  	var probeParams = {};
  	var probeValues = {"computer": configObj.service_account.sys_id, "ecc_high_priority" : true};
  	var ppe = this._buildPPE(configObj.service_account.sys_id);
  	var nextPatternId = this._getPatternId( configObj.service_account.datacenter_type , patternType);
  	var invocationContext = {};
  	invocationContext['service_account_id'] = configObj.service_account.account_id;
  	var midName = midServer ? midServer : this._getAutoMid(configObj.service_account.datacenter_type, JSON.stringify(invocationContext));
  	
  	if (nextPatternId && probeParams && ppe && probeValues){
  		this._invokePhase(configObj, nextPatternId, midName, probeParams, probeValues, ppe, msg);
  	} else {
  		this._handleError("_refreshData-> Error invocation of next phase missing mandatory parms -", { "configObj": configObj,
  																									  "nextPatternId": nextPatternId,
  																									  "probeParams": probeParams,
  																									  "probeValues": probeValues,
  																									  "ppe" : ppe										  
  																									}, {});
  		return null;
  	}
  	this._debug("_refreshData->Phase end-" + msg ,  configObj);
  	return this.statusId;
  },
  	
  
  _refreshDataCenter: function(listAccountSysId , patternType, midServer) {
  	var msg = (patternType === this.SPECIAL_PATTERNS.LDCS_DISCOVERY) ? 'Refresh Datacenters' : 'Refresh Member Accounts' ;
  	
  	
  	this.statusId = this._createDiscoveryStatus("Perform "+ msg + " for accounts", this.type);
  	var configObj ={};
  	for (var item in  listAccountSysId){
  		this._debug("_refreshDataCenter-> Start -"+ msg , String(item) );
  		var SA = this._getAccountGR(String(item));
  		configObj = this._createEmptyConfigObj();
  		configObj.service_account.sys_id = String(item);
  		configObj.service_account.datacenter_type = String(SA.datacenter_type);
  		configObj.service_account.account_id	=  String(SA.account_id);
  		configObj.service_account.is_master_account = SA.getValue("is_master_account");
  		
  		var probeParams = {};
  		var probeValues = {"computer": configObj.service_account.sys_id, "ecc_high_priority" : true };
  		var ppe = this._buildPPE(configObj.service_account.sys_id);
  		var nextPatternId = this._getPatternId( configObj.service_account.datacenter_type , patternType);
  		var invocationContext = {};
  		invocationContext['service_account_id'] = configObj.service_account.account_id;
  		var midName = midServer ? midServer : this._getAutoMid(configObj.service_account.datacenter_type, JSON.stringify(invocationContext));
  		
  				
  		if (nextPatternId && probeParams && ppe && probeValues){
  			this._invokePhase(configObj, nextPatternId, midName, probeParams, probeValues, ppe, msg+  "-" +configObj.service_account.account_id );
  		} else {
  			this._handleError("_refreshDataCenter-> Error invocation of next phase missing mandatory parms -", { "configObj": configObj,
  																										  "nextPatternId": nextPatternId,
  																										  "probeParams": probeParams,
  																										  "probeValues": probeValues,
  																										  "ppe" : ppe										  
  																										}, {});
  			return null;
  		}
  	}
  	

  	this._debug("_refreshDataCenter->Phase end-" + msg ,  configObj);
  	return this.statusId;
  },
  
  
  type: 'CloudWizardDiscovery'

});

Sys ID

4b4c7dd0c75423000a1123622b976351

Offical Documentation

Official Docs: