cmdb-patterns
SKILL.md
CMDB Patterns for ServiceNow
The Configuration Management Database (CMDB) is the foundation of ServiceNow ITSM, tracking all Configuration Items (CIs) and their relationships.
CMDB Architecture
CI Class Hierarchy
cmdb (Base)
└── cmdb_ci (Configuration Item)
├── cmdb_ci_computer
│ ├── cmdb_ci_server
│ │ ├── cmdb_ci_linux_server
│ │ ├── cmdb_ci_win_server
│ │ └── cmdb_ci_unix_server
│ └── cmdb_ci_pc_hardware
├── cmdb_ci_service
│ ├── cmdb_ci_service_auto
│ └── cmdb_ci_service_discovered
├── cmdb_ci_appl
│ ├── cmdb_ci_app_server
│ └── cmdb_ci_db_instance
└── cmdb_ci_network_gear
├── cmdb_ci_netgear
└── cmdb_ci_lb
Key CI Tables
| Table | Purpose | Key Fields |
|---|---|---|
cmdb_ci |
Base CI table | name, sys_class_name, operational_status |
cmdb_ci_server |
Servers | ip_address, os, cpu_count, ram |
cmdb_ci_service |
Business Services | service_classification, busines_criticality |
cmdb_ci_appl |
Applications | version, install_directory |
cmdb_rel_ci |
CI Relationships | parent, child, type |
Creating Configuration Items
Basic CI Creation (ES5)
// Create a new server CI
var ci = new GlideRecord("cmdb_ci_server")
ci.initialize()
ci.setValue("name", "PROD-WEB-001")
ci.setValue("ip_address", "10.0.1.100")
ci.setValue("os", "Linux Red Hat")
ci.setValue("os_version", "8.5")
ci.setValue("cpu_count", 8)
ci.setValue("ram", 32768)
ci.setValue("operational_status", 1) // Operational
ci.setValue("install_status", 1) // Installed
ci.setValue("used_for", "Production")
ci.setValue("owned_by", "sys_id_of_owner")
ci.setValue("support_group", "sys_id_of_group")
var sysId = ci.insert()
CI with Discovery Source
// CI from Discovery
var ci = new GlideRecord("cmdb_ci_linux_server")
ci.initialize()
ci.setValue("name", "discovered-server-001")
ci.setValue("discovery_source", "ServiceNow")
ci.setValue("first_discovered", new GlideDateTime())
ci.setValue("last_discovered", new GlideDateTime())
ci.setValue("ip_address", "10.0.2.50")
// Set classification
ci.setValue("classification", "Production")
ci.setValue("environment", "Production")
ci.insert()
CI Relationships
Relationship Types
| Type | Parent → Child | Example |
|---|---|---|
Runs on::Runs |
App → Server | ERP runs on PROD-DB-01 |
Depends on::Used by |
Service → App | HR Service depends on SAP |
Contains::Contained by |
Cluster → Server | Cluster contains Node1 |
Hosted on::Hosts |
VM → Hypervisor | VM01 hosted on ESX01 |
Members::Member of |
CI → Group | Server member of Pool |
Creating Relationships (ES5)
// Create relationship between CIs
function createCIRelationship(parentSysId, childSysId, relationType) {
// Find relationship type
var relType = new GlideRecord("cmdb_rel_type")
relType.addQuery("name", relationType)
relType.query()
if (!relType.next()) {
gs.error("Relationship type not found: " + relationType)
return null
}
// Check if relationship already exists
var existing = new GlideRecord("cmdb_rel_ci")
existing.addQuery("parent", parentSysId)
existing.addQuery("child", childSysId)
existing.addQuery("type", relType.getUniqueValue())
existing.query()
if (existing.next()) {
gs.info("Relationship already exists")
return existing.getUniqueValue()
}
// Create new relationship
var rel = new GlideRecord("cmdb_rel_ci")
rel.initialize()
rel.setValue("parent", parentSysId)
rel.setValue("child", childSysId)
rel.setValue("type", relType.getUniqueValue())
return rel.insert()
}
// Usage
createCIRelationship(appSysId, serverSysId, "Runs on::Runs")
Querying Relationships
// Find all servers an application runs on
function getAppServers(appSysId) {
var servers = []
var rel = new GlideRecord("cmdb_rel_ci")
rel.addQuery("parent", appSysId)
rel.addQuery("type.name", "Runs on::Runs")
rel.query()
while (rel.next()) {
var server = rel.child.getRefRecord()
servers.push({
sys_id: server.getUniqueValue(),
name: server.getValue("name"),
ip_address: server.getValue("ip_address"),
})
}
return servers
}
// Find all dependencies of a service
function getServiceDependencies(serviceSysId) {
var deps = []
var rel = new GlideRecord("cmdb_rel_ci")
rel.addQuery("parent", serviceSysId)
rel.addQuery("type.name", "Depends on::Used by")
rel.query()
while (rel.next()) {
deps.push({
sys_id: rel.child.getUniqueValue(),
name: rel.child.getDisplayValue(),
class: rel.child.sys_class_name.toString(),
})
}
return deps
}
Impact Analysis
Upstream/Downstream Analysis
// Get all CIs affected by a CI outage (downstream impact)
function getDownstreamImpact(ciSysId, depth) {
if (typeof depth === "undefined") depth = 3
var impacted = []
var processed = {}
function traverse(sysId, currentDepth) {
if (currentDepth > depth || processed[sysId]) return
processed[sysId] = true
var rel = new GlideRecord("cmdb_rel_ci")
rel.addQuery("child", sysId)
rel.query()
while (rel.next()) {
var parentId = rel.parent.toString()
if (!processed[parentId]) {
impacted.push({
sys_id: parentId,
name: rel.parent.getDisplayValue(),
depth: currentDepth,
})
traverse(parentId, currentDepth + 1)
}
}
}
traverse(ciSysId, 1)
return impacted
}
// Get all CIs this CI depends on (upstream dependencies)
function getUpstreamDependencies(ciSysId, depth) {
if (typeof depth === "undefined") depth = 3
var dependencies = []
var processed = {}
function traverse(sysId, currentDepth) {
if (currentDepth > depth || processed[sysId]) return
processed[sysId] = true
var rel = new GlideRecord("cmdb_rel_ci")
rel.addQuery("parent", sysId)
rel.query()
while (rel.next()) {
var childId = rel.child.toString()
if (!processed[childId]) {
dependencies.push({
sys_id: childId,
name: rel.child.getDisplayValue(),
depth: currentDepth,
})
traverse(childId, currentDepth + 1)
}
}
}
traverse(ciSysId, 1)
return dependencies
}
Business Service Impact
// Find all business services impacted by a CI
function getImpactedServices(ciSysId) {
var services = []
var processed = {}
function findServices(sysId) {
if (processed[sysId]) return
processed[sysId] = true
// Check if this CI is a service
var ci = new GlideRecord("cmdb_ci")
if (ci.get(sysId)) {
if (ci.sys_class_name.toString().indexOf("cmdb_ci_service") === 0) {
services.push({
sys_id: sysId,
name: ci.getValue("name"),
criticality: ci.getValue("busines_criticality"),
})
}
}
// Traverse upstream
var rel = new GlideRecord("cmdb_rel_ci")
rel.addQuery("child", sysId)
rel.query()
while (rel.next()) {
findServices(rel.parent.toString())
}
}
findServices(ciSysId)
return services
}
CMDB Health & Data Quality
Orphan CI Detection
// Find CIs without relationships
function findOrphanCIs(ciClass) {
var orphans = []
var ci = new GlideRecord(ciClass || "cmdb_ci")
ci.addQuery("operational_status", 1) // Operational only
ci.query()
while (ci.next()) {
var sysId = ci.getUniqueValue()
// Check for any relationships
var rel = new GlideRecord("cmdb_rel_ci")
rel.addQuery("parent", sysId).addOrCondition("child", sysId)
rel.setLimit(1)
rel.query()
if (!rel.hasNext()) {
orphans.push({
sys_id: sysId,
name: ci.getValue("name"),
class: ci.getValue("sys_class_name"),
})
}
}
return orphans
}
Stale CI Detection
// Find CIs not updated by discovery
function findStaleCIs(daysOld) {
if (typeof daysOld === "undefined") daysOld = 30
var stale = []
var cutoff = new GlideDateTime()
cutoff.addDaysLocalTime(-daysOld)
var ci = new GlideRecord("cmdb_ci")
ci.addQuery("operational_status", 1)
ci.addQuery("last_discovered", "<", cutoff)
ci.addNotNullQuery("last_discovered")
ci.query()
while (ci.next()) {
stale.push({
sys_id: ci.getUniqueValue(),
name: ci.getValue("name"),
last_discovered: ci.getValue("last_discovered"),
})
}
return stale
}
MCP Tool Integration
Available CMDB Tools
| Tool | Purpose |
|---|---|
snow_create_ci |
Create new CI with proper class |
snow_cmdb_search |
Search CIs with filters |
snow_create_ci_relationship |
Create CI relationships |
snow_impact_analysis |
Analyze CI impact |
snow_get_ci_details |
Get full CI information |
snow_run_discovery |
Trigger discovery |
Example Workflow
// 1. Search for existing CI
await snow_cmdb_search({
ci_class: "cmdb_ci_server",
query: "name=PROD-WEB-001",
include_relationships: true,
})
// 2. Create new CI if not found
await snow_create_ci({
ci_class: "cmdb_ci_linux_server",
name: "PROD-WEB-002",
ip_address: "10.0.1.101",
operational_status: 1,
})
// 3. Create relationship
await snow_create_ci_relationship({
parent: appSysId,
child: serverSysId,
type: "Runs on::Runs",
})
// 4. Impact analysis
await snow_impact_analysis({
ci_sys_id: serverSysId,
direction: "downstream",
depth: 3,
})
Best Practices
- Use Correct CI Class - Always use most specific class (cmdb_ci_linux_server, not cmdb_ci)
- Maintain Relationships - CIs without relationships have limited value
- Discovery Alignment - Align manual CIs with discovery patterns
- Operational Status - Keep status current (Operational, Retired, etc.)
- Unique Identifiers - Use serial_number, asset_tag for uniqueness
- Service Mapping - Connect CIs to business services
- Regular Cleanup - Archive retired CIs, remove orphans
Weekly Installs
51
Repository
groeimetai/snow-flowGitHub Stars
53
First Seen
Jan 22, 2026
Security Audits
Installed on
github-copilot46
gemini-cli46
opencode46
codex46
claude-code46
cursor45