Skip to main content

Automating ServiceNow with Red Hat Ansible Automation Platform

Ansible Automation Platform and Ansible Certified Content Collection for ServiceNow are crucial tools that help sysadmins manage service actions and inventory sources, streamlining service management
Image
Automating ServiceNow with Red Hat Ansible Automation Platform

Photo by cottonbro from Pexels

Sysadmins are asked regularly to quickly complete service requests to better serve business and user needs, with more and more admins relying on Ansible to do so. How can we, as sysadmins, respond faster when these requests come up?

IT service management (ITSM) is a collection of policies and processes for the management and support of IT services. The main focus of ITSM is increasing the value of the customers’ service chain. But without the proper automation support, providing IT services can quickly become a major time-sink for administrators.

[ You might also like: Quick start guide to Ansible for Linux sysadmins ]

This is where the Red Hat Ansible Automation Platform and the Red Hat Ansible Certified Content Collection for ServiceNow come into play. Ansible Automation (with some help from existing Ansible content) can automate just about any task, while the modules from this Certified Collection allow you to keep the ServiceNow information up to date.

This Collection was designed and developed by the XLAB Steampunk team in close collaboration with Red Hat Ansible, specifically keeping end-users in mind. ServiceNow modules have an intuitive user interface backed by a robust implementation, offering support for things Ansible users expect (e.g., check mode and change detection).

In this post, I demonstrate a few sample Ansible Playbooks that take care of essential admin tasks such as:

  1. Updating incidents, problems, and change requests
  2. Updating the ServiceNow configuration management database (CMDB)
  3. Using the CMDB as an inventory source

Installing the Certified Content Collection for ServiceNow

You can download the servicenow.itsm Collection from automation hub or Ansible Galaxy. Before you can access content in the automation hub, you must first configure your credentials in the Ansible configuration file. For details, please refer to the "Hands On With Ansible Collections" blog post.

Once you have your credentials, you can install the ServiceNow Collection by running the following command:

$ ansible-galaxy collection install servicenow.itsm

If everything goes according to plan, you now have access to the following modules:

  1. servicenow.itsm.incident for managing incident tickets
  2. servicenow.itsm.problem for interacting with problems
  3. servicenow.itsm.change_request for handling changes
  4. servicenow.itsm.configuration_item for managing the CMDB

Each of the modules also has a counterpart that gives you read-only access to ServiceNow records.

The Certified Content Collection for ServiceNow also contains an inventory plugin called servicenow.itsm.now that allows you to use CMDB as an inventory source.

To verify nothing went awry, display the documentation for one of the modules by executing the following command:

$ ansible-doc servicenow.itsm.incident

If Ansible did not yell at us, you're all set.

Managing incidents, the Ansible way

Creating a new incident ticket using Ansible is reasonably straightforward, but before you can do that, you need to tell Ansible where your ServiceNow instance lives and what credentials to use. Do that by setting three environment variables:

$ export SN_HOST='https://dev12345.service-now.com'
$ export SN_USERNAME='user'
$ export SN_PASSWORD='pass'

Now that you have your credentials ready, you can create a new incident. The minimal Ansible playbook would look something like this:

---
- hosts: localhost
  gather_facts: false
  tasks:
    - name: Create new incident
      servicenow.itsm.incident:
        state: new
        short_description: Demo incident

Once the previous playbook finishes executing, you'll find a new incident listed in ServiceNow.

Image
ServiceNow web user interface
Figure 1: The ServiceNow web UI.

You can update an existing incident by providing either a ticket number or system id of the incident record. Ansible will compare the current and the desired states of the incident and make necessary changes to get them in sync.

---
- hosts: localhost
  gather_facts: false
  tasks:
    - name: Update incident
      servicenow.itsm.incident:
        number: INC0010022
        state: in_progress

If you run Ansible with the --diff switch, it will report what changes it implemented to the incident record:

TASK [Update incident with a problem information] ***************************
--- before
+++ after
@@ -50,7 +50,7 @@
     "parent": "",
     "parent_incident": "",
     "priority": "5",
-    "state": "new",
+    "state": "in_progress",
     "reassignment_count": "0",
     "reopen_count": "0",
     "reopened_by": "",
@@ -71,10 +71,10 @@
     "sys_domain": "global",
     "sys_domain_path": "/",
     "sys_id": "2396e496074f2010d4a1fa9e7c1ed01c",
-    "sys_mod_count": "0",
+    "sys_mod_count": "1",
     "sys_tags": "",
     "sys_updated_by": "admin",

You can also delete an existing incident by setting the state parameter to absent.

---
- hosts: localhost
  gather_facts: false
  tasks:
    - name: Delete incident
      servicenow.itsm.incident:
        number: INC0010022
        state: absent

You can interact with problems and change requests in the same manner. However, managing configuration items is a bit different, so let’s focus on this area next.

Updating the CMDB

Because the ServiceNow CMDB has more than one configuration item type, you need to specify the sys_class_name parameter when adding new items. By default, the servicenow.itsm.configuration_item module will use the cmdb_ci system class name, but you can change it to any other cmdb_ci-derived class.

