Tuesday, February 20, 2024

DiscoveryFunctions Script Include

 var DiscoveryFunctions = Class.create();


(function() {


var relTypes = { };


DiscoveryFunctions.prototype = {

    initialize: function() {

    },

getDiscoverySource: function() {

var gr = new GlideRecord("sys_properties");

if(gr.get("name", "glide.discovery.source_name"))

return gr.getValue('value');

return "";

},


    getScheduleRecord: function() {

        var statusGR = this.getStatusRecord();

        if (!statusGR)

            return;


        var gr = new GlideRecord('discovery_schedule');

        if (statusGR.dscheduler)

            gr.get('sys_id', statusGR.dscheduler);

        return gr;

    },


    getStatusRecord: function() {

        var statusSysId = g_probe.getCorrelator();

        if (gs.nil(statusSysId)) {

            if (typeof agent_correlator != 'string' && agent_correlator)

                statusSysId = agent_correlator;

            else if (current) {

                if (current.agent_correlator)

                    statusSysId = current.agent_correlator;

                else if (current.getTableName() == "discovery_status")

                    return current;

            }

        }


        if (!statusSysId)

            return null;


        var gr = new GlideRecord('discovery_status');

        if (statusSysId)

            gr.get('sys_id', statusSysId);

        return gr;

    },


    getDiscoveryType: function(statusID) {

        var statusGR = new GlideRecord('discovery_status');

        statusGR.get(statusID);

        var schedGR = new GlideRecord('discovery_schedule');

        schedGR.get(statusGR.dscheduler);

        return schedGR.discover;

    },


    getService: function(port) {

        var gr = new GlideRecord("cmdb_ip_service");

        if (!gr.get("port", port)) {

            gr.initialize();

            gr.setValue("port", port);

            gr.setValue("name", "unknown - port(" + port + ")");

            gr.insert();

        }


        return gr;

    },


    isInRange: function(ip) {

        var gr = this.getStatusRecord();

        if (gr != null) {

            var hostList = gr.scratchpad.host_list;


            if (hostList) {

                var hosts = StringUtil.split(hostList, ",");

                if (hosts.contains(ip))

                    return true;

            }


            return SncDiscoveryRangesDB.inRanges(ip, gr.dscheduler);

        }


        return false;

    },


    getXMLMemoryTable: function(tableName, doc, path) {

        var result = null;

        try {

            result = GlidesoftXMLMemoryTable.getFromDocAndXPath(tableName, doc, path);

        } catch (iae) {

            // do nothing; we'll return a null...

        }

        return result;

    },


    getFieldsThatChanged: function(gr) {

        var changes = [];


        if (gr == null || !gr.isValid())

            return changes;


        var gru = GlideScriptRecordUtil.get(gr);

        var ignoreables = new Packages.java.util.ArrayList();

        ignoreables.add("last_discovered");


        var whatChanged = gru.getChangedFields(ignoreables);

        for (var i = 0; i < whatChanged.size(); i++) {

            var f = whatChanged.get(i);

            changes.push(f);

        }


        return changes;

    },


    updatedHistory: function(gr, sensor, eccID) {

        var fieldsChanged = this.getFieldsThatChanged(gr);

        if (fieldsChanged.length > 0)

            g_device.log("Updated device fields " + fieldsChanged.join(", "), sensor, eccID);

    },


/*

     *  Return the sys_id of the relationship created. Otherwise return null or undefined.

     */

createRelationshipFromSysIds: function(parentId, childId, pDescription, cDescription) {

        if (JSUtil.nil(parentId) || JSUtil.nil(childId))

            return;

        if (!this.validCISysId(parentId) || !this.validCISysId(childId)) {

return;

}


        if (!cDescription && pDescription.indexOf("::") > -1) {

            var parts = pDescription.split("::");

            pDescription = parts[0];

            cDescription = parts[1];

        }


var ECMDBUtil = SncECMDBUtil;

        return ECMDBUtil.createCIRelationship('cmdb_rel_ci', parentId, childId, pDescription, cDescription);

    },


    // Validate sysid

validCISysId: function(sysID) {

// Case 1: Check for null sys id

if (gs.nil(sysID)) {

gs.log('Invalid Rel CI Record :: Null SysID');

return false;

}


//extracting only alphanumeric and comparing 32 chars

if (sysID.match(/[0-9a-f]{32}/) == sysID) {

return true;

} else {

// Case 3:SysID is not null

// but it is not a valid sysID by its strig format [Alphanumeric and exactly 32 chars]

gs.log('Invalid Rel CI Record :: Invalid SysID(Regex only) :SysID ' + sysID);

return false;

}

},


    //

    // Args:    parent <pDescription> child   /    child <cDescription> parent

    // Example: vmware   Runs on      sanops  /    sanops    Runs       vmware

    // parent, child input can either be GlideRecord or sys_id

    //

    createRelationship: function(parent, child, pDescription, cDescription) {

        if (JSUtil.nil(parent) || JSUtil.nil(child))

            return;


        var parentId = parent;

        var childId  = child;


        //If parent or child is a GlideRecord object, we need to extract the sys_id

        if (parent instanceof GlideRecord)

            parentId = parent.sys_id;

        if (child instanceof GlideRecord)

            childId  = child.sys_id;


return this.createRelationshipFromSysIds(parentId, childId, pDescription, cDescription);

    },


    /*

     *  Return the sys_id of the relationship if found or created. Otherwise return null or undefined.

     */

    createRelationshipIfNotExists: function(parent, child, descriptor, ensureUnique) {

        var result = this.relationshipExists(parent, child, descriptor);

        if (JSUtil.notNil(result))

            return result;


        var createdRelationship =  this.createRelationship(parent, child, descriptor);


//checking unique for the newly created relationship

if (ensureUnique)

this.deleteRelationshipIfMultipleExists(parent, child, descriptor);


return createdRelationship;

    },


    /*

     *  Checks to see if a relationship already exists

     */

    relationshipExists: function(parent, child, descriptor) {

        if (JSUtil.nil(parent) || JSUtil.nil(child) || JSUtil.nil(descriptor))

            return;


        var parentId = parent;

        var childId  = child;


        //If parent or child is a GlideRecord object, we need to extract the sys_id

        if (parent instanceof GlideRecord)

            parentId = parent.sys_id;

        if (child instanceof GlideRecord)

            childId  = child.sys_id;


        var relationType = this.findCIRelationshipType("cmdb_rel_type", descriptor);


        var gr = new GlideRecord("cmdb_rel_ci");

        gr.addQuery("parent", parentId);

        gr.addQuery("child", childId);

        gr.addQuery("type", relationType);

        gr.query();

        if (gr.next())

            return gr;


        return;

    },


/*

     *  Deleted duplicate relationship from cmdb_rel_ci

     */

deleteRelationshipIfMultipleExists: function  (parent, child, relTypeName) {

var gr = new GlideRecord('cmdb_rel_ci');

var relTypeId = this.findCIRelationshipType('cmdb_rel_type', relTypeName);


gr.addQuery('parent', parent);

gr.addQuery('child', child);

gr.addQuery('type', relTypeId);

gr.orderBy('sys_id');

gr.query();


if (gr.getRowCount() > 1) {

gs.info('Duplicate relationship %% ' + relTypeName + ' exists between the parent  ' + parent + ' and child ' + child);


// Don't allow exact duplicates.  We'll keep the one with the lowest sys_id

// to avoid a race condition where two threads insert a record at the same

// time and both decide to delete it.

gr.next();


// Delete duplicate record

while (gr.next()) {

gr.deleteRecord();

gs.info('Deleted Duplicate relationship %% ' + relTypeName + ' between the parent  ' + parent + ' and child ' + child);

}

}

},


/**

  * get a child of this parent of type matched by the descriptor

  *

  * Descriptor is of form <Parent Relationship>::<Child Relationship>

  * so, for example calling this method on a web server with descriptor "RunsOn::Runs"

  * returns the computer it runs on.  Thus, web server is the parent and computer is the child

  */


getChildCI: function(parent, descriptor) {

var gr = new GlideRecord("cmdb_rel_ci");

gr.addQuery("parent", parent.sys_id);

if (descriptor) {

var relationType = this.findCIRelationshipType("cmdb_rel_type", descriptor);

if (relationType)

gr.addQuery("type", relationType);

}

gr.query();


if (gr.next()) {

var cigr = new GlideRecord("cmdb_ci");

if (gr.child && cigr.get('sys_id', gr.child)) {

return cigr;

}

}

return null;

},


    reclassify: function(gr, newClassName, reason) {

        // we are already that class, just return

        if (gr.sys_class_name == newClassName)

            return gr;


        var rci = SncReclassifyCI.createFromGlideRecord(gr, newClassName);

        rci.setApplyDefaults(false);

        rci.setReason(reason);

        return rci.reclassify();

    },


    deleteCIBySysId: function(sysId, workflow) {

        var gr = new GlideRecord("cmdb_ci");

        if (!sysId || !gr.get('sys_id', sysId))

            return;


        this.deleteCI(gr, workflow);

    },


    deleteCI: function(gr, workflow) {

        var al = [];

        al.push(gr.getValue("sys_id"));


        //Check to see if it matches these two criteria

        if (!(gr.instanceOf("cmdb_ci_computer") || gr.instanceOf("cmdb_ci_appl"))) {

            gr.deleteRecord();

            return;

        }


        if (workflow && workflow != "false") {

            this.deleteCIAndRelationshipsRecursive(al);

            return;

        }


        try {

            var oldWorkflow = session.getWorkflow();

            this.deleteCIAndRelationshipsRecursive(al);

        } finally {

            session.setWorkflow(oldWorkflow);

        }


    },


    /*

    * This is where the heavy lifting of traversing through the relationship tree is done

    * We only traverse through the relatinoships that have RUNS_ON and HOSTED_ON relationships at this point

    *

    * We basically look for all the parent CIs that runs on or is hosted on the child CI(s) and delete them.

    */


     deleteCIAndRelationshipsRecursive: function(appList) {

     if (appList.length == 0)

            return appList;


     var appListNew = [];

     var tempSysId;

     var sysID;

         for (var i = 0; i < appList.length; i++) {

             sysID = appList[i];

         var gr = new GlideRecord("cmdb_rel_ci");

         gr.addQuery("child", sysID);

         var qc = gr.addQuery("type", this.findCIRelationshipType("cmdb_rel_type", "Runs on::Runs"));

         qc.addOrCondition("type", this.findCIRelationshipType("cmdb_rel_type", "Hosted on::Hosts"));

         gr.query();

         while (gr.next()) {

         tempSysId = gr.getValue("parent");


         //Check to see if same CI could runs-on or be hosted on same child (maybe possible?)

         if (!contains(appListNew, tempSysId))

            appListNew.push(tempSysId);


                 gr.deleteRecord(); //delete the relationship entry

         }


         var cigr = new GlideRecord("cmdb_ci");

         if (sysID && cigr.get('sys_id', sysID))

        cigr.deleteRecord();

          }


      return this.deleteCIAndRelationshipsRecursive(appListNew);


          function contains(arr, value) {

             for (var i=0; i<arr.length; i++)

               if (arr[i] == value)

                  return true;

             return false;

          }


       },


findOrCreateRelationshipType: function(refTable, descriptor) {

var result = this.findCIRelationshipType(refTable, descriptor);

if (JSUtil.notNil(result))

return result;


var al = descriptor.split("::");

        var gr = new GlideRecord(refTable);

        gr.parent_descriptor = al[0];

        gr.child_descriptor = al[1];

return gr.insert();

},


    findCIRelationshipType: function(refTable, descriptor) {


// refTable should be an optional parameter (because we always pass the

// same value).  I can't change the function signature, so this is the

// only way to make it optional.

if (!descriptor)

return this.findCIRelationshipTypeByDesc('cmdb_rel_type', refTable);


return this.findCIRelationshipTypeByDesc(refTable, descriptor);

    },


    findCIRelationshipTypeByDesc: function(refTable, pDescriptor, cDescriptor) {


var descriptor = pDescriptor;

if (cDescriptor)

descriptor += '::' + cDescriptor;


relTypes[descriptor] = relTypes[descriptor] || getRelType();


return relTypes[descriptor];


function getRelType() {


if (pDescriptor && !cDescriptor) {

pDescriptor = pDescriptor.split('::');

cDescriptor = pDescriptor[1];

pDescriptor = pDescriptor[0];

}


var gr = new GlideRecord(refTable);

gr.addQuery("parent_descriptor", pDescriptor);

gr.addQuery("child_descriptor", cDescriptor);

gr.query();

if (gr.next())

return '' + gr.getValue("sys_id");


return "";

}

    },



    /* Manage the PIDs creation and update */

    insertPIDs: function(pids, app_sys_id, ci_sys_id) {

        if (StringUtil.nil(pids))

            return;


        var pid_array = pids.match(/\d+/g);

        var gr = new GlideRecord("cmdb_pid");

        gr.initialize();

        for (var i=0; i<pid_array.length; i++) {

           gr.pid = pid_array[i];

           gr.application = app_sys_id;

           gr.cmdb_ci = ci_sys_id;

           gr.insert();

        }

    },


    updatePIDs: function(pids, app_sys_id, ci_sys_id) {

        if (StringUtil.nil(pids))

            return;


        var gr = new GlideRecord("cmdb_pid");

        gr.addQuery("application", app_sys_id);

        gr.query();

        gr.deleteMultiple();


        this.insertPIDs(pids, app_sys_id, ci_sys_id);

    },


    /**********************************************

     * Manage the Windows installed software xml

     *

     * Example payload:

     *   <results probe_time="6313">

     *     <result>

     *       <Registry>

     *         <entry key="HKEY_LOCAL_MACHINE">

     *           <entry key="Software">

     *             <entry key="Microsoft">

     *               <entry key="Windows">

     *                 <entry key="Name">

     *                   <value>Just a name</value>

     *                 </entry>

     *               </entry>

     *             </entry>

     *           </entry>

     *         </entry>

     *       </Registry>

     *     </entry>

     *   </results>

     *

     *   // To find the value of the key called "name", here's how these methods can be used.

     *   // registry is a variable representing the payload

     *   var node = findRegistryNode(registry, "HKEY_LOCAL_MACHINE.Software.Microsoft");

     *   var name = findNodeValueWithAttribute(node, "Name");

     *********************************************/

    findRegistryNode: function(currNode, regName){

    var node = currNode;

    var names = regName.split(".");


    for (var i=0; i<names.length; i++) {

        node = this.findNodeWithAttribute(node, names[i]);

            if (!node)

                return null;

        }


    return node;

    },


    findNodeWithAttribute: function(currNode, attrName) {

        if (JSUtil.nil(currNode))

            return "";


        var nodeArray = g_array_util.ensureArray(currNode.entry);

    for (var i=0; i<nodeArray.length; i++)

        if (nodeArray[i]['@key'] == attrName)

            return nodeArray[i];


    return null;

    },


    findNodeValueWithAttribute: function(currNode, attrName) {

        if (JSUtil.nil(currNode))

            return "";


        var nodeArray = g_array_util.ensureArray(currNode.entry);

    for (var i=0; i<nodeArray.length; i++)

        if (nodeArray[i]['@key'] == attrName)

            return nodeArray[i].value;


        return "";

    },


    type: "DiscoveryFunctions"

};


}());


No comments:

Post a Comment

Discovery troubleshooting | Error messages

  Discovery troubleshooting | Error messages - Support and Troubleshooting (servicenow.com) Description Learn how to resolve common Discover...