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');
}