Article

Cloning SLAs More Easily in ServiceNow

Author: Agus Budi Harto, 2025-08-11 15:15:06

One of the key responsibilities in IT Service Management (ITSM) is identifying which services have exceeded their agreed resolution times. This is exactly where ServiceNow proves its value—by helping organizations detect overdue services quickly and take immediate corrective action. Monitoring and managing service deadlines is one of the platform’s most crucial functions.

These deadlines are defined within a module called Service Level Agreement (SLA). In ServiceNow, you can access it through:
All > Service Level Management > SLA > SLA Definitions.


From there, creating a new SLA involves clicking New and filling in several required fields. Although the process is fairly straightforward, it still demands a few minutes of focused work for each SLA.

That’s just one scenario. In reality, organizations often need different SLA configurations for remote offices or branch locations, especially if each location operates under different working hours. With dozens or even hundreds of branches, and each branch potentially requiring multiple SLAs, the total number of SLAs to manage can be overwhelming.

From my experience, one way to clone SLAs is by using the Import Set feature in ServiceNow. I exported 41 SLAs from one remote office into an Excel file, imported the data into a staging table, and used Transform Maps to transfer the records to the main SLA table: contract_sla. While the import itself was successful, several key fields such as duration and conditions (start, pause, stop, reset, etc.) failed to copy correctly. Fixing this required adding scripts for each individual field, which turned out to be a complex and time-consuming process.


Eventually, I found a much simpler and more effective solution: using a Script Include. By writing a custom Script Include and executing it through a Background Script, I was able to clone all 41 SLAs in a single click. This method not only saved time but also eliminated the need for manual correction and field-specific scripting.

Script:

var PM_CloningSLA = Class.create();
PM_CloningSLA.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    cloneSLA: function(){
        var siteToClone = 'ABCD';
        var siteToNew = 'EFGH';
        var gr = new GlideRecord("contract_sla");
        gr.addEncodedQuery("nameLIKE"+siteToClone);
        gr.query();
        while(gr.next()){
            var newSLA = new GlideRecord("contract_sla");
            newSLA.initialize();
            newSLA.name = gr.name.replace(siteToClone,siteToNew);
            newSLA.active = gr.active;
            newSLA.adv_condition_type = gr.adv_condition_type;
            newSLA.sys_scope = gr.sys_scope;
            newSLA.cancel_condition = gr.cancel_condition;
            newSLA.sys_class_name = gr.sys_class_name;
            newSLA.condition_class = gr.condition_class;
            newSLA.sys_name = gr.sys_name.replace(siteToClone,siteToNew);
            newSLA.sys_domain = gr.sys_domain;
            newSLA.sys_domain_path = gr.sys_domain_path;
            newSLA.duration = gr.duration;
            newSLA.duration_type = gr.duration_type;
            newSLA.enable_logging = gr.enable_logging;
            newSLA.flow = gr.flow;
            newSLA.sys_overrides = gr.sys_overrides;
            newSLA.sys_package = gr.sys_package;
            newSLA.pause_condition = this.getDetailCond(gr.pause_condition,siteToClone,siteToNew);
            newSLA.sys_policy = gr.sys_policy;
            newSLA.relative_duration_works_on = gr.relative_duration_works_on;
            newSLA.reset_action = gr.reset_action;
            newSLA.reset_condition = this.getDetailCond(gr.reset_condition,siteToClone,siteToNew);
            newSLA.resume_condition = gr.resume_condition;
            newSLA.retroactive_pause = gr.retroactive_pause;
            newSLA.retroactive = gr.retroactive;
            newSLA.schedule = this.getSchedule(siteToNew);
            newSLA.schedule_source = gr.schedule_source;
            newSLA.schedule_source_field = gr.schedule_source_field;
            newSLA.set_start_to = gr.set_start_to;
            newSLA.start_condition = this.getDetailCond(gr.start_condition,siteToClone,siteToNew);
            newSLA.stop_condition = this.getDetailCond(gr.stop_condition,siteToClone,siteToNew);
            newSLA.collection = gr.collection;
            newSLA.target = gr.target;
            newSLA.timezone = gr.timezone;
            newSLA.type = gr.type;
            newSLA.sys_update_name = gr.sys_update_name.replace(siteToClone,siteToNew);
            newSLA.vendor = gr.vendor;
            newSLA.when_to_cancel = gr.when_to_cancel;
            newSLA.when_to_resume = gr.when_to_resume;
            newSLA.workflow = gr.workflow;
            gs.info("New SLA Created: "+newSLA.name.toString());
            newSLA.insert();
        }
    },
    getDetailCond: function(cond,siteToClone,siteToNew){
        var start_cond = cond.split("^");
        var start_condnew = "";
        for(var i=0;i
            if(start_cond[i].contains("=")){
                var start_cond1 = start_cond[i].split("=");
                var key = start_cond1[0];
                var value = start_cond1[1];
                if(key.includes("OR")){
                    key = key.replace("OR","");
                }
                if(key.includes("!")){
                    key = key.replace("!","");
                }              
                var gr1 = "";
                var gr2 = "";
                var name = "";
                if(key=="assignment_group.u_district"||key=="request.location"){
                    gr1 = new GlideRecord("cmn_location");
                    gr1.addQuery("sys_id",value);
                    gr1.query();
                    if(gr1.next()){
                        name  = gr1.getDisplayValue("name");
                        name = name.replace(siteToClone,siteToNew);
                        gr2 = new GlideRecord("cmn_location");
                        gr2.addQuery("name",name);
                        gr2.query();
                        if(gr2.next()){
                            value = gr2.sys_id;
                        }
                    }
                } else if(key=="assignment_group"){
                    gr1 = new GlideRecord("sys_user_group");
                    gr1.addQuery("sys_id",value);
                    gr1.query();
                    if(gr1.next()){
                        name  = gr1.getDisplayValue("name");
                        name = name.replace(siteToClone,siteToNew);
                        gr2 = new GlideRecord("sys_user_group");
                        gr2.addQuery("name",name);
                        gr2.query();
                        if(gr2.next()){
                            value = gr2.sys_id;
                        }
                    }
                }
                start_cond[i] = start_cond1[0] + "=" + value;
            }
            start_condnew = start_condnew + start_cond[i]+"^";
        }
        start_condnew = start_condnew.slice(0, -1);
        return start_condnew;
    },
    getSchedule: function(siteToNew){
        gr2 = new GlideRecord("cmn_schedule");
        gr2.addQuery("name",siteToNew);
        gr2.query();
        var schedule = "";
        if(gr2.next()){
            schedule = gr2.sys_id;
        }
        gs.info(schedule);
        return schedule;
    },
    type: 'PM_CloningSLA'
});

Background script:

var helper = new PM_CloningSLA();
helper.cloneSLA();


In conclusion, while Import Sets offer a way to clone SLAs, they come with limitations that can complicate the process. Leveraging Script Includes provides a far more efficient and scalable solution, especially when dealing with a large number of SLAs across multiple business units.

LinkedIn

Tags: Opinion Servicenow

235 reviews


Add comment