Some Impacted Services/CIs are missing on the list

MandyMaseyM
Tera Contributor

Hi guys, I need help on what seems to be the problem with our UI Action Refresh Impacted Services.

 

Some Impacted Services/CIs of the Affected CI are missing on the list whenever we click the Refresh Impacted Services.

 

For example, In this screenshot, it supposed to have 14 records, but only 9 are added.

 

CI 1.jpg

 

var CI_rel_Utils = Class.create();
CI_rel_Utils.prototype = Object.extendsObject(CIUtils, {

    /*
     * Refresh impacted services by analyzing affected CIs.
     * This will only considers in scope classess on Affected CI when analyzing the impacted Services
     */

	// This is the function that will be called once the Refresh Impacted Services button was clicked
    refreshImpactedServicesAffectedCIs: function(current) {
        this.removeImpactedServices(current.sys_id); // Clear Existing Impacted Services

        // Call the system property: CMDB_Scope_CI
        var inScopeProp = gs.getProperty('CMDB_Scope_CI, '');

		// Convert the sys_propertyto an array to extract all the in scope classes and use it in the logic to make sure only in scope Affected CI will be included when it refresh the impacted services
        var inScopeClasses = inScopeProp.split(',').map(function(cls) {
            return cls.trim(); 
        });

		// Initiate the Array to store later the impacted Services
        var impactedServices = [];

        // Fetch affected CIs from task_ci table
        var affectedCI = new GlideRecord('task_ci');
        affectedCI.addQuery('task', current.sys_id);
        affectedCI.query();

		// Loop through the affected CI's and decide which affected CI's will be included to be analyzed
        while (affectedCI.next()) {
            var ci = affectedCI.ci_item;
            var ciName = ci.name.toString();
            var ciClass = ci.sys_class_name.toString();

			// If the aFfected CI is not included in the in scope classes, then skip it
            if (inScopeClasses.indexOf(ciClass) === -1) {
                gs.info('[Excluded CI - Not in Scope] ' + ciName + ' [' + ciClass + ']');
                continue; // This Skips the Affected CI if it is not included in the in scope classes
            }

            // Fetch all the Services that are impacted by the Affected CI
			// Calls the function _getRelevantRelatedCIs and pass the affected CI sys_id as a parameter
            var relatedCIs = this._getRelevantRelatedCIs(ci.sys_id); 

			// Set the Returned result of the function to impacted Services
            impactedServices = relatedCIs; 
        }

        // Remove any duplicate Impcated Service
		// Use the ArrayUtil to call the functiOn unique to remove the duplicate services
        var arrayUtil = new ArrayUtil();

		// This has now the array or storage of the unique Impacted Services
        var uniqueServices = arrayUtil.unique(impactedServices);

        // Remove services already linked
        var existing = new GlideRecord('task_cmdb_ci_service');
        existing.addQuery('task', current.sys_id);
        existing.query();
        while (existing.next()) {
            var sid = existing.cmdb_ci_service.toString();
            var index = uniqueServices.indexOf(sid);
            if (index > -1) {
                uniqueServices.splice(index, 1);
                gs.info('[Excluded Service - Already Linked] ' + existing.cmdb_ci_service.name);
            }
        }

        if (uniqueServices.length > 0) {
            this.addImpactedServices(current.sys_id, uniqueServices);

            // Show Log for debugging purposes while making the code
			// This will show all the Impacted Services that are added
            var svcNames = [];
            var svcGR = new GlideRecord('cmdb_ci_service');
            svcGR.addQuery('sys_id', 'IN', uniqueServices.join(','));
            svcGR.query();
            while (svcGR.next()) {
                svcNames.push(svcGR.name.toString());
            }
            gs.info('[Included Services] ' + svcNames.join(', '));
            gs.addInfoMessage('Impacted services added: ' + uniqueServices.length);
        } else {
            gs.addInfoMessage('No new impacted services to add.');
        }
    },

    /**
     * Identify relevant CIs by following specific upstream relationships:
     * - Depends on::Used by (child = affected CI)
     * - Contains::Contained by (child = affected CI)
     * - Virtualized by::Virtualizes (parent = affected CI)
     *   → then find upstream (Used by / Contained by) of the virtualized CI
     */
    _getRelevantRelatedCIs: function(ciSysId) {
        gs.info("SYSID OF CiSysId" + ciSysId); 
        var relevant = [];

        // Handle the Mapped Application Service and Service Offering
		// This will handle the analization as well as inclusion of the Impacted Services for Mapped Application Service and Service Offering
        var upstreamRel = new GlideRecord('cmdb_rel_ci');
        upstreamRel.addEncodedQuery(
            'child.sys_id=' + ciSysId +
			// Include Service Offering and Mapped Application Service
            '^parent.sys_class_name=cmdb_ci_service_offering' + 
			'^ORparent.sys_class_name=cmdb_ci_service_discovered' + 
			// Exclude the windows server for now as this needs to be handled in a different approach
            '^ORparent.sys_class_name!=cmdb_ci_win_server' + 
			// exclude anything related to VM
            '^child.sys_class_name!=cmdb_ci_vmware_instance' + 
            '^ORchild.sys_class_name!=cmdb_ci_vcenter_dv_port_group' + 
            '^ORchild.sys_class_name!=cmdb_ci_vcenter_vm_group' + 
			// Relationship Type provided by::provides and members::member of
	    '^type.sys_id!=4afd799338a02000c186b817' + 
            '^type.sys_id!=55c913d3c0a8010e012d6050' 
        );
        upstreamRel.query();
		// As sys_id cannot be used due to cmdb_rel_ci has a different sys_id from the cmdb_ci_service so the name was used instead
        while (upstreamRel.next()) {
			// Query the cmdb_ci_service using the name to get the real sys_id of the impacted Service
            var getCmdbServiceSysId = new GlideRecord('cmdb_ci_service');
            getCmdbServiceSysId.addEncodedQuery(
				// Name of the Parent of the Affected CI
                'name=' + upstreamRel.parent.name 
            );
            getCmdbServiceSysId.query();
            if (getCmdbServiceSysId.next()) {
				// Store the Impacted Service Offering or Mapped Application Service Services
                relevant.push(getCmdbServiceSysId.sys_id);
                gs.info('[Final Relevant CI - Upstream] ' + getCmdbServiceSysId.name + ' (' + getCmdbServiceSysId.sys_id + ') via ' + upstreamRel.type.name);
            } else {
                gs.warn('No cmdb_ci_service found with name=' + upstreamRel.parent.name);
            }
        }

        // Handle the Windows Server/Virtualized by::Virtualizes
        var virtRel = new GlideRecord('cmdb_rel_ci');
        virtRel.addEncodedQuery(
            'child.sys_id=' + ciSysId +
			// exclude VM Instance
            '^child.sys_class_name!=cmdb_ci_vmware_instance' + 
			// exclude vcenter port group
            '^ORchild.sys_class_name!=cmdb_ci_vcenter_dv_port_group' + 
			// exclude bm group
            '^ORchild.sys_class_name!=cmdb_ci_vcenter_vm_group' + 
			// Include all Windows Server
            '^parent.sys_class_name=cmdb_ci_win_server' + 
			// Include Virtualized by::Virtualizes type
            '^type.sys_id=d93304fb0a0a6081a72ef08444' 
        );
        virtRel.query();
        while (virtRel.next()) {
			// As sys_id cannot be used due to cmdb_rel_ci has a different sys_id from the cmdb_ci_win_server so the name was used instead
            var getCmdb = new GlideRecord('cmdb_ci_win_server');
            getCmdb.addEncodedQuery(
                'name=' + virtRel.parent.name
            );
            getCmdb.query();
			// Log the Windows Server Parent of the Affected CI
            if (getCmdb.next()) {
                gs.info('[Relevant CI - Upstream VM] ' + getCmdb.name + ' (' + getCmdb.sys_id + ') via ' + virtRel.type.name + 'name in relationship is' + virtRel.parent.name);
            } else {
                gs.warn('No cmdb_ci_service found with name=' + virtRel.parent.name);
            }
            // Set the correct sys_id of the Window Server Parent to a new variable
            var vmId = getCmdb.sys_id; 

            // Since we already have the correct sys_id of the Windows Server Parent, We will now query the Parent and get the Impacted Services
            var vmUpstream = new GlideRecord('cmdb_rel_ci');
            vmUpstream.addEncodedQuery(
                'child.sys_id=' + vmId +
				// Exclude the Service Offering and Mapped Application Services since they are already handled completely and has a different approach to get
                '^parent.sys_class_name!=cmdb_ci_service_offering' +
                '^ORparent.sys_class_name!=cmdb_ci_service_discovered' +
				// Exclude anything related to VM
                '^child.sys_class_name!=cmdb_ci_vmware_instance' +
                '^ORchild.sys_class_name!=cmdb_ci_vcenter_dv_port_group' +
                '^ORchild.sys_class_name!=cmdb_ci_vcenter_vm_group' +
				// Include only Parents that are Windows Server
                '^parent.sys_class_name!=cmdb_ci_win_server'
            );
            vmUpstream.query();
            while (vmUpstream.next()) {
				// Query the cmdb_ci_service to get the correct sys_id of the Impacted Services as the cmdb_rel_ci has a different sys_id
                var getWindowsServerCmdbServiceSysId = new GlideRecord('cmdb_ci_service');
                getWindowsServerCmdbServiceSysId.addEncodedQuery(
                    'name=' + vmUpstream.parent.name // name of parent in cmdb_rel_ci
                );
                getWindowsServerCmdbServiceSysId.query();
				// Store the Impacted Services
                if (getWindowsServerCmdbServiceSysId.next()) {
                    relevant.push(getWindowsServerCmdbServiceSysId.sys_id);
                    gs.info('[FINAL Relevant CI for Windows Server] ' + getWindowsServerCmdbServiceSysId.name + ' (' + getWindowsServerCmdbServiceSysId.sys_id + ') via ' + vmUpstream.type.name);
                } else {
                    gs.warn('No cmdb_ci_service found with name=' + vmUpstream.parent.name);
                }
            }
        }

        gs.info('Final Relevant CI Sys IDs: ' + JSON.stringify(relevant));
        gs.info('Final Relevant CI Sys IDs: ' + relevant);
        return new ArrayUtil().unique(relevant);
    },

    type: 'CI_rel_Utils'
});