LVM Snapshots rotate scripts

snapstats

#!/bin/sh
lvs -o vg_name,lv_name,lv_size,snap_percent

snapshots

#!/bin/bash
# $Id: snapshots,v 1.3 2011-04-09 15:18:24 cbellot Exp $
 
export PATH=$PATH:/sbin
 
# rotate function
function rotate() {
    name=$1
    nb=`printf "%.02d" $2`
    # List of LV for that name
    lvdisplay -C 2>/dev/null|grep "$name"|awk '{print $1}'>/tmp/snapshots.tmp
    # If a LV named LV-snapNB-hour exists, we remove it
    for last in `grep $name$nb- /tmp/snapshots.tmp`
    do
	if [ "$last" != "" ]
	then
	     if [ "$debug" = "1" ]
	     then
		 echo "DEBUG: lvremove -f $VG/$last"
	     else
	        if lvremove -f $VG/$last >/dev/null 2>&1
	        then
		    logger -p local1.info "lvmsnapshot($$) Removing $last: OK"
	        else
		    logger -p local1.info "lvmsnapshot($$) Removing $last: ERROR"
	        fi
	    fi
	fi
    done
    # For all the others
    nb=`expr $nb - 1`
    nb=`printf "%.02d" $nb`
    while [ $nb != 00 ]
    do
	nnb=`expr $nb + 1`
        nnb=`printf "%.02d" $nnb`
	# Is there a LV named LV-snap[hd]-$nb ?
	if grep -q $name$nb- /tmp/snapshots.tmp
	then
	    for cur in `grep $name$nb- /tmp/snapshots.tmp`
	    do
		if [ "$cur" != "" ]
		then
		    # We rename it with NB-1
		    lasth=${cur##*-}
		    new=$name$nnb-$lasth
		    if [ "$debug" = "1" ]
		    then
			echo "DEBUG: lvrename $VG $cur $new"
		    else
			if lvrename $VG $cur $new >/dev/null 2>&1
			then
			    logger -p local1.info "lvmsnapshot($$) Renaming $cur to $new : OK"
			else
			    logger -p local1.info "lvmsnapshot($$) Renaming $cur to $new : ERROR"
			fi
		    fi
		fi
	    done
	fi
	nb=`expr $nb - 1`
	nb=`printf "%.02d" $nb`
    done
}
 
# snap function
function snap() {
    name=$1
    size=$2
    date=``
    if [ "$debug" = "1" ]
    then
	echo "DEBUG: lvcreate --size $size --snapshot --name $name $VG/$LV"
    else
	if lvcreate --size $size --snapshot --name $name $VG/$LV >/dev/null 2>&1
	then
	    logger -p local1.info "lvmsnapshot($$) Snapshoting to $name: OK"
	else
	    logger -p local1.info "lvmsnapshot($$) Snapshoting to $name: ERROR"
	fi
    fi
}
 
# Args
MAX=$2
VG=$3
LV=$4
SNAPSIZE=$5
 
if [ "$2" = "" ] || [ "$3" = "" ] || [ "$4" = "" ] || [ "$5" = "" ]
then
    exit 1
fi
 
if [ "$6" = "DEBUG" ]
then
	debug=1
fi
 
# Mode (hourly/daily)
case $1 in
    hourly)
	hour=$(date +%H)h
	logger -p local1.info "lvmsnapshot($$) RUNNING IN $1 MODE; $VG $LV, $MAX, $SNAPSIZE $6"
	rotate $LV-snaph $MAX
	snap $LV-snaph01-$hour $SNAPSIZE
	logger -p local1.info "lvmsnapshot($$) DONE"
	;;
    daily)
	day=$(date +%a)
	logger -p local1.info "lvmsnapshot($$) RUNNING IN $1 MODE; $VG $LV, $MAX, $SNAPSIZE $6"
	rotate $LV-snapd $MAX
	snap $LV-snapd01-$day $SNAPSIZE
	logger -p local1.info "lvmsnapshot($$) DONE"
	;;
    weekly)
	week=$(date +%U)
	logger -p local1.info "lvmsnapshot($$) RUNNING IN $1 MODE; $VG $LV, $MAX, $SNAPSIZE $6"
	rotate $LV-snapw $MAX
	snap $LV-snapw01-w$week $SNAPSIZE
	logger -p local1.info "lvmsnapshot($$) DONE"
	;;
    *)
	exit 1
	;;
esac

snapshots-expand

#!/bin/bash
# $Id: snapshots-expand,v 1.2 2011-04-09 15:18:24 cbellot Exp $
# Expand snapshots size if they reach a limit
 
export PATH=/sbin:/usr/sbin:$PATH
lvdisplay -C 2>/dev/null | grep -v "^  LV" | while read line
do
    cur=`echo $line|awk '{print $1}'`
    VG=`echo $line|awk '{print $2}'`
    cursize=`echo $line|awk '{printf("%d",$4)}'`
    curunit=`echo $line|awk '{printf(substr($4,length($4),1))}'`
    curusage=`echo $line|awk '{printf("%d",$6)}'`
    #echo "$cur $curusage% ($cursize$curunit)"
    if [ $curusage -gt 85 ] && [ $curusage -lt 100  ]
    then
	# Expand to 1.2*size
	newsize=`expr $cursize \* 120 / 100`
	#echo "  resize to : $newsize$curunit"
	if lvresize $VG/$cur -L $newsize$curunit >/dev/null 2>&1
	then
	    logger -p local1.info "snapshot-expand($$) Expanding $cur from $cursize to $newsize : OK"
	else
	    logger -p local1.info "snapshot-expand($$) Expanding $cur from $cursize to $newsize : ERROR"
	fi
    fi
    if [ $curusage -eq 100  ]
    then
	if lvremove -f $VG/$cur >/dev/null 2>&1
	then
	    logger -p local1.info "snapshot-expand($$) Removing $cur (Full) : OK"
	else
	    logger -p local1.info "snapshot-expand($$) Removing $cur (Full) : ERROR"
	fi
    fi
done

Cron samples

#  -- ROOT (system is on LV sys1/root ) --
01 * * * * root /opt/app/bin/snapshots hourly 1 sys1 root 500M
31 4 * * * root /opt/app/bin/snapshots daily  1 sys1 root 800M
31 5 * * 7 root /opt/app/bin/snapshots weekly 1 sys1 root 900M
#  -- MAIL (date is on LV data/mail) --
03 * * * * root /opt/app/bin/snapshots hourly 2 data mail 100M
33 4 * * * root /opt/app/bin/snapshots daily  2 data mail 200M
33 5 * * 7 root /opt/app/bin/snapshots weekly 2 data mail 200M