Configuration Backup

How to backup network device configuration through ssh protocol.

Things Used for this Job:

  • Python 3.6
  • Pycharm/Visual code IDLE
  • CISCO Switches
  • ASA Firewall

I have created a topology with switches and a Firewall to perform Configuration Backup with SSH protocol. network devices will be configured with ssh enabled including firewall, Python Controller will connect to them through ssh and perform PUT/GET operations which is basically writing command on device and capturing the output and writing it to a text file.

Libraries used:

Netmiko:

  • This library is easy to use and it gets updated regularly. Standard devices supported are below.
  • Arista EOS
    Cisco ASA
    Cisco IOS/IOS-XE
    Cisco IOS-XR
    Cisco NX-OS
    Cisco SG300
    HP Comware7
    HP ProCurve
    Juniper Junos
    Linux

OS:

  • This is more popular library used to set path for target files or directory. It takes help of Operating System functionalities to perform operations. Here I use it to set target directory location where backup files can be stored.

Getpass:

  • Library used for authenticating user with node in encrypted way which is, you can’t see the password when you type it.

Steps involved:

Step -1: Connect

First thing is first let’s connect to devices and gain access to them. Using netmiko we can connect to device through SSH protocol and authenticate. I have grabbed basic netmiko ssh code. In below code, target device details are entered in dictionary ” cisco “. Make sure correct device type is entered in ” device_type ” because based on the device string values such as host , username, password and secret would change according to device. ConnectHandler is used to connect device with details in my dictionary. If enable mode is supported by your device and want to set enable password on this code “net_connect.enable()” is used to do that. Once you got through authentication with device you have to send command and perform PUT/GET operation, to do that ” send_command("*****") ” is used. Finally to print the output use print() statement. Below is the code for single device, but it’s same any number of devices to connect, connecting to device is done one by one.

from netmiko import ConnectHandler

cisco = {
    'device_type': 'cisco_ios',
    'host': '10.0.3.1',
    'username': 'admin',
    'password': 'admin',
    'secret': 'admin',
}
net_connect = ConnectHandler(**cisco)
net_connect.enable()
# output = net_connect.send_command(user_cmd)
print(output)
Step – 2: PUT/GET Operations

After you connect to devices you have to perform some kind operation it may be PUT or GET. Over here, I am extracting current version information from device, which is GET operation using command ” Show version “. send_command helps us to send the code as per device format.

from netmiko import ConnectHandler

cisco = {
    'device_type': 'cisco_ios',
    'host': '10.0.3.1',
    'username': 'admin',
    'password': 'admin',
    'secret': 'admin',
}
net_connect = ConnectHandler(**cisco)
net_connect.enable()
output = net_connect.send_command("show ver | i Ver")
print(output)
Result on terminal
Step – 3: Backup Configurations

Pulling current config or any information from list of devices is easy now but the problem is, I see all the data on terminal and i have to copy all of it save them as per my need either in a single text file or multiple files for all devices to organize them. This isn’t the best point to stop with with our code, Let me add few more lines to it with cool functionality. So, once my code get the information I need it should save it to a text file in a location I want, by this I can save all data collected under each file with the device name or what ever I want it be named.

To save collected information on to an individual file in a location, I used “OS” library to specify path for file. I used With condition and created a file by specifying path to it inside the for loop.

In below code, I started code with condition to open Hosts file where list of IP address for devices is entered, then start reading it line by line. Once code read a line(which is IP address of a device) in Hosts file it saves the value to dictionary cisco, now connect to the device and does PUT/GET operations and get the output data. Now, after it had data from the device using with condition I create a text file naming it with Hostline itself to identify each file individually and write the output data into it, close the file and again iterate the for loop for next line in Hosts.txt file. at the end you will have all devices data saved separately in a directory. Below is the code and screen shot how they look.

Note: Hosts.txt file is located in same directory where python file is located.

Code:
from netmiko import ConnectHandler
import getpass
import os

location = '/home/venkat/Documents/SDN_bckup_Cfg/'

with open("Hosts.txt", 'r') as hostsfile:
    for line in hostsfile:
        hostline = line.strip()
        cisco = {
            'device_type': 'cisco_ios', 
            'host': '10.0.3.1',
            'username': 'username', 
            'password': 'password',
            'secret': 'admin',
        }
        net_connect = ConnectHandler(**cisco)
        net_connect.enable()
        output = net_connect.send_command(user_cmd)
        #print(output)

        outputfile = os.path.join(location, hostline +".txt")
        with open(outputfile, 'w') as result:
            x = result.write(output)
            print(x)
Result:

So far everything looks good, but it not perfect. Let me replace some of values in directionary cisco to input variables, which would help user to enter the values on terminal like username, password and commands.

Final Code:

from netmiko import ConnectHandler
import getpass
import os

location = '/home/venkat/Documents/SDN_bckup_Cfg/'
#host = input("Enter Hostname: ")
username = input("Enter Username: ")
password = getpass.getpass()
user_cmd = input("Enter command: ")

with open("Hosts.txt", 'r') as hostsfile:
    for line in hostsfile:
        hostline = line.strip()
        cisco = {
            'device_type': 'cisco_ios', 
            'host': hostline,
            'username': username, 
            'password': password,
            'secret': 'admin',
        }
        net_connect = ConnectHandler(**cisco)
        net_connect.enable()
        output = net_connect.send_command(user_cmd)
        #print(output)

        outputfile = os.path.join(location, hostline +".txt")
        with open(outputfile, 'w') as result:
            x = result.write(output)
            print(x)
files saved through code