Monday, September 14, 2015

Backup F5 units (LTM or GTM) using one script!

So in case you have gone down this rabbit hole, the BigIP series are great but certain things about them require finesse. Case in point - the management interface does not always play well with other published services like TACACS or NTP. Sometime they require custom routes and that can become a hassle.

So backing up the config on an F5 can sometimes encounter these challenges too. I want to:

1. Generate a config backup on my F5 unit using tmsh commands
2. Securely transfer that config backup somewhere else, preferably on a secure network
3. I don't want to deploy a webserver or entire development suite just to accomplish goals 1 or 2

Enter Python Fabric.

Yes, getting Fabric will take some setup....but this is an environment that you will be able to use over & over again (not just for F5 backups)

The script you can grab below permits you to use Fabric to open an SSH session, generate the config backup and then pull it back (via SFTP) to the system where you originally ran the fabric script.

Be sure to edit the user ("myname" variable) and the list of F5 units ("theList" variables) that you want to run this on. This can be used to be fully automated and headless but I'm going to let you work out those details yourself. Files will be stored on the local box in ./my_F5_backups under a date directory for each day or you could customize this script to go hand in glove with logrotate.

       
#!/usr/bin/python
#
# Designed and tested on LTM v11.x
#
import urllib2, base64, getpass, json, re, sys, os
from fabric.api import *
from datetime import datetime
#
i = datetime.now()
now_is = i.strftime('%Y%m%d-%H%M%S')
today_is = i.strftime('%Y%m%d')
print now_is
#
#
#
myname = ('my_admin_user')
print ('')
print ('Username is ' + myname)
pw = getpass.getpass()
print ('')
#
#
theList = ['ltm01.company.com','gtm01.company.com']
#
#
#
how_many = len(theList)
#
# I am using someone else's yes/no logic here
#
def query_yes_no(question, default="yes"):
        valid = {"yes":"yes",   "y":"yes",  "ye":"yes",
                "no":"no",     "n":"no"}
        if default == None:
                prompt = " [y/n] "
        elif default == "yes":
                prompt = " [Y/n] "
        elif default == "no":
                prompt = " [y/N] "
        else:
                raise ValueError("invalid default answer: '%s'" % default)

        while 1:
                sys.stdout.write(question + prompt)
                choice = raw_input().lower()
                if default is not None and choice == '':
                        return default
                elif choice in valid.keys():
                        return valid[choice]
                else:
                        sys.stdout.write("Please respond with 'yes' or 'no' "\
                                "(or 'y' or 'n').\n")
#
keep_going = query_yes_no("This will backup " + str(how_many) + " systems. Would you like to continue?\n (No will list systems that it would have run on and exit)")
if keep_going == "no":
        print (theList)
        sys.exit()
print ('')
#
env.user = myname
env.hosts = theList
env.password = pw
#
#@parallel(pool_size=5)
#
# generate the backup file (ucs) on the F5 unit itself - will create some load on F5 while running
def run_on_f5_first():
        run( "tmsh save sys ucs %s" % now_is, shell=True )
# copy backup file (ucs) back to local system
def file_get():
    get("/var/local/ucs/%s.ucs" % now_is,"./my_F5_backups/%s/%s-%s.ucs" % (today_is,now_is,env.host))
# delete config backup just genrated so disk does not fill
def run_on_f5_last():
        run( "rm -f /var/local/ucs/%s.ucs" % now_is, shell=True )
#
if __name__ == '__main__':
        execute(run_on_f5_first)
        execute (file_get)
        execute(run_on_f5_last)
       
 

And there you go. One script that does something that I've meant to do for years and just didn't get around to until now. Boy am I glad that I waited until Fabric came along!

No comments:

Post a Comment