Automatic backup Cisco SAN switches

First step: ssh without password

Automatic connexions from a UNIX host to Cisco without password: If you haven't yet enable ssh, go to the installation steps

On the UNIX host print your public key (cat /root/.ssh/id_rsa.pub), use the first 2 word to add to the Cisco account

Problem is solved, it was at NX5K as well. Its mainly caused by a documentation bug:

Bind the sshkey to an existing nexus user. Take care that you exactly use the first 2 words of the generated pubkey, allthough the key consists of 3 words:

Nexus7KA(config)# username admin sshkey ssh-rsa AAAAB3Nz...
Nexus7KA(config)# sh user-account admin
user:admin
this user account has no expiry date
roles:network-operator
ssh public key: ssh-rsa AAAAB3Nz....
Important hint: In the Cisco-SSH documentation you will see:
"username User1 sshkey ssh-rsa
AAAAB3Nz..."

That is no new-line. It is a blanc: “ssh-rsa AAAAB3Nz…”

Second step: accept the ssh key for all switches

Try an ssh connection to each switch and accept the key

Third step: the backup script

Now on your unix server, create a script to backup the config:

Customize the Cisco Shell prompt:

[root@nim]/root/scripts # cat /root/scripts/backup_mds_config.sh
#!/bin/ksh
#####################################################
#
#@(#) Backup Cisco switch config and zoning into /export/mksysb/
# This is used for a cron entry. No arguments are
# allowed in cron.Absolute paths to commands must
# be specified to ssh for it to work properly
# ssh key exchange must be separately configured
# for the account "USER"
#
# Adjust the variables for your host and switch
######################################################

dir=`dirname $0`
#. $dir/.env
export binpath=/root/scripts
export sn=`basename $0 | cut -d. -f1`
export logpath=/root/scripts/logs
export logname=$logpath/$sn.log


BACKUP_DIR=/export/mksysb/san
DATE=`date "+%Y-%m-%d_%H%M%S"`
SWITCH_NAME="mds1 mds2"
USER=admin

COMMAND1="copy running-config startup-config"
COMMAND2="show startup-config"

backup_config ()
{
echo $DATE
for switch in $(echo $SWITCH_NAME)
do
  echo "Copy running to startup-config : $switch"
  ssh -l $USER $switch $COMMAND1

  echo "Backup MDS $switch config to local file : $BACKUP_DIR/$switch.$DATE"
  ssh -l $USER $switch $COMMAND2 > $BACKUP_DIR/$switch.$DATE
done
}

backup_config > $logname 2>&1

Generate zoning commands for Cisco SAN switches

Samples:

root@nim - /root/scripts/san > ./mkzone.sh config_file
User Access Verification
User Access Verification
User Access Verification
User Access Verification
                         #####  #######   ###    #####             #
 #    #  #####    ####  #     # #        #   #  #     #           ##
 ##  ##  #    #  #      #     # #       #     # #                # #
 # ## #  #    #   ####   ###### ######  #     # ######   #####     #
 #    #  #    #       #       #       # #     # #     #            #
 #    #  #    #  #    # #     # #     #  #   #  #     #            #
 #    #  #####    ####   #####   #####    ###    #####           #####

** Login to switch mds9506-1
** Enter the following commands:
***************************************************

ssh admin@mds9506-1
copy run start

config t
c0:50:76:01:45:b6:00:18
fcalias name v_prodsrv1_p0 vsan 1
member pwwn c0:50:76:01:45:b6:00:18
c0:50:76:01:45:b6:00:08
fcalias name v_server1_p0 vsan 1
member pwwn c0:50:76:01:45:b6:00:08
exit

config t
zone name v_server1_p0_svc3-prd_p1 vsan 1
member fcalias v_server1_p0
member fcalias svc3-prd_p1
zone name v_server1_p0_svc3-prd_p3 vsan 1
member fcalias v_server1_p0
member fcalias svc3-prd_p3
zone name v_server1_p0_svc4-prd_p2 vsan 1
member fcalias v_server1_p0
member fcalias svc4-prd_p2
zone name v_server1_p0_svc4-prd_p4 vsan 1
member fcalias v_server1_p0
member fcalias svc4-prd_p4
zone name v_prodsrv1_p0_svc3-bcp_p1 vsan 1
member fcalias v_prodsrv1_p0
member fcalias svc3-bcp_p1
zone name v_prodsrv1_p0_svc3-bcp_p3 vsan 1
member fcalias v_prodsrv1_p0
member fcalias svc3-bcp_p3
zone name v_prodsrv1_p0_svc4-bcp_p2 vsan 1
member fcalias v_prodsrv1_p0
member fcalias svc4-bcp_p2
zone name v_prodsrv1_p0_svc4-bcp_p4 vsan 1
member fcalias v_prodsrv1_p0
member fcalias svc4-bcp_p4
exit

