Name
sn_agent.AgentDiscoveryHandlerADMHelper
Description
No description available
Script
var AgentDiscoveryHandlerADMHelper = Class.create();
AgentDiscoveryHandlerADMHelper.prototype = {
initialize: function(tcp_connections, runningProcess, ciSysId) {
this.running_processes = runningProcess;
this.connections = tcp_connections;
this.ciSysId = ciSysId;
},
/**
*
* This is an exact replica of DiscoveryADMSensor finish block
* Unlike DiscoveryADMSensor this does not depend on discoverysensor script include
*
**/
addConnectionsAndRelationshipsToCMDB: function(postionInCIJson, hostname, agentGr) {
// massage our raw connections data a bit...
this.connections = new global.CookConnections('' + this.ciSysId).process(this.connections);
// enrich the connections and running processes...
var epac = new global.EnrichProcessesAndConnections(this);
epac.process();
var ciSysId = this.ciSysId;
var relatedData = {
running_processes: this.running_processes,
connections: this.connections,
getCmdbCi: function() {
return ciSysId;
},
};
var adm = new global.ApplicationDependencyMapping(relatedData);
// filter the running processes for only things that we classify...
if (gs.getProperty('glide.discovery.active_processes_filter', 'false') == 'true' &&
gs.getProperty('glide.discovery.auto_adm', 'false') != 'true')
running_processes = adm.matched_processes;
this.runningProcessReconcile(epac, ciSysId, this.running_processes);
var relatedListdataObj = {};
relatedListdataObj['cmdb_tcp'] = {
data: this.connections,
refName: 'computer',
keyName: 'type,ip,port,pid',
deleteGr: false
};
var cmdbGr = new GlideRecord("cmdb_ci");
cmdbGr.get("sys_id", ciSysId);
new global.DiscoveryReconciler(cmdbGr, relatedListdataObj).process();
var applClassificationBehavior = this.getApplicationClassificationBehavior();
switch (applClassificationBehavior) {
case 'simple':
return this.createApplicationCIs(adm.matched_processes, postionInCIJson, hostname);
case 'full':
if (!GlidePluginManager.isActive('com.snc.discovery')) {
gs.warn("In AgentDiscoveryHandlerADMHelper.addConnectionsAndRelationshipsToCMDB: Cannot trigger application patterns on agent as 'com.snc.discovery' plugin is not activated.");
return;
}
gs.debug("In AgentDiscoveryHandlerADMHelper.addConnectionsAndRelationshipsToCMDB: Triggering application patterns for CI.sysId = " + ciSysId);
this.triggerPatternExecution(relatedData, adm, agentGr); //launch Application Patterns
break;
}
},
/**
*
* Need to overwrite this since RunningProcessReconciler needs the Ci Sysid
* by default EnrichProcessesAndConnections looks at discoverysensor script include
*
**/
runningProcessReconcile: function(epac, ciSysId, running_process) {
// rebuild the process tree roots
epac.rps = running_process;
epac.indexPIDs();
epac.buildProcessTree();
// get rid of any nonsense connections...
epac.noNonsense();
// flip any "to" connections to "on" connections that need to be flipped
epac._flipAllConnections();
// Remove connections if process or any parent process has the same listening port as the process
// The order is important that this follows _flipAllConnections
epac._removeConnections();
// fix up the values in the sensor...
epac.sensor.running_processes = epac.rps;
epac.sensor.connections = epac.conns;
epac.fixProcessPorts();
// reconcile the running processes...
var rpr = new global.RunningProcessReconciler(ciSysId, epac.rps, epac.processTreeRoots, epac.byPID);
rpr.reconcile();
// now that we've got process sys_ids, fix up our connection references...
epac.fixConnectionField('sys_id', 'process');
// deduplicate connections before reconciling...
epac.dedupeConnections();
},
/**
*
* Inputs:
* - ADM matched processes
* - CI reference in IRE payload
* - hostname
*
* Loops through all the ADM matches process and creates Application CI with relationship records
*
**/
createApplicationCIs: function(matched_processes, currentPositioninCIJson, hostname) {
var pidToPorts = this.getProcessWithAssociatedPorts(this.connections);
var applicationCIPosition = currentPositioninCIJson;
var items = [];
var relations = [];
var references = [];
for (var process in matched_processes) {
var matchedProcess = matched_processes[process];
if (!matchedProcess.computer) {
gs.info('No computer field in on the matchedProcess. application CI will not be created');
continue;
}
var applicationCI = {};
applicationCI['className'] = matchedProcess.classifier.table;
var applicationCIValues = {};
applicationCI['values'] = applicationCIValues;
var tcpPort = pidToPorts[matchedProcess.pid];
if (typeof tcpPort != 'undefined') {
if (tcpPort.substring(1).indexOf(':') == tcpPort.length - 2) {
tcpPort = tcpPort.substring(1, tcpPort.length - 1);
}
applicationCIValues['tcp_port'] = tcpPort;
}
applicationCIValues['running_process_command'] = matchedProcess['command'];
applicationCIValues['running_process_key_parameters'] = matchedProcess['key_parameters'];
var applicationCIGr = new GlideRecord(matchedProcess.classifier.table);
var appName = applicationCIGr.getClassDisplayValue();
appName = appName + '@' + hostname;
applicationCIValues['name'] = appName;
// Find the running process sys_id
var processGr = new GlideRecord('cmdb_running_process');
processGr.addQuery('computer', matchedProcess.computer);
processGr.addQuery('pid', matchedProcess.pid);
processGr.query();
if (processGr.next())
applicationCIValues['running_process'] = processGr.getUniqueValue();
else
gs.info('process ' + matchedProcess.pid + ' not found on computer ' + matchedProcess.computer);
items.push(applicationCI);
relations.push(this.addRelationForPositionsAndType("Runs on::Runs", applicationCIPosition, 0));
applicationCIPosition++;
}
return [items, relations];
},
/**
*
* helper to add relationship
*
**/
addRelationForPositionsAndType: function(type, parent, child) {
var relationJsonObj = {};
relationJsonObj.type = type;
relationJsonObj.parent = parent;
relationJsonObj.child = child;
return relationJsonObj;
},
/**
*
* Construct PID to Ports mapping
*
**/
getProcessWithAssociatedPorts: function(connections) {
var pidToPorts = {};
if (connections != null && typeof connections != 'undefined' && connections.length > 0) {
for (var idx = 0; idx < connections.length; idx++) {
var tcp = connections[idx];
this.addPortToPID(pidToPorts, tcp.pid, tcp.port);
}
}
return pidToPorts;
},
/**
*
* Format ports with ":" separator.
* handle multiple ports found for PID
*
**/
addPortToPID: function(pidToPorts, pid, port) {
var ports = pidToPorts[pid];
if (typeof ports == 'undefined') {
pidToPorts[pid] = ':' + port + ':';
} else {
if (!ports.includes(':' + port + ':')) {
pidToPorts[pid] = ports + port + ':';
}
}
},
/*
*
* Trigger pattern execution on agent
* Input: relatedData - reference to object that has ADM info.
* adm - reference to global.ApplicationDependencyMapping
* agentGr - agent GlideRecord
*
**/
triggerPatternExecution: function(relatedData, adm, agentGr) {
if (!agentGr) {
gs.error("Error in AgentDiscoveryHandlerADMHelper.triggerPatternExecution: Cannot execute Application Patterns on agents for CI.sysId = " + this.ciSysId + ", 'agentGr' is not defined");
return;
}
try {
var agentInfo = this.getAgentInfo(agentGr);
//cannot trigger application patterns if agentId & osType are undefined
if (Object.keys(agentInfo).length == 0 || !agentInfo.agentId || !agentInfo.osType)
return;
var _this = this;
relatedData.accAgentId = agentInfo.agentId;
relatedData.getCmdbRecord = function() {
return _this.getCmdbRecord();
};
adm.sensor = relatedData;
gs.debug("In AgentDiscoveryHandlerADMHelper, adm.sensor.accAgentId =" + adm.sensor.accAgentId);
adm.initializeForMapping(this.ciSysId);
adm.matches = adm.get_matches();
var agentGlobalsHelper = new global.AgentGlobalsHelper();
agentGlobalsHelper.setOSType(agentInfo.osType); //set necessary global variables
// relatedData serves as g_sensor mainly to fetch CI info. in ADM script include
agentGlobalsHelper.setSensor(relatedData);
agentGlobalsHelper.setSource(agentInfo.ipAddress);
this.process(adm, agentInfo);
} catch (e) {
gs.error("Exception occurred in AgentDiscoveryHandlerADMHelper.triggerPatternExecution for the agent = " + agentInfo.ipAddress + ", error due to :", e);
}
},
getApplicationClassificationBehavior: function() {
return '' + gs.getProperty('sn_agent.appl_classification_behavior', 'simple');
},
/*
* This method does the actual application dependency mapping:
* First it classifies the running processes, then it launches probes for the matched processes
*/
process: function(adm, agentInfo) {
this.indexByID(); // required to find the matching pid within sn_agent scope
adm.procByID = this.procByID; // ensures that ADM.putScriptGlobals sets necessary global variables
this.classified = adm.classify();
this.launchProbes(this.classified, adm, agentInfo);
},
/**
* Make a map (in this.procByID) of all running processes by ID.
*/
indexByID: function() {
this.procByID = {};
for (var i = 0; i < this.running_processes.length; i++) {
var proc = this.running_processes[i];
this.procByID[proc.sys_id] = proc;
}
},
/**
* Launch probes for matching classified processes as needed.
*/
launchProbes: function(classified, adm, agentInfo) {
for (var rp in classified) {
var match = classified[rp];
// get the probes we need to trigger; bail out if there weren't any...
var probes = this.getTriggeredProbes(match, adm);
if (!probes)
continue;
var proc = this.procByID[match.running_process];
try {
adm.createPatternProbeForAgent(agentInfo, match, proc, probes);
} catch (e) {
gs.error("Exception occurred in AgentDiscoveryHandlerADMHelper.launchProbes for the agent = " + agentInfo.ip_address + ", due to :", e);
}
}
},
getTriggeredProbes: function(match, adm) {
// first, figure out which probes, if any, we need to launch...
var probe_ids = [];
var pgr = new GlideRecord('discovery_classifier_probe');
pgr.addQuery('child', '4f64c6389f230200fe2ab0aec32e7068'); // get only horizontal pattern probe related entries
pgr.addQuery('classy', match.classifier);
pgr.addActiveQuery();
pgr.query();
while (pgr.next()) {
if (adm.triggerCondition(pgr)) {
probe_ids.push('' + pgr.child);
}
}
// get out of dodge if there are no probes needed...
if (probe_ids.length == 0)
return null;
// now get a glide record with just these probes in it...
var rgr = new GlideRecord('discovery_probes');
rgr.addQuery('sys_id', probe_ids);
rgr.query();
return rgr;
},
getAgentInfo: function(agentGr) {
var agent = {};
if (agentGr.next()) {
agent.agentId = agentGr.getValue('agent_id');
agent.ipAddress = agentGr.getValue('ip_address');
agent.midServerName = this.getMidServerName(agentGr.getValue('mid'));
agent.osType = this.getOSType();
agent.name = this.getCmdbRecord().name;
}
return agent;
},
/**
* Returns the operating system type (windows, unix, or esx) based on the CI's type...
* Applicable only for servers at this time, not for Computer
*/
getOSType: function() {
var ci_class = '' + this.getCmdbRecord().sys_class_name;
if (ci_class == 'cmdb_ci_esx_server')
return 'esx';
if (ci_class.indexOf('win_server') >= 0)
return 'windows';
if (ci_class == 'cmdb_ci_computer') {
gs.info("Execution of Application Patterns on agents is not currently supported for endpoints, skipping the CI {sysId=" + this.ciSysId + ", sys_class_name=" + ci_class + "}");
return;
}
return 'unix';
},
getCmdbRecord: function() {
if (!this.validSysId(this.ciSysId))
return null;
var gr = new GlideRecord('cmdb_ci');
gr.addQuery('sys_id', this.ciSysId);
gr.query();
if (!gr.next()) {
gs.info("Unable to retrieve CI record from the database.");
return null;
}
return gr;
},
validSysId: function(sysId) {
return !gs.nil(sysId) && /^[\dA-F]{32}$/i.test(sysId);
},
getMidServerName: function(midSysId) {
var midGr = new GlideRecord('ecc_agent');
if (midGr.get('sys_id', midSysId)) {
return midGr.name;
}
return "";
},
type: 'AgentDiscoveryHandlerADMHelper'
};
Sys ID
df4391a2ff0520108ec45897d53bf1c3