Custom business rule for closing change requests

To decide whether an action must be run, Turbonomic periodically checks the state values of the associated action approval records in ServiceNow. If a schedule is configured in Turbonomic for the automation policy, the approved actions that are run during that time frame; otherwise, the action executor starts right away.

As part of running actions, Turbonomic connects to ServiceNow to update the action approval states. It can set them to the following states:

  • IN_PROGRESS

  • FAILED

  • SUCCEEDED

  • MISSED

Note:

MISSED is used when Turbonomic no longer recommends the action.

When ServiceNow administrators use custom business rules to create the matching CRs, they must close the matching CR as successful or unsuccessful, depending on their action approval state. This logic can be implemented in a business rule that is triggered when state changes are made to the Turbonomic Action Approval table entries.

To create this rule, select System Definition > Business Rules and create a rule for the Turbonomic Actions Approval table that is similar to the following.

Business Rules dialog

Main fields

Field name Value
Name Custom matching change requests
Table Turbonomic action approval x_turbo_turbonomic_turbonomic_action_approval
Application Turbonomic actions
Active ON
Advanced ON

When to run

Field name Value
When after
Order 100
Insert OFF
Update ON
Delete OFF
Query OFF

For the other fields, use the defaults.

Advanced

Add JavaScript code similar to the following, where you specify the CR values that you want the rule to populate:

(function executeRule(current, previous /*null when async*/) {

  var changeRequest = null;
  var dao = new x_turbo_turbonomic.TurbonomicActionDAO();
  var actionApprovalState = dao.getActionStateById(current.state_id);

  var succeededApprovals = 0;
  var failedApprovals = 0;
  var missedApprovals = 0;
  var replacedApprovals = 0;
  var allApprovals = 0;

  var combinedActionIds = current.combine_with;
  if (combinedActionIds) {
    var combinedOIDs = combinedActionIds.split(',');
      
    for (var i = 0; i < combinedOIDs.length; i++) {
      var combinedApproval = new 
        GlideRecordSecure('x_turbo_turbonomic_turbonomic_action_approval');
      combinedApproval.addQuery('oid', combinedOIDs[i]);
      combinedApproval.orderByDesc('sys_updated_on');
      combinedApproval.query();

      // If a valid combined action exists
      if (combinedApproval.next()) {
        allApprovals = allApprovals + 1;
        var actionApprovalState = dao.getActionStateById(combinedApproval.state_id);
        if (actionApprovalState == ‘FAILED’) {
          failedApprovals = failedApprovals + 1;
        } else if (actionApprovalState == ‘SUCCEEDED’) {
          succeededApprovals = succeededApprovals + 1;
        } else if (actionApprovalState == ‘MISSED’) {
          missedApprovals = missedApprovals + 1;
        } else if (actionApprovalState == ‘REPLACED’) {
          replacedApprovals = replacedApprovals + 1;
        }
      }
    }
  }

  if (succeededApprovals + failedApprovals + missedApprovals + replacedApprovals != allApprovals) {
    gs.info(‘CR won’t closed. Not all referenced action approvals are on ‘ + 
      FAILED, SUCCEEDED, REPLACED or MISSED state’);
    return;
  }

  switch (actionApprovalState) {
    case 'FAILED':
    case 'MISSED':
      changeRequest = new GlideRecordSecure('change_request');
      changeRequest.addQuery('sys_id', current.change_request_id);
      changeRequest.query();

      if (changeRequest.next()) {
        changeRequest.state = '3'; // Default change request closed state
        changeRequest.close_code = 'unsuccessful'
        changeRequest.work_notes = 'Matching CR for the failed Turbonomic action has been closed as unsuccessful';

        // TODO: Update additional change request fields, as required
        changeRequest.close_notes = '...';

        changeRequest.update();
      }
      break;

    case 'SUCCEEDED':
      changeRequest = new GlideRecordSecure('change_request');
      changeRequest.addQuery('sys_id', current.change_request_id);
      changeRequest.query();

      if (changeRequest.next()) {
        changeRequest.state = '3'; // Default change request closed state
        changeRequest.close_code = 'successful';
        if (failedApprovals > 0) {
          changeRequest.close_code = 'unsuccessful';
        }
        changeRequest.work_notes = 'Matching CR for the succeeded Turbonomic action has been closed as successful';

        // TODO: Update additional change request fields, as required
        changeRequest.close_notes = '...';

        changeRequest.update();
    }
    break;

    default:
      gs.debug('Change request changes are not required for Turbonomic action approval');
  }

})(current, previous);