zoneset name cfg_A_vsan1 vsan 1
member v_server1_p0_svc3-prd_p1
member v_server1_p0_svc3-prd_p3
member v_server1_p0_svc4-prd_p2
member v_server1_p0_svc4-prd_p4
member v_prodsrv1_p0_svc3-bcp_p1
member v_prodsrv1_p0_svc3-bcp_p3
member v_prodsrv1_p0_svc4-bcp_p2
member v_prodsrv1_p0_svc4-bcp_p4
exit
zoneset distribute vsan 1
sleep 10
zoneset activate name cfg_A_vsan1 vsan 1
sleep 10
copy run start
exit
exit
***************************************************
** Logout of switch mds9506-1
                         #####  #######   ###    #####          #
 #    #  #####    ####  #     # #        #   #  #     #         #    #
 ##  ##  #    #  #      #     # #       #     # #               #    #
 # ## #  #    #   ####   ###### ######  #     # ######   #####  #    #
 #    #  #    #       #       #       # #     # #     #         #######
 #    #  #    #  #    # #     # #     #  #   #  #     #              #
 #    #  #####    ####   #####   #####    ###    #####               #

** Login to switch mds9506-4
** Enter the following commands:
***************************************************

ssh admin@mds9506-4
copy run start

config t
c0:50:76:01:45:b6:00:12
fcalias name v_prodsrv1_p0 vsan 2
member pwwn c0:50:76:01:45:b6:00:12
c0:50:76:01:45:b6:00:02
fcalias name v_server1_p0 vsan 2
member pwwn c0:50:76:01:45:b6:00:02
exit

config t
zone name v_server1_p0_svc3-prd_p2 vsan 2
member fcalias v_server1_p0
member fcalias svc3-prd_p2
zone name v_server1_p0_svc3-prd_p4 vsan 2
member fcalias v_server1_p0
member fcalias svc3-prd_p4
zone name v_server1_p0_svc4-prd_p1 vsan 2
member fcalias v_server1_p0
member fcalias svc4-prd_p1
zone name v_server1_p0_svc4-prd_p3 vsan 2
member fcalias v_server1_p0
member fcalias svc4-prd_p3
zone name v_prodsrv1_p0_svc3-bcp_p2 vsan 2
member fcalias v_prodsrv1_p0
member fcalias svc3-bcp_p2
zone name v_prodsrv1_p0_svc3-bcp_p4 vsan 2
member fcalias v_prodsrv1_p0
member fcalias svc3-bcp_p4
zone name v_prodsrv1_p0_svc4-bcp_p1 vsan 2
member fcalias v_prodsrv1_p0
member fcalias svc4-bcp_p1
zone name v_prodsrv1_p0_svc4-bcp_p3 vsan 2
member fcalias v_prodsrv1_p0
member fcalias svc4-bcp_p3
exit

zoneset name cfg_B_vsan2 vsan 2
member v_server1_p0_svc3-prd_p2
member v_server1_p0_svc3-prd_p4
member v_server1_p0_svc4-prd_p1
member v_server1_p0_svc4-prd_p3
member v_prodsrv1_p0_svc3-bcp_p2
member v_prodsrv1_p0_svc3-bcp_p4
member v_prodsrv1_p0_svc4-bcp_p1
member v_prodsrv1_p0_svc4-bcp_p3
exit
zoneset distribute vsan 2
sleep 10
zoneset activate name cfg_B_vsan2 vsan 2
sleep 10
copy run start
exit
exit
***************************************************
** Logout of switch mds9506-4
***** Warning report:
WWN c0:50:76:01:45:b6:00:18 still exists
fcalias name v_prpds1_p0 vsan 1
  pwwn c0:50:76:01:45:b6:00:18
  pwwn c0:50:76:01:45:b6:00:19

WWN c0:50:76:01:45:b6:00:08 still exists
fcalias name v_prpas1_p0 vsan 1
  pwwn c0:50:76:01:45:b6:00:08
  pwwn c0:50:76:01:45:b6:00:09

WWN c0:50:76:01:45:b6:00:12 still exists
fcalias name v_prpds1_p0 vsan 2
  pwwn c0:50:76:01:45:b6:00:12
  pwwn c0:50:76:01:45:b6:00:13

WWN c0:50:76:01:45:b6:00:02 still exists
fcalias name v_prpas1_p0 vsan 2
  pwwn c0:50:76:01:45:b6:00:02
  pwwn c0:50:76:01:45:b6:00:03

mkzone.sh

