Help with Script for Automatically Updating CI Install Status Based on Discovery Date
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 hours ago - last edited an hour ago
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_statusshould be changed to Absent (100). - If a CI hasn’t been discovered in the last 90+ days, its
install_statusshould be changed to Retired (7 ), and theoperational_statusshould 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
38m ago
so is the above script not working fine?
Ankur
✨ Certified Technical Architect || ✨ 10x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11m ago
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! 🙏
Ankur
✨ Certified Technical Architect || ✨ 10x ServiceNow MVP || ✨ ServiceNow Community Leader
