BIG-IP Backup Scripts
Problem this snippet solves:
A set of scripts that can manage F5 configuration backups, runs on a scheduler, currently geared towards a Windows Server for remote backups. Requires SSH and passwordless key-based authentication.
All files backed up are date stamped with the current day and can be used to perform a b config load and restore the appliances to a different state.
There are 2 scripts as follows:
- f5confbkp.pl (runs on the BIG-IP). Uses b config save to save a copy under /var/tmp/f5configs
- f5getconf.pl (runs on a Windows server, modify the script if you want to run it on a UNIX system). Uses the key pair generated above to remote scp the files off of the F5's to a directory structure, in the scripts example that is e:\f5backups.)
Key Exchange Setup
Note: Only required for backup from a remote system. Generate a set of keys without a passphrase. (Reference ssh-keygen for details on generating keys). Take the id_dsa.pub key and put that into the /root/.ssh/authorized_keys file on the BIG-IP's you want to back up. Permissions on the authorized_keys file must be set to 644. Test your ssh connections from the remote system to ensure the account you are using on the remote backup server can ssh into the F5's you are backing up without getting prompted, as this will cause the script to fail otherwise.
Cron job setup
Setup the cronjob on the BIG-IP's. A job similar to the following will run the f5confbkp.pl script every day at 1
30 1 * /usr/bin/perl /root/scripts/f5confbkp.pl
#!/usr/bin/perl # ------------------------------------ # # Name: f5getconf.pl # Purpose: Using SSH key based authentication gets the most current date stamped ucs file # Compatible: v4X and v9X versions of BigIP appliances, Windows 2k/2k3 or any Unix system # Requirements: On Windows cygwin (including ssh service installed) # SSH Key gen with no password for passwordless authentication # Requires that you connect and accept the key finger print before running # as a cron or via the Windows scheduler, otherwise it will stick trying to # connect via SCP. # Also requires an F5hosts.txt with the following entries: # bigipname (Case sensitive) IP Address. Example: # noc-f5-somehostname 10.0.1.1 # noc-f5-somehostnameb 10.0.1.2 # # Version: 2.0 # Author: Wes North # Currently geared for: Windows 2k/2k3 # ------------------------------------ # #Get LocalTime use Net::Telnet; #to test the socket before trying to SCP use Sys::Hostname; @T=localtime(); $year = $T[5] + 1900; $month = $T[4] + 1; $day = $T[3]; if ($T[2] > 12) { $hour = $T[2] - 12; $time = "$hour$T[1]PM"; } else { $hour = $T[2]; $time = "$hour$T[1]AM"; } if ($month < 10) { $month = "0$month"; } if ($day < 10) { $day = "0$day"; } $date = "$year$month$day"; #returns yyyymmdd $bakfile = "${hostname}-${date}.ucs"; $destdrive = qq!E:\\!; $destdir = qq!${destdrive}f5backups!; if (!-d $destdir) { `mkdir $destdir`; } $errdir = qq!$destdir\\errors!; if (!-d $errdir) { `mkdir $errdir`; } $errfile = "$errdir/debug.log"; open (ERROR, ">>$errfile") || die "Cannot open $errfile because $!\n"; #Get the current backup file for the F5 running config $cathosts = qq!cmd \/c type f5hosts.txt!; @f5list = split '\n', `$cathosts`; foreach $f5 (@f5list) { next if ($f5 =~ /^\#/); $errnum = ""; @sepline = split ' ', $f5; $hostname = $sepline[0]; $ip = $sepline[1]; $connection=Net::Telnet->new(Timeout => 2, Host => "$ip", port=>22, Errmode => sub {&error;}); if ($errnum ne "") { print ERROR "$month\/$day\/$year: $ip is not accessible $!\n"; next; } $bkfile = qq!${hostname}-${date}.ucs!; $putdir = qq!${destdir}\\$hostname!; if (!-d $putdir) { `mkdir $putdir`; } $getdir = qq!/var/tmp/f5configs!; $getfile = qq!${getdir}/${bkfile}!; #Replace the directory path and private key file reference with your own. $scpcmd = qq!cmd \/c scp -i "/cygdrive/c/Documents\ and\ Settings//.ssh/id_dsa" \ root\@${ip}\:${getfile} /cygdrive//f5backups/${hostname}/${bkfile}!; $Error = 0; $Error += system($scpcmd); if ($Error > 0) { print ERROR "$month\/$day\/$year: $scp command failed $!\n"; } else { print ERROR "$month\/$day\/$year: scp command for $hostname at $ip was successful\n"; } } close ERROR; #Cheesy and can be done differently, I didn't have a whole lot of time, so I settled for something like this. sub error { $errnum = 1; return $errnum; #print "Connection Failed!\n"; } exit 0;
Code :
#!/usr/bin/perl # ------------------------------------ # # Name: f5confbkp.pl # Purpose: without the enterprise management appliance, this can be run as a cron to backup configs from F5 appliances # Compatible: v4X and v9X versions of BigIP appliances # Requirements: Enough space to store ucs files, and really nothing else, it uses the builtin perl binaries # # Version: 2.0 # Author: Wes North # Currently geared for: Any version that supports b config save # ------------------------------------ # #Get LocalTime # use Sys::Hostname; #Locatime section, cheesy but have to set specific month and hour values @T=localtime(); $year = $T[5] + 1900; $month = $T[4] + 1; $day = $T[3]; if ($T[2] > 12) { $hour = $T[2] - 12; $time = "$hour$T[1]PM"; } else { $hour = $T[2]; $time = "$hour$T[1]AM"; } if ($month < 10) { $month = "0$month"; } if ($day < 10) { $day = "0$day"; } $date = "$year$month$day"; #returns yyyymmdd $fqdn = hostname(); #returns node.domain.suffix @n = split '\.', $fqdn; $hostname = $n[0]; #$bakfile = "${hostname}-${date}_${time}.ucs"; $bakfile = "${hostname}-${date}.ucs"; $errdir = "/var/tmp/f5configs"; if (!-d $errdir) { `mkdir $errdir`; } $errfile = "$errdir/$date-Error.log"; open (ERROR, ">>$errfile") || die "Cannot open $errfile because $!\n"; #Create a backup file for the F5 running config $bcmd = "b config save"; $path = "/var/tmp"; $f5cmd = "${bcmd} ${path}/f5configs/${bakfile} >> /dev/null 2>&1 &"; if (-f "$path/f5configs/$bakfile") { print ERROR "$month\/$day\/$year: $bakfile already exists exiting $0\n"; exit 1; } else { $possiblefile = "$path/f5configs/$hostname-*"; $ls = `ls $path/f5configs | grep .ucs`; if ($ls ne "" ) { @files = split '\n', $ls; foreach (@files) { $rm = qq!rm -rf "$path/f5configs/$_"!; `$rm`; } } $Error = 0; $Error += system($f5cmd); if ($Error != 0) { print ERROR "$month\/$day\/$year: $f5cmd command failed for $hostname\n"; exit 1; } else { print ERROR "$month\/$day\/$year: $f5cmd command completed successfully\n"; } } close ERROR; exit 0;