Name
global.CimIDSensor
Description
Performs identification for CIM probe results.
Script
// Discovery
/**
* Performs identification for CIM probe results.
* @author roy.laurie
*/
var CimIDSensor = Class.create();
CimIDSensor._ATTRIBUTE_ID = '@id';
CimIDSensor.PARAMETER_SYS_ID = 'sys_id';
CimIDSensor.PARAMETER_INSTANCE = 'instance';
CimIDSensor.PARAMETER_INSTANCE_ID = 'instance_id';
CimIDSensor.PARAMETER_NAMESPACE = 'namespace';
CimIDSensor.PARAMETER_DEVICE_INSTANCE = 'device_instance'
CimIDSensor.prototype = Object.extendsObject(DiscoveryIDSensor, {
init: function(definition) {
DiscoverySensor.prototype.init.call(this, definition);
// use a device history just for this device within the CIMOM, unless it's the actual CIMOM itself
g_device = this.getDeviceHistoryGlobal();
},
/**
* CIM device history uses a hash of the device's CIMQL identity string and uses that
* as the device history source rather than IP, which is used in normal discoveries.
* IPs cannot be used here uniquely, as CIM probes query the CIMOM - or CIM Server - which may not
* necessarily be the same physical device as
* the one we're discovering.
* @override DiscoverySensor.prototype.getDeviceHistory
* @return DeviceHistoryJS
*/
getDeviceHistory: function() {
var source = this.getInstanceHashToken();
var status = this.getAgentCorrelator();
var classificationProbe = g_probe.getParameter('classification_probe');
var deviceHistory = new DeviceHistoryJS();
deviceHistory.setSource(source);
deviceHistory.setStatus(status);
deviceHistory.setClassificationProbe(classificationProbe);
deviceHistory.getDeviceRecord();
return deviceHistory;
},
getDeviceHistoryGlobal: function() {
var source = this.getInstanceHashToken();
var deviceHistory = SncDeviceHistory.createDeviceHistory(source, null, g_probe.getEccQueueId(), g_probe.getParameter('classification_probe'));
if (deviceHistory === null)
throw new DiscoveryException('Unable to determine current Device History for instance `' + source + '`.');
return deviceHistory;
},
getInstanceHashToken: function() {
var instanceToken = new CimInstanceToken(''+this.getParameter(CimIDSensor.PARAMETER_INSTANCE));
var hashToken = instanceToken.getHashToken(''+this.getSource());
return hashToken;
},
prepare: function() {
DiscoveryIDSensor.prototype.prepare.call(this);
},
/**
* Process all CIM Probe query results for a CIM ID Sensor.
* @param { name: [XMLObj(//cimqueryset/cimquery/result/instance)],.. } results
* @param CimCIData cimdata The CI data of the device being identified.
* @param CimIDSensor sensor This wrapping sensor (extends CimIDSensor).
* @throws DiscoveryException On error
*/ /*
function process(results, cimdata, sensor) {
} */
/**
* Runs a multi-probe script against a probe result. The function declaration is ahove.
* @param string script
* @param XMLObj(//result/results/result) probeResult
* @param string probeId
* @override
* @throws DiscoveryException On error.
*/
runMultiProbeScript: function(script, probeResult, probeRecord) {
try {
var queryResults = this._prepareQueryResults(probeResult, ''+probeRecord.sys_id);
var multiprobeFunction = new Function('results', 'cimdata', 'sensor', 'return (' + script + '(results, cimdata, sensor));');
var cimdata = new CimCIData(this.ciData);
multiprobeFunction(queryResults, cimdata, this);
} catch (e) {
throw new DiscoveryException('CIM MultiProbe script for probe `' + probeRecord.name + '` failed. ' + e, e);
}
},
/**
* Parses a CIM Probe result and returns all result instances, mapped by query name.
* @param XMLObj(//result) probeResult
* @return { name: XMLObject(//cimqueryset/result/instance) }
*/
_prepareQueryResults: function(probeResult, probeId) {
var namedQueries = new CimProbe(probeId).getNamedStatements();
var cimProbeResult = new CimProbeResult(probeResult);
return cimProbeResult.getNamedInstances(namedQueries);
},
/**
* Configure a triggered probe before it is launched.
* @param Probe probe Already configured and ready to fire.
* @return boolean Return TRUE to fire this probe, FALSE to skip it.
* @override
*/
configureTriggeredProbe: function(probe) {
probe.addParameter(CimIDSensor.PARAMETER_SYS_ID, ''+this.getCmdbCi());
probe.addParameter(CimIDSensor.PARAMETER_DEVICE_INSTANCE, this.getParameter(CimIDSensor.PARAMETER_INSTANCE));
probe.addParameter(CimIDSensor.PARAMETER_INSTANCE, this.getParameter(CimIDSensor.PARAMETER_INSTANCE));
probe.addParameter(CimIDSensor.PARAMETER_NAMESPACE, this.getParameter(CimIDSensor.PARAMETER_NAMESPACE));
probe.addParameter(CimIDSensor.PARAMETER_INSTANCE_ID, ''+this.getCmdbCi());
probe.addParameter('multipleOperationsSupported', this.getParameter('multipleOperationsSupported'));
new ProbeHandlerCim(probe).run();
return true;
},
updateDeviceCount: function() {
DiscoveryIDSensor.prototype.updateDeviceCount.call(this);
var history = DeviceHistory.getFromSourceAndStatusAndClassification(this.getSource(), this.getEccQueueId(), g_probe.getParameter('classification_probe'));
if (history !== null)
history.completed();
},
relateDiscoveredToDiscovers: function(discoveredSysId, discoversSysId) {
if (gs.nil(discoversSysId)) {
// determine the parent history id
var deviceHistory = this.getDeviceHistory();
var deviceHistorySysId = ''+deviceHistory.getDeviceRecord().sys_id;
var parentHistoryId = deviceHistory.getScratchpadValue('parentDeviceHistorySysId');
if (parentHistoryId === null)
return;
// create the encoded JSON string to search for all sibling histories for the same parent
var scratchPadStr = '"parentDeviceHistorySysId":"' + parentHistoryId + '"';
var discoveryStatusSysId = this.getAgentCorrelator();
// find the device histories that come from the same parent
var historiesGr = new GlideRecord('discovery_device_history');
historiesGr.addQuery('sys_id', '!=', deviceHistorySysId); // ignore current history history
historiesGr.addQuery('status', discoveryStatusSysId); // match against current status
historiesGr.addQuery('scratchpad', 'CONTAINS', scratchPadStr); // only child histories
historiesGr.query();
// find the history that created the WBEM Service CI
discoversSysId = null; // populate this ...
while (historiesGr.next()) {
if (historiesGr.cmdb_ci.sys_class_name == 'cmdb_ci_wbem_service') {
discoversSysId = ''+historiesGr.cmdb_ci.sys_id;
}
}
// skip if we did not find the WBEM Service CI
if (gs.nil(discoversSysId))
return;
}
// get the relationship type for later
var relTypeId = g_disco_functions.findCIRelationshipTypeByDesc('cmdb_rel_type', 'Discovers', 'Discovered from');
if (relTypeId === '')
throw 'Unable to find Discovers::Discovered from relationship type';
// determine if we need to create a relationship or not, which requires a mutex
var existingGr = new GlideRecord('cmdb_rel_ci');
existingGr.addQuery('parent', discoversSysId); // wbem service
existingGr.addQuery('type', relTypeId); // discovered :: discovers
existingGr.addQuery('child', discoveredSysId);
existingGr.query();
if (existingGr.hasNext())
return;
// lock on insert, to prevent dupes between discovered and discovers sensor race conditions
var key = 'discoveredToDiscovers:' + discoversSysId;
var mutexMetricName = 'CimIDSensor';
var mutex = new SelfCleaningMutex(key, mutexMetricName);
mutex.setSpinWait(200); // 200 ms
mutex.setMaxSpins(1500); // 5 mins
if (mutex.get()) {
// re-query after the lock
existingGr.query();
if (existingGr.hasNext())
return;
try {
var relGr = new GlideRecord('cmdb_rel_ci');
relGr.parent = discoversSysId;
relGr.type = relTypeId;
relGr.child = discoveredSysId;
relGr.insert();
} finally {
mutex.release();
}
} else {
this.warn('Unable to create to lock on CimSensor mutex for: ' + key);
}
},
after: function() {
DiscoveryIDSensor.prototype.after.apply(this, arguments);
// relate discovered to discovers
if (this.getParameter('relate_discovered_to_discovers') != 'true')
return;
// CISysID is set after either a successful identify() or insert()
this.relateDiscoveredToDiscovers(''+this.CISysID);
},
type: 'CimIDSensor'
});
Sys ID
1e178d9f3781200032ff8c00dfbe5d1b