Efficient way to navigate and find certain CIs downstream from an individual Business Service CI
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-25-2023 03:29 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-25-2023 04:37 AM
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.
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(', '));
Regards,
Riya Verma
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-25-2023 05:48 AM
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()) {
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-31-2023 10:54 AM
Hey @kc1959 Please let me knowhow if you did achieved this. I'm looking for the same answer.
Thank you