Name

global.ClassifierProbes

Description

Provides classifier probe launch facility.

Script

// Discovery class

/**
* Provides classifier probe launch facility.  Encapsulates an array of probe information records, initialized either from a 
* JavaScript array or the XML serialized version. 
* 
* Tom Dilatush tom.dilatush@service-now.com 
*/
var ClassifierProbes = Class.create();

ClassifierProbes.prototype = {
  initialize: function(source, deviceHistoryParams) {
      if (JSUtil.nil(source))
          this.probeInfo = [];
      else if ((typeof source == 'object') && (source instanceof Array))
          this.probeInfo = source;
  	else
  		this.probeInfo = JS2XML.fromXML('' + source);
  	
  	// will be used to launch new classification probes
  	this.deviceHistoryParams = deviceHistoryParams instanceof String ? JSON.parse(deviceHistoryParams.toString()) : deviceHistoryParams;
  	
      // sort the array in priority order...
      this.probeInfo.sort(function(a, b) {
          return a['classificationPriority'] - b['classificationPriority'];
      });
  },
  
  getClassificationProbes: function(portProbe) {
  	var gr = new GlideRecord('trigger_probe_m2m');
  	gr.addQuery('port_probe', portProbe);
  	gr.addQuery('active', true);
  	gr.query();
  	return gr;
  },

  /*
   * Check to see if there are any host classification probes left to trigger
   */
  hostClassificationDone: function() {
  	
  	for (var i = 0; i < this.probeInfo.length; i++) {
  		var probeInfo = this.probeInfo[i];
  		var classificationProbesGr = this.getClassificationProbes(probeInfo.portProbeID);
  		
  		while (classificationProbesGr.next()) {
  			var probeGr = new SNC.ProbeCache().getBySysId(classificationProbesGr.getValue('classification_probe'));
  			if (probeGr.host_classification)
  				return false;
  		}
  	}
  			
  	return true;
  },

  /*
   * Launch the next highest priority classifier from those in our list.  If a classifier is launched, return true.
   */
  launch: function() {
      if (this.probeInfo.length < 1)
          return false;

  	/*
  	*  The classification priority tells us in general what port Discovery should go after first, however, 
  	*  If there's service affinity record, use it instead!
  	*/
  	var ipServiceAffinity = JSUtil.toBoolean(gs.getProperty("glide.discovery.ip_service_affinity", "false"));	
  	if (ipServiceAffinity && this.probeInfo.length > 1)
  		this.probeInfo = this._sortByServiceAffinity(this.probeInfo);
  					
      // get our probe info, for the highest priority classifier probe...
      var probeInfo = this.probeInfo.shift();
      return this._launchProbeInfo(probeInfo);
  },
 
  launchSupplementary: function() {
  	for (var i = 0, n = this.probeInfo.length; i < n; ++i) {
  		var probeInfo = this.probeInfo.shift();
  		if (probeInfo === null || !probeInfo.supplementary)
  			continue;
  		
  		probeInfo.is_supplementary = true;
  		this._launchProbeInfo(probeInfo);
  	}	
  },
 
  _launchProbeInfo: function(probeInfo) {
  	//Extracting parameters to create DeviceHistory
  	var ip = this.deviceHistoryParams.result.ip;
  	var eccQueueId = this.deviceHistoryParams.ecc_queue;
  	var result = this.deviceHistoryParams.result;
  	var status = this.deviceHistoryParams.status;
  	var errMsgs = this.deviceHistoryParams.errMsgs;
  	var dnsName = this.deviceHistoryParams.dns_name;
  	var classificationProbesGr = this.getClassificationProbes(probeInfo.portProbeID);

  	// sequentially launch classification probes linked to port probe
      while(classificationProbesGr.next()) {
  		var classificationProbe = classificationProbesGr.getValue('classification_probe');
  		var mutexName = this.getMutexName(ip, status, classificationProbe);
  		var classificationMutex = new Mutex(mutexName);
  		classificationMutex.setSpinWait(200);       // time to wait between attempts, in ms
  		classificationMutex.setMaxSpins(125);       // maximum number of times to try

  		if (classificationMutex.get()) {
  			try {
  				var g_device = DeviceHistory.getFromSourceAndStatusAndClassification(ip, status.sysID, classificationProbe);
  				if (!this.hasMultipleIpServices(probeInfo.portProbeID) && !JSUtil.nil(g_device) && !this.operatesOnMultiplePorts(classificationProbe))
  					continue;
  				// create device history here to prevent duplicate inserts
  				if (!g_device)
  					g_device = DeviceHistory.createDeviceHistory(ip, null, eccQueueId, classificationProbe);
  			}
  			finally {
  				classificationMutex.release();
  			}
  			
  			if (!JSUtil.nil(dnsName))
  				g_device.setDNSName(dnsName);

  			g_device.state('Active', result.active ? 'Classifying' : '', status.logStateChanges, 'Shazzam', eccQueueId);
  			for (var i = 0; i < errMsgs.length; i++) {
  				DiscoveryLogger.warn(errMsgs[i], 'Shazzam', this.getEccQueueId(), null);
  				g_device.issue();
  			}

  			var probe = Probe.getById(classificationProbe);

  			probe.setSource(probeInfo.ip);
  			probe.setMidSelectDetails(probeInfo.mid_selector_details);
  			probe.addParameter('use_class', probeInfo.classificationTable);
  			probe.addParameter('port_probe', probeInfo.portProbeID);
  			probe.addParameter('port', probeInfo.scannerPort);
  			probe.addParameter('discover', probeInfo.discover);
  			probe.addParameter('deviceHistoryParams', JSON.stringify(this.deviceHistoryParams));
  			probe.addParameter('classification_probe', classificationProbe);

  			if (probeInfo.ciSysID)
  				probe.addParameter('cmdb_ci', probeInfo.ciSysID);
  			if (probeInfo.ciData)
  				probe.addParameter('cidata', probeInfo.ciData);
  			if (GlideHostUtil.isLocalhost(probeInfo.ip)) {
  				var aka = StringUtil.join(GlideHostUtil.getNonLoopbackIPs());
  				probe.addParameter( 'aka', aka);
  			}
  			if (this.probeInfo.length > 0)
  				probe.addParameter('classifiers', JS2XML.toXML(this.probeInfo));
  			if (probeInfo.is_supplementary)
  				probe.addParameter('is_supplementary', '1');
  			if (probeInfo.priority)
  				probe.setEccPriority(probeInfo.priority);
  			var midServer = new MIDServer(probeInfo.midServerID);
  			probe.create('mid.server.' + midServer.name, probeInfo.shazzamSensorID);
  		}
  	}
  	return true;
  },

  /*
  * If the classification probe is triggered by multiple port probes, it probably operates on multiple ports
  * for example: Windows - Classify is triggered by wmi, winrm, winrm_ssl
  */
  operatesOnMultiplePorts: function(classificationProbe) {
  	var gr = new GlideAggregate('trigger_probe_m2m');
  	gr.addQuery('classification_probe',classificationProbe);
  	gr.addQuery('active', true);
  	gr.query();
  	return gr.getRowCount() > 1;
  },
  
  getMutexName: function(source, status, classificationProbe) {
  	return "Classifierprobe_" + source + status + classificationProbe;
  },

  /*
  * If port affinity is found and it exists in the port probes being launched, bring the particualr port probe to the start of the queue...
  */
  _sortByServiceAffinity: function(probeInfo) {
  	var ipsa = new IPServiceAffinity(probeInfo[0].ip)
  	var port = ipsa.getServicePort();
  	
  	if (JSUtil.nil(port)) 
  		return probeInfo;
  		
  	var newArr = [];
  	for (var i=0; i<probeInfo.length; i++) {				
  		var pprobe = probeInfo[i];				
  		if (pprobe.scannerPort == port)
  			newArr.unshift(pprobe); // move it to the beginning of the array
  		else
  			newArr.push(pprobe);				
  	}
  	
  	return newArr;							
  },

  hasMultipleIpServices: function(portProbe) {
  	var gr = new GlideRecord('discovery_port_probe');
  	gr.addQuery('sys_id', portProbe);
  	gr.query();
  	gr.next();
  	return gr.services.split(',').length > 1;
  },

  size: function() {
      return this.probeInfo.length;
  },
  
  type: "ClassifierProbes"
}

Sys ID

cea19a970ab3015300f10bda87362122

Offical Documentation

Official Docs: