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