Technical vRealize Automation vRealize Automation Ecosystem vRealize Suite

vRA and ServiceNow – beyond the boring stuff

Many companies are using our vRealize Automation plug-in for ITSM which delivers blueprints to standard ServiceNow catalogs. For the majority of use cases it is working well and many find it useful. And boring as hell. The reason for this is that the plug-in is not giving you everything the vRA portal does. However, just because we are not given something, it doesn’t mean we can’t take it. We can take it, abuse it and make it our own, thanks to ServiceNow’s vast possibilities for extending functionality.

This piece of blog is about making ServiceNow talk to vRO for the simplest scenario I could think of – getting validations for a field in an XaaS blueprint. The concept and scripts in this example can be churned, stirred and sodomized for any other purpose you can think of. Again, your imagination is limited only by your own imagination. Some say these limits can be pushed further by the right mix of substances, but we’re here to talk about vRA.

I need to be as precise as possible and evade any additional noise, so I have made the following assumptions before continuing:

  • Integration between ServiceNow and vRA has already been configured
  • Services and Catalog Items have been imported from vRA
  • There are no issues with the integration between ServiceNow and vRA
  • vRA is using the embedded vRO for extensibility
  • The personnel implementing this has basic vRA, vRO and ServiceNow skills
  • The personnel implementing this has basic Javascript skills
  • The personnel implementing this has tenant administrator rights in vRA
  • The personnel implementing this has administrator rights in vRO.
  • The personnel implementing this has System Administrator rights in ServiceNow

So, the basic idea is to have an XaaS blueprint and modify the constraints of one of the fields so that it validates against a vRO action:

Here’s the procedure to configure and test the blueprint:

  1. Create an XaaS blueprint
  2. Create a vRO Workflow with two input parameters called input1 and input2. Set input1 to be of type string and input2 to be of type number:

3. Add a Scriptable task to the Schema of the workflow and set input1 and input2 as its IN parameters.

4. Add the following Javascript code to the Scriptable task:

System.log(input1);
System.log(input2);

5. Test the workflow by clicking on the Run button.

6. In vRA click the Design tab and then XaaS -> XaaS Blueprints -> New

7. Choose the workflow that was just created, click Next multiple times, accepting all default settings and click Finish.

8. Publish the XaaS blueprint and add it to a service that is imported into ServiceNow.

9. Request the XaaS blueprint from vRA and check if it runs without issues. Also, try to type some alphabetic characters into input2 and see if they get accepted.

10. It’s time to create validation for the input2 variable in the XaaS blueprint.

11. Open the XaaS blueprint for editing in vRA and select the Blueprint Form tab.

12. Click on input1 and modify the label to “input1 (String)”, click Apply, then click on input2 and modify the label to “input2 (Number)” and click Apply.

13. Open vRO Client and switch to Design view from the top drop down box next to the vRO logo.

14. Select the actions tab from the left pane (gear wheel with play button), create a new module and create an action inside (in this example it has the rather dull name setMaximumforInput2).

15. Open the action for editing and in the Scripting tab type the following code:

return 1000;

16. Set the return type to Number and save the action.

17. Go back to vRA and select input2, then select the Constraints tab and click Maximum value -> External. Select the newly created action from the dialog box and click Apply.

18. Test the blueprint again and enter a number bigger than 1000 in the input2 field. Click submit, then hover your mouse over the field surrounded by red line and check the message.

 

Okay, we have created an XaaS blueprint with a constraint value coming from vRO. Now, the real deal – ServiceNow syncs the catalog item, but the plug-in ignores the constraint if it’s an external one. So, we end up with a catalog item in SNow that is not having a validation. To go around this problem – or maybe crash through it – we need to configure ServiceNow to vRO integration, so that the request form is aware of the field validation.

Setting vRO Permissions – we want to do things properly, so we will create an integration user just for the vRO connection.

