Differences
This shows you the differences between two versions of the page.
— |
rb:brocade-backup [09/07/2019 15:49] (current) andrew created |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Backup Brocade SAN switch ====== | ||
+ | |||
+ | Note, this is a few years old and updates to the fabos may require changes to the expect script. | ||
+ | |||
+ | ===== Background ===== | ||
+ | |||
+ | In the event of a hardware failure, a switch config is desirable to enable the rebuild of the config with minimal downtime. The Brocade Fibre Channel switches have a command which will produce a switch config and put it on a remote server. As this is an interactive command which requires feeding with answers, it cannot just be run without user interaction. | ||
+ | |||
+ | The scripts below feed a txt file containing switch details in to a bash script which calls an expect script. The expect script drives the backup process. | ||
+ | |||
+ | |||
+ | |||
+ | ===== Script details ===== | ||
+ | |||
+ | A new user was created on mon01 with the home directory of /home/backupsan. The config files live in this directory. | ||
+ | The switches to back up are defined in a text file:- | ||
+ | |||
+ | [backupsan@mon01 ~]$ more SANswitchlist.txt | ||
+ | fcsw1-01 | ||
+ | fcsw2-01 | ||
+ | fcsw1-02 | ||
+ | fcsw2-02 | ||
+ | fcsw1-03 | ||
+ | fcsw2-03 | ||
+ | fcsw1-04 | ||
+ | fcsw2-04 | ||
+ | msasw01 | ||
+ | msasw02 | ||
+ | |||
+ | |||
+ | This file is given to a shell script as the $1 argument (./SANswitchbackup.sh SANswitchlist.txt):- | ||
+ | |||
+ | [backupsan@mon01 ~]$ more SANswitchbackup.sh | ||
+ | #!/bin/bash | ||
+ | #Written Andrew S 08/09/2010 | ||
+ | #Purpose is to backup SAN switch config | ||
+ | #This should be run from cron once per week, maybe less frequently. | ||
+ | | ||
+ | | ||
+ | #turn on debugging, -x starts, +x stops | ||
+ | set +x | ||
+ | | ||
+ | DAY=`date +%F` | ||
+ | | ||
+ | SWITCHUSER="admin" | ||
+ | SWITCHPASS="password" | ||
+ | SWITCHLOGIN="login:" | ||
+ | SWITCHPROMPT="admin>" | ||
+ | #BACKUPHOST="mon01.company.net" | ||
+ | BACKUPHOST="172.27.206.210" | ||
+ | BACKUPUSER="backupsan" | ||
+ | BACKUPPASS="topsecret" | ||
+ | BACKUPPATH="/home/backupsan/backupfiles" | ||
+ | SENDEMAIL=no | ||
+ | EMAILSUBJECT="SAN Switch Backup" | ||
+ | | ||
+ | #e-mail distribution list | ||
+ | dist1="andrew.s@company.net" | ||
+ | | ||
+ | TMPMAILFILE=/tmp/SANswitchBackup-$$ | ||
+ | DEBUGLOG=/tmp/SANswitch-debug-$$ | ||
+ | | ||
+ | SANLIST=$1 | ||
+ | if [ "$1" = "" ] | ||
+ | then | ||
+ | echo "You need to provide a server list file, eg. ./SAN-backup.sh sanswitchlist.txt." | ||
+ | exit 1 | ||
+ | fi | ||
+ | | ||
+ | | ||
+ | echo "To: ${dist1}" > ${TMPMAILFILE} | ||
+ | echo "From: backupsan@mon01.prod.company.net" >> ${TMPMAILFILE} | ||
+ | echo "Subject: SAN Switch Backup. " >> ${TMPMAILFILE} | ||
+ | | ||
+ | echo "From /home/backupsan/SANswitchbackup.sh" >> ${TMPMAILFILE} | ||
+ | echo "Start of debug log file" > ${DEBUGLOG} | ||
+ | | ||
+ | #loop through all switches | ||
+ | for SWITCH in `cat ${SANLIST}`; | ||
+ | do | ||
+ | echo "-------------------------------------------" >> ${DEBUGLOG} | ||
+ | echo "Switch ${SWITCH}" >> ${DEBUGLOG} | ||
+ | echo "Switch ${SWITCH}" >> ${TMPMAILFILE} | ||
+ | export BACKUPFILE="${BACKUPPATH}/${SWITCH}-${DAY}" | ||
+ | echo "Backup file is ${BACKUPFILE} - exported." >> ${DEBUGLOG} | ||
+ | | ||
+ | #run expect to get backup file | ||
+ | /usr/bin/expect SAN_config_upload.exp ${SWITCH} ${SWITCHUSER} ${SWITCHPASS} ${SWITCHLOGIN} \ | ||
+ | ${SWITCHPROMPT} ${BACKUPHOST} ${BACKUPUSER} ${BACKUPPASS} ${BACKUPFILE} | ||
+ | #>> ${DEBUGLOG} | ||
+ | RC=$? | ||
+ | echo "\$RC is >${RC}<" | ||
+ | | ||
+ | if [ ${RC} -eq 0 ] | ||
+ | then | ||
+ | SUCCESS=true | ||
+ | else | ||
+ | SENDEMAIL=yes | ||
+ | fi | ||
+ | | ||
+ | | ||
+ | #echo "Pipestatus is >$PIPESTATUS<" | ||
+ | | ||
+ | echo "Expect return code is ${RC}" >> ${TMPMAILFILE} | ||
+ | echo "Expect return code is ${RC}" >> ${DEBUGLOG} | ||
+ | echo "-------------------------------------------" >> ${TMPMAILFILE} | ||
+ | echo "-------------------------------------------" >> ${DEBUGLOG} | ||
+ | echo " " >> ${TMPMAILFILE} | ||
+ | echo " " >> ${DEBUGLOG} | ||
+ | done | ||
+ | | ||
+ | echo "All switches done" >> ${TMPMAILFILE} | ||
+ | echo " " >> ${TMPMAILFILE} | ||
+ | | ||
+ | | ||
+ | | ||
+ | #Housekeeping, delete files older than 4 weeks | ||
+ | echo "Housekeeping." >> ${TMPMAILFILE} | ||
+ | echo "-------------" >> ${TMPMAILFILE} | ||
+ | | ||
+ | #How old do the files need to be? | ||
+ | AGE=28 | ||
+ | | ||
+ | NUMFILES='zero' | ||
+ | NUMFILES=`find ${BACKUPPATH}/ -mtime +${AGE} | wc -l` | ||
+ | | ||
+ | echo " " | ||
+ | echo "Deleting these files (${NUMFILES}) as they are older than 4 weeks:-" >> ${TMPMAILFILE} | ||
+ | | ||
+ | | ||
+ | #Do the deed! | ||
+ | find ${BACKUPPATH} -mtime +${AGE} -exec ls -l {} \; >> ${TMPMAILFILE} | ||
+ | find ${BACKUPPATH} -mtime +${AGE} -exec rm -f {} \; | ||
+ | | ||
+ | | ||
+ | echo " " >> ${TMPMAILFILE} | ||
+ | echo "SAN switch backup report." >> ${TMPMAILFILE} | ||
+ | echo "-------------------------" >> ${TMPMAILFILE} | ||
+ | echo " " >> ${TMPMAILFILE} | ||
+ | echo " " >> ${TMPMAILFILE} | ||
+ | echo "Current backup files in ${BACKUPPATH}:-" >> ${TMPMAILFILE} | ||
+ | echo " " >> ${TMPMAILFILE} | ||
+ | | ||
+ | ls -1rt ${BACKUPPATH} >>${TMPMAILFILE} | ||
+ | | ||
+ | | ||
+ | #Mail Out | ||
+ | if [ ${SENDEMAIL} == yes ] | ||
+ | then | ||
+ | echo "Sending notification mail at `date +%H:%M:%S` UTC." >> ${TMPMAILFILE} | ||
+ | echo " " >> ${TMPMAILFILE} | ||
+ | echo "Return Codes:-" >> ${TMPMAILFILE} | ||
+ | echo " " >> ${TMPMAILFILE} | ||
+ | echo "RC=0, all ok." >> ${TMPMAILFILE} | ||
+ | echo "RC=1, expect failed to log in to the FC switch." >> ${TMPMAILFILE} | ||
+ | echo "RC=2, switch failed to log in to the backup server over ssh." >> ${TMPMAILFILE} | ||
+ | echo "RC=3, switch reported it didn't complete backup." >> ${TMPMAILFILE} | ||
+ | echo "RC=130, expect was killed with ctrl-c." >> ${TMPMAILFILE} | ||
+ | | ||
+ | echo " " >> ${TMPMAILFILE} | ||
+ | /bin/mail ${dist1} -s "${EMAILSUBJECT}" < ${TMPMAILFILE} | ||
+ | else | ||
+ | #don't send mail, so mail command is commented out. Left in for testing | ||
+ | echo "Sending notification mail at `date +%H:%M:%S` UTC." >> ${TMPMAILFILE} | ||
+ | /bin/mail ${dist1} -s "${EMAILSUBJECT} - Test!" < ${TMPMAILFILE} | ||
+ | fi | ||
+ | | ||
+ | | ||
+ | #/usr/sbin/sendmail -t < ${TMPMAILFILE} | ||
+ | | ||
+ | rm ${TMPMAILFILE} | ||
+ | | ||
+ | #Comment if you want to see debug messages. | ||
+ | #rm ${DEBUGLOG} | ||
+ | | ||
+ | exit 0 | ||
+ | |||
+ | |||
+ | | ||
+ | |||
+ | The above script calls an expect script which does the real work:- | ||
+ | |||
+ | #!/usr/bin/expect | ||
+ | | ||
+ | #Andrew S, 09/09/2010 | ||
+ | #Purpose is to automate saving SAN switch to backup02 server | ||
+ | #This is to be run from within the backup shell script | ||
+ | #variables are set in the scell script. | ||
+ | | ||
+ | #Sample transcript of the session to automate | ||
+ | | ||
+ | #Older firmware | ||
+ | #[backupsan@mon01 ~]$ ssh -l admin fcsw1-01 | ||
+ | #admin@fcsw1-01's password: | ||
+ | #fcsw1-01:admin> configupload | ||
+ | #Protocol (scp or ftp) [ftp]: scp | ||
+ | #Server Name or IP Address [host]: mon01 | ||
+ | #User Name [user]: backupsan | ||
+ | #File Name [config.txt]: /home/backupsan/backupfiles/ajs11.txt | ||
+ | #backupsan@mon01's password: | ||
+ | #Upload complete | ||
+ | #fcsw1-01:admin> exit | ||
+ | #logout | ||
+ | #Connection to fcsw1-01 closed. | ||
+ | #[backupsan@mon01 ~]$ | ||
+ | | ||
+ | | ||
+ | #Newer firmware | ||
+ | #[backupsan@mon01 ~]$ ssh -l admin gy-fcsw1-04 | ||
+ | #admin@fcsw1-04's password: | ||
+ | # | ||
+ | #----------------------------------------------------------------- | ||
+ | #fcsw1-04:FID128:admin> configupload | ||
+ | #Protocol (scp, ftp, local) [ftp]: scp | ||
+ | #Server Name or IP Address [host]: mon01 | ||
+ | #User Name [user]: backupsan | ||
+ | #Path/Filename [<home dir>/config.txt]: /home/backupsan/backupfiles/file12.txt | ||
+ | #Section (all|chassis|FID# [all]): all | ||
+ | #backupsan@mon01's password: | ||
+ | # | ||
+ | #configUpload complete: All selected config parameters are uploaded | ||
+ | #fcsw1-04:FID128:admin> | ||
+ | | ||
+ | | ||
+ | set force_conservative 1 ;# set to 1 to force conservative mode even if | ||
+ | ;# script wasn't run conservatively originally | ||
+ | if {$force_conservative} { | ||
+ | set send_slow {1 .1} | ||
+ | proc send {ignore arg} { | ||
+ | sleep .1 | ||
+ | exp_send -s -- $arg | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | | ||
+ | # | ||
+ | # Process the configupload commands | ||
+ | set SWITCH [lindex $argv 0] | ||
+ | set SWITCHUSER [lindex $argv 1] | ||
+ | set SWITCHPASS [lindex $argv 2] | ||
+ | set SWITCHLOGIN [lindex $argv 3] | ||
+ | set SWITCHPROMPT [lindex $argv 4] | ||
+ | set BACKUPHOST [lindex $argv 5] | ||
+ | set BACKUPUSER [lindex $argv 6] | ||
+ | set BACKUPPASS [lindex $argv 7] | ||
+ | set BACKUPFILE [lindex $argv 8] | ||
+ | | ||
+ | set timeout 15 | ||
+ | spawn $env(SHELL) | ||
+ | match_max 100000 | ||
+ | | ||
+ | | ||
+ | #Login | ||
+ | send -- "ssh -l ${SWITCHUSER} ${SWITCH}\r" | ||
+ | | ||
+ | expect { | ||
+ | default {exit 0} | ||
+ | "Permission denied" {exit 1} | ||
+ | "password:" {send -- "${SWITCHPASS}\r"} | ||
+ | } | ||
+ | #send -- "${SWITCHPASS}\r" | ||
+ | | ||
+ | #get prompt and start upload | ||
+ | #fcsw1-01:admin> | ||
+ | #or | ||
+ | #fcsw1-04:FID128:admin> | ||
+ | expect "admin>" | ||
+ | send -- "configupload\r" | ||
+ | | ||
+ | | ||
+ | #Choose scp from options | ||
+ | #Protocol (scp or ftp) [ftp]: | ||
+ | #or | ||
+ | #Protocol (scp, ftp, local) [ftp]: scp | ||
+ | expect "scp" | ||
+ | send -- "scp\r" | ||
+ | | ||
+ | | ||
+ | #host name for sending config file | ||
+ | expect "host" | ||
+ | send -- "${BACKUPHOST}\r" | ||
+ | | ||
+ | | ||
+ | #Remote User name | ||
+ | expect "user" | ||
+ | send -- "${BACKUPUSER}\r" | ||
+ | | ||
+ | | ||
+ | #send file and path remote | ||
+ | expect "config.txt" | ||
+ | send -- "${BACKUPFILE}.conf\r" | ||
+ | | ||
+ | #Only on later firmware, earlier firmware does not ask | ||
+ | #Section (all|chassis|FID# [all]): all | ||
+ | expect "all" {send -- "all\r"} | ||
+ | | ||
+ | #send remote password | ||
+ | expect { | ||
+ | |||
+ | |||
+ | #All done, time to quit! | ||
+ | expect { | ||
+ | default {exit 3} | ||
+ | "complete" | ||
+ | } | ||
+ | send -- "exit\r" | ||
+ | | ||
+ | exit 0 | ||
+ | | ||
+ | | ||
+ | |||
+ | |||
+ | The backed up files will look similar to this:- | ||
+ | [backupsan@mon01 ~]$ more /home/backupsan/backupfiles/fcsw1-01-2011-10-03.conf | ||
+ | | ||
+ | [Switch fcsw1-01 configuration saved on Oct 03 15:04:45] | ||
+ | | ||
+ | [Boot Parameters] | ||
+ | boot.name:fcsw1-01 | ||
+ | boot.ipa:172.27.206.215:ffffff00 | ||
+ | boot.mac:10:00:00:05:1e:02:76:68 | ||
+ | boot.device:fei | ||
+ | boot.server.name:host | ||
+ | boot.server.ipa: | ||
+ | boot.gateway.ipa:172.27.206.1 | ||
+ | boot.user:user | ||
+ | boot.file:/usr/switch/firmware | ||
+ | |||