Script not working as expected

pardhiv
Tera Contributor

I am trying to create 3 reports,
1. To show servers that are in scope (Operational status = operation AND install status = installed, Environment=Production) (Count 1424)

2. Servers that are in scope mapped to a application , (used sysId is one of and called a Script include) - 559 seems realistic

3. Servers that are in Scope and not mapped to a application (used sysId is one of and called a Script include) -Number is more than servers that are in Scope

 

unMappedSrvr: function() {

        var unMapdServer = [];
        var inScopeQuery = gs.getProperty('inscope.server.app.mapping');// Used same property for Mapped servers too
        var grSer2 = new GlideRecord('cmdb_ci_server');
        //grSer2.addEncodedQuery(inScopeQuery ); //Seems like this failing , return count shows more thanCIs as per below scope , returns 9000~
        grSer2.addEncodedQuery('install_status=1^environment=Production^operational_status=1'); //This is same filter as property, count is within scope, returns 751
        grSer2.query();
        while (grSer2.next()) {
            var grCrel = new GlideRecord('cmdb_rel_ci');
            grCrel.addQuery('child', grSer2.sys_id);
            grCrel.addQuery('parent.sys_class_name', 'INSTANCEOF', 'cmdb_ci_service_discovered');
            grCrel.query();
            if (!grCrel.next()) {
                unMapdServer.push(grSer2.sys_id.toString());
            }
            while (grCrel.next()) {
                var grDrel = new GlideRecord('cmdb_rel_ci');
                grDrel.addQuery('child', grCrel.parent);
                grDrel.addQuery('parent.sys_class_name', 'cmdb_ci_business_app');
                grDrel.query();
                if (!grDrel.next()) {
                    unMapdServer.push(grSer2.sys_id.toString());
                }
            }
        }
        return unMapdServer.join(',');
    },

 

pardhiv_0-1767848029986.png

pardhiv_1-1767848101035.png

 

 

 

1 ACCEPTED SOLUTION

SIVASANKARIS
Mega Guru

Hi @pardhiv ,

 I can see that there is some logic issues in the code, which may cause the mismatching in count

First One: You are using two grCrel.next() function along with if and while here 

 

  " if (!grCrel.next()) { ...

         while (grCrel.next()) {"  which is wrong because consider below scenarios

 

Scenario 1: When Server has NO relations, it will work fine

Step                                  What happens
grCrel.next()returns FALSE
IF blockruns → push server
while(grCrel.next())returns FALSE → loop skipped

BUT

Scenario 2:Server HAS relations (example: 2 relations) Rel1, Rel2

IFCondition: !grCrel.next()here our rel1 is checked and cursor is moved to rel2.

while(grCrel.next()) here in the while loop rel2 is checked, so rel1 will always be skipped

 

Second One: You are pushing server inside the loop which is causing the duplicates

 in this code portion: 

while(..){

{if (!grDrel.next())

{ unMapdServer.push(grSer2.sys_id.toString()); }}

 

Consider: If server 1 has 3 discovered service, none of these services are linked to business application means the same server will be pushed 3 times in the array

 

So the corrected code is...

unMappedSrvr: function() {

    var unMapdServer = [];
    var inScopeQuery = gs.getProperty('inscope.server.app.mapping'); 
    var grSer2 = new GlideRecord('cmdb_ci_server');

    grSer2.addEncodedQuery('install_status=1^environment=Production^operational_status=1');
    grSer2.query();

    while (grSer2.next()) {

        var isUnmapped = false;

        var grCrel = new GlideRecord('cmdb_rel_ci');
        grCrel.addQuery('child', grSer2.sys_id);
        grCrel.addQuery('parent.sys_class_name', 'INSTANCEOF', 'cmdb_ci_service_discovered');
        grCrel.query();

        // 1 If NO discovered service relation
        if (!grCrel.hasNext()) {
            isUnmapped = true;
        }

        // 2 If discovered services exist, check business app mapping
        while (!isUnmapped && grCrel.next()) {

            var grDrel = new GlideRecord('cmdb_rel_ci');
            grDrel.addQuery('child', grCrel.parent);
            grDrel.addQuery('parent.sys_class_name', 'cmdb_ci_business_app');
            grDrel.query();

            // If service NOT linked to business app
            if (!grDrel.hasNext()) {
                isUnmapped = true;
                break; // stop checking further services
            }
        }

        // 3 Push only once
        if (isUnmapped) {
            unMapdServer.push(grSer2.sys_id.toString());
        }
    }

    return unMapdServer.join(',');
}

 

Fix I applied

1) hasNext() ==> if (!grCrel.hasNext()) { ... } -> only checks if record exists, will not move the cursor to next record.

2)Handled duplicates ==> I avoided pushing the server inside the loop. Instead, I used a flag to mark the server as unmapped and immediately broke out of the loop when the condition was met. After exiting the loop, I pushed the server only once, which prevents duplicate entries.

 