1. Create a custom group in vRA with the name SNowVROUsers by going to the vRA console and clicking Administration -> Users and Groups -> Custom Groups. Do not add any role to the group. Do not add any users to the group yet.

2. Log in to vRA as administrator@vsphere.local and create a new local administrator (e.g. SNowVROUser).

3. Log back in to vRA as tenant administrator and add the user to the custom group.

4. Open the vRO Client and right click on the action module that is the parent of the setMaximumforInput2 action. At this point, I’m sure you have come up with a much more original name for the action.

5. Choose Edit Access rights…

6. Click Add Access rights…

7. In the Search box type the name of the group (e.g. SNowVROUsers)

8. Ensure that the rights assigned are at least ViewExecuteInspect.

Good. We have achieved basic security level and are now GDPR compliant. Next, we need to create a Script Include for connecting and authenticating ServiceNow to vRO. With Script Includes we govern how ServiceNow communicates with the MID server and they can be used in other scripts as libraries of functions, just like we include files in any other programming language.

1. Connect to a vRA appliance via SSH.

2. Issue the following command and copy the result. This will be the client we will use for OAuth requests to vRO:

grep -i cafe_cli= /etc/vcac/solution-users.properties | sed -e 's/cafe_cli=//'

3. Log in to ServiceNow as System Administrator.

4. Go to System Definition – Script Includes.

5. Click New.

6. Specify a meaningful and distinguishable name for the Script Include, set it to Active and make the Accessible from field set to “All application scopes”.

7. Paste the following code into the Script box and substitute with your own information where it’s marked with comments:

var GeneratevROToken = Class.create(); //Substitute with own script name    GeneratevROToken.prototype = Object.extendsObject(AbstractAjaxProcessor, {//Substitute with own           VROLogin: function(){                  try{                         VRASNLogger.debug('Inside  GeneratevROToken.VROLogin: used to fetch vRO login token');//Substitute with own                       var errorHandler = new VRASNErrorHandling();                       var midServer = gs.getProperty('vrasn.midserver.name');  //The MID server name.                        var endPoint = gs.getProperty('vrasn.end.point'); // This is the embedded vRO, which basically is our vRA server.                       var VRAUsername = "SNowVROUser"; //This is the vRO user we just created. Substitute with your own                       var VRAPassword = ""; //password, duh                       var cafeClient = ""; //Substitute with your own - This is the result of the command for getting the OAuth client we just issued over SSH                       var _endPoint = endPoint+"/SAAS/t/vsphere.local/auth/oauthtoken?grant_type=password"; //This is the URL of the authentication point                       var request = new sn_ws.RESTMessageV2();                       request.setEndpoint(_endPoint);                       request.setHttpMethod("post");                       request.setRequestHeader("Accept", "application/json");                       request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");                       request.setMIDServer(midServer);                       request.setRequestBody('username='+VRAUsername+'&password='+VRAPassword+'&client_id='+cafeClient+'&domain=vsphere.local');                       var response = request.execute();                       VRASNLogger.info('Inside  GeneratevROToken.VROLogin: REST call for fetching vRO login token'); //Substitute with your own script name                       if(response.haveError()) {                             VRASNLogger.error('REST call error found inside GeneratevROToken.VROLogin: '+ response.getErrorMessage()); //Substitute with your own                             errorHandler.notify("REST call error found inside GeneratevROToken.VROLogin: "+ response.getErrorMessage()); //Substitute with your own                       }                       var responseBody = response.getBody();                       var parser = new JSONParser();                       var parsed = parser.parse(responseBody);                       var token = parsed.access_token;                       return token;                }                catch(e){                       var errorHandlerCatch = new VRASNErrorHandling();                       VRASNLogger.error('Exception caught inside GeneratevROToken.VROLogin: '+e);//Substitute with own                       errorHandlerCatch.notify("Exception caught inside GeneratevROToken.VROLogin: "+e);//Substitute with own                }         },         type: 'GeneratevROToken'//Substitute with own    });

