Impacted Services/Cis population

Sam Ogden
Tera Guru

Hi All,

I have a question around the impacted Services/Cis tab on the change request form.

We are expecting that this populates all the CIs that are downstream of the Configuration item that has been entered on the form.   Does anyone know how this population works?

In our instance this is not working as we are expecting.   An example CI below:

We have a CI of 1Answer 1Aces UAT_Strata Release, Diagram below:

find_real_file.png

We would expect that all the CIs in the highlighted box would then be put into the impacted Services/CIs tab.

As you can see below this is not happening - The only CI that is being populated is the one we have added to this field.   I would like to know what populates this tab and what changes we need to make to get this to work as expected.

find_real_file.png

find_real_file.png

I have seen the following business rule which I think is currently being used to populate this, but not sure what changes need to be made to this:

function onAfter(current, previous) {

//current.update();

action.setRedirectURL(current);

removeAffectedServices();

addAffectedServices();

//checkAffectedServices();

function removeAffectedServices()

{

  var m2m = new GlideRecord('task_cmdb_ci_service');

  m2m.addQuery('task',current.sys_id);

  m2m.addQuery('manually_added','false');

  m2m.query();

  m2m.deleteMultiple();

}

function addAffectedServices()

{

  var ciu = new CIUtils2();

  //Find all impacted business services

  var services = ciu.cisAffectedByTask(current);

  //var services = ciu.cisAffectedByTask(current, ["cmdb_ci_service", "cmdb_ci_windows_server"]);

  //var services = ciu.cisAffectedByTask(current, ["ALL"]);

  var m2m = new GlideRecord('task_cmdb_ci_service');

  for (var i = 0; i < services.length; i++) {

    m2m.initialize();

    m2m.task = current.sys_id;

    m2m.cmdb_ci_service = services[i];

    m2m.manually_added = 'false';

    m2m.insert();

  }

}

/*function checkAffectedServices()

{

  var ciu = new CIUtils2();

  //Find all impacted business services

  var services = ciu.cisAffectedByTask(current);

  //var services = ciu.cisAffectedByTask(current, ["cmdb_ci_service", "cmdb_ci_windows_server"]);

  //var services = ciu.cisAffectedByTask(current, ["ALL"]);

  var m2m = new GlideRecord('cmdb_ci_service');

  m2m.addQuery('sys_id','IN',services.toString() );

  m2m.query();

  while(m2m.next())

    {

    var service_name= m2m.name;

    var owner= m2m.owned_by;

    gs.eventQueue("incident.impact.notify",current,owner,service_name);//Triggers the event for generating email Notification.

  }

}*/

}

find_real_file.png

Any help on this is greatly appreciated.

Thanks

Sam

Sam Ogden
Tera Guru

Hi All,



Just a further screenshot that may help.   This is the CI relationships that are in place where 1Answer 1Aces UAT_strata Release is the parent:



find_real_file.png



Thanks


Sam Ogden
Tera Guru

Also below is the script includes for CIUtils2:



find_real_file.png



gs.include('PrototypeServer');


var CIUtils2 = Class.create();


