Help with Script for Automatically Updating CI Install Status Based on Discovery Date

Abdul333
Tera Contributor

 

Hello Everyone,

 

I’m working on a story to automatically update the install_status of Configuration Items (CIs) based on the number of days since their last discovery. Specifically, I need to update CIs with the following criteria:

  • If a CI hasn’t been discovered in the last 45–90 days, its install_status should be changed to Absent (100).
  • If a CI hasn’t been discovered in the last 90+ days, its install_status should be changed to Retired (7 ), and the operational_status should be set to Non-Operational (2).

Class names: cmdb_ci_db_mssql_database,cmdb_ci_vm_instance,cmdb_ci_db_ora_instance,cmdb_ci_linux_server,cmdb_ci_vmware_instance

I created a system property with all the classes mentioned above. Property name(ci.auto.manage.classes)

Script:

(function () {
gs.info('=== CI Auto Absent / Retire Job STARTED ===');

// System Properties
var classList = gs.getProperty('ci.auto.manage.classes', '').split(',');
var absentDays = parseInt(gs.getProperty('ci.absent.days', '45'), 10);
var retireDays = parseInt(gs.getProperty('ci.retire.days', '90'), 10);

var absentInstallStatus = gs.getProperty('ci.absent.install_status', '100');
var retireInstallStatus = gs.getProperty('ci.retire.install_status', '7');
var retireOperStatus = gs.getProperty('ci.retire.operational_status', '2');

// Date calculations
var now = new GlideDateTime();

var absentCutoff = new GlideDateTime(now);
absentCutoff.addDaysUTC(-absentDays);

var retireCutoff = new GlideDateTime(now);
retireCutoff.addDaysUTC(-retireDays);

gs.info('Absent Cutoff : ' + absentCutoff.getDisplayValue());
gs.info('Retire Cutoff : ' + retireCutoff.getDisplayValue());

for (var i = 0; i < classList.length; i++) {
var table = classList[i].trim();
if (!table) continue;

gs.info('--- Processing Table: ' + table + ' ---');

var gr = new GlideRecord(table);
gr.addNotNullQuery('last_discovered');
gr.query();

while (gr.next()) {
var lastDiscovered = gr.last_discovered;

/* ===============================
RETIRE (>= 90 days)
================================ */
if (lastDiscovered < retireCutoff) {
if (gr.install_status != retireInstallStatus) {
gr.setWorkflow(false);
gr.autoSysFields(false);

gr.install_status = retireInstallStatus;
gr.operational_status = retireOperStatus;
gr.update();

gs.info(' RETIRED CI: ' + gr.name + ' | ' + gr.sys_id);
}
}

/* ===============================
ABSENT (45–89 days)
install_status ONLY
================================ */
else if (lastDiscovered < absentCutoff) {
if (gr.install_status != absentInstallStatus) {
gr.setWorkflow(false);
gr.autoSysFields(false);

gr.install_status = absentInstallStatus;
// operational_status untouched
gr.update();

gs.info('MARKED ABSENT (install_status only): ' + gr.name + ' | ' + gr.sys_id);
}
}
}
}

gs.info('=== CI Auto Absent / Retire Job COMPLETED ===');
})();


I created the system properties mentioned in the script.

 

Could you please help me review this script, and let me know if there are any improvements or changes I should make to ensure it works as expected? Specifically, I want to confirm if the logic for updating the install_status and operational_status is correct, and if any optimizations can be made to improve performance.

 

@Ankur Bawiskar @Amit Gujarathi @Ravi Gaurav 

 

Thanks,
Abdul

 

2 REPLIES 2

Ankur Bawiskar
Tera Patron

@Abdul333 

so is the above script not working fine?

Regards,
Ankur
Certified Technical Architect  ||  10x ServiceNow MVP  ||  ServiceNow Community Leader

Ankur Bawiskar
Tera Patron

@Abdul333 

try this optimized script

(function () {
    gs.info('=== CI Auto Absent / Retire Job STARTED ===');

    var classProp = gs.getProperty('ci.auto.manage.classes', '');
    var classList = classProp ? classProp.split(',') : [];

    var absentDays = parseInt(gs.getProperty('ci.absent.days', '45'), 10);
    var retireDays = parseInt(gs.getProperty('ci.retire.days', '90'), 10);

    var absentInstallStatus = gs.getProperty('ci.absent.install_status', '100');
    var retireInstallStatus = gs.getProperty('ci.retire.install_status', '7');
    var retireOperStatus = gs.getProperty('ci.retire.operational_status', '2');

    if (!classList.length) {
        gs.warn('No classes configured in ci.auto.manage.classes');
        return;
    }

    if (isNaN(absentDays) || isNaN(retireDays) || absentDays >= retireDays) {
        gs.error('Invalid property configuration. Ensure absentDays < retireDays.');
        return;
    }

    for (var i = 0; i < classList.length; i++) {
        var table = (classList[i] || '').trim();
        if (!table) {
            continue;
        }

        gs.info('--- Processing Table: ' + table + ' ---');

        // 1) Retire: last_discovered older than retireDays
        var retireGR = new GlideRecord(table);
        retireGR.addEncodedQuery(
            'last_discoveredRELATIVELT@dayofweek@ago@' + retireDays +
            '^NQlast_discoveredISEMPTY'
        );
        retireGR.addQuery('install_status', '!=', retireInstallStatus);
        retireGR.setValue('install_status', retireInstallStatus);
        retireGR.setValue('operational_status', retireOperStatus);
        retireGR.setWorkflow(false);
        retireGR.autoSysFields(false);
        var retiredCount = retireGR.updateMultiple();

        gs.info('Retire update issued for table ' + table + ', result: ' + retiredCount);

        // 2) Absent: between absentDays and retireDays
        var absentGR = new GlideRecord(table);
        absentGR.addEncodedQuery(
            'last_discoveredRELATIVELT@dayofweek@ago@' + absentDays +
            '^last_discoveredRELATIVEGE@dayofweek@ago@' + retireDays
        );
        absentGR.addQuery('install_status', '!=', absentInstallStatus);
        absentGR.addQuery('install_status', '!=', retireInstallStatus);
        absentGR.setValue('install_status', absentInstallStatus);
        absentGR.setWorkflow(false);
        absentGR.autoSysFields(false);
        var absentCount = absentGR.updateMultiple();

        gs.info('Absent update issued for table ' + table + ', result: ' + absentCount);
    }

    gs.info('=== CI Auto Absent / Retire Job COMPLETED ===');
})();

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

Regards,
Ankur
Certified Technical Architect  ||  10x ServiceNow MVP  ||  ServiceNow Community Leader