I have made lot of efforts for this , if you find these useful please mark it as helpful and please accept my solution...

Best Regards,

SIVASANKARI S

ITOM Engineer

View solution in original post

5 REPLIES 5

SIVASANKARIS
Mega Guru

Hi @pardhiv ,

 I can see that there is some logic issues in the code, which may cause the mismatching in count

First One: You are using two grCrel.next() function along with if and while here 

 

  " if (!grCrel.next()) { ...

         while (grCrel.next()) {"  which is wrong because consider below scenarios

 

Scenario 1: When Server has NO relations, it will work fine

Step                                  What happens
grCrel.next()returns FALSE
IF blockruns → push server
while(grCrel.next())returns FALSE → loop skipped

BUT

Scenario 2:Server HAS relations (example: 2 relations) Rel1, Rel2

IFCondition: !grCrel.next()here our rel1 is checked and cursor is moved to rel2.

while(grCrel.next()) here in the while loop rel2 is checked, so rel1 will always be skipped

 

Second One: You are pushing server inside the loop which is causing the duplicates

 in this code portion: 

while(..){

{if (!grDrel.next())

{ unMapdServer.push(grSer2.sys_id.toString()); }}

 

Consider: If server 1 has 3 discovered service, none of these services are linked to business application means the same server will be pushed 3 times in the array

 

So the corrected code is...

unMappedSrvr: function() {

    var unMapdServer = [];
    var inScopeQuery = gs.getProperty('inscope.server.app.mapping'); 
    var grSer2 = new GlideRecord('cmdb_ci_server');

    grSer2.addEncodedQuery('install_status=1^environment=Production^operational_status=1');
    grSer2.query();

    while (grSer2.next()) {

        var isUnmapped = false;

        var grCrel = new GlideRecord('cmdb_rel_ci');
        grCrel.addQuery('child', grSer2.sys_id);
        grCrel.addQuery('parent.sys_class_name', 'INSTANCEOF', 'cmdb_ci_service_discovered');
        grCrel.query();

        // 1 If NO discovered service relation
        if (!grCrel.hasNext()) {
            isUnmapped = true;
        }

        // 2 If discovered services exist, check business app mapping
        while (!isUnmapped && grCrel.next()) {

            var grDrel = new GlideRecord('cmdb_rel_ci');
            grDrel.addQuery('child', grCrel.parent);
            grDrel.addQuery('parent.sys_class_name', 'cmdb_ci_business_app');
            grDrel.query();

            // If service NOT linked to business app
            if (!grDrel.hasNext()) {
                isUnmapped = true;
                break; // stop checking further services
            }
        }

        // 3 Push only once
        if (isUnmapped) {
            unMapdServer.push(grSer2.sys_id.toString());
        }
    }

    return unMapdServer.join(',');
}

 

Fix I applied

1) hasNext() ==> if (!grCrel.hasNext()) { ... } -> only checks if record exists, will not move the cursor to next record.

2)Handled duplicates ==> I avoided pushing the server inside the loop. Instead, I used a flag to mark the server as unmapped and immediately broke out of the loop when the condition was met. After exiting the loop, I pushed the server only once, which prevents duplicate entries.

 

I have made lot of efforts for this , if you find these useful please mark it as helpful and please accept my solution...

Best Regards,

SIVASANKARI S

ITOM Engineer