8. Click Submit or Update to save the new script.

If you pay attention to the logging lines, you’ll see that I use the ITSM plug-in’s own logging facility. This way, I make this script part of the plug-in, so when you go to vRealize Automation → Logs, you will see the messages from using this custom Script Include.

Next, we have to create another Script Inlcude, that sends requests to vRO and fires the action used for validation.

1. Log in to ServiceNow as System Administrator.

2. Go to System Definition – Script Includes.

3. Click New.

4. Specify a meaningful and distinguishable name for the Script Include, set it to Active and make the Accessible from field set to “All application scopes”.

5. Select the checkbox Client callable. With this option we enable calling this script from the request form.

6. Paste the following code into the Script box and substitute with your own information where it’s marked with comments:

var RESTValidation = Class.create(); //substitue with own  RESTValidation.prototype = Object.extendsObject(AbstractAjaxProcessor, {         getVarMaximum : function()         {                //Initialize                this.midServer = gs.getProperty('vrasn.midserver.name');                this.endPoint = gs.getProperty('vrasn.end.point'); //embedded vRO                this.__orderVar = 0;                this.errorHandler = new VRASNErrorHandling();                //Implementation                try{                          VRASNLogger.debug('Inside  RESTValidation.getVarMaximum'); //substitute with own                       var auth = new GeneratevROToken(); //substitute with own. This is the script include used for vRO authentication                       var _endPoint = this.endPoint+"/vco/api/actions/a_nikolovn/SetMaximumforInput2/executions"; //substitute with your own path in vRO                       var request = new sn_ws.RESTMessageV2();                       request.setEndpoint(_endPoint);                       request.setHttpMethod('post');                       request.setRequestBody('{}');                       var authGen = auth.VROLogin();                       request.setRequestHeader("Accept", "application/xml");                       request.setRequestHeader("Authorization", "Bearer "+authGen);                       request.setRequestHeader("Content-Type", "application/json");                       request.setMIDServer(this.midServer);                       var response = request.execute();                       if(response.haveError()) {  VRASNLogger.error('REST call error found inside RESTValidation.getVarMaximum: '+ response.getErrorMessage());//substitute with your own class  this.errorHandler.notify("REST call error found inside RESTValidation.getVarMaximum: "+ response.getErrorMessage());//substitute with your own class                             return response.getErrorMessage();                       } else {                             var responsedata = response.getBody();                             return gs.getXMLText(responsedata, "//number"); //parsing the XML Response from the action result                       }                }                catch(e){                       VRASNLogger.error('Exception caught inside  RESTValidation.getVarMaximum: '+e);//substitute with your own                       this.errorHandler.notify("Exception caught inside  RESTValidation.getVarMaximum: "+e);//substitute with your own                }         },      type: 'RESTValidation'  });

7. Click Submit or Update.

I’m sure you have noticed, that I have hardcoded the path to my action. I did so for simplicity, but the function can actually be modified to accept a path parameter so that the script include becomes more generic.

Time to create ServiceNow client scripts. The client scripts govern our request forms and control the behaviour of the field controls.

1. Ensure the XaaS blueprint has been imported into ServiceNow.

2. Go to Service Catalog – Maintain Items and search for the XaaS blueprint.

3. Click on input2 (Number) and copy the Name property (it should be “input2”).

4. Go to Catalog Administration – Catalog Client Scripts and click New.

5. Specify a meaningful and distinguishable name for the new client script (e.g. SNowValidation onLoad – it’s important to be as descriptive as possible)

6. Set the Applies to field to “A Catalog Item”.

7. Check the Active check box.

8. Set the Type field to onLoad. It will tell Service Now to run our script while loading the form.

9. In the Catalog item field search for the XaaS blueprint.

10. For the Script function enter the following Javascript. Ensure that the “input2” string is substituted with the name from step 3:

