Over the last several years, I’ve found myself in situations where I need to manage multiple MID servers over multiple hosts. Management of these servers, while infrequent, was always extremely tedious as I would need to manually log into each host to adjust configuration, install or update software, or add/remove/recreate MIDs. In order to avoid this tedious work in the future, I started looking for ways to automate the entire process to make it easy to stand up and tear down fleets of MID servers with ease. To do that, I used Ansible.

This post will assume basic knowledge of Ansible. Reference the Getting Started with Ansible guide if you are unfamiliar with this tool set. Additionally, if you’d like to skip the explanations and download the role, you can find it here.

Defining the Scope

The goals for this project were simple:

  1. Create an easily portable solution
  2. Provide the ability to standardize host setup by with a basic MID directory structure and installing commonly used applications
  3. Automatically copy and unpack the MID server ZIP file to the host
  4. Apply standard configuration files for the MID server(s) (config.xml and wrapper-override.conf)
  5. Provide the ability to start, restart, stop, and remove MID server(s)

Creating an Inventory

Now that we understand what we intend to do with our Ansible configuration, we can move into creating some files. The first and arguably most important file is the inventory file. Our inventory file will include our hosts, the MID servers on them, and their state (new, up, down, restart, absent).


# State options: new, up, down, restart, absent
# Last updated date: ****
dev_mids:
  hosts:
    hostname.domainname.com:
      mid_servers:
        - name: # mid name
          state: # state
          env: # instance_name
          path: # dir path

test_mids:
  hosts:
    hostname.domainname.com:
      mid_servers:
        - name: # mid name
          state: # state
          env: # instance_name
          path: # dir path

prod_mids:
  hosts:
    hostname.domainname.com:
      mid_servers:
        - name: # mid name
          state: # state
          env: # instance_name
          path: # dir path

# Groups of Groups
all_mids:
  children:
    dev_mids:
    test_mids:
    prod_mids:

The MID servers have a few configuration options associated to them that will be utilized in later steps:

  • state: allows us to conditionally run tasks to handle provisioning, operational status, and removing MIDs
  • env: the instance name that you want the MID associated to (e.g. dev0001)
  • path: the path to the MID server directory

Creating a Role

In order to make a an easily portable solution, we will create a role. In our case, the role is called mid_controller and is structured like this:

roles
 └─mid_controller
    ├─files
    │  ├─installer
    │  │  ├─midinstaller.zip
    │  │  └─npp.8.4.6.Installer.x64.exe
    │  └─tools
    │     ├─baretail.exe
    │     └─procexp64.exe
    ├─tasks
    │  ├─hostsetup.yml
    │  ├─main.yml
    │  ├─midremoval.yml
    │  ├─midsetup.yml
    │  └─opstatus.yml
    ├─templates
    │  ├─config.xml.j2
    │  └─wrapper-override.conf.j2
    └─vars
       └─main.yml

Define the Tasks

At the time of writting, the following is supported in the mid_controller role: Host Setup (tags: hostsetup,software)

  • Sets up a basic directory structure for the MID and supporting applications
  • Must be run at least once to prepare your host for future tasks
  • Installs Notepad++ and 7Zip if installers and propr tags are provided

MID Setup (tag: midsetup)

  • Sets up a temp directory for all MID servers
  • Creates a mid server directory based on the name in the inventory
  • Copies and unzips the MID installer
  • Sets templated configuration
  • Creates a MID server record in your instance
  • Installs / runs the MID server service

Operational Status (tag: status)

  • Restarts, powers on, or powers off the MID server based on its state in the inventory

MID Removal (tag: midremoval)

  • Removes the MID server service, directory, and SN record

One key thing to note: in order for any action to take place on your ServiceNow instance, you must have the pysnow Python library and servicenow.servicenow Ansible library installed on localhost.

Defining MID Configuration

Within the templates directory of the role, there are jinja templates for the config.xml and wrapper-override.conf files. Its current configuration is pretty basic and should be adjusted to your company’s standards wherever needed. For example, at some organizations you may need to define proxies for the MID to work properly within your network.

Running the Role

Running the role is as simple as defining a playbook that looks similar to this:


- name: Set Up MID Server Environment
  hosts: all_mids
  gather_facts: false
  roles:
    - mid_controller

and running it with the following command ansible-playbook --tags "comma,separated,list". Once ran, you have a fleet of MID servers ready to use!