In my previous post I have shown you what playbook is, how to write and how you can run playbook. In this post I’ll show you another playbook which will be used for managing a Cisco router. I’ll use the below simple topology for this tutorial. (All files used in this lab can be found here)
If you are new to Ansible then its better to check my other article “Ansible for Beginners: Introduction and Installation” and “Ansible for Beginners: Playbook” before continuing with this article.
Prepare the router
Ansible need ssh connection to communicate with the managing device, So ssh need to configured in our router. I use GNS3 in this lab and a Cisco 3745 router image. Perform the below steps to configure SSH on the router.
Router(config)#hostname trainigrouter
trainigrouter(config)#ip domain-name training.local
trainigrouter(config)#crypto key generate rsa
The name for the keys will be: trainigrouter.training.local
Choose the size of the key modulus in the range of360 to 4096for
your General Purpose Keys. Choosing a key modulus greater than
512 may take a few minutes.
How many bits in the modulus [512]: 2048
% Generating 2048 bit RSA keys, keys will be non-exportable... [OK] (elapsed time was 10 seconds) trainigrouter(config)# *Nov 16 07:11:59.495: %SSH-5-ENABLED: SSH 1.99 has been enabled trainigrouter(config)#
trainigrouter(config)#ip ssh version 2
Allow SSH access to the router:
trainigrouter(config)#line vty 0 15
trainigrouter(config-line)#login local
trainigrouter(config-line)#transport input ssh
trainigrouter(config-line)#exit
Let’s create the user now:
trainigrouter(config)#username <YOUR_USER_NAME> secret <YOUR_SECRET_PASSWORD>
We will use this user for connecting the router from Ansible host. Try to make an ssh connection from your Ansible host to your router using the user you just created. it should connect.
The hosts file
The hosts file is the place where Ansible looks for the nodes which it needs to manage. In this file you tell Ansible that these are my hosts or nodes and your (Ansible) job is to manage this hosts. Create a directory called inventory and make a file called hosts inside that directory.
writeimtiaz➜~/blog» mkdir inventory writeimtiaz➜~/blog» cd inventory writeimtiaz➜~/blog/inventory» touch hosts
Now open the file with your favourite editor and add our router information in that hosts file like below.
[IOS] router_a ansible_host=192.168.45.10
(assume my router IP address is 192.168.45.10). Save and exit from that file. Now exit from inventory directory and create the playbook.
The Playbook
Open a file name playbook.yml with your favourite editor and type the bellow line in that file. It’s a yml file so you should be careful about the space.
--- - hosts: router_a gather_facts: no connection: local tasks: - name: OBTAIN LOGIN INFORMATION include_vars: secrets.yml - name: DEFINE PROVIDER set_fact: provider: host: "{{ ansible_host }}" username: "{{ creds['username'] }}" password: "{{ creds['password'] }}" auth_pass: "{{ creds['auth_pass'] }}" - name: SET IP ADDRESS ios_config: provider: "{{ provider }}" authorize: yes parents: "interface FastEthernet0/1" lines: - description SOUTH-CUSTOMER - ip address 10.10.20.1 255.255.255.248 - ipv6 address 2001:db8:2001::9/64 - no shutdown - name: SAVE & BACKUP CONFIGURATION ios_config: provider: "{{ provider }}" authorize: yes save: yes backup: yes
Let me explain the playbook to you. In this playbook we have one play and four tasks. The file start with three dashes (—) means its a yml file. Then we told ansible that run this play against the router_a host, which can be found on our hosts file. During runtime ansible collect host information from the remote devices like host name. host type, os version, ip address etc which is called facts. Here we are telling Ansible that we don’t want any facts from our remote device. instead of running on the device we tell ansible run it locally.
We have four tasks in this file, the first task is “OBTAIN LOGIN INFORMATION” where I show you how you can include other yml file in your playbook. In our case we add secrets.yml file, we will create the file shortly. In this file we will put our username, password etc.
Our second task name is “DEFINE PROVIDER“. provider is a collection of arguments used to define the characteristics of how to connect to the device. You can put your hostname, username, user password, auth password inside provider and when require you can call this provider.
Our third task name is “SET IP ADDRESS“. In this task we call ios_config module. To configure Cisco router with ansible we can use this module. This time we will use this module to configure the router interface. You can see that we call our provider in this task. For configuring IP address in the router you should be in privileged mode. authorize: yes is actually giving you that permission.
Our final task is “SAVE & BACKUP CONFIGURATION“. This task is simply saves the running configuration and take a backup on your local drive.
secrets.yml file
It’s time to create the secrets.yml file. You can give any other name if you like. Create the file and open it with your favourite editor and type the below line. Again, it’s a yml file so indenting should be handle carefully.
--- creds: username: "<YOUR_ROUTER_USERNAME>" password: "<YOUR_PASSWORD>" auth_pass: "<YOUR_AUTH_PASSWORD>"
Run the Playbook
Our playbook is ready and for running the playbook all other supporting files are ready now it’s time to run the playbook. You can check the syntax and can make a dry run before the final run. For run the palybook type the bellow command in your command line.
ansible-playbook -i inventory playbook.yml
PLAY [router_a] ******************************************************************************************************** TASK [OBTAIN LOGIN INFORMATION] **************************************************************************************** ok: [router_a] TASK [DEFINE PROVIDER] ************************************************************************************************* ok: [router_a] TASK [SET IP ADDRESS] ************************************************************************************************** changed: [router_a] TASK [SAVE & BACKUP CONFIGURATION] ************************************************************************************* changed: [router_a] PLAY RECAP ************************************************************************************************************* router_a : ok=4 changed=2 unreachable=0 failed=0 writeimtiaz➜~/blog»
If you see the output like above, then it’s working. Your script is running without any error. Notice the last line where you will find a play recap where failed=0 means it’s working. Go to your router and check your configuration. The IP address should be configured in the mention interface. (In my case I have Interface FastEthernet0/1 but you may have other interface. Change the interface and the IP address according to your environment.)
This is how you can manage a router with Ansible. This playbook which I have shown here is kind of a static thing, because if you need to use it again you have to edit the main script playbook.yml. You can make this script more robust and more dynamic with the help of Ansible role. In my next post I’ll show you how you can make ansible role using the same scenario.
Thanks for reading the post. If you enjoyed the post, please share it with your network and let me know your thoughts in the comments.
About the Author: Imtiaz is working in a financial organization in Bangladesh and having experience in system, network and security administration. Feel free to contact with him on LinkedIn or Twitter.
Great site and thank you!. I hope you may be able to assist with:
I receive the following error when running your playbook:
TASK [test] *********************************************************************************************************************************************************************************************************************************
fatal: [10.82.2.119]: FAILED! => {“ansible_facts”: {“discovered_interpreter_python”: “/usr/bin/python”}, “changed”: false, “msg”: “show running-config\r\nshow running-config\r\n ^\r\n% Invalid input detected at ‘^’ marker.\r\n\r\nS-TWN-TST01#”}
Thanks for your comments. Can you please tell me which OS and python version you are using for running the playbook?
It is using python2 instead of python3.
If you have python3 installed a solution could be to add a variable for your host groups.
======================
Add to your hosts file:
[xxxxx:vars]
ansible_python_interpreter=/usr/bin/python3
Assalam o alaikum,
Thanks for this post. I found it very useful. A lot of the posts related to configuring Cisco routers via Ansible either contain old and outdated content, or the text is not formatted properly as a valid YAML file. Keep up the good work and stay blessed!