CMDB Health Inclusion Rule Best Practices

Larry Youngqui2
Tera Contributor

I am in the process of developing the CMDB Dashboard with the associated health rules.   The first iteration will be aimed at the Asset Management set of 'Managed Classes'.   Those CMDB classes that they actively manage and are responsible for.

Our CMDB contains a lot of what we consider "non-managed" classes, such as the Next Hop Routing records and other CI classes.   We have chosen to keep those in the CMDB but wish to exclude them from the CMDB dashboard.   And as we upgrade to Kingston, we want to take advantage of the Health Inclusion rule introduced in Jakarta.

But before beginning a large effort at configuring the rules, I'd like to ask for any best practices or advice that we should be aware of.  The documentation (Create identification inclusion rule) is clear on how to provision the necessary filters, but I want to ensure we're doing it in the most efficient manner.   And importantly, in a manner that is manageable and understandable by both myself and our Managed Class Owners.  Because the Asset Management set of Managed Classes is somewhat lengthy and messy, I'm starting with their set of classes first.  As I create the filters, I don't want to create such a fragile filter that it requires constant tweaking and fiddling.   I also want to avoid the question from my Managed Class Owners, as to "why" or "why not" any particular class is included or not.    They should have a clear understanding of what CIs they own and manage.  And if they need to adjust, they need to clearly provide the detail needed for the filter

At the top of the hierarchy, the cmdb_ci table, I plan on excluding the majority of classes that we just don't want incorporated in the scorecard calculations.   Especially, the classes that have large numbers of records, such as the aforementioned Next Hop Routing Rule.    The active record filter is a simple "Class != <class>" and so forth.    Basically, the global exclusion rule.

Under each specific managed class, I would include an inclusion of which specific records to include.  That is, "Active = True", or "Status = [Installed | Available | Deployed | etc.]" or "Managed by != NULL", etc.   Whatever the Managed Class Owner considers as an active CI record that needs to be managed.

Is this a feasible strategy to follow for building the set of CMDB CI records contained in our dashboard?   Are there other methods that have been used and tested?     Is there performance concerns that need to be considered when running the dashboard scripts?

Thanks in advance,

Larry

17 REPLIES 17

Thanks Andrew. Yes, if you could share any details, I would appreciate it.

Here's a great article around automation that I followed for our Next Hop issues:
https://community.servicenow.com/community?id=community_blog&sys_id=894131c5dbe96700afc902d5ca96196d

I wrote a workflow (like is suggested in the article) which fires automatically when a Duplicate Task is logged that looks at the CIs and deletes the duplicate "Old" ones, and only keeps the newest. The parts that I think the above article didn't make clear enough:

The workflow needs to be on the "Remediate Duplicate Task" table

Here's my script:

// Find all duplicate records associated with the current task
var grResult = new GlideRecord ('duplicate_audit_result');
grResult.addQuery ( 'follow_on_task', current.sys_id );
grResult.query();
var cis = [];
while (grResult.next())
	cis.push(grResult.getValue('duplicate_ci'));

// Query for the duplicate records, and order in reverse chronological order
var grCi = new GlideRecord ( 'cmdb_ci' );
grCi.addQuery('sys_id', 'IN', cis.toString());
grCi.orderBy('sys_created_on');
grCi.query();
grCi.next(); // Skip the CI that was created first
while (grCi.next()) {
	grCi.deleteRecord();
}

 

The workflow looks like this:
find_real_file.png

(It's that simple)

 

Then you create "Remediation Rule" from the table "remediation_rule" that specifies that workflow to run on duplicate tasks when specific criteria are met (the short description has Next Hop Routing Rule for example). This will start the automation.

I found that I had a lot (1000+) duplicate tasks, so I wrote a script to run in the backgorund which steps through all those tasks, and runs the workflow manually. for each. They should all close then.

 

Some issues I still have is the tasks often don't close, so you may want to put a "close task" step in the workflow, and we had to expand it to a few other CI types like "Disk" for physical disks which were being duplicated

 

Hope this helps!
-Andrew

Hello Andrew,

I created remediation_rule, added a workflow (with Set Values step added to close the Task) and copied your script (and make small changes - see below). It works fine when I run remediation manually from the Task but when I set it to auto it closed the Task (workflow step is unconditional) but did not remove the duplicate CIs.

With the cis.length check added to the script I found out that there is 0 CIs related to the Task during the automated run and correct number when I run it manually. It seems they are added to duplicate_audit_result after automated remediation! Do you know what could be the reason? We are on Madrid Patch 4.

Thank you in advance!

// Find all duplicate records associated with the current task
var grResult = new GlideRecord ('duplicate_audit_result');
grResult.addQuery ( 'follow_on_task', current.sys_id );
grResult.query();
var cis = [];
while (grResult.next())
	cis.push(grResult.getValue('duplicate_ci'));

// *** for debug only
gs.info('De-Dupl Task:' + current.number + '. Number of duplicated CIs: '+cis.length);

// Query for the duplicate records with discovery_source = 'Duplicate'
var grCi = new GlideRecord ( 'cmdb_ci' );
grCi.addQuery('sys_id', 'IN', cis.toString());
grCi.addQuery('discovery_source','Duplicate');
grCi.query();
while (grCi.next()) {
	grCi.deleteRecord();
	gs.info('De-Dupl Task:' + current.number + '. The duplicate CI removed: '+grCi.getValue('name'));
}

duplicate_audit_result:

find_real_file.png

wf_history_list:

find_real_file.png

 

 EDIT: I was able to make this working to some extend by adding "Timer" step in the workflow. But still looking for a "proper" solution...