CIUtils2.prototype = {
     
      initialize : function() {
            this.maxDepth = gs.getProperty('glide.relationship.max_depth',10); // how deep to look
            this.currentDepth = 0;
           
            this.CIs = {}; // list of affected CIs
            this.maxSize = gs.getProperty('glide.relationship.threshold',1000); // how many records to return
            this.added = 0; // track how many added, since can't get size() for an Object
            this.parents = {}; // track parents already iterated
      },
     
      /**
        * Determine which CIs are affected by a specific CI
        *
        * Inputs:
        * id is the sys_id of a configuration item (cmdb_ci)
        * classArr is an array of CI class names that should be returned
        *
        * Returns:
        * an array of sys_id values for cmdb_ci records downstream of
        * (or affected by) the input item
        */
     
      cisAffectedByCI: function(id, classArr) {
            var ci = new GlideRecord('cmdb_ci');
            ci.get(id);
            //If no class specified then assume business service
            if(classArr == null){
                  classArr = ['cmdb_ci_service','service_offering'];
                  for (var ciClass in classArr){
                        if (ci.sys_class_name == classArr[ciClass]){
                              this._addCI(id, this.CIs);
                        }
                  }
            }
            //If class = 'ALL' then just add the CI
            else if(classArr[0] == 'ALL'){
                  this._addCI(id, this.CIs);
            }
            else{
                  for (var ciClass2 in classArr){
                        if (ci.sys_class_name == classArr[ciClass2]){
                              this._addCI(id, this.CIs);
                        }
                  }
            }
            this._addParentCIs(id, this.CIs, this.currentDepth, classArr);
           
            var ciarr = []; // CIs is an Object, convert to Array for final query
            for (var i in this.CIs)
                  ciarr.push(i);
           
            return ciarr; // list of affected CIs
      },
     
      /**
        * Determine which CIs are affected by a task
        *
        * Inputs:
        * task is a task GlideRecord (e.g., incident, change_request, problem)
        * classArr is an array of CI class names that should be returned
        *
        * Returns:
        * an array of sys_id values for cmdb_ci records downstream of
        * (or affected by) the configuration item referenced by the task's cmdb_ci field and Affected CIs list
        */
     
      cisAffectedByTask: function(task, classArr) {
            //Find the impacted CIs for the 'cmdb_ci' value
            var id = task.cmdb_ci.toString();
            var allCIArr = [];
            if(id){
                  allCIArr = this.cisAffectedByCI(id, classArr);
            }
           
            //Find the impacted CIs for any Affected CIs listed on the task
            var affCIArr = [];
            var affCI = new GlideRecord('task_ci');
            affCI.addQuery('task', task.sys_id);
            affCI.query();
            while(affCI.next()){
                  affCIArr = this.cisAffectedByCI(affCI.ci_item.sys_id, classArr);
                  if(allCIArr.length > 0){
                        //Concat the array with the current array
                        allCIArr = allCIArr.concat(affCIArr);
                  }
                  else{
                        allCIArr = affCIArr;
                  }
            }
            //Strip the array of any duplicate values
            return this.unique(allCIArr);
      },
     
      /**
        * Returns an XML-formatted string showing all CIs impacted by an outage to the CI given
        *
        * Inputs:
        * id is the sys_id of the root CI
        *
        * Returns:
        * an XML-formatted string containing cmdb_ci records downstream of
        * (or affected by) the configuration item provided as input
        */
     
      getCIXML: function(id) {
            var gr = new GlideRecord('cmdb_rel_ci');
            gr.addQuery('child', id);
            gr.query();
            gr.next();
            var str = '';
            str += '<CI>';
            str += '<sys_id>'+gr.child.sys_id+'</sys_id>';
            str += '<name>'+gr.child.name+'</name>';
            str += '<relType>SELF</relType>';
            ret = this._recurs(id);
            if(ret){
                  str += '<children>';
                  str += ret;
                  str += '</children>';
            }
           
            str += '</CI>';
            return str;
      },
     
      _recurs: function(ci) {
            var gr = new GlideRecord('cmdb_rel_ci');
            gr.addQuery('child', ci);
            gr.query();
            var str = '';
            while(gr.next()){
                  str += '<CI>';
                  str += '<sys_id>'+gr.parent.sys_id+'</sys_id>';
                  str += '<name>'+gr.parent.name+'</name>';
                  str += '<relType>'+gr.type.name+'</relType>';
                 
                  ret = this._recurs(gr.parent.sys_id);
                  if (ret) {
                        str += '<children>';
                        str += ret;
                        str += '</children>';
                  }
                 
                  str += '</CI>';
            }
            return str;
      },
     
      _addParentCIs : function(value, CIs, currentDepth, classArr) {
            if (this.parents[value])
                  return;
            else this.parents[value] = true;


            if (this.added >= this.maxSize) {
                  // gs.print('reached threshold of ' + this.maxSize);
                  return;
            } else {
                  currentDepth++;
                  var g;
                  if (typeof SncEcmdbRelationships != 'undefined')
                        g = SncEcmdbRelationships();
                  else
                        g = new Packages.com.glideapp.ecmdb.Relationships();


                  var al = g.getRelatedRecords(value, null, 'cmdb_ci', 'cmdb_ci', 'child'); // returns ArrayList
                 
                  // first add the unique cis
                  var kids = new GlideRecord('cmdb_ci');
                  kids.addQuery('sys_id', al);
                  kids.query();
                  while (kids.next()) {
                        var str = kids.sys_id;
                        if (!CIs[str]) {
                              var rec = new GlideRecord('cmdb_ci');
                              rec.get(str);
                             
                              for (var ciClass in classArr){
                                    if ((kids.sys_class_name == classArr[ciClass]) || (classArr[0] == 'ALL')){
                                          this._addCI(str, CIs);
                                    }
                              }
                              if (this.added >= this.maxSize)
                                    return;
                              if (currentDepth < this.maxDepth)
                                    this._addParentCIs(str, CIs, currentDepth, classArr);
                        }
                  }
            }
      },
     
      _addCI: function(id, CIs) {
            CIs[id] = true;
            this.added++;
      },
     
      unique: function(a) {
            //Check all values in the incoming array and eliminate any duplicates
            var r = [];
            o:for(var i = 0, n = a.length; i < n; i++){
                  for(var x = 0, y = r.length; x < y; x++){
                        if(r[x]==a[i]){
                              continue o;
                        }
                  }
                  r[r.length] = a[i];
            }
            return r;
      },
     
      type: 'CIUtils2'
};


Sam Ogden
Tera Guru

Hi All,



Has anyone got any suggestions on the above?



Any help is greatly appreciated.



Thanks



Sam


Sam Ogden
Tera Guru

Hi All,



just wondering if anyone had any thoughts on this at all?



Thanks