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
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(', '));
​

 

 

 
 
Please mark the appropriate response as correct answer and helpful, This may help other community users to follow correct solution.
Regards,
Riya Verma

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