cmdb-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

CMDB Patterns for ServiceNow

ServiceNow的CMDB模式

The Configuration Management Database (CMDB) is the foundation of ServiceNow ITSM, tracking all Configuration Items (CIs) and their relationships.
配置管理数据库(CMDB)是ServiceNow ITSM的核心基础,用于跟踪所有配置项(CI)及其相互关系。

CMDB Architecture

CMDB架构

CI Class Hierarchy

CI类层级结构

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
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

核心CI表

TablePurposeKey Fields
cmdb_ci
Base CI tablename, sys_class_name, operational_status
cmdb_ci_server
Serversip_address, os, cpu_count, ram
cmdb_ci_service
Business Servicesservice_classification, busines_criticality
cmdb_ci_appl
Applicationsversion, install_directory
cmdb_rel_ci
CI Relationshipsparent, child, type
表名用途关键字段
cmdb_ci
CI基础表name, sys_class_name, operational_status
cmdb_ci_server
服务器表ip_address, os, cpu_count, ram
cmdb_ci_service
业务服务表service_classification, busines_criticality
cmdb_ci_appl
应用表version, install_directory
cmdb_rel_ci
CI关系表parent, child, type

Creating Configuration Items

创建配置项

Basic CI Creation (ES5)

基础CI创建(ES5)

javascript
// 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();
javascript
// 创建新的服务器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);  // 运行中
ci.setValue('install_status', 1);      // 已安装
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创建

javascript
// 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();
javascript
// 来自发现的CI
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');

// 设置分类
ci.setValue('classification', 'Production');
ci.setValue('environment', 'Production');

ci.insert();

CI Relationships

CI关系

Relationship Types

关系类型

TypeParent → ChildExample
Runs on::Runs
App → ServerERP runs on PROD-DB-01
Depends on::Used by
Service → AppHR Service depends on SAP
Contains::Contained by
Cluster → ServerCluster contains Node1
Hosted on::Hosts
VM → HypervisorVM01 hosted on ESX01
Members::Member of
CI → GroupServer member of Pool
类型父→子示例
Runs on::Runs
应用→服务器ERP运行于PROD-DB-01
Depends on::Used by
服务→应用HR服务依赖SAP
Contains::Contained by
集群→服务器集群包含Node1
Hosted on::Hosts
虚拟机→虚拟化管理服务器VM01托管于ESX01
Members::Member of
CI→组服务器属于资源池

Creating Relationships (ES5)

创建关系(ES5)

javascript
// 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');
javascript
// 创建CI间的关系
function createCIRelationship(parentSysId, childSysId, relationType) {
    // 查找关系类型
    var relType = new GlideRecord('cmdb_rel_type');
    relType.addQuery('name', relationType);
    relType.query();

    if (!relType.next()) {
        gs.error('未找到关系类型: ' + relationType);
        return null;
    }

    // 检查关系是否已存在
    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('关系已存在');
        return existing.getUniqueValue();
    }

    // 创建新关系
    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();
}

// 使用示例
createCIRelationship(appSysId, serverSysId, 'Runs on::Runs');

Querying Relationships

查询关系

javascript
// 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;
}
javascript
// 查找应用运行的所有服务器
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;
}

// 查找服务的所有依赖项
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

上游/下游分析

javascript
// 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;
}
javascript
// 获取CI故障影响的所有CI(下游影响)
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;
}

// 获取该CI依赖的所有上游CI
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

业务服务影响

javascript
// 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;
}
javascript
// 查找受CI影响的所有业务服务
function getImpactedServices(ciSysId) {
    var services = [];
    var processed = {};

    function findServices(sysId) {
        if (processed[sysId]) return;
        processed[sysId] = true;

        // 检查该CI是否为服务
        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')
                });
            }
        }

        // 向上游遍历
        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

CMDB健康度与数据质量

Orphan CI Detection

孤立CI检测

javascript
// 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;
}
javascript
// 查找无关联关系的CI
function findOrphanCIs(ciClass) {
    var orphans = [];

    var ci = new GlideRecord(ciClass || 'cmdb_ci');
    ci.addQuery('operational_status', 1);  // 仅运行中的CI
    ci.query();

    while (ci.next()) {
        var sysId = ci.getUniqueValue();

        // 检查是否存在任何关联关系
        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

陈旧CI检测

javascript
// 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;
}
javascript
// 查找未被发现更新的CI
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

MCP工具集成

Available CMDB Tools

可用的CMDB工具

ToolPurpose
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
工具用途
snow_create_ci
使用正确的类创建新CI
snow_cmdb_search
带筛选条件的CI搜索
snow_create_ci_relationship
创建CI关系
snow_impact_analysis
分析CI影响
snow_get_ci_details
获取完整CI信息
snow_run_discovery
触发发现任务

Example Workflow

示例工作流

javascript
// 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
});
javascript
// 1. 搜索现有CI
await snow_cmdb_search({
    ci_class: 'cmdb_ci_server',
    query: 'name=PROD-WEB-001',
    include_relationships: true
});

// 2. 若未找到则创建新CI
await snow_create_ci({
    ci_class: 'cmdb_ci_linux_server',
    name: 'PROD-WEB-002',
    ip_address: '10.0.1.101',
    operational_status: 1
});

// 3. 创建关系
await snow_create_ci_relationship({
    parent: appSysId,
    child: serverSysId,
    type: 'Runs on::Runs'
});

// 4. 影响分析
await snow_impact_analysis({
    ci_sys_id: serverSysId,
    direction: 'downstream',
    depth: 3
});

Best Practices

最佳实践

  1. Use Correct CI Class - Always use most specific class (cmdb_ci_linux_server, not cmdb_ci)
  2. Maintain Relationships - CIs without relationships have limited value
  3. Discovery Alignment - Align manual CIs with discovery patterns
  4. Operational Status - Keep status current (Operational, Retired, etc.)
  5. Unique Identifiers - Use serial_number, asset_tag for uniqueness
  6. Service Mapping - Connect CIs to business services
  7. Regular Cleanup - Archive retired CIs, remove orphans
  1. 使用正确的CI类 - 始终使用最具体的类(如cmdb_ci_linux_server,而非cmdb_ci)
  2. 维护关联关系 - 无关联关系的CI价值有限
  3. 与发现任务对齐 - 手动创建的CI需与发现模式保持一致
  4. 更新运行状态 - 及时维护CI状态(运行中、已退役等)
  5. 唯一标识符 - 使用serial_number、asset_tag作为唯一标识
  6. 服务映射 - 将CI与业务服务关联
  7. 定期清理 - 归档已退役CI,移除孤立CI