Skip to Content

CMDB Utilities

Reusable functions for working with Configuration Items (CIs) in the CMDB.

#cmdb #configuration-items #ci #relationships #utilities #impact-analysis

Script Code

JavaScript
1var CMDBUtils = Class.create();
2CMDBUtils.prototype = {
3
4  /**
5   * Get all related CIs for a given CI
6   *
7   * @param {string} ciId - sys_id of CI
8   * @param {string} relationshipType - (Optional) Type of relationship
9   * @returns {Array} Array of related CI objects
10   */
11  getRelatedCIs: function(ciId, relationshipType) {
12    var relatedCIs = [];
13
14    if (!ciId) {
15      return relatedCIs;
16    }
17
18    // Query CI relationships
19    var grRel = new GlideRecord('cmdb_rel_ci');
20    grRel.addQuery('parent', ciId);
21    grRel.addQuery('child', ciId);
22    grRel.setORCondition();
23
24    if (relationshipType) {
25      grRel.addQuery('type.name', relationshipType);
26    }
27
28    grRel.query();
29
30    while (grRel.next()) {
31      var relatedId = grRel.parent.toString() === ciId ? 
32                      grRel.child.toString() : 
33                      grRel.parent.toString();
34
35      var grCI = new GlideRecord('cmdb_ci');
36      if (grCI.get(relatedId)) {
37        relatedCIs.push({
38          sys_id: grCI.sys_id.toString(),
39          name: grCI.name.toString(),
40          sys_class_name: grCI.sys_class_name.toString(),
41          operational_status: grCI.operational_status.getDisplayValue(),
42          relationship_type: grRel.type.name.toString()
43        });
44      }
45    }
46
47    return relatedCIs;
48  },
49
50  /**
51   * Get CI hierarchy (parent and children)
52   *
53   * @param {string} ciId - sys_id of CI
54   * @param {number} levels - Number of levels to traverse (default: 3)
55   * @returns {object} {parents: Array, children: Array}
56   */
57  getCIHierarchy: function(ciId, levels) {
58    levels = levels || 3;
59
60    return {
61      parents: this._getParentCIs(ciId, levels),
62      children: this._getChildCIs(ciId, levels)
63    };
64  },
65
66  /**
67   * Get parent CIs recursively
68   * @private
69   */
70  _getParentCIs: function(ciId, levels, currentLevel) {
71    currentLevel = currentLevel || 1;
72    var parents = [];
73
74    if (currentLevel > levels) {
75      return parents;
76    }
77
78    var grRel = new GlideRecord('cmdb_rel_ci');
79    grRel.addQuery('child', ciId);
80    grRel.query();
81
82    while (grRel.next()) {
83      var parentId = grRel.parent.toString();
84      var grParent = new GlideRecord('cmdb_ci');
85
86      if (grParent.get(parentId)) {
87        parents.push({
88          sys_id: parentId,
89          name: grParent.name.toString(),
90          level: currentLevel
91        });
92
93        // Recursively get grandparents
94        var grandparents = this._getParentCIs(parentId, levels, currentLevel + 1);
95        parents = parents.concat(grandparents);
96      }
97    }
98
99    return parents;
100  },
101
102  /**
103   * Get child CIs recursively
104   * @private
105   */
106  _getChildCIs: function(ciId, levels, currentLevel) {
107    currentLevel = currentLevel || 1;
108    var children = [];
109
110    if (currentLevel > levels) {
111      return children;
112    }
113
114    var grRel = new GlideRecord('cmdb_rel_ci');
115    grRel.addQuery('parent', ciId);
116    grRel.query();
117
118    while (grRel.next()) {
119      var childId = grRel.child.toString();
120      var grChild = new GlideRecord('cmdb_ci');
121
122      if (grChild.get(childId)) {
123        children.push({
124          sys_id: childId,
125          name: grChild.name.toString(),
126          level: currentLevel
127        });
128
129        // Recursively get grandchildren
130        var grandchildren = this._getChildCIs(childId, levels, currentLevel + 1);
131        children = children.concat(grandchildren);
132      }
133    }
134
135    return children;
136  },
137
138  /**
139   * Check if CI is affected by ongoing incidents or changes
140   *
141   * @param {string} ciId - sys_id of CI
142   * @returns {object} {hasIncidents: boolean, hasChanges: boolean, incidents: Array, changes: Array}
143   */
144  checkCIImpact: function(ciId) {
145    var result = {
146      hasIncidents: false,
147      hasChanges: false,
148      incidents: [],
149      changes: []
150    };
151
152    if (!ciId) {
153      return result;
154    }
155
156    // Check for active incidents
157    var grIncident = new GlideRecord('incident');
158    grIncident.addQuery('cmdb_ci', ciId);
159    grIncident.addQuery('active', 'true');
160    grIncident.query();
161
162    while (grIncident.next()) {
163      result.hasIncidents = true;
164      result.incidents.push({
165        number: grIncident.number.toString(),
166        short_description: grIncident.short_description.toString(),
167        state: grIncident.state.getDisplayValue(),
168        priority: grIncident.priority.getDisplayValue()
169      });
170    }
171
172    // Check for active changes
173    var grChange = new GlideRecord('change_request');
174    grChange.addQuery('cmdb_ci', ciId);
175    grChange.addQuery('state', 'NOT IN', '-5,3,4,7');  // Not: Closed, Cancelled, etc.
176    grChange.query();
177
178    while (grChange.next()) {
179      result.hasChanges = true;
180      result.changes.push({
181        number: grChange.number.toString(),
182        short_description: grChange.short_description.toString(),
183        state: grChange.state.getDisplayValue(),
184        risk: grChange.risk.getDisplayValue()
185      });
186    }
187
188    return result;
189  },
190
191  /**
192   * Update CI operational status
193   *
194   * @param {string} ciId - sys_id of CI
195   * @param {string} newStatus - New operational status value
196   * @param {string} reason - Reason for status change
197   * @returns {boolean} True if updated successfully
198   */
199  updateCIStatus: function(ciId, newStatus, reason) {
200    if (!ciId || !newStatus) {
201      return false;
202    }
203
204    var grCI = new GlideRecord('cmdb_ci');
205    if (!grCI.get(ciId)) {
206      gs.error('CMDBUtils: CI not found: ' + ciId);
207      return false;
208    }
209
210    var oldStatus = grCI.operational_status.toString();
211    grCI.operational_status = newStatus;
212
213    if (reason) {
214      grCI.comments = 'Status changed from ' + oldStatus + ' to ' + newStatus + '. Reason: ' + reason;
215    }
216
217    grCI.update();
218
219    gs.info('CMDBUtils: Updated CI ' + grCI.name + ' status from ' + oldStatus + ' to ' + newStatus);
220    return true;
221  },
222
223  /**
224   * Get CI with all related information
225   *
226   * @param {string} ciId - sys_id of CI
227   * @returns {object} Complete CI information
228   */
229  getCIDetails: function(ciId) {
230    if (!ciId) {
231      return null;
232    }
233
234    var grCI = new GlideRecord('cmdb_ci');
235    if (!grCI.get(ciId)) {
236      return null;
237    }
238
239    return {
240      sys_id: grCI.sys_id.toString(),
241      name: grCI.name.toString(),
242      sys_class_name: grCI.sys_class_name.toString(),
243      operational_status: grCI.operational_status.getDisplayValue(),
244      u_criticality: grCI.u_criticality ? grCI.u_criticality.toString() : '',
245      owned_by: grCI.owned_by.getDisplayValue(),
246      managed_by: grCI.managed_by.getDisplayValue(),
247      supported_by: grCI.supported_by.getDisplayValue(),
248      location: grCI.location.getDisplayValue(),
249      impact: this.checkCIImpact(ciId),
250      relatedCIs: this.getRelatedCIs(ciId)
251    };
252  },
253
254  type: 'CMDBUtils'
255};

How to Use

1. Create a new Script Include 2. Set Name to "CMDBUtils" 3. Leave "Client callable" unchecked 4. Copy the code above 5. Use in Business Rules or Background Scripts to work with CIs Example usage: var cmdb = new CMDBUtils(); var ciDetails = cmdb.getCIDetails('ci_sys_id'); var impact = cmdb.checkCIImpact('ci_sys_id'); if (impact.hasIncidents) { gs.info('CI has active incidents'); }

Explore More Scripts

Browse our complete library of ServiceNow scripts

View All Scripts