Advertisement
Guest User

Untitled

a guest
Sep 22nd, 2014
183
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 10.30 KB | None | 0 0
  1. #!/bin/bash
  2. #==============================================================================
  3. # Name:     snapshot-all-lvs
  4. # Purpose:  Perform daily snapshot management pre-backups
  5. #
  6. # Version:  $Header: $
  7. #==============================================================================
  8.  
  9. LC_CTYPE=en_US.UTF-8
  10. PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/dell/srvadmin/bin:/opt/dell/srvadmin/sbin
  11.  
  12.  
  13. #
  14. # Set global variables
  15. #
  16.  
  17. PROG=$(basename $0)
  18. CONFIG=/opt/ag/etc/${PROG}.cfg
  19. BACKUP_PATH=/srv/backup
  20. LVS_OVERRIDES=/opt/ag/etc/${PROG}.overrides
  21. LOG=$(date +"/tmp/snapshot-all-lvs.%Y%m%d%H%M")
  22.  
  23. MAILUSER=example@example.com
  24.  
  25. ERRORS=0
  26.  
  27. DATE=`date +%d%m%y`
  28. CLEANDATE=`date +%d%m%y --date='2 days ago'`
  29. UMOUNTDATE=`date +%d%m%y --date='1 days ago'`
  30.  
  31.     # For testing.
  32. #    CLEANDATE=010101
  33. #    UMOUNTDATE=010101
  34. #    DATE=020101
  35. BACKUP_MOUNT_DIR=$BACKUP_PATH/$DATE
  36. export DATE EMAIL BACKUP_PATH lv lv_lvmsize lv_snapsize lvfile LVS_OVERRIDES CONFIG LOG
  37.  
  38.  
  39. #
  40. #    Display message with date and time for logging purposes
  41. #
  42. function log_echo () {
  43.     echo -e "`date '+%d-%b-%y %H:%M:%S'` ${PROG}: ${*}" |  tee -a ${LOG}
  44. }
  45.  
  46.  
  47. #
  48. # Obtain config overrides - if none set, return default
  49. # Usage: <variable>=$(get_config_override <Override_string> <Default_Value>)
  50. #
  51. function get_config_override () {
  52.  
  53.     DfltVal=$2    
  54.     tmp=$(grep ^$1 $CONFIG | awk -F = '{print $2}')
  55.     if [ -z "$tmp" ] ; then
  56.         echo $DfltVal
  57.     else
  58.         echo $tmp
  59.     fi
  60.  
  61. }
  62.  
  63.  
  64. #
  65. # Obtain LVS overrides - if none set, return default
  66. # Usage: <variable>=$(get_lvs_override <Override_string>)
  67. #
  68. function get_lvs_override () {
  69.  
  70.     tmp=$(grep ^$1 $LVS_OVERRIDES | awk '{print $2}')
  71.     if [ -z "$tmp" ] ; then
  72.         echo $SNAP_PERCENT
  73.     else
  74.         echo $tmp
  75.     fi
  76.  
  77. }
  78.  
  79.  
  80. function mount_fs () {
  81.     MOUNTDEVICE=$1
  82.     MOUNTPATH=$BACKUP_MOUNT_DIR/$2
  83.     TYPE=$3
  84.     SUCCESS=FALSE
  85.     TYPEOPTION=""
  86.     FSCK_CMD=fsck
  87.  
  88.     if fsck -n $MOUNTDEVICE 2>&1 |grep -q fsck.drbd
  89.     then
  90.         # we think we're DRBD, but we are really ext3.
  91.         TYPEOPTION="-t ext3"
  92.         FSCK_CMD="fsck.ext3"
  93.     fi
  94.     mkdir -p $MOUNTPATH
  95.  
  96.     if [ "$TYPE" != "NTFS" ]
  97.     then
  98.         $FSCK_CMD -y $MOUNTDEVICE >& /tmp/snaperrorlogtmp
  99.         if [ $? != 0 ]
  100.         then
  101.             ERRORS=`expr $ERRORS + 1`
  102.             log_echo FSCK $MOUNTDEVICE failed - log follows
  103.             cat /tmp/snaperrorlogtmp >> $LOG
  104.         fi
  105.     fi
  106.    
  107.     mount $TYPEOPTION -o ro $MOUNTDEVICE $MOUNTPATH >& /tmp/snaperrorlogtmp
  108.     if [ $? != 0 ]
  109.     then
  110.         ERRORS=`expr $ERRORS + 1`
  111.         log_echo mounting /$MOUNTDEVICE failed - log follows
  112.         cat /tmp/snaperrorlogtmp >> $LOG
  113.     fi
  114.     # Confirm successful mount
  115.     if grep -q $MOUNTPATH /proc/mounts
  116.     then
  117.         # successfully mounted
  118.         SUCCESS="TRUE"
  119.         MOUNTCOUNT=`expr $MOUNTCOUNT + 1`
  120.     else
  121.         ERRORS=`expr $ERRORS + 1`
  122.         log_echo "Failure to mount DEVICE $MOUNTDEVICE for $DATE"
  123.     fi
  124. }
  125.  
  126.  
  127.  
  128.  
  129. function process {
  130.     # Recursive process to recognise LVM, partitions, and filesystems.
  131.     local NAME="$1"
  132.     local DEVICE="$2"
  133.     if [ ! -e $DEVICE  ]
  134.     then
  135.         ERRORS=`expr $ERRORS + 1`
  136.         log_echo DEVICE $DEVICE does not exist.
  137.         return
  138.     fi
  139.     local TYPE=$(file -Lsb $DEVICE 2> /dev/null)
  140.     # Mount filesystems
  141.     if echo $TYPE | grep -qE 'filesystem|Reiser'
  142.     then
  143.         mount_fs $DEVICE $NAME filesystem
  144.         return
  145.     fi
  146.     if echo $TYPE | grep -q NTFS
  147.     then
  148.         mount_fs $DEVICE $NAME NTFS
  149.         return
  150.     fi
  151.     if echo $TYPE | grep -q 'swap file'
  152.     then
  153.         # Swap files cannot be mounted
  154.         return
  155.     fi
  156.     # Import LVM volume groups.
  157.     if [ "$(echo $TYPE|awk '{ print $1}')" = LVM2 ]
  158.     then
  159.         VG="$NAME-$DATE"
  160.         ORIGVG=$(pvs --noheadings -o vg_name $DEVICE|awk '{print $1}')
  161.         vgimportclone -n $VG $DEVICE &> /dev/null
  162.         sleep 2
  163.          # cleanup the leftover LVs - these shouldn't exist.
  164.         for lvname in $(lvs --noheadings -o lv_name $VG)
  165.         do
  166.             dmsetup remove $(echo $ORIGVG|sed s/-/--/g)-$(echo $lvname|sed s/-/--/g)
  167.             lvdevice=$(echo $VG|sed s/-/--/g)-$(echo $lvname|sed s/-/--/g)
  168.             sleep 2 # Queisce
  169.             process $NAME-LVM-$lvname /dev/mapper/$lvdevice
  170.         done
  171.         return
  172.     fi
  173.     # split partitions out and process them (last due to delay)
  174.     DEVMAP=`kpartx -av $DEVICE | awk '{print $3}'`
  175.     PARTITIONS=`echo $DEVMAP | wc -w`
  176.     FILENUM=0
  177.     if [ $PARTITIONS -gt 0 ]
  178.     then
  179.         sleep 3
  180.         for FILE in $DEVMAP
  181.         do
  182.             FILENUM=$(expr $FILENUM + 1)
  183.             process "$NAME-$FILENUM" "/dev/mapper/$FILE"
  184.         done
  185.         return
  186.     fi
  187.     # we still don't know what it is - let's try and mount it anyway
  188.     mount_fs $DEVICE $NAME ''
  189.     if [ $SUCCESS != "TRUE" ]
  190.     then
  191.         print "Unknown volume: $DEVICE $NAME $TYPE"
  192.     fi
  193. }
  194.  
  195.  
  196.  
  197. function cleanup {
  198.  
  199.     # unmount everything for the UMOUNTDATE.
  200.     unmount $UMOUNTDATE;
  201.  
  202.  
  203.     # Decomission VGs
  204.     for VG in $(vgs --noheadings -o vg_name 2> /dev/null |grep $CLEANDATE)
  205.     do
  206.         vgremove --force $VG &> /dev/null
  207.     done
  208.  
  209.     # remove LVM PVs
  210.     for DEVICE in $(pvs --noheadings -o pv_name 2> /dev/null |grep $CLEANDATE)
  211.     do
  212.         pvremove --force $DEVICE &> /dev/null
  213.         sleep 1
  214.         dmsetup remove $DEVICE &> /dev/null
  215.     done
  216.  
  217.     # Remove partition mappings
  218.     for DEVICE in $(ls /dev/mapper/*--snapshot--${CLEANDATE}* 2> /dev/null | grep -v cow | grep -v -- "--${CLEANDATE}\$" | sort -r )
  219.     do
  220.         kpartx -d $DEVICE &> /dev/null
  221.         dmsetup remove "$DEVICE" &> /dev/null
  222.         if [ $? -ne 0 ] ; then
  223.             log_echo "Both kpartx -d and dmsetup remove falied: $DEVICE"
  224.         fi
  225.     done
  226.  
  227.  
  228.     # remove the actual snapshot.
  229.     for LV in $(lvs  --noheadings -o lv_name,vg_name 2> /dev/null | grep snapshot-${CLEANDATE} | awk '{print $2 "/" $1}')
  230.     do
  231.         lvremove --force $LV &> /dev/null
  232.         if [ $? -ne 0 ];then
  233.             log_echo "Falied to remove snapshot: $LV"
  234.         fi
  235.     done
  236.  
  237. }
  238.  
  239.  
  240.  
  241. function unmount {
  242.     local MYUNMOUNTDATE=$1
  243.     for FS in $(mount|grep $MYUNMOUNTDATE|awk '{print $3}')
  244.     do
  245.         umount $FS
  246.         if [ $? -ne 0 ] ; then
  247.             log_echo "Failed to umount snapshot $FS"
  248.         else
  249.             rmdir $FS
  250.         fi
  251.     done
  252.     rmdir $BACKUP_PATH/$MYUNMOUNTDATE &> /dev/null
  253. }
  254.  
  255.  
  256. #### Main section
  257.  
  258. # Default snapshot percentage
  259. SNAP_PERCENT="$(get_config_override SNAP_PERCENT 20)"
  260. IGNORE_LVS="$(get_config_override IGNORE_LVS 'swap|temp')"
  261.  
  262.  
  263. log_echo "Running for $DATE, cleaning up $CLEANDATE\n\n"
  264.  
  265. cleanup
  266.  
  267. printf "Default Snap Percentage: %s\n" $SNAP_PERCENT
  268. printf "LV's to ignore: %s\n" "$IGNORE_LVS"
  269.  
  270. if [ -s "$LVS_OVERRIDES" ] ; then
  271. {
  272.     printf "`date`: Snap Percentage Overrides:\n\n"
  273.     printf "LV                   Percentage\n"
  274.     printf "==================== ==========\n"
  275.     cat $LVS_OVERRIDES | awk '{ printf "%-20s    %3d\n", $1, $2 }'
  276.     print
  277. } | tee -a $LOG
  278. fi
  279.  
  280.  
  281. # Display headings
  282. log_echo " STATUS   Volume Group                   Logical Volume                                SNAP Percent   Mount Count"
  283. log_echo "======== ============================== ============================================= ============== ============="
  284.  
  285.  
  286. #### Iterate over logical volumes. - exclude those in the list, exclude those with a dated volume group, and snapshots.
  287. LVS=$(lvs --noheadings -o lv_name,vg_name,origin 2>/dev/null | grep -vE $IGNORE_LVS |grep -vE '[0-9]{6}' | awk '{ if ($3=="") {printf("%s ", $1)}}')
  288. for lv in  $LVS
  289. do
  290.     lv_line=`lvs --noheadings -o lv_name,lv_size,vg_name,origin --units m $VOLUMEGROUP 2>/dev/null | grep " $lv "`
  291.     lv_lvmsize=`echo "$lv_line " \
  292.             | awk '{
  293.                if ($4=="") {\
  294.                    DENOM=substr($2,length($2),1);
  295.                    printf "%d",$2 \
  296.                    } \
  297.                }'`
  298.     if [ -z "$lv_lvmsize" ]
  299.     then
  300.         log_echo ERROR: Weird Issue with LVM with $lv - can\'t calculate snapshot size
  301.         continue
  302.     fi
  303.  
  304.     # Obtain override, if not set, receives default percentage
  305.     mysnappercent=$(get_lvs_override "$lv ")
  306.    
  307.     snap_mb=$(expr $(expr $lv_lvmsize \* $mysnappercent) / 100 )
  308.     lv_snapsize=${snap_mb}m
  309.         vg_name=`echo "$lv_line " \
  310.             | awk '{
  311.                if ($4=="") {\
  312.                    printf "%s",$3 \
  313.                    } \
  314.                }'`
  315.     SNAPSHOT="$lv-backup-snapshot-$DATE"
  316.    
  317.     SNAPSHOT_DEV="/dev/mapper/$vg_name-"$(echo $SNAPSHOT|sed s/-/--/g)
  318.  
  319.     lvcreate -s -n $SNAPSHOT -L $lv_snapsize $vg_name/$lv >& /tmp/snaperrorlogtmp
  320.     if [ $? != 0 ]
  321.     then
  322.         ERRORS=`expr $ERRORS + 1`
  323.         log_echo "Failed to create snapshot  $NEW_SNAPSHOT  of $vg_name/$lv"
  324.         cat /tmp/snaperrorlogtmp >> $LOG
  325.     fi
  326.  
  327.  
  328.     # Create mapping and mount
  329.     MOUNTCOUNT=0
  330.     process $lv $SNAPSHOT_DEV
  331.     if [ $MOUNTCOUNT -eq 0 ]
  332.     then
  333.         fstatus=$(printf "FAILED   %-30s %-45s      %-3.3d         %-2d"  $vg_name  $lv  $mysnappercent  $MOUNTCOUNT)
  334.     else
  335.         fstatus=$(printf "SUCCESS  %-30s %-45s      %-3.3d         %-2d"  $vg_name  $lv  $mysnappercent  $MOUNTCOUNT)
  336.     fi
  337.     log_echo "$fstatus"
  338.  
  339. done
  340.  
  341. #
  342. # If not running on a terminal (i.e. cron), cat log file so it appears on the email from cron
  343. #
  344. if [ ! -t 1 ]; then
  345.     echo "\n\n=========== $LOG ===========\n\n"
  346.     cat $LOG
  347.     echo "\n\n========= END $LOG =========\n\n"
  348. fi
  349.  
  350. #
  351. # If old snapshots exist, email this result
  352. #
  353. OLDSNAPS=`lvs 2>/dev/null | grep backup-snapshot | grep -vE -- "-$DATE|-$UMOUNTDATE"`
  354. if [ "$OLDSNAPS" ] ; then
  355.     (
  356.         printf "************************************************************\n"
  357.         printf "************************************************************\n"
  358.         printf "****** Old Snapshots exist and require manual cleanup ******\n\n"
  359.         lvs | grep backup-snapshot | grep -vE -- "-$DATE|-$UMOUNTDATE"
  360.         printf "\n************************************************************\n"
  361.         printf "************************************************************\n"
  362.     ) | mail -s "`hostname`: Old snapshots exist and require manual cleanup" $MAILUSER
  363. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement