Intro

StackStorm or as it is affectionately known ST2 is marketed as an opensource IFTTT for ops. I like to think of ST2 as glue for software allowing you to piece together simple tasks to complex workflows to automate your infrastructure.

Lab Environment

blog/stackstorm-from-the-start-to-the-beginning/lab-topology.svg

For reference I am building this lab with Vagrant utilizing the following code versions.

  • Centos - 7 minimal
  • StackStorm - 2.10.1
  • Juniper vMX - 18.2R1.9

Installation

StackStorm can be installed in many ways. The official documentation is very good so I will not repeat the instructions here. Follow the method that suits your situation.

I have personally tried the one-liner, docker, ansible and puppet installers and they all work very well. If you are not familiar with docker, ansible or puppet I recommend the one-line installer for labs.

I did encounter an issue with the puppet install that was related to the permissions of the /etc/sudoers.d/vagrant file, so more an issue with the way the vagrant box was built rather than an issue with the puppet installer. Thankfully I received the following very helpful error message so was able to find a solutions pretty quickly. /etc/sudoers.d/vagrant: bad permissions, should be mode 0440

I then used the below bash script to correct the file permissions and install ST2 with puppet.

bash
#! /bin/bash

if [[ -f /etc/sudoers.d/vagrant ]]; then
  chmod 0440 /etc/sudoers.d/vagrant;
fi

/opt/puppetlabs/bin/puppet module install stackstorm-st2
/opt/puppetlabs/bin/puppet apply -e "include ::st2::profile::fullinstall"

ST2 Management

Once ST2 is installed there is a web interface you can login to that provides a history of tasks executed, add/remove packs, etc. In this post I will focus on the CLI.

The main CLI commands start with st2 and st2ctl . Built in help for both commands can be viewed by using the -h or --help flags.

Packs

Packs are pre-built bundles of actions, rules, sensors, triggers, aliases and workflows packaged up to be shared and re-used by StackStorm. For this lab I will use the Napalm pack . For those that are not aware, Napalm is a python library that provides a common API abstracting away the management differences between network vendors APIs.

Lets search for the Napalm pack.

cmd
sudo st2 pack search napalm

# output

+-------------+-----------------------------------------+---------+-----------------------+
| name        | description                             | version | author                |
+-------------+-----------------------------------------+---------+-----------------------+
| napalm      | NAPALM network automation library       | 0.2.15  | mierdin, Rob Woodward |
|             | integration pack                        |         |                       |
| napalm_logs | Runs a napalm-logs client as a sensor   | 0.1.1   | John Anderson         |
|             | and dispatches rendered logs as         |         |                       |
|             | triggers.                               |         |                       |
+-------------+-----------------------------------------+---------+-----------------------+

Good we found it, now lets install the Napalm pack.

cmd
sudo st2 pack install napalm

# output

For the "napalm" pack, the following content will be registered:

rules     |  4
sensors   |  1
triggers  |  0
actions   |  27
aliases   |  1

Installation may take a while for packs with many items.

	[ succeeded ] download pack
	[ succeeded ] make a prerun
	[ succeeded ] install pack dependencies
	[ succeeded ] register pack

+-------------+----------------------------------------------------+
| Property    | Value                                              |
+-------------+----------------------------------------------------+
| name        | napalm                                             |
| description | NAPALM network automation library integration pack |
| version     | 0.2.15                                             |
| author      | mierdin, Rob Woodward                              |
+-------------+----------------------------------------------------+

Great the Naplam pack is installed but whats all this about rules, sensors, triggers actions and aliases? Lets dig into that a little.

Actions

Actions are the building blocks of code that perform automation tasks. View the list of available actions with the following command.

cmd
sudo st2 action list

Sensors

Sensors can either poll an endpoint or listen for events then activate triggers when a match is found. View the list of available sensors with the following command.

cmd
sudo st2 sensor list

Triggers

Triggers are used to map events to rules. View the list of available triggers with the following command.

cmd
sudo st2 trigger list

Rules

Rules define what action is applied when a trigger is matched. View the list of available rules with the following command.

cmd
sudo st2 rule list

Aliases

Aliases are a shortcut for actions used to add functionality to bots in chatops. View the list of available aliases with the following command.

cmd
sudo st2 action-alias list

Workflows

Workflows are groups of actions that are chained together and provide the IFTTT functionality to StackStorm. Workflows are where the real power of ST2 lies and I will cover them in a future post.

Config

