VaranAwesomenow
Mega Sage

Link to video explaining below steps

CMDB Data Model ServiceNow - YouTube

Considering the nature of CMDB it is very custom to a customer. While we use most of OOB classes we tend to create custom classes as needed, hence having a data model helps having deeper understanding of CMDB.

Below are steps I have followed to create a data model

1. Get list of classes that are in scope (filter to be updated as needed to get required classes in scope)

 
//1. get list of classes
var sDebug = '';
var classNameHash = {};
var className = '';
var grCI = new GlideRecord('cmdb_ci');
grCI.addEncodedQuery('discovery_source='ServiceNow'');
grCI.query();
while(grCI.next()) {
className = grCI.sys_class_name + '';
classNameHash[className] = 1;
}

// show the values stored
for (var k in classNameHash) {
// use hasOwnProperty to filter out keys from the Object.prototype
if (classNameHash.hasOwnProperty(k)) {
sDebug +=k + "|" + classNameHash[k];
}
}
gs.print(sDebug);

 

//2. Get list of relationships for CIs
var sDebug = '';
var relArray = [];
var relTypeHash = {};
var relType = '';
var grRelCI = new GlideRecord('cmdb_rel_ci');
grRelCI.addEncodedQuery('child.sys_idISNOTEMPTY^parent.sys_idISNOTEMPTY');
grRelCI.query();
while(grRelCI.next()) {
relType = grRelCI.parent.sys_class_name + "|" + grRelCI.type.sys_name + "|" + grRelCI.child.sys_class_name + '';
relTypeHash[relType] = 1;
}

// show the values stored
for (var k in relTypeHash) {
// use hasOwnProperty to filter out keys from the Object.prototype
if (relTypeHash.hasOwnProperty(k)) {
relArray.push(k + "|" + relTypeHash[k]);
}
}

sDebug +="ParentClass|RelationshipType|ChildClass|Index" + "\n";
for(var m=0 ; m < relArray.length ; m++) {
    sDebug +=relArray[m] +"\n";
}
gs.print(sDebug);

//3. Get Hierarchy for CI classes identified as part of script 1
var sDebug = '';
var tableArray = [];
tableArray.push('TableName|Parent|ParentLevel');
var grTableList = new GlideRecord('sys_db_object');
grTableList.addEncodedQuery('super_class.nameLIKEcmdb^nameIN<commaseperatedlistofclassnames>');
grTableList.query();
while (grTableList.next()) {
classLevel = getClassLevel(grTableList.name);
tableArray.push(classLevel);
//tableArray.push(grTableList.name + "|" + grTableList.super_class.name + "|" + classLevel);
}
for (var k = 0; k < tableArray.length; k++) {
    sDebug += tableArray[k];
}
gs.print(sDebug);

function getClassLevel(name) {
var level = 0;
var parentList = name;
var grTableList = new GlideRecord('sys_db_object');
grTableList.addQuery('name', name);
grTableList.query();
if (grTableList.next()) {
if (grTableList.sys_id != 'f1592a79db02001070a1f482ba961996') { // CMDB class sys_id
parentList += "|" + getClassLevel(grTableList.super_class.name);
//level++;
} else {
//parentList += "|" + grTableList.super_class.name;
//return parentList + "|" + level;
return parentList;
}
}
//return parentList + "|" + level;
return parentList;
}

//4.Get related lists for CI classes identified as part of script 1

var sDebug = '';
var tableArray = [];
tableArray.push('TableName|RelatedList|Filter');
var grFieldList = new GlideRecord('sys_ui_related_list_entry');
grFieldList.addEncodedQuery('list_id.nameIN<commaseparatedlistofclassnames>^list_id.view.titleLIKEdefault');
grFieldList.query();
tableArray.push('TableName|RelatedList|Filter');
while(grFieldList.next()) {
tableArray.push(grFieldList.list_id.name + "|" + grFieldList.related_list + "|" + grFieldList.filter);
}
for(var k=0 ; k < tableArray.length ; k++) {
    sDebug +=tableArray[k];
}
gs.print(sDebug);

//5. Get references for CI classes identified as part of script 1
var sDebug = '';
var tableArray = [];
tableArray.push('TableName|column|ReferenceTable');
var grFieldList = new GlideRecord('sys_dictionary');
grFieldList.addEncodedQuery('internal_type.labelSTARTSWITHreference^reference.nameIN<commaseparatedlistofclassnames>');
grFieldList.query();
tableArray.push('TableName|ColumnName|ReferenceTable');
while(grFieldList.next()) {
tableArray.push(grFieldList.name + "|" + grFieldList.element + "|" + grFieldList.reference.name);
}
for(var k=0 ; k < tableArray.length ; k++) {
sDebug += tableArray[k];
}
gs.print(sDebug);

6. Collect the output from each script into an excel sheet.

7. Build data model using a modelling tool such as visio or GraphML editor. 

8. Start from base class and traverse through rest of the heirarchy.

9. Once classes are modeled next step is to connect them interms of relationship types, references and related lists. When connecting related lists some additional tables such as task or knowledge may need to be added to the data model diagram and setup the connections.

Finally review and refine the model as needed based on additions / changes to CMDB classes.

Version history
Last update:
‎03-26-2024 10:45 AM
Updated by:
Contributors