---
- name: Demonstrate CMDB management
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Simulate VM creation
      ansible.builtin.set_fact:
        instance:
          name: some-name
          id: vm1234567890
          public_ip_address: 1.2.3.4

    - name: Register the newly-created VM instance
      servicenow.itsm.configuration_item:
        name: "{{ instance.name }}"
        sys_class_name: cmdb_ci_vm_instance
        ip_address: "{{ instance.public_ip_address }}"
        other:
          vm_inst_id: "{{ instance.id }}"

You used the generic other parameter that can contain arbitrary key-value pairs in the last task. Because ServiceNow tables are extensible, all modules have this parameter. You can use the other parameter to set column values that modules do not expose as top-level parameters. All ServiceNow Ansible modules have this parameter.

When updating or deleting an existing item, you don't have to specify the system class name because the module will automatically retrieve the name from the current record. But, you do have to provide a sys_id parameter value.

---
- name: Demonstrate CMDB item update and deletion
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Update the VM state
      servicenow.itsm.configuration_item:
        sys_id: b0ccabf1c0a80009001f14fd151d8df0
        install_status: in_maintenance

    - name: Remove item from CMDB
      servicenow.itsm.configuration_item:
        sys_id: b0ccabf1c0a80009001f14fd151d8df0
        state: absent

Dynamic inventory

The CMDB can also serve as an inventory source. Because configuration items that represent servers and virtual machines (VMs) usually contain IP addresses, you can use them as an inventory source.

The minimal configuration for the inventory plugin looks like this:

---
plugin: servicenow.itsm.now

When used as an inventory source, the plugin will list all servers from the cmdb_ci_server table. You can automatically group and filter inventory hosts based on the conditions specified in the group_by configuration option:

---
plugin: servicenow.itsm.now
group_by:
  os:
    includes:
      - Linux Red Hat
      - Windows XP

In the previous example, Ansible created two groups: one for Windows XP and one for Linux computers. The inventory plugin performs as much filtering as possible on the backend, minimizing the amount of downloaded data.

You can also configure which column values the inventory plugin adds as host variables:

---
plugin: servicenow.itsm.now

columns:
  - name
  - classification
  - cpu_type

group_by:
  os:
    includes:
      - Linux Red Hat
      - Windows XP

To test the configuration, execute the following command:

$ ansible-inventory -i inventory.now.yaml --graph --vars

Assuming that you stored the inventory configuration in the inventory.now.yaml file. The output should look something like this:

@all:
 |--@Linux_Red_Hat:
 |  |--P1000019
 |  |  |--{ansible_host = my1.server.com}
 |  |  |--{classification = Production}
 |  |  |--{cpu_type = Intel}
 |  |  |--{name = SAP-SD-01}
 |--@Windows_XP:
 |  |--P1000020
 |  |  |--{ansible_host = my2.server.com}
 |  |  |--{classification = Production}
 |  |  |--{cpu_type = Intel}
 |  |  |--{name = SAP-SD-02}
 |--@ungrouped:

And now that you know how to use individual modules and the inventory plugin, it is time for the grand finale.

Automatic resolution of a standard change request

Standard change requests are pre-approved procedures with minimal risks, and these properties make them prime candidates for automation.

So without any further ado, here is the playbook that will:

  1. Look up the change request by its number
  2. Mark the change request as being worked on
  3. Retrieve the affected configuration item from the change request
  4. Perform requested operations on said configuration item, and finally
  5. Close the change request
---
- hosts: localhost
  gather_facts: false
  tasks:
    - name: Mark change request as in progress
      servicenow.itsm.change_request:
        number: "{{ change_number }}"
        state: implement
      register: change

    - name: Fetch configuration item we will update
      servicenow.itsm.configuration_item_info:
        sys_id: "{{ change.record.cmdb_ci }}"
      register: citem

    - name: Create an in-memory inventory with the item
      ansible.builtin.add_host:
        name: host_to_update
        ansible_host: "{{ citem.record.ip_address }}"

- hosts: host_to_update
  tasks:
    - name: Simulate some work
      ansible.builtin.debug:
        msg: Doing real work here

- hosts: localhost
  gather_facts: false
  tasks:
    - name: Mark change request as done
      servicenow.itsm.change_request:
        number: "{{ change_number }}"
        state: closed

Who could have thought that one can stuff this much awesomeness into a single playbook?

[ Looking for more on system automation? Get started with The Automated Enterprise, a free book from Red Hat. ] 

The future is automatic

I covered quite a lot yet still only managed to scratch the surface of what is possible. So head over to automation hub or Ansible Galaxy, download the ServiceNow ITSM Ansible Collection, and start exploring. You can also see this new solution in action in this webinar.

If you need help with your ServiceNow process automation and integration with the Red Hat Ansible Automation Platform, reach out to our team at XLAB Steampunk who can help you get up and running in no time.

Topics:   Linux   Linux administration   Ansible   Automation  
Author’s photo

Tadej Borovšak

Tadej Borovšak is an Ansible Evangelist at XLAB Steampunk, where he works on tools that make the lives of fellow programmers and system administrators easier. More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.