Orphan Rule does not return the expected result

Giovanni Eggidi
Tera Contributor

Hi,

I would like to get the CIs of some classes (server, application, service, process groups) which have not relations to other CIs. 

To have good performance, I tried to create an orphan rule on Server Class, configured as the follow:

GiovanniEggidi_0-1674660770173.png

But in this way, I never find new orphaned records in table "cmdb_health_result".

I am sure that there are Servers which not have relations with other CIs in "cmdb_rel_ci".

Why this rule does not work?

 

Thanks & Regards, Giovanni

2 REPLIES 2

CMDB Whisperer
Mega Sage
Mega Sage

This will filter your orphan rule to say that in order for the Server to be an orphan it must have been last discovered by SGO-Dynatrace.  On the surface that seems a bit restrictive, as you may have Servers coming in from other sources like Discovery.  I wouldn't normally use Discovery Source as a condition for an orphan rule.  The attribute to use is more to clarify which CIs you want to enforce the existence of a relationship on.  Good attributes to filter this down might be Status/Operational Status and Environment.


The opinions expressed here are the opinions of the author, and are not endorsed by ServiceNow or any other employer, company, or entity.

Daniel Needles1
Kilo Guru

I'd start by creating a report with the same conditions to get a subset of records that could have the problem.  If that isn't obvious, you could modify the script below and see if there are any hits.  At least then you would be troubleshooting from a known dataset.  (This script is based on (I think) somewhere in this playbook - https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0829101.

 

 

///////////////////////////////////////////////////////////////////////////////////
// PROGRAM: delete_orphans   Daniel L. Needles
// PURPOSE: CIs refer to other CIs. If there is no "mother ship", delete the CI.
///////////////////////////////////////////////////////////////////////////////////
CDK_CMDB_deduplicate.delete_orphans = function(command) {
	/**
 * Script used to list or delete orphan CIs
 */

	// VALID IDENTIFICATION INDEXING?
	if (command != 'listAll' && command != 'deleteAll') {
		gs.log('ERROR: command must be either listAll or deleteAll');
		return;
	}

	// *********************************** SETUP ************************************************************

	var deleteCount = 4000;
	var batchSize = 1000;
	var deleteAll = false;

	//  ********************EDITING NOT REQUIRED PAST THIS POINT ********************************************
	var deletionsCompleted = 0;     // DO NOT CHANGE
	var loopControl = true;         // DO NOT CHANGE, var to delete multiple at least once
	var resultString = 'CDK_CMDB_DeDuplicate Library Delete_Orphans Function\n\n';
	var agg = new GlideAggregate('cmdb_rel_ci');
	agg.addQuery('parent.sys_class_name', '').addOrCondition('child.sys_class_name', '');
	agg.addAggregate('COUNT');
	agg.query();

	// LETS FIND OUT HOW MANY ORPHANS NEED TO BE DELETED
	agg.next();

	var deletionCandidates = agg.getAggregate("COUNT");
	resultString += 'Found : ' + deletionCandidates + ' invalid relationships!\n';

	if (command == 'listAll'){
		resultString += 'To delete Orphaned Relationship, call with deleteAll, not listAll!\n';
	} else {
		//let's delete some records
		var orphans = new GlideRecord('cmdb_rel_ci');
		orphans.addQuery('parent.sys_class_name', '').addOrCondition('child.sys_class_name', '');

		if (deleteCount == 0 && deleteAll){
			orphans.setWorkflow(false);
			orphans.setUseEngines(false);
			orphans.deleteMultiple();
			deletionsCompleted = deletionCandidates;
		} else {
			while (loopControl){
				//delete n (deleteCount) records at a time
				orphans.setLimit(batchSize);
				orphans.query();

				var deletedActualCount = orphans.getRowCount();
				if (deletedActualCount!=0){
					orphans.setWorkflow(false);
					orphans.setUseEngines(false);
					orphans.deleteMultiple();
					deletionsCompleted += deletedActualCount;

					if (deletionsCompleted >= deleteCount){
						loopControl = false;
					}
				} else {
					loopControl = false;
				}
			}
		}
		resultString += '\nSuccesfully deleted ' + deletionsCompleted + ' records!\n';
	}

	gs.print(resultString);
	return(resultString);
};