#!/bin/ksh93
#set -x
#
# mkzone.sh - Utility that will take a config file and generate a
#             procedure that can be used for Change Management as well
#             as cut/pasted into an ssh session to configure.
#             Script is able to be run on unix/linux platforms and
#             inside Cygwin on Windows.
#
# Usage: mkzone.sh <mkzone_config_file>
#
# This script generate commands to create zoning.
# it detect on which fabric the wwn is available : show flogi database
# So you have to bring your server up on SAN
#

# Condense the config file. Get rid of blank lines and comments.
if [ ! -f ${1:-CONFIG} ]; then
     echo "ERROR: Config file ${1} not found."
     echo "Usage: mkzone.sh <mkzone_config_file>"
     echo ""
     exit 1
fi

logpath=/root/scripts/san/logs
errlog=$logpath/errlog
cat ${1} | egrep -v "^$|^#" > $logpath/zones.config.$$


CONFIG=$logpath/zones.config.$$
CONFIG1=$logpath/zones.config.ok

HOST_FABRIC_A=mds9506-1
HOST_FABRIC_B=mds9506-4
ALL_HOST_A="mds9506-1 mds9506-3"
ALL_HOST_B="mds9506-2 mds9506-4"
LOGIN=admin

# Set some variables.
#VSAN=`grep "^VSAN," ${CONFIG} | cut -d, -f2`
#SWITCH_NAME=`grep "^SwitchName," ${CONFIG} | cut -d, -f2`
#ZONESET_NAME=`grep "^ZonesetName," ${CONFIG} | cut -d, -f2`
#ZONE_BY=`grep "^ZoneBy," ${CONFIG} | cut -d, -f2`
DATE=`date '+%Y%m%d'`

if [ -e $errlog ]
then
  rm $errlog
fi

convert_wwn ()
{
wwn=$1
wwn_nodot=$(echo $wwn | sed 's/://g;s/\.//g' | tr 'a-z' 'A-Z')
wwn_dot=$(echo $wwn_nodot | sed 's/../&:/g;s/:$//' | tr 'A-Z' 'a-z')
echo $wwn_dot
}

ssh $LOGIN@mds9506-1 "show flogi database" | grep : | grep fc > $logpath/flogi.A 2>/dev/null
ssh $LOGIN@mds9506-3 "show flogi database" | grep : | grep fc >> $logpath/flogi.A 2>/dev/null
ssh $LOGIN@mds9506-2 "show flogi database" | grep : | grep fc > $logpath/flogi.B 2>/dev/null
ssh $LOGIN@mds9506-4 "show flogi database" | grep : | grep fc >> $logpath/flogi.B 2>/dev/null

grep "^ARRAY" ${CONFIG} > $CONFIG1.A
grep "^ARRAY" ${CONFIG} > $CONFIG1.B
for line in $(grep "^SERVER" ${CONFIG})
do
  DEVICE_WWN=$(echo $line | cut -d, -f3)
  PWWN=$(convert_wwn $DEVICE_WWN)
  fabric=$(grep "$PWWN" $logpath/flogi.* | cut -d'.' -f2- | cut -d':' -f1)
  line1=$(echo $line | cut -d',' -f1-2)
  echo $fabric | egrep "A|B" > /dev/null
  if [ $? -ne 0 ]
  then
    echo "$PWWN doesn't exists on a FABRIC"
  else
    echo $line1,$PWWN,$fabric >> $CONFIG1.$fabric
  fi
done

for connect in ${HOST_FABRIC_A} ${HOST_FABRIC_B}
do
  # Backup of config before
  ssh $LOGIN@$connect "show zoneset active" > $logpath/zoneset_active_before.$connect.$DATE 2>/dev/null
  ssh $LOGIN@$connect "show startup-config" > $logpath/backup_config.$connect.$DATE 2>/dev/null
  ssh $LOGIN@$connect "show zoneset brief active" > $logpath/zoneset.$connect 2>/dev/null
  VSAN=$(grep "zoneset name" $logpath/zoneset.$connect | awk '{print $5}')
  ZONESET_NAME=$(grep "zoneset name" $logpath/zoneset.$connect | awk '{print $3}')

  echo $ZONESET_NAME | grep "cfg_A" > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
    CONFIGOK="${CONFIG1}.A"
  else
    echo $ZONESET_NAME | grep "cfg_B" > /dev/null 2>&1
    if [ $? -eq 0 ]
    then
      CONFIGOK="${CONFIG1}.B"
    else
      echo "ERROR fabric not found"
      exit 1
    fi
  fi

  banner "$connect"
  echo "** Login to switch ${connect}"
  echo "** Enter the following commands:"
  echo "***************************************************"
  echo ""
  echo "ssh $LOGIN@${connect}"
  echo "copy run start"
