Using Ansible Networking Modules

From Building Network Automation Solutions

Building Network Automation Solutions
6 week advanced interactive online course Button-click-here.png
Course starting in
September 2017

At a Glance

  • High-intensity interactive online course;
  • Jump-start your network automation career;
  • Hands-on experience working on a solution to your own problem;
  • 6 week course spread across ~2 months;
  • Live discussion and guest speaker sessions;
  • Design and coding assignments and group work;
  • Final course completion certificate.

Ansible network modules (in particular the ones configuring routers and switches) differ significantly from the more traditional server-managing modules. The modules managing servers (including Windows servers) are usually executed on the servers themselves; the modules managing network devices (changing configurations or executing commands) have to be executed on the Ansible host.

Example

Assume you want to execute show version on a set of Cisco IOS routers. Your Ansible inventory file might be similar to this one:

[routers]
R1.lab.local
R2.lab.local
R3.lab.local

[routers:vars]
ansible_user=cisco
ansible_ssh_pass=cisco

The simplest playbook that would execute a command on all routers would be:

---
- hosts: all
  tasks:
  - ios_command:
      commands: show version
      host:     "{{inventory_hostname}}"
      username: "{{ansible_user}}"
      password: "{{ansible_ssh_pass}}"
Network modules typically don’t use standard Ansible SSH variables like ansible_user or ansible_ssh_pass. If you’re not using SSH keys to log into your networking devices you have to supply username, password, and optionally enable password in the module parameters. For more details see the Authentication section below.

However, this playbook fails miserably when executed in a default Ansible environment.

Behind the Scenes

This is the process Ansible usually uses when executing a task on a managed node (see Introduction to Ansible video from Ansible for Networking Engineers webinar for more details).

  • Collect the Python code that is required by the task (module source code + libraries referenced by the module);
  • Open an SSH connection to the managed node;
  • Copy source code to a temporary directory on the managed node;
  • Execute Python code on the managed node;
  • Collect results and return them to Ansible playbook.

Most of these steps cannot be executed on a typical switch or router. Networking modules thus use a different approach:

  • Python code is executed on Ansible host;
  • The code executed on Ansible host generates commands to be sent to the managed device, open SSH or NETCONF connection to the managed device, and executes the commands;
  • The printouts generated by the managed device are parsed and returned as module results to Ansible playbook.

Unfortunately there is no way for an Ansible module to indicate that it should be executed on the Ansible host and not on a managed device. You have to solve that problem in your playbook or configuration file.

Local Connection

While Ansible usually uses SSH to connect to the managed node, you can specify other connection types for nodes that don’t behave like a typical Linux server. For example, winrm connection plugin is used to manage Windows hosts and docker connection type is used to manage containers. What you need to execute networking modules is the local connection (meaning “execute the code on Ansible host”).

Ansible version 2.3 provides network_cli connection plugin. More details will be available when Ansible 2.3 ships.

There are numerous ways you can set the connection type to local:

  • Set ansible_connection variable. You can do that in inventory, host or group variable files;
  • Specify connection parameter within a play;
  • Specify default connection type in transport parameter in Ansible configuration file;
  • Use local_action module (see Play and Task Execution video for more details);
  • Use --connection=local CLI parameter when invoking Ansible playbook.

For example, you can add ansible_connection variable to routers:vars section of our inventory file to tell Ansible to use local connection when connecting to routers (using, for example, ios_command or ios_config modules):

[routers]
R1.lab.local
R2.lab.local
R3.lab.local

[routers:vars]
ansible_connection=local
ansible_user=cisco
ansible_ssh_pass=cisco
You’ll find all you need to know about Ansible variables, variable files, and other ways of setting variables in Ansible playbooks in Ansible Variables video (part of Ansible Deeper Dive section of Ansible for Networking Engineers webinar).

You could also set the default connection type in Ansible configuration file. This is a typical ansible.cfg file I’m using in my Ansible examples:

[defaults]
inventory=./hosts
gathering=explicit
transport=local

Authentication

Ansible uses SSH keys or passwords to authenticate the Ansible host to remote device and sudo to switch from non-privileged user to privileged user on remote device.

You can disable the use of SSH keys in ansible.cfg. More details in the Adjusting Paramiko Settings section below.

Ansible connects to remote node with the username of the user running Ansible playbook; you can overwrite the username used in SSH authentication with ansible_user variable.

To use a password instead of SSH keys, you should define ansible_ssh_pass variable for the host.

Network Module Authentication

Ansible network modules use the local username as SSH username unless an explicit username is defined, and SSH keys as authentication mechanism unless a password is specified.

In Ansible releases 2.1 and 2.2 the network modules don’t use standard Ansible mechanism to specify SSH username and password (described above). Behavior might change with the network_cli plugin in Ansible release 2.3.

Username and password used for SSH authentication has to be specified as parameters of network module:

  • username parameter specifies username used when authenticating to remote device;
  • password parameter specifies a password to use in SSH authentication;
  • Both parameters can be specified in a dictionary that is then used in the provider parameter in a network module call.

You should use the standard way of specifying SSH usernames and passwords in ansible_user and ansible_ssh_pass parameters to ensure compatibility with network_cli plugin in Ansible release 2.3.

The following example shows how to use these standard Ansible variable when running a networking module:

---
- hosts: all
  tasks:
  - ios_command:
      commands: show version
      host:     "{{inventory_hostname}}"
      username: "{{ansible_user}}"
password: "{{ansible_ssh_pass}}"

Alternatively, if you’re using a provider dictionary, use code similar to the following example to create the dictionary in a group variables file:

---
myConnection:
  username:  "{{ansible_user}}"
  password:  "{{ansible_ssh_pass}}"
  host:      "{{inventory_hostname}}"
  transport: cli

You can use that dictionary when calling a network module:

---
- hosts: all
  tasks:
  - ios_command:
      commands: show version
      host:     "{{inventory_hostname}}"
      provider: "{{myConnection}}"

Privileged Mode Operations

Ansible network modules support authorize (enter enable mode) and auth_pass (enable password) parameters. Authorize parameter is functionally identical to become parameter used by other Ansible modules.

You can use the authorize approach (equivalent to entering enable command in an interactive session) or use usernames with different privilege levels on network devices, and log into the device with appropriate (privileged versus non-privileged) username.

Adjusting Paramiko Settings

To prevent Paramiko library (used by network modules to connect to the network devices) from using SSH keys for user authentication set ANSIBLE_PARAMIKO_LOOK_FOR_KEYS environment variable to False or set look_for_keys parameter in Paramiko section of ansible.cfg to False like shown in the following printout. See the Paramiko client documentation for more details.

[paramiko_connection]
look_for_keys = False

Want to know more?

If you want to move beyond google-and-paste and understand how to use Ansible for network automation, I can highly recommend the Ansible for Networking Engineers webinar, and if you want to get a bigger picture (including architect-level perspective of network automation), register for the Building Network Automation Solutions online course.

Navigation menu