Blog |Follow Nick on Twitter| About
 

As part of my ISE work I generally make changes to WLCs, I'm not really a Wi-Fi Guy so don't ask me about channel width but I do a lot with authentication and in ISE's case that usually includes an ACL or two on the WLC!

There are a number of options for backing up a WLC but they're all a bit clunky if you have say 10 of the blighters to backup!!

Using python (and the Netmiko module), I've written a python script to do the job. If you're a windows user, I recommend you look at MicroSoft's Subsystem for linux as setting up python & netmiko is very straight forward... i.e. the same as linux!

Here's what it looks like when you run it.

linickx:~ $ python3 backup_wlc.py
Username: admin
Password:
[INFO] 2017-08-28 16:51:11,065 Connecting to 10.10.10.9
[INFO] 2017-08-28 16:51:16,502 Connected (version 2.0, client CISCO_WLC)
[INFO] 2017-08-28 16:51:17,620 Authentication (password) successful!
[INFO] 2017-08-28 16:51:24,366 Working on CHWC01
[INFO] 2017-08-28 16:51:24,367 Filename: CHWC01_170828-165124.txt
[INFO] 2017-08-28 16:51:24,367 Sending cmd: show run-config commands
[INFO] 2017-08-28 16:51:25,773 Connecting to 10.10.11.10
[INFO] 2017-08-28 16:51:31,205 Connected (version 2.0, client CISCO_WLC)
[INFO] 2017-08-28 16:51:32,322 Authentication (password) successful!
[INFO] 2017-08-28 16:51:39,124 Working on CHWC02
[INFO] 2017-08-28 16:51:39,125 Filename: CHWC02_170828-165139.txt
[INFO] 2017-08-28 16:51:39,125 Sending cmd: show run-config commands
[INFO] 2017-08-28 16:51:40,530 Connecting to 10.11.18.5
[INFO] 2017-08-28 16:51:45,647 Connected (version 2.0, client CISCO_WLC)
[INFO] 2017-08-28 16:51:45,998 Authentication (password) successful!
[INFO] 2017-08-28 16:51:51,782 Working on DEWC01
[INFO] 2017-08-28 16:51:51,783 Filename: DEWC01_170828-165151.txt
Finished:
 CHWC01_170828-165124.txt
 CHWC02_170828-165139.txt
 DEWC01_170828-165151.txt
linickx:~ $ 

Each WLC gets it's own text file, time/date stamped, of "show run-config commands" which you can use to compare before and after changes... potentially useful for nightly backups if you want to use cron.

The script can be downloaded here (rename to .py), I've pasted it below for your reading pleasure ;-)

Please take note of the comments at the top, the WLC IP addresses are stored in the script, you'll need to update and change as appropriate. By default the script prompts you for credentials which works for runs manually but if used with cron you'll need insecure hardcoded variables (use and secure wisely!)

"""
    Script to backup Cisco WLCs using netmiko

    # Version 1.0 28.Aug.2017
    # Nick Bettison - Linickx.com

    # External Credit...
    # https://github.com/AlexMunoz905/Cisco-Backup-Config/blob/master/WLC.py
    # Thanks to ^that^ for getting me started! :)
"""
import logging
import getpass
import re
import datetime
import sys

try:
    import netmiko
except:
    print("Error Netmiko not installed - https://github.com/ktbyers/netmiko")
    sys.exit()

"""
    This array stores a list if IPS to connect to
    eg.
        one device: `ips = ["10.1.2.12"]`
        two devices: `ips = ["10.1.2.12", "10.1.3.13"]
`
"""
ips = ["10.1.2.12", "10.1.3.13"]

"""
    By default, ths scipt prompts for credentials.
    If you're feeling insecure and want to store them in the file, replace below with...
    um = "admin"
    pw = "insecure_password"
"""
un = input('Username: ')
pw = getpass.getpass()

"""
    No Need to change below here!
"""
logging.basicConfig(format='[%(levelname)s] %(asctime)s %(message)s', level=logging.INFO)
logger = logging.getLogger("wlc_backup")
devices = [] # Empty array to store wlcs
files = [] # Empty array to store filenames

for ip in ips:
    # device definition
    cisco_wlc = {
        'device_type': 'cisco_wlc',
        'ip': ip,
        'username': un,
        'password': pw,
    }
    devices.append(cisco_wlc)

for device in devices:
    logger.info("Connecting to %s", device['ip'])
    # connect to the device w/ netmiko
    try:
        net_connect = netmiko.ConnectHandler(**device)
    except:
        logger.error("Failed to connect to %s", device['ip'])
        logger.debug("Exception: %s", sys.exc_info()[0])
        continue

    # get the prompt as a string
    prompt = net_connect.find_prompt()

    logger.debug("prompt: %s", prompt)

    regex = r'^\((.*)\)[\s]>'

    regmatch = re.match(regex, prompt)
    if regmatch:
        hostname = regmatch.group(1)
        logger.info("Working on %s", hostname)
    else:
        logger.error("Hostname Not Found!")
        logger.debug(regmatch)

    filetime = datetime.datetime.now().strftime("%y%m%d-%H%M%S") # File timestamp
    config_filename = hostname + "_" + filetime + ".txt" # Filname with hostname
    files.append(config_filename)
    logger.info("Filename: %s", config_filename)

    commands = ['show run-config commands'] # commands to run

    for cmd in commands:
        logger.info("Sending cmd: %s", cmd)
        this_cmd = net_connect.send_command(cmd)
        config_filename_f = open(config_filename, 'a')
        config_filename_f.write(this_cmd)
        config_filename_f.write('\n')
        config_filename_f.close()

print("Finished:")
for fname in files:
    print(" %s " % fname)

Enjoy your backups!

 

 
Nick Bettison ©