How to use Ansible with Cisco routers
Quick Intro
For those who don't know, there is an Ansible plugin called network_cli to retrieve network device configuration for backup, inspection and even execute commands.
So, let's assume we have Ansible already installed and 2 routers:
I used Debian Linux here and I had to install Python 3:
I've also installed pip as we can see above because I wanted to install a specific version of Ansible (2.5.+) that would allow myself to use network_cli plugin:
Note: we can list available Ansible versions by just typing pip install ansible==
I've also created a user named ansible:
Edited Linux sudoers file with visudo command:
And added Ansible user permission to run root commands without prompting for password so my file looked liked this:
Quick Set Up
This is my directory structure:
These are the files I used for this lab test:
Note: we can replace cisco1.rodrigo.example for an IP address too.
In Ansible, there is a default config file (ansible.cfg) where we store the global config, i.e. how we want Ansible to behave.
We also keep the list of our hosts into an inventory file (inventory.yml here).
There is a default folder (group_vars) where we can store variables that would apply to any router we ran Ansible against and in this case it makes sense as my router credentials are the same.
Lastly, retrieve_backup.yml is my actual playbook, i.e. where I tell Ansible what to do.
Note: I manually logged in to cisco1.rodrigo.example and cisco2.rodrigo.example to populate ssh known_hosts files, otherwise Ansible complains these hosts are untrusted.
Populating our Playbook file retrieve_backup.yml
Let's say we just want to retrieve the OSPF configuration from our Cisco routers.
We can use ios_command to type in any command to Cisco router and use register to store the output to a variable:
Note: be careful with the indentation. I used 2 spaces here.
We can then copy the content of the variable to a file in a given directory. In this case, we copied whatever is in ospf_output variable to ospf_config directory.
From the Playbook file above we can work out that variables are referenced between {{ }} and we might probably be wondering why do we need to append stdout[0] to ospf_output right?
If you know Python, you might be interested in knowing a bit more about what's going on under the hood so I'll clarify things a bit more here.
The variable ospf_output is actually a dictionary and stdout is one of its keys. In reality, ospf_output.stdout could be represented as ospf_output['stdout']
We add the [0] because the object retrieved by the key stdout is not a string. It's a list! And [0] just represents the first object in the list.
Executing our Playbook
I'll create ospf_config first:
And we execute our playbook by issuing ansible-playbook command:
Now let's check if our OSPF config was retrieved:
We can pretty much type in any IOS command we'd type in a real router, either to configure it or to retrieve its configuration. We could also append the date to the file name but it's out of the scope of this article.
That's it for now.
- JRahmAdmin
Nice work, Rodrigo!