Name

global.DiscoveryRunningProcessSensor

Description

The abstract sensor for running processes

Script

var DiscoveryRunningProcessSensor = Class.create();

DiscoveryRunningProcessSensor.prototype = Object.extendsObject(DiscoverySensor, {
  process: function(result) {
      this.deviceGR = null;
      this.discoveredEntries = {};

      this.deviceGR = this.getCmdbRecord();
      if (gs.nil(this.deviceGR))
          return;

      var procs = this.mapProcesses(result);

      if (this.newADM()) {
          this.defaultKeyParameters(procs);
          this.runHandlers(procs);
          this.addToRelatedList('cmdb_running_process', procs, 'computer', 'command,key_parameters');
          return;
      }

      this.addToRelatedList('cmdb_running_process', procs, 'computer', 'command,parameters');

      var classificationMap = DiscoveryClassification.loadClassifications("discovery_classy_proc");
      for (var i = 0; i < procs.length; i++) {
          var proc = procs[i];
          var fc = new DiscoveryClassification(this.getEccQueueRecord(), classificationMap);
          if (fc.find("discovery_classy_proc", proc)) {
              var classyName = '' + fc.getClassificationRecord().getValue('name');

              if (gs.getProperty('glide.discovery.debug.classification') == 'true')
                  gs.log("*********** The process is classified as " + classyName + " *******************" );             

              this.addDiscovered(fc);
          }
      }

      this.processDiscovered();
  },
  
  /**
   * Child classes must override this (and return true) if they implement new-style ADM.
   */
  newADM: function() {
      return false;
  },
  
  /**
   * Runs the handlers that are enabled for running in the sensor, mainly to set key_parameters.
   */
  runHandlers: function(procs) {
      // get a list of all our handlers, in name order...
      var handlers = [];
      var gr = new GlideRecord('discovery_proc_handler');
      gr.addActiveQuery();
      gr.addQuery('rps', true);
      gr.orderBy('name');
      gr.query();
      while (gr.next()) {
          var handler = {};
          handler.condition = '' + gr.condition;
          handler.classify  = ('true' == '' + gr.classify);
          handler.script    = '' + gr.script;
          handlers.push(handler);
      }

      // for each running process...
      var rp_gr = new GlideRecord('cmdb_running_process');
      for (var p = 0; p < procs.length; p++) {
          // make a fake GlideRecord...
          var proc = procs[p];
          rp_gr.initialize();
          for (var field in proc)
              rp_gr[field] = proc[field];
          
          // run our handlers against our fake record...
          for (var i = 0; i < handlers.length; i++) {
              var handler = handlers[i];
              if (handler.condition && SNC.Filter.checkRecord(rp_gr, handler.condition)) {
                  // update the classify setting...
                  rp_gr.setValue('classify', handler.classify);
                  
                  // run the script...
                  var old_current = current;
                  current = rp_gr;
                  eval(handler.script);
                  current = old_current;
                  
                  // update the appropriate field in our proc record...
                  proc.name           = '' + rp_gr.name;
                  proc.pid            = '' + rp_gr.pid;
                  proc.ppid           = '' + rp_gr.ppid;
                  proc.command        = '' + rp_gr.command;
                  proc.parameters     = '' + rp_gr.parameters;
                  proc.key_parameters = '' + rp_gr.key_parameters;
                  proc.classify       = '' + rp_gr.classify;
                  proc.listening_on   = '' + rp_gr.listening_on;
                  proc.connecting_to  = '' + rp_gr.connecting_to;
              }
          }
      }
  },
  
  /**
   * Default the key_parameters field to parameters
   */
  defaultKeyParameters: function(procs) {
      for (var i = 0; i < procs.length; i++)
          procs[i].key_parameters = procs[i].parameters;
  },
      
  
  // everything below here is old-style classification...

  mapProcesses: function(result) {
      // this function should be overwritten by classes extending this object
      return [];
  },

  after: function() {
      // Rewire clustered processes
      new DiscoveryClusteredProcessHelper().process(this.deviceGR);

  },

  processDiscovered: function() {
      for (var uniqId in this.discoveredEntries) {
          var cp = this.discoveredEntries[uniqId];
          this.debug("Matched process from classification: " + cp.getName() + " " + cp.getCommand());
          var sys_id = this.insertOrUpdate(cp);
          if (JSUtil.nil(sys_id))
              return;

          var dc = cp.getClassification();
          if (dc != null)
              dc.triggerProbesWithCIAndPort(sys_id, this.getParameter("port"));
      }
  },

  addDiscovered: function(fc) {
      var cp = new SncClassifiedProcess(fc);

      if (gs.nil(cp.getCommand()) && gs.nil(cp.getParameters())) {
          this.handleError(['Insufficient information to classify process: ' + cp.getName()]);
          return;
      }

      if (this.discoveredEntries[cp.getUniqueId()]) {
          var originalProcess = this.discoveredEntries[cp.getUniqueId()];
          originalProcess.addSimilarProcess(cp);
          return;
      }

      this.discoveredEntries[cp.getUniqueId()] = cp;
  },

  insertOrUpdate: function(classifiedProcess) {
      var correlationId = classifiedProcess.getUniqueId() + "@" + this.getCmdbCi();
      var processAppMatch = new DiscoveryProcessAppMatch(classifiedProcess, this.deviceGR);
      var gr = processAppMatch.match();
      if (gr.next())
          this.updateCiProcess(gr, correlationId, classifiedProcess);
      else
          gr = this.insertCiProcess(correlationId, classifiedProcess);

      return gr.sys_id;
  },

  insertCiProcess: function(correlationId, classifiedProcess) {
      var ci = new GlideRecord(classifiedProcess.getClassifiedTableName());
      ci.name = classifiedProcess.getName() + "@" + this.deviceGR.name;
      ci.correlation_id = correlationId;
      ci.pid = classifiedProcess.getValue("pid");

      this.setFields(ci, classifiedProcess.getSetFields());

      if (ci.isActionAborted())
          return;

      ci.insert();

      //Insert the pids into the PID table
      var pids = classifiedProcess.getValue("pids");
      g_disco_functions.insertPIDs(pids, ci.getUniqueValue(), this.deviceGR.getUniqueValue());

      // create a cmdb_rel_ci -- make the relationship
      var relID = g_disco_functions.createRelationship(ci, this.deviceGR, classifiedProcess.getClassifiedType());
      
      g_device.log("Created process application " + this._buildURL(ci.getDisplayValue(), ci.sys_class_name, ci.sys_id) + " (" + ci.getTableName() + ") and its " + this._buildURL("relationship", "cmdb_rel_ci", relID) + " (" + classifiedProcess.getClassifiedType()+ ")  to " + this._buildURL(this.deviceGR.getDisplayValue(), this.deviceGR.sys_class_name, this.deviceGR.sys_id), this.getSensorName(), this.getEccQueueId());
      
      return ci;
  },

  updateCiProcess: function(ci, correlationId, classifiedProcess) {
      ci.correlation_id = correlationId;
      ci.pid = classifiedProcess.getValue("pid");
      this.setFields(ci, classifiedProcess.getSetFields());
      ci.update();

      //Update the pids field in the PID table
      var pids = classifiedProcess.getValue("pids");
      g_disco_functions.updatePIDs(pids, ci.getUniqueValue(), this.deviceGR.getUniqueValue());

      var fieldsChanged = g_disco_functions.getFieldsThatChanged(ci);
      if (fieldsChanged.length > 0)
          g_device.log("Updated " + ci.getDisplayValue() + " fields " + fieldsChanged.join(", "), this.getSensorName(), this.getEccQueueId());

      // Verify the relationship, if somehow it's severed, recreate it! Unless, of course, it has a relationship with a parent cluster.
      if (this.isClusterable(classifiedProcess) && this.hasClusterRelationship(ci))
          return;
      
      if (JSUtil.notNil(g_disco_functions.relationshipExists(ci, this.deviceGR, classifiedProcess.getClassifiedType())))
          return;
          
      var relID = g_disco_functions.createRelationship(ci, this.deviceGR, classifiedProcess.getClassifiedType());
      var relationship = classifiedProcess.getClassifiedType();
      
      g_device.log("Recreated " + this._buildURL("relationship", "cmdb_rel_ci", relID) + " (" + relationship + ") between " + this._buildURL(ci.getDisplayValue(), ci.sys_class_name, ci.sys_id) + " (" + ci.getTableName() + ") and " + this._buildURL(this.deviceGR.getDisplayValue(), this.deviceGR.sys_class_name, this.deviceGR.sys_id), this.getSensorName(), this.getEccQueueId());
  },

  isClusterable: function(classifiedProcess) {
      var gr = new GlideRecord("discovery_classy_proc_to_param");
      gs.addNotNullQuery("parameter");
      gr.addQuery("process_classifier", classifiedProcess.getRecord().getUniqueValue());
      gr.query();
      while (gr.next())
          if (gr.parameter.type.match(/^cluster$/i))
              return true;

      return false;
  },

  hasClusterRelationship: function(ci) {
      var gr = new GlideRecord("cmdb_ci_cluster_node");
      gr.addQuery("server", this.deviceGR.sys_id);
      gr.query();
      while (gr.next()) {
          var cluster = new GlideRecord("cmdb_ci_cluster");
          // Make sure that the cluster we are a node for is real
          if (!cluster.get(gr.cluster))
              continue;

          if (g_disco_functions.relationshipExists(ci.getUniqueValue(), cluster.getUniqueValue(), "Runs on::Runs"))
              return true;
      }
      return false;
  },

  setFields: function(ci, fields) {
      if (fields == null || fields.isEmpty())
          return;

      var it = fields.keySet().iterator();
      while (it.hasNext()) {
          var key = it.next();
          var value = fields.get(key);
          if (key == "setAbortAction")
              ci.setAbortAction(value);
          else
              ci.setValue(key, value);
      }
  },

  _buildURL: function(display, table, sysID) {
      return "[code]<a title='" + display + "' class='linked' href='" + table + ".do?sysparm_query=sys_id=" + sysID + "'>" + display + "</a>[/code]";
  },

  updateDeviceCount: function() {
      if (!g_device)
          return;

      g_device.completedRunningProcesses();
  },

  type: "DiscoverySensor"
});

Sys ID

c3fa3a200a0a0baa00442d77546d53f8

Offical Documentation

Official Docs: