Efficient way to navigate and find certain CIs downstream from an individual Business Service CI

kc1959
Tera Contributor

Hi all,

I wonder if there are any CMDB experts that can help me with this.

 

Given a particular Business Service we need to navigate the CI relationships that are 'downstream' and locate those CIs that are related (at any level) where the relationship is 'Owns::Owned by' and the child class is 'IP Address' (cmdb_ci_ip_address) - this needs to be scripted as a callable script include from a scheduled job.

 

I understand that IP addresses are most relevant to Servers, Network Adapters etc, but I wondered if the number of levels of recursive 'downstream' navigation would make these queries inefficient if we are navigating all levels of the parent/child records of the CI Relationships table. 

 

Can anyone suggest the best way to do this?

 

Hope you can help,

Keiron.

3 REPLIES 3

Riya Verma
Kilo Sage

Hi @kc1959 ,

 

Hope you are doing great.

 

To achieve the task of locating CI relationships in ServiceNow, specifically looking for 'Owns::Owned by' relationships where the child class is 'IP Address' (cmdb_ci_ip_address), we can create a callable script include that will be executed from a scheduled job.

 

  1. Create a new Script Include: Write the script in the Script Include (assuming ServiceNow Glide API usage):

 

var CIRelationshipNavigator = Class.create();
CIRelationshipNavigator.prototype = {
  initialize: function() {},

  // Function to find CI relationships and return the related IP Addresses.
  findRelatedIPs: function(parentCiSysId) {
    var relatedIPs = [];

    // Fetch all 'Owns::Owned by' relationships for the given parent CI.
    var relGR = new GlideRecord('cmdb_rel_ci');
    relGR.addQuery('parent', parentCiSysId);
    relGR.addQuery('type', 'Owns::Owned by');
    relGR.query();

    while (relGR.next()) {
      // Check if the child CI is an IP Address (cmdb_ci_ip_address).
      if (relGR.child.getRefRecord().getValue('sys_class_name') === 'cmdb_ci_ip_address') {
        relatedIPs.push(relGR.child.getDisplayValue());
      } else {
        // Recursively call the function for downstream navigation.
        var downstreamIPs = this.findRelatedIPs(relGR.child);
        relatedIPs = relatedIPs.concat(downstreamIPs);
      }
    }

    return relatedIPs;
  },

  type: 'CIRelationshipNavigator'
};

 

  • Create a Scheduled Job to call the script include:

 

var serviceCiSysId = 'your_business_service_sys_id_here';
var navigator = new CIRelationshipNavigator();
var relatedIPs = navigator.findRelatedIPs(serviceCiSysId);
gs.info('Related IP Addresses: ' + relatedIPs.join(', '));
​

 

 

 
 

Hi Riya,

many thanks for taking the time to reply.

Unfortunately the Business Service record itself will never directly have a relationship with an IP address - it will be a child CI any number of levels downstream so the lookup of the 'cmdb_rel_ci table as shown below will result in no records found and therefore the while loop will not be entered.

 

// Function to find CI relationships and return the related IP Addresses.
findRelatedIPs: function(parentCiSysId) {
var relatedIPs = [];

// Fetch all 'Owns::Owned by' relationships for the given parent CI.
var relGR = new GlideRecord('cmdb_rel_ci');
relGR.addQuery('parent', parentCiSysId); //

relGR.addQuery('type', 'Owns::Owned by');

// The service will never have a direct relationship with an IP address - this will normally be downstream servers and network adapters related to the service
relGR.query();

while (relGR.next()) {

Hey @kc1959 Please let me knowhow if you did achieved this. I'm looking for the same answer. 

Thank you