Send Command to MID Server ECC Queue and Capture Response (Blog)

Katie A
Mega Guru

Purpose: The purpose of this post is to describe how to send a command to the ECC Queue and to capture the response. Please feel free to let me know if you have any feedback or suggestions. Also please like/mark helpful if this article helped you

Background: I build Workflows to launch automation scripts directly from a MID Server very often. Typically, a script (bash/python/perl etc) is sitting on a host on our network and is launched by the workflow. The appropriate parameters are passed in to the script based on the input values from a form.

I was able to easily create an Output record in the ECC Queue in a "Run Script" workflow activity.

However, the issue I was running into was that, although the Input (response) would appear in the ECC queue a few minutes later, the "response_to" field was not automatically populating with a link to the originating Output record. Thus, there was no reliable way to capture the record that was in response to the original Output command.

Here's a good reference for creating ECC queue records. In this example, it seems as though the response_to was populating automatically. http://www.john-james-andersen.com/blog/service-now/live-jdbc-queries-displayed-in-servicenow.html

Solution:

In my case, since I did not have response_to populating automatically, I write a script include class that creates a reference to the original Output command. Thus, the correct Input (response) can be queried by matching on sys_id of the response_to reference value.

//Send Output command

      sendCommand: function(name, server, command) {

        var ecc_queue = new GlideRecord("ecc_queue");

        ecc_queue.initialize();

        ecc_queue.agent = "mid.server." + server;

        ecc_queue.name = name;

        ecc_queue.queue = "output";

        ecc_queue.topic = "Command";

        ecc_queue.payload = '<?xml version="1.0" encoding="UTF-8"?><parameters><parameter name="name" value="' + command + '"/></parameters>';

        //Get SysID of new ECC Queue record

        var ecc_sysid = ecc_queue.insert();

        //Set Response to current record sys_id

        ecc_queue.response_to = ecc_sysid;

        //Update new ECC Queue record

        ecc_queue.update();

        return ecc_sysid;      

      },

//Get Response from ECC Queue that was linked to the original Output command in the response_to reference

      getResponse: function(ecc_sysid, att) {

      var response_sysid;

      var ecc_response = new GlideRecord("ecc_queue");

      //Get response that matches response to record set in output command sent earlier

        ecc_response.addQuery("response_to", ecc_sysid);

        ecc_response.addQuery("queue", "input");

        ecc_response.query();

        if (ecc_response.next()) {

                response_sysid = ecc_response.sys_id;

                } else {

                response_sysid = false;

                }

          if (response_sysid) {

                  var response_payload_xml = this.getResponsePayload(response_sysid);

                  var response_json = this.parseXMLPayload(response_payload_xml);

                  return response_json;

              } else {

          return false;

              }

      },

4 REPLIES 4

Brian B
Kilo Contributor

Hi Katie,

I was just wondering if you or anyone else would be willing to help a new guy out.   What you've done is exactly what I need to do but I am fairly new to ServiceNow Orchestration and since we are not using Ansible Tower... and only using the Ansible Engine,  I need a way to be able to execute ansible-playbook on a Linux mid server and of course then retrieve the JSON response from the command.

That said,  I can read Javascript but i'm not so good at writing it yet.   I found a YouTube video that is definitely using the code you wrote here, with some additional code at the bottom to actually send the command and presumably wait for the response using a while loop.   

Do you have any real-world examples of using this code?    In his YouTube video he submits a powershell.exe command and then presumably waits for the response to exist,  but never scrolls down far enough (2:26 in his video, linked below) to show the very bottom of his script.

https://youtu.be/is8vSW4aFQk?t=145

Any thoughts, tips, suggestions?   His example command is perfect for testing, I'm just not sure how to go about successfully waiting for the response to exist.  

Thanks in advance!

Brian

 

Hi Brian,

I would recommend that you try creating a custom SSH activity for this purpose. The custom SSH activity can login to a Linux server, run a command and use the "TAGS" to capture the response.

Note: This requires Orchestration. This is the newer and preferred way instead of the technique described in my post above.

The documentation is here: https://docs.servicenow.com/bundle/kingston-servicenow-platform/page/administer/orchestration-activi...

Brian B
Kilo Contributor
Thanks Katie. I really appreciate the reply. I’m 95% of the way through getting what I need using the SSH Activity. Just some json parsing output stuff left to work out and I’m there. Thanks again! Brian

Hi Brian,

Late to the party, was just working on implementing something similar the past couple of days.

Stumbled upon a John Anderson blog post that uses another script include specifically to continuously 'check' the ecc_queue table until it gets a response (or exceeds a defined time limit)

GETTING A SERVICENOW ECC QUEUE RESPONSE

Checkout the first function 

getEccResponse: function(outputSysId,waitMS){
        if(!waitMS) {
            waitMS = 25000;
        }
        var start = new GlideDateTime;
        
        
        //Loop waiting for a record that is created in response to your query
        var resp = new GlideRecord("ecc_queue");
        resp.addQuery("response_to", outputSysId);
        resp.addQuery("queue", "input");
        do{
            resp.query();
            resp.next();
            gs.sleep(1000);
            if ( GlideDateTime.subtract(start, new GlideDateTime()).getNumericValue() > waitMS ) {
                return null;
            }
        } while(!resp.sys_id);
        
        //Found a response
        return this.getEccPayload(resp);
        
    }

hope this helps!