#  echo "copy run bootflash:pre-${DATE}"
  echo ""

  # Check alias
  ssh $LOGIN@$connect "show fcalias" > $logpath/fcalias.$connect 2>/dev/null
  # Create the fcaliases.
  echo "config t"
  for TYPE in SERVER
  do
    for DEVICE in $(grep "^${TYPE}" ${CONFIGOK} | cut -d, -f2| sort -u)
    do
      DEVICE_WWN=$(grep ",${DEVICE}," ${CONFIGOK} | cut -d, -f3 | head -1)
      PWWN=$(convert_wwn $DEVICE_WWN)
      grep "fcalias $DEVICE " $logpath/fcalias.$connect > /dev/null 2>&1
      if [ $? -eq 0 ]
      then
        grep -p "$PWWN" $logpath/fcalias.$connect > /dev/null 2>&1
        if [ $? -eq 0 ]
        then
          echo "FCalias $DEVICE $DEVICE_WWN still exists" >> $errlog
        else
          echo "FCalias $DEVICE still exists but with wrong WWN" >> $errlog
        fi
      else
        grep $PWWN $logpath/fcalias.$connect > /dev/null 2>&1
        if [ $? -eq 0 ]
        then
          echo "WWN $PWWN still exists" >> $errlog
          grep -p "$PWWN" $logpath/fcalias.$connect >> $errlog
        fi
        echo "fcalias name ${DEVICE} vsan ${VSAN}"
        echo "member pwwn ${PWWN}"
      fi
    done
  done
  echo "exit"
  echo ""

  # Create all of the zones
  echo "config t"
  ZONE_ADD=""

  for line in $(grep "^SERVER" ${CONFIGOK})
  do
    SERVER=$(echo $line | cut -d, -f2)
    NUMBER=$(echo $line | cut -d, -f1 | sed 's/SERVER//')
    for storage in $(grep "^ARRAY${NUMBER}," ${CONFIGOK} | cut -d, -f2- | sed 's/,/\ /g')
    do
      case ${storage} in
                svc-prd)   word1=svc3-prd ; word2=svc4-prd ;;
                svc-bcp)   word1=svc3-bcp ; word2=svc4-bcp ;;
                ds8100prd) word1=ds8100prd ; word2=ds8100prd ;;
                ds8100bcp) word1=ds8100bcp ; word2=ds8100bcp ;;
      esac
      for ARRAY in $(egrep "$word1|$word2" $logpath/fcalias.$connect | awk '{print $3}' | grep -v "_mm_")
      do
        echo "zone name ${SERVER}_${ARRAY} vsan ${VSAN}"
        echo "member fcalias ${SERVER}"
        echo "member fcalias ${ARRAY}"
        ZONE_ADD=$(echo "$ZONE_ADD ${SERVER}_${ARRAY}")
      done
    done
  done
  echo "exit"
  echo ""

  # Create the active zoneset and activate it
  echo "zoneset name ${ZONESET_NAME} vsan ${VSAN}"

  for ZONEADD in ${ZONE_ADD}
  do
    echo "member ${ZONEADD}"
  done
  echo "exit"
  echo "zoneset distribute vsan ${VSAN}"
  echo "sleep 10"
  echo "zoneset activate name ${ZONESET_NAME} vsan ${VSAN}"
  echo "sleep 10"
  echo "copy run start"
#  echo "copy run bootflash:post-${DATE}"
  echo "exit"
  echo "exit"
  echo "***************************************************"
  echo "** Logout of switch ${connect}"

  # Backup of config after
  #ssh $LOGIN@$connect "show zoneset active" > $logpath/zoneset_active_after.$DATE 2>/dev/null

done

if [ -e $errlog ]
then
  echo
  echo "***** Warning report:"
  cat $errlog
fi



# Clean up and exit.
rm $CONFIG
exit 0

config_file (server1 is connected to array1…)

# Choose an array in ds8100prd ds8100bcp svc-prd svc-bcp
# ARRAYx,<storage>
# the array number and server number must match
ARRAY1,svc-prd
ARRAY2,ds8100prd
ARRAY3,svc-prd
ARRAY4,svc-prd
ARRAY5,ds8100bcp
ARRAY6,svc-prd
ARRAY7,svc-prd
ARRAY8,svc-prd
# add SERVERx,<fcalias>,<WWN>
# WWN can be with different formats: C05076004B64002A c0:50:76:00:4b:64:00:2a
SERVER1,v_prpas1_p0,c050760145b60002
SERVER1,v_prpas1_p0,c050760145b60008
SERVER1,v_prpas1_p1,c050760145b60006
SERVER1,v_prpas1_p1,c050760145b60004
SERVER2,v_prpds1_p0,c050760145b60012
SERVER2,v_prpds1_p0,c050760145b60018
SERVER2,v_prpds1_p1,c050760145b60016
SERVER2,v_prpds1_p1,c050760145b60014