Welcome to Community Week 2025! Join us to learn, connect, and be recognized as we celebrate the spirit of Community and the power of AI. Get the details  

How to remove duplicate relationships on each affected CI ?

Community Alums
Not applicable

Hi Everyone,

How can we restrict duplicate relationships on each affected CI and also  Prevention the creation of new duplicate relationships (Patches::Patched by).

Script Include has been written for this, still its effecting with duplicate CI's

Script Include :

var FA_CMDB_DupRelationshipHelper = Class.create();
FA_CMDB_DupRelationshipHelper.prototype = {
   

    validateCIRelationships: function(appNumber,ciSysID,ciDisplayName,trigger) {
        var errorReason = '';
        var grInserOrUpdRel = new GlideRecord('cmdb_rel_ci');
        var relType = gs.getProperty('cmdb.rel.runs_on_runs_type'); // Runs on relationship sys id
        var grApp = new GlideRecord("cmdb_ci_service_discovered");
        grApp.addEncodedQuery("number=" + appNumber);
        grApp.setLimit(1);
        grApp.query();
        if (grApp.next()) {
            var gaRel = new GlideAggregate('cmdb_rel_ci');
            gaRel.addEncodedQuery("child=" + ciSysID + "^type=" + relType + "^parent.sys_class_name=cmdb_ci_service_discovered"); // Query to check any relationships existed with provided appNumber, ciSysID & cmdb_ci_service_discovered table as parent 
            gaRel.addAggregate('COUNT');
            gaRel.query();
            if (gaRel.next()) {
                if (gaRel.getAggregate('COUNT') == 0) { // No records Create a new relationship
                    grInserOrUpdRel.initialize();
                    grInserOrUpdRel.setValue('child', ciSysID);
                    grInserOrUpdRel.setValue("type", relType); // setting Runs on :Runs relationship type
                    grInserOrUpdRel.setValue('parent', grApp.getUniqueValue());
                    grInserOrUpdRel.insert();
                    if (ciDisplayName) {
                        this.checkOSIRel(ciDisplayName, grApp.getUniqueValue(), relType, appNumber, trigger);
                    }
                } else if (gaRel.getAggregate('COUNT') > 1) { // if we have more than one record need to delete all and create one relationship
                    this.delDuplicateRecords(ciSysID, relType);
                    grInserOrUpdRel.initialize();
                    grInserOrUpdRel.setValue('child', ciSysID);
                    grInserOrUpdRel.setValue("type", relType); // setting Runs on :Runs relationship type
                    grInserOrUpdRel.setValue('parent', grApp.getUniqueValue());
                    grInserOrUpdRel.insert();
                    if (ciDisplayName) {
                        this.checkOSIRel(ciDisplayName, grApp.getUniqueValue(), relType, appNumber, trigger);
                    }
                } else if (gaRel.getAggregate('COUNT') == 1) { // if we have one record need to verify any changes based on that update
                    grInserOrUpdRel.initialize();
                    grInserOrUpdRel.addEncodedQuery("child=" + ciSysID + "^type=" + relType + "^parent.sys_class_name=cmdb_ci_service_discovered"); 
                    grInserOrUpdRel.setLimit(1);
                    grInserOrUpdRel.query();
                    if (grInserOrUpdRel.next()) {
                        if (grInserOrUpdRel.getValue('parent') != grApp.getUniqueValue()) {
                            grInserOrUpdRel.parent = grApp.getUniqueValue();
                            grInserOrUpdRel.update();
                        }
                        if (ciDisplayName) {
                            this.checkOSIRel(ciDisplayName, grApp.getUniqueValue(), relType, appNumber, trigger);
                        }
                    }
                }
            }
        } else {
            errorReason = 'Cannot find matching Application Service with the number in Key Value "ApplicationServiceNumber" entry from the VMI: <strong>' + ciDisplayName + '</strong>';
            gs.eventQueue('fa.cmdb.relationship.failed', null, errorReason, trigger);
        }
    },
    
    delDuplicateRecords: function(CI, relType) {
        var grRel = new GlideRecord('cmdb_rel_ci');
        grRel.addEncodedQuery("child=" + CI + "^type=" + relType + "^parent.sys_class_name=cmdb_ci_service_discovered");
        grRel.query();
        while (grRel.next()) {
            grRel.setWorkflow(false);
            grRel.deleteRecord();
        }
    },

    checkOSIRel: function(displayName, appSerID, relType, appNumber, trigger) {
        // Check on Cmdb server table
        var ciClass = '';
        var ciSysID = '';
        var errorReason= '';
        var gtServerNme = new GlideRecord('cmdb_ci_server');
        gtServerNme.addQuery('name', displayName);
        gtServerNme.addQuery('install_status', '!=', '7');
        gtServerNme.setLimit(1);
        gtServerNme.query();
        if (gtServerNme.next()) {
            ciClass = gtServerNme.getValue('sys_class_name');
            ciSysID = gtServerNme.getUniqueValue();
        } else {
            errorReason = 'Cannot find matching OS Server with same name as the VMI: ' + displayName +' server with the inserted/updated Key Value: <strong>' + appNumber + '</strong>';
            gs.eventQueue('fa.cmdb.relationship.failed', null, errorReason, trigger);
        }
        if (ciSysID) {
            var qry = "typeLIKERuns on::Runs^child.sys_class_name!=cmdb_ci_vm_instance^parent.sys_class_name=cmdb_ci_service_discovered^child.sys_id=" + ciSysID;
            var getOSrel = new GlideRecord('cmdb_rel_ci');
            getOSrel.addEncodedQuery(qry);
            getOSrel.query();
            if (getOSrel.hasNext()) {
                while (getOSrel.next()) {
                    getOSrel.setWorkflow(false);
                    getOSrel.deleteRecord();
                }
                getOSrel.initialize();
                getOSrel.setValue('child', ciSysID);
                getOSrel.setValue("type", relType); // setting Runs on :Runs relationship type
                getOSrel.setValue('parent', appSerID);
                getOSrel.insert();
            } else {
                getOSrel.initialize();
                getOSrel.setValue('child', ciSysID);
                getOSrel.setValue("type", relType); // setting Runs on :Runs relationship type
                getOSrel.setValue('parent', appSerID);
                getOSrel.insert();
            }
        }
    },
    type: 'FA_CMDB_DupRelationshipHelper'
}

 

Thanks and Regards @Ankur Bawiskar , @Mohith Devatte 

Venugopal S

1 ACCEPTED SOLUTION

A before insert business rule on cmdb_rel_ci table with below script would do the job for you

 

var rel = new GlideRecord('cmdb_rel_ci');

rel.addQuery('parent', current.parent);

rel.addQuery('child', current.child);

rel.addQuery('type', <sys_id of Patches::Patched by >);

rel.query();

 

if (rel.next()){

gs.addInfoMessage("relationship already exists");

current.setAbortAction(true);

}

View solution in original post

7 REPLIES 7

suvro
Mega Sage

when this script include is called ?

It should be called in before insert business rule on cmdb_rel_ci

Community Alums
Not applicable

There are 3 business rules are written before insert. which doesn't have the relation for duplicates.

Thanks

A before insert business rule on cmdb_rel_ci table with below script would do the job for you

 

var rel = new GlideRecord('cmdb_rel_ci');

rel.addQuery('parent', current.parent);

rel.addQuery('child', current.child);

rel.addQuery('type', <sys_id of Patches::Patched by >);

rel.query();

 

if (rel.next()){

gs.addInfoMessage("relationship already exists");

current.setAbortAction(true);

}