Cisco Router Configuration Backup using Ansible
In this Ansible Cisco tutorial for beginners I will take you from the very beginning, installing Ansible on Ubuntu, to setting up the folders and running through a simple playbook which will backup Cisco router config.
I will say that I am not a Linux expert so if you notice any Linux errors or better ways of doing things please comment and I will update this article.
If you have never heard of Ansible before then please read: What is Ansible?
Tutorial: Backup Cisco Router Configuration with Ansible in less than 15 minutes
What is Ansible?
Ansible is an open source automation platform that enables you to automation IT infrastructure and more importantly for us, network devices!
It’s an automation engine that runs Ansible Playbooks written in YAML
Ansible is a free-software platform for configuring and managing computers or network devices which combines multi-node software deployment, ad hoc task execution, and configuration management. (description taken from wikipedia)
It can also be used for network management. The beauty of Ansible is that it is does not require an agent on the host system, it uses SSH for transport.
As long as Ansible can make an SSH connection to the target device you are good to go. Ansible used to be primarily used for server administration but in the last few years more and more network modules have been added to the software and Ansible is a great skill to acquire for network engineers looking to get started with network automation.
This Ansible tutorial will cover the free version installed on an Ubuntu desktop, known as Ansible Core – the current version at the time of writing is 2.10..3
If you are a network engineer and looking for other tutorials: check out all my other Ansible Tutorials
How to Install Ansible on Ubuntu
You can install Ansible on many versions of Linux but for this tutorial I will using Ubuntu 20.04 running within VMWorkstation Pro
From this point on I am assuming that you have a clean version of Ubuntu installed.
There will be a few enhancements I make to Ubuntu to make running Ansible easier which will be detailed along the way.
Installing Ansible
Before we start lets just establish that Ansible is not already installed on this syste
You can do this with the ansible –version command
roger@ubuntu:~$ ansible --version
The program 'ansible' is currently not installed.
You can install it by typing: sudo apt install ansible
The best way to get Ansible for Ubuntu is to add the project’s PPA (personal package archive) to your system.
Open a terminal and run the command:
sudo apt-get update
Then run the command
sudo apt-get install software-properties-common
Now the package is installed you can install Ansible by entering the following command.
sudo apt-add-repository ppa:ansible/ansible
You will need to press ENTER to accept the PPA addition.
Next run the command
sudo apt-get update
Finally to install Ansible run the command
sudo apt-get install ansible
Ansible is now installed and can be verified with the command
ansible --version
At the time of writing the current Ansible version is 2.9.6
roger@ubuntu:~$ ansible --version ansible 2.9.6 config file = /etc/ansible/ansible.cfg configured module search path = Default w/o overrides roger@ubuntu:~$
Ok so now we have Ansible installed lets start using it.
Enable Colorful Terminal in Debian and Ubuntu
One of the extras I have enabled in my Ubuntu install is the colorful terminal as shown below
To get the coloured prompt you need to edit the file .bashrc
This process is described here
Start using Ansible
The first thing to do is to drop into the Ansible folder and explore the default folder structure.
From your home prompt run the command
cd /etc/ansible
then issue a dir and let’s see whats in there
In the default Ansible installation there are two files and a directory
ansible.cfg contains all the default values and the main ones are listed below
# some basic default values... #inventory = /etc/ansible/hosts #library = /usr/share/my_modules/ #remote_tmp = ~/.ansible/tmp #local_tmp = ~/.ansible/tmp #forks = 5 #poll_interval = 15 #sudo_user = root #ask_sudo_pass = True #ask_pass = True #transport = smart #remote_port = 22 #module_lang = C #module_set_locale = False
For this tutorial we are going to create a folder within your home directory and then look at creating a custom hosts file, you just need to be aware that the default inventory file location is /etc/ansible/hosts
Read more on the Ansible Hosts file and how to create a custom file and change it’s location below
This file defines all the hosts you will be connecting to – so let’s look at that file.
First drop into your home directory, yours will look a bit different but in mine I have a folder called network-programmability where I keep all my files.
vi hosts
You can see all hosts in the default file are commented out
For our backup Cisco Router config playbook we just need to add one router in there so I am going to add a group called CSR-Routers and add one router.
My hosts files now looks like this
# Ex 2: A collection of hosts belonging to the CSR-Routers' group [CSR-Routers] CSR-01 ansible_host=192.168.244.129
You can enter names of devices in here if your Ubuntu host can resolve them in DNS but for this basic tutorial I am just using the ansible_host command
I can now reference this host in one of two ways. Either by calling CSR-Routers or CSR-01. If I call CSR-Routers my playbook will action on every device within the CSR-Routers group if I call CSR-01 in my playbook then it will only action on that single device.
Change Inventory File Location
If you want to change the Ansible inventory file location from the default hosts file (the default hosts file resides in /etc/ansible/hosts ) you can create a file anywhere and reference it in your configuration. There are two simple ways to do this.
1: Create a file in the same folder that you are creating playbooks in called hosts and then when running your playbook simply reference this file This file can be located anywhere as long as you reference the file path as shown below, but it is much simpler to create the file in the same folder as your playbooks. This also makes it easier for creating project folders.
ansible-playbook <playbook name>.yml -i hosts
2: Create the hosts file in the same folder as your playbooks and then also create a custom ansible.cfg file in the same folder as your playbooks.
Read my in depth guide on the Ansible Inventory
My custom ansible.cfg file I create in every folder looks like this
[defaults] inventory=./hosts # Use local hosts file in root folder host_key_checking = False # Don't worry about RSA Fingerprints retry_files_enabled = False # Do not create them
The first line specifies to use the inventory file called hosts in the same folder
The second line specifies to not check for RSA Fingerprint – this is just for a lab environment, in production you might want to enable this but it does mean you have to connect to each device from the Ansible host first.
The third line stops Ansible creating retry files in the event a playbook fails. I personally find this behaviour annoying and will just run any failed playbook again. The retry files just fill up the folder and have to be deleted.
What is an Ansible Playbook?
Before we go any further I just need to define one term that you will be using every day whilst working with Ansible and that is a playbook. In simple terms a playbook is a file formatted in YAML
YAML stands for YAML Ain’t Markup Language but is also referred to as Yet Another Markup Language. Basically YAML is a very readable code that defines all the actions and tasks that your playbook will perform. Let’s look at the finished playbook below to backup a cisco router and go through each line step by step in a very quick Ansible playbook tutorial.
Using Ansible for Network Automation is a common approach being adopted by many companies around the world.
Ansible Backup Cisco Config Playbook
My playbook is called backup_cisco_router.yaml
--- - hosts: CSR-01 gather_facts: true connection: local tasks: - name: show run ios_command: commands: - show run host: "{{ ansible_host }}" username: roger password: password register: config - name: save output to /etc/ansible/backups copy: content: "{{ config.stdout[0] }}" dest: "/etc/ansible/backups/show_run_{{ inventory_hostname }}.txt"
I have this saved in a folder called playbooks /etc/ansible/playbooks
I have also created a folder called backups in /etc/ansible/backups
Let’s step through each line
— the first line of any YAML file has to start with three dashes – this denotes it as a YAML file
– hosts: CSR-01 the next line starts with a single dash and defines the hosts that this playbook should run agains, in this case our single CSR router
gather_facts: true this line needs to be here to define we are collecting information
connection: local this defines the connection will be made from this box
tasks: we now start to define the actual task that will run
– name: show run – this is the name of our first task
ios_command: this is an ansible module and is some code within the Ansible core that can be used to run commands in ios – more info here
commands: what follows here is the command that will be run
– show run in our case show run
host: “{{ ansible_host }}” this defines the connection variables for the ansible host – username / password etc
username: local username defined on the router
password: local password defined on the router
register: config Once Ansible has connected to the router and run the show run command it registers that information to a variable called config (you can call this what you want)
-name save output to /etc/ansible/backups – this is the name of the next task and is just a description
copy: this is calling another Ansible Module called copy
content: “{{ config.stdout[0] }}” this registers the config to a format called stdout
dest: “/etc/ansibe/backups/show_run_{{ inventory_hostname }}.txt” – this defines the destination and filename format which will be show_run_hostname.txt
Running the Ansible Playbook
So we now have an Ansible playbook written, we have defined a host and we now need to run the playbook.
I have a CSR1000v router running so lets see what happens
To run an Ansible Playbook you run the command
ansible-playbook <playbook name>
so in our case
ansible-playbook backup_cisco_router.yaml
You can see the descriptions of each task and if the play was successful.
In this case the playbook failed as it failed to connect to the router 192.168.244.129:22
The problem in this case is the password was wrong on the router – I am going to change the password and run the play again
This time you can see the playbook ran successfully and the task status has moved to changed=1
This means the backup file has changed.
If we now go to /etc/ansible/backups we can see our backup file
Conclusion
So we have successfully created an Ansible Playbook that will backup a single Cisco router, you can hopefully see that this could easily be scaled out to perform this task on 100’s or 1000’s of devices and also to run other commands like sh ip int brief, sh log, sh ip ospf neighbor etc. This will also backup nxos devices as well if you wanted and could be used to backup Cisco switch config.
I hope this Ansible Network Automation Example has given you some food for thought and will spark your interest to take this further.
Ansible is a very powerful tool and is going to change the way network engineers work in the future.
If you want to automate cisco configuration using Ansible you should have all the information you need.
I hope you enjoyed this simple tutorial and there will be more to come.
My latest Ansible Post: How to upgrade Cisco IOS using Ansible
For all my posts relating to Ansible – click the link below.
Ansible for Network Automation
Check out my AnsibleFest London 2017 Review
What is Ansible Galaxy?
Ansible Galaxy is Ansible’s official community hub for sharing Ansible roles. A role is the Ansible way of bundling automation content and making it reusable.
https://galaxy.ansible.com/intro
What is Ansible Tower?
Ansible Tower (formerly ‘AWX’) is a web-based solution that makes Ansible even more easy to use for IT teams of all kinds. It’s designed to be the hub for all of your automation tasks. Tower is free for usage for up to 10 nodes, and comes bundled with amazing support from Ansible, Inc.
http://docs.ansible.com/ansible/latest/tower.html
Does Ansible work on Windows?
The short answer is No, can Ansible run on windows is one of the most common questions I get and sadly at this point in time it is Linux only.
You can manage windows machines with Ansible, it uses powershell instead of SSH
Can I use Ansible on a legacy Cisco Router?
This depends on what you clasify as legacy? The only requirement for Ansible to be able to automate a Cisco device is that is has SSH connectivity to it. If you can log into the device using SSH and use standard IOS commands then Ansible can do it’s thing as well.
Who owns Ansible?
Ansible was bought by Red Hat in October 2015, it is now referred to as Ansible by Red Hat
What is Ansible Engine?
Ansible Engine is the same Ansible Core you get when running the free version but with Ansible Engine you pay for support. Ansible Engine is developed by Red Hat with the explicit intent of being used as an enterprise IT platform.
Why is Ansible better than Chef or Puppet?
The big debate about is Ansible better than Chef or Puppet will go on, but in a sentence, the main advantage Ansible has over Puppet and Chef is that it is agentless. For managing servers using Chef and Puppet you need to install an agent onto the server, which is not a big task and I have seen some people using Ansible to do that!
But for managing network devices, in the most part you are not able to install an agent on a Cisco Switch, so for the network engineer Ansible is better.
What is Ansible written in?
Ansible is written in Python but you don’t need any Python knowledge to operate it.
Who created Ansible?
You can read about the origins of Ansible here – https://www.ansible.com/blog/2013/12/08/the-origins-of-ansible
What is Ansible AWX
The AWX project is the open source version of Ansible Tower. AWX is the upstream project from which the Red Hat Ansible Tower offering is ultimately derived.
You can run AWX for free with as many nodes as you want, however is does not come with any support, but the code is what Ansible Tower is based on.
The product is pretty much the same.
https://www.ansible.com/awx-project-faq
Other Ansible articles:
- What are the benefits of using Ansible Roles?
- My Ansible Course <<
- Understanding the Ansible Hosts File
- Ansible vs Python Scripts – Which is best?
- Ansible Vault Tutorial
- Cisco IOS upgrade using Ansible
- AnsibleFest London – Review
- How to install Ansible Tower
- Ansible IOS Command Example
- Backup Cisco Router using Ansible Example Playbook
some one
I’m new to this (using your tutorial for my first attempt), but it appears that the spacing in your yaml files is way off. it’s creating problems when trying to run the playbook.
Roger Perkin
I imagine its to do with the formatting of the text on the website
Take it from here instead
https://github.com/rogerperkin/playbooks/blob/master/backup_cisco_router.yaml
some one
Also, your use of the COPY module does not use the correct syntax according to the ansible docs: http://docs.ansible.com/ansible/latest/copy_module.html
Hemant
hello,
I am facing below error message while running playbook
“msg”: “unable to open shell. Please see: https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell“,
any SOLUTION you have
Roger Perkin
Can you SSH to your device from the Ansible host?
ssh -l
Fenila
Hi,
Am facing below Error
TASK [show run] ************************************************************************************************************************************************
fatal: [CSR-01]: FAILED! => {“changed”: false, “failed”: true, “msg”: “unable to open shell. Please see: https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell“}
to retry, use: –limit @/etc/ansible/router1.retry
PLAY RECAP *****************************************************************************************************************************************************
CSR-01 : ok=1 changed=0 unreachable=0 failed=1
root@ansible-virtual-machine:/etc/ansible#
Roger Perkin
Can you SSH to the device from your host machine?
This is typically a password problem or connectivity to the target device.
If you can get to it from your host machine then verify password details are correct.
Fenila
i’m able to take ssh to a device from my host machine, but still it shows the same error
Roger Perkin
Can you run the playbook with -vvv at the end and see if you can see any further error messages?
fENILA
IT DOESN’T SHOW ANY FURTHER ERROR MESSAGES
sTILL RECEIVING THE SAME ERROR
TASK [show run] ****************************************************************
task path: /etc/ansible/backup_router.yaml:7
using connection plugin network_cli
failed: [CSR-01] (item=3YAlNucrK8gylvMwH9HQ) => {
“changed”: false,
“failed”: true,
“item”: “3YAlNucrK8gylvMwH9HQ”,
“msg”: “unable to open shell. Please see: https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell”
}
to retry, use: –limit @/etc/ansible/backup_router.retry
PLAY RECAP *********************************************************************
CSR-01 : ok=1 changed=0 unreachable=0 failed=1
Roger Perkin
Can you run the playbook with -vvv at the end and send me the output
pal
i have an invetory list of devices and i am trying to backup running configs. There is no error few of the running config files for respective hosts remains empty. Why ?
Roger Perkin
Run your playbook with -vvv at the end and this will log all the activity – you should be able to spot the issue there.
Tru Le
I have the error messages of unable to open shell while running Ansible 2.4 playbook on Cisco ios and iosxe.
Please help!
Tru Le
[email protected]
Roger Perkin
Hi Tru,
This could be a few things, firstly can you confirm you can ssh to your host device from the command line of your Ansible host
ssh@
This may prompt you to accept a fingerprint, if so great you can SSH to it
In a lab enivronment you can disable this behaviour by going into ansible.cfg and making host-checking=false
if this still doesn’t fix it make sure the username / password is correct and you can SSH to the device form a normal client
Let me know how it goes?
dez
ansible-playbook 2.7.5
config file = /etc/ansible/ansible.cfg
configured module search path = [u’/home/martello/.ansible/plugins/modules’, u’/usr/share/ansible/plugins/modules’]
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible-playbook
python version = 2.7.15rc1 (default, Nov 12 2018, 14:31:15) [GCC 7.3.0]
Using /etc/ansible/ansible.cfg as config file
/etc/ansible/hosts did not meet host_list requirements, check plugin documentation if this is unexpected
/etc/ansible/hosts did not meet script requirements, check plugin documentation if this is unexpected
/etc/ansible/hosts did not meet auto requirements, check plugin documentation if this is unexpected
[WARNING]: * Failed to parse /etc/ansible/hosts with yaml plugin: Syntax
Error while loading YAML. did not find expected The error
appears to have been in ‘/etc/ansible/hosts’: line 46, column 1, but may be
elsewhere in the file depending on the exact syntax problem. The offending
line appears to be: [CSR-Routers] CSR-01 ansible_host=10.20.1.7 ^ here
File “/usr/lib/python2.7/dist-packages/ansible/plugins/inventory/yaml.py”, line 96, in parse
data = self.loader.load_from_file(path, cache=False)
File “/usr/lib/python2.7/dist-packages/ansible/parsing/dataloader.py”, line 92, in load_from_file
parsed_data = self.load(data=file_data, file_name=file_name, show_content=show_content)
File “/usr/lib/python2.7/dist-packages/ansible/parsing/dataloader.py”, line 75, in load
return from_yaml(data, file_name, show_content, self._vault.secrets)
File “/usr/lib/python2.7/dist-packages/ansible/parsing/utils/yaml.py”, line 76, in from_yaml
_handle_error(yaml_exc, file_name, show_content)
File “/usr/lib/python2.7/dist-packages/ansible/parsing/utils/yaml.py”, line 41, in _handle_error
raise AnsibleParserError(YAML_SYNTAX_ERROR % to_native(err_msg), obj=err_obj, show_content=show_content, orig_exc=yaml_exc)
[WARNING]: * Failed to parse /etc/ansible/hosts with ini plugin:
/etc/ansible/hosts:48: Section [cisco:vars] not valid for undefined group:
cisco
File “/usr/lib/python2.7/dist-packages/ansible/plugins/inventory/ini.py”, line 132, in parse
self._parse(path, data)
File “/usr/lib/python2.7/dist-packages/ansible/plugins/inventory/ini.py”, line 241, in _parse
raise AnsibleError(“%s:%d: Section [%s:vars] not valid for undefined group: %s” % (path, decl[‘line’], decl[‘name’], decl[‘name’]))
[WARNING]: Unable to parse /etc/ansible/hosts as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match ‘all’
ERROR! Syntax Error while loading YAML.
did not find expected ‘-‘ indicator
The error appears to have been in ‘/etc/ansible/playbooks/cisco.yaml’: line 8, column 4, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
– name: show run
ios_command:
^ here
not sure if a new version broke this but this is the error message im getting
Roger Perkin
You need to put two spaces before ios_command
tasks:
– name: Show Run on Device
ios_command:
commands:
– show run
register: config
Roger Perkin
No sorry I think the formatting in the comments is not showing correctly and your playbook may indeed be correct.
Are you saying it was working and then now fails after upgrade to 2.7.5?