Before you can use the napalm pack you need to define a config file that specifies the connection and authentication parameters for each device.

Create a file named napalm.yaml under the /opt/stackstorm/config/ directory.

Note
I am not using DNS in this lab so I am using the management IP addresses for the hostname.
yaml
sudo tee /opt/stackstorm/configs/napalm.yaml > /dev/null << "EOF"
---
html_table_class: napalm

credentials:
  junos:
    username: "vagrant"
    password: "Vagrant"

devices:
  - hostname: "192.168.121.253" # R1
    driver: "junos"
    credentials: "junos"
  - hostname: "192.168.121.63" # R2
    driver: "junos"
    credentials: "junos"
EOF

Reload StackStorm and register the configuration into memory.

cmd
sudo st2ctl reload --register-configs
Important
When a configuration file is added or updated the st2ctl command must be used to load the configuration into memory so they take effect.

Testing

Lets have a look the napalm actions and see what is available.

cmd
sudo st2 action list -p napalm

# output

+--------------------------------------+--------+------------------------------------------------------+
| ref                                  | pack   | description                                          |
+--------------------------------------+--------+------------------------------------------------------+
| napalm.bgp_prefix_exceeded_chain     | napalm | Action Chain to process a BGP neighbor prefix limit  |
|                                      |        | exceeded event.                                      |
| napalm.check_consistency             | napalm | Check that the device's configuration is consistent  |
|                                      |        | with the 'golden' config in a Git repository         |
| napalm.cli                           | napalm | Run CLI commands on a device using NAPALM.           |
| napalm.configuration_change_workflow | napalm | Workflow to process a configuration change on a      |
|                                      |        | device.                                              |
| napalm.get_arp_table                 | napalm | Get the ARP table from a device using NAPALM.        |
| napalm.get_bgp_config                | napalm | Get BGP configuration from a device using NAPALM.    |
| napalm.get_bgp_neighbors             | napalm | Get the BGP neighbors from a device using NAPALM.    |
| napalm.get_bgp_neighbors_detail      | napalm | Get a detailed BGP neighbor from a device using      |
|                                      |        | NAPALM.                                              |
| napalm.get_config                    | napalm | Get configuration from the device using NAPALM.      |
| napalm.get_environment               | napalm | Get the environment sensor output from a device      |
|                                      |        | using NAPALM.                                        |
| napalm.get_facts                     | napalm | Get the various facts (Version, Serial Number,       |
|                                      |        | Vendor, Model, etc.) from a device using NAPALM.     |
| napalm.get_firewall_policies         | napalm | Get firewall policies from a device using NAPALM.    |
| napalm.get_interfaces                | napalm | Get interfaces from a device using NAPALM.           |
| napalm.get_lldp_neighbors            | napalm | Get the LLDP Neighbors from a device using NAPALM.   |
| napalm.get_log                       | napalm | Get logs from devices using NAPALM.                  |
| napalm.get_mac_address_table         | napalm | Get the MAC Address table from a device using        |
|                                      |        | NAPALM.                                              |
| napalm.get_network_instances         | napalm | Get details of network/routing instances/vrfs from a |
|                                      |        | network device using NAPALM.                         |
| napalm.get_ntp                       | napalm | Gets NTP information from a network device using     |
|                                      |        | NAPALM.                                              |
| napalm.get_optics                    | napalm | Fetches the power usage on the various transceivers  |
|                                      |        | installed on the device (in dbm) using NAPALM.       |
| napalm.get_probes_config             | napalm | Get RPM (JunOS) or IP SLA (IOS-XR) probe             |
|                                      |        | configuration from a device using NAPALM.            |
| napalm.get_probes_results            | napalm | Get RPM (JunOS) or IP SLA (IOS-XR) probe results     |
|                                      |        | from a device using NAPALM.                          |
| napalm.get_route_to                  | napalm | Shows an IP route on a network device using NAPALM.  |
| napalm.get_snmp_information          | napalm | Get the SNMP information from a device using NAPALM. |
| napalm.interface_down_workflow       | napalm | Workflow to process an interface down event on a     |
|                                      |        | device.                                              |
| napalm.loadconfig                    | napalm | Loads (merge) a configuration to a network device    |
|                                      |        | using NAPALM.                                        |
| napalm.ping                          | napalm | Run a ping from a network device using NAPALM.       |
| napalm.traceroute                    | napalm | Run a traceroute from a network device using NAPALM. |
+--------------------------------------+--------+------------------------------------------------------+

Now run the get_facts action to get information about R1. The syntax for running an action is as follows.

sudo st2 run <pack>.<action> <parameters>

cmd
sudo st2 run napalm.get_facts hostname=192.168.121.253

# output

...................................................
id: 5c31269e9dc6d6140855d946
status: succeeded
parameters:
  hostname: 192.168.121.253
result:
  exit_code: 0
  result:
    raw:
      fqdn: r1
      hostname: r1
      interface_list:
      - ge-0/0/0
      - lc-0/0/0
      - pfe-0/0/0
      - pfh-0/0/0
      - ge-0/0/1
      - ge-0/0/2
      - ge-0/0/3
      - ge-0/0/4
      - ge-0/0/5
      - ge-0/0/6
      - ge-0/0/7
      - ge-0/0/8
      - ge-0/0/9
      - .local.
      - cbp0
      - demux0
      - dsc
      - em1
      - esi
      - fti0
      - fti1
      - fti2
      - fti3
      - fti4
      - fti5
      - fti6
      - fti7
      - fxp0
      - gre
      - ipip
      - irb
      - jsrv
      - lo0
      - lsi
      - mtun
      - pimd
      - pime
      - pip0
      - pp0
      - rbeb
      - tap
      - vtep
      model: VMX
      os_version: 18.2R1.9
      serial_number: VM5B92396683
      uptime: 204344
      vendor: Juniper
  stderr: ''
  stdout: ''

Good we received the facts about R1, now lets apply some configuration to R1 and R2. First create a directory for the device configurations.

cmd
sudo mkdir /opt/stackstorm/packs/napalm/device-configs

Next create the configuration for R1 and R2

cmd
sudo tee /opt/stackstorm/packs/napalm/device-configs/r1.cfg > /dev/null << "EOF"
set system host-name r1
set protocols lldp interface all
set protocols lldp neighbour-port-info-display port-description
set interfaces ge-0/0/0.0 family inet address 10.0.0.0/31
EOF
cmd
sudo tee /opt/stackstorm/packs/napalm/device-configs/r2.cfg > /dev/null << "EOF"
set system host-name r2
set protocols lldp interface all
set protocols lldp neighbour-port-info-display port-description
set interfaces ge-0/0/0.0 family inet address 10.0.0.1/31
EOF

Now apply the configuration to R1.

Note
The absolute path to the configuration file must be supplied.
cmd
sudo st2 run napalm.loadconfig hostname=192.168.121.253 config_file=/opt/stackstorm/packs/napalm/device-configs/r1.cfg

# output

.....................................
id: 5c312dba9dc6d6140855d94c
status: succeeded
parameters:
  config_file: /opt/stackstorm/packs/napalm/device-configs/r1.cfg
  hostname: 192.168.121.253
result:
  exit_code: 0
  result: load (merge) successful on 192.168.121.253
  stderr: ''
  stdout: ''

Great that worked, now do the same for R2.

cmd
sudo st2 run napalm.loadconfig hostname=192.168.121.63 config_file=/opt/stackstorm/packs/napalm/device-configs/r2.cfg

# output

...
id: 5c312ece9dc6d6140855d952
status: succeeded
parameters:
  config_file: /opt/stackstorm/packs/napalm/device-configs/r2.cfg
  hostname: 192.168.121.63
result:
  exit_code: 0
  result: load (merge) successful on 192.168.121.63
  stderr: ''
  stdout: ''

With the configuration applied to both devices as a final test lets have a look at the LLDP neighbors of R1.

cmd
sudo st2 run napalm.get_lldp_neighbors hostname=192.168.121.253

# output

..............
id: 5c312f189dc6d6140855d955
status: succeeded
parameters:
  hostname: 192.168.121.253
result:
  exit_code: 0
  result:
    raw:
      ge-0/0/0:
      - hostname: r2
        port: ge-0/0/0
  stderr: ''
  stdout: ''

R1 sees R2 as its LLDP neighbour on interface ge-0/0/0 so it looks like its all working as expected.

Outro

StackStorm (ST2) is a powerful opensource automation tool with an active community and corporate backing from Extreme networks. There are a great number of quality packs available ready to consume with very little effort required from the administrators to get started. ST2 has many features, in future posts I will be covering chatops and workflows.

Remember: This is not the end, it's merely the beginning!

The "from the start to the beginning" series aims to take you from nothing to getting you up and running. This is not meant to be a comprehensive guide, but should be enough to get you started on the journey.