var input2Maximum=0; //we need to set a default limit and declare it on top to make the variable global  function onLoad() {         function ajaxResponse(serverResponse) {  //set the input2Maximum global variable to the result from the API call         input2Maximum = serverResponse.responseXML.documentElement.getAttribute("answer");         var labelElement = $('label_' + g_form.getControl("input2").id).select('label')[0];             labelElement.innerHTML = g_form.getLabelOf('input2') + " <font color=\"#278EFC\">Maximum:" + input2Maximum + "</font>";         }          function hide_error() {            g_form.hideErrorBox(g[h].variable);     }     try {           var f = new GlideAjax('RESTValidation'); //substitute with the name of your REST validation Script Include           f.addParam('sysparm_name', 'getVarMaximum');           f.getXML(ajaxResponse); //run the getVarMaximum function from the 'VGRRESTValidation' script. This is an async call and its own result is passed to the ajaxResponse function. This way the page loads without waiting for the call to finish     }catch(error)     {            g_form.showErrorBox("input2",  'There was an issue with getting the field validation information' + error);            window.setTimeout(hide_error, 5e3);            return false;     }                         }

A few words on this script. While the form is loading, ServiceNow runs the getVarMaximum function from the VGRRESTValidation script and doesn’t wait for an answer. This allows for the request to reach the vRO server through the MID server and get back with a response, without freezing the form, so the user can freely interact with it. This is achieved with f.getXML(ajaxResponse). If we don’t do it asynchronously, then the form will stop loading until a response has been received.  Afterwards, we use the ajaxResponse function to get the actual value from the VRO action and display it as part of the field label. There is a reason why input2Maximum is a global variable.

We have received the maximum value, but how do we make the validation?

1. Go to Catalog Administration – Catalog Client Scripts and click New.

2. Specify a meaningful and distinguishable name for the new client script (e.g. SNowValidation onSubmit)

3. Set the Applies to field to “A Catalog Item”.

4. Check the Active check box.

5. Set the Type field to onSubmit.

6. In the Catalog item field search for the XaaS blueprint.

7. For the Script function enter the following Javascript. Ensure that the “input2” string is substituted with the correct field name:

function onSubmit() {     function hide_error() {            g_form.hideErrorBox(g[h].variable);     }     try {          if(Number(g_form.getValue("input2"))> input2Maximum) //compares the result coming from vRO to the value currently in the field          {                 g_form.showErrorBox("input2", "You can't specify a number larger than "  + input2Maximum + ". Current value:" + g_form.getValue("input2"));                 window.setTimeout(hide_error, 5e3);                 return false;          }     }catch(error)     {            g_form.showErrorBox("input2", 'Please specify an integer value (non decimal value) ' + error);            window.setTimeout(hide_error, 5e3);            return false;     }                         }

What we do here is comparing the input value against the global variable we defined in the previous script. If it’s bigger, then we show an error message in the form. The comparison itself is triggered when the user clicks Submit. You can always change it so that it triggers the comparison during a change in the field by setting the type to onChange.

Test by requesting the blueprint from ServiceNow and wait a few seconds until a blue notice pops up on the page next to the label of the field. When it does, it means the vRO action has been executed and the result has been passed to ServiceNow successfully.

Enter a value bigger than 1000 and click Order Now to test the validation.

The client script can be enhanced further to check if the input is having alphabetic or special characters, etc.

The onload script can be further optimized by creating a mechanism that caches frequently the information from vRO in a ServiceNow table. The onload script can then read the table which is much faster than calling vRO every time the page loads.

Comments

12 comments have been added so far

  1. Nikolay, what kind of performance are you getting from the round trip for SN instance to vRA/vRO and back again? I’m doing something similar where I’m getting some vCenter info (disks) through a REST call, and although it’s very quick on the vRO execution side, from the SN client script invocation and completion back to the UI (I’m doing it sync in my case), it takes ~2 minutes. I’m not sure if I have a problem somewhere, or that’s typical latency going back and forth.

    thanks

  2. Hello, while doing my tests I never had to wait more than 10 seconds before the form gets refreshed with the data from the vRO workflow/action. I tested with both sync and async calls.
    If you want to troubleshoot further you can do a wireshark trace on the MID server to see if there is any delay between the server and vRO or between the server and SNow. Also, check if there is any proxy between the MID server and Internet. Another reason for the delay could be that the MID server is overwhelmed with other tasks. In such cases it might require installing an additional MID server.
    Check these two links for MID Server performance monitoring:
    https://community.servicenow.com/community?id=community_blog&sys_id=9d1deea5dbd0dbc01dcaf3231f961939
    https://docs.servicenow.com/bundle/istanbul-servicenow-platform/page/product/mid-server/task/t_ViewMIDStats.html

  3. Hi Nikolay Nikolov,

    currently we are pulling vRA templates into servicenow using scheduled job and values are populating to template as {capacity_value}. However customer is asking to populate templates dynamically to servicenow.

    if the capacity value is 50, it should populate 50 and it will be dynamic.
    how can we do this?

    please suggest. Happy to have a call or email conversation @ chinna.snow1@gmail.com

    1. Hello, Chinna
      You can actually utilize the ITSM plugin version 5 which will enable you to have dynamic dropdowns in your forms out of the box. I think currently this is your best solution.

  4. Hi Nikolay,

    Thanks for the reply. Actually we have custom service catalog form in ServiceNow and we are triggering vRA from workflow. now customer is asking to pull blueprints(catalog ids) and vRA templates dynamically.
    any suggested solution for this?

    Thanks.

    1. Hi, Chinna
      I can recommend you to just install the ITSM plugin and use it as a straw for your own customizations. There you can see how the import is done automatically. If you need more assistance, I suggest you to contact your VMware account manager.

  5. Hi Nikolay,

    we have a Catalog Item in ServiceNow for “adding permissions to a folder”. We are planning to automate the underlying tasks via vRO vRA. To accomplish this, I was wondering

    1. Is it possible to communicate from ServiceNow directly with vRO and to pass the information stored in the variables coming from the request form in ServiceNow so that this data input is used to execute the workflows in vRO? ( In this case to add a user to a security group)
    2. Or is it always necessary to create a blueprint in vRA in first place and to import it to ServiceNow via the plugin

    This is maybe off-topic but your insights would be a great help 🙂

    Thanks

    1. Hi, You can go directly to vRO. I have used the embedded vRO for the sake of simplicity, but you can define the vRO URL as a separate variable and use it just as any other REST API server.

      1. Hi Nicolay, thanks for the quick reply 🙂

        So basically on a high-level the steps that need to be performed during the process are:

        1. Create Request in ServiceNow
        2. Outbound REST Call to vRO included in the ServiceNow Workflow (to pass the request information to vRO)
        3. vRO retrieves the request information
        4. Execute Workflow in vRO

        If I understood correctly (and please correct me if I am wrong), with this there is no need for any development activities in vRA like customized blueprints in vRA.

        Thanks

        1. Well, yes with this approach you don’t really need a blueprint in vRA unless you want to leverage some of vRA’s innate features.
          There should be a step 5 in your high level procedure – vRO should notify SNOW somehow about the worfklow status.

  6. Nikolay,
    I am back again 🙂 I was wondering, in your code above, with you specifying the midserver, endpoint, etc. right within the code, does this circumvent the request being dropped onto the ECC queue? After working on many more calls, but defining the REST message within ServiceNow, I have found that the placement of the request onto the ECC queue is what causes the delay. I’m working on another vRO request and I need it come back rather quickly so i came back to your article again. Thanks again.

    ed

Leave a Reply

Your email address will not be published. Required fields are marked *