Am Donnerstag, den 16.11.2006, 22:53 +0100 schrieb Volker Lendecke:
> On Thu, Nov 16, 2006 at 02:32:43PM +0100, Christian Schwamborn wrote:
> > OK, here it comes ...
> > it's not really finished, but I will work on it if I can spare some
> > time.
> 
> No attachment around...
> 
> Volker
> 
curious, seems something has eaten the attachment, I will past it
directly into the mesage. I hope its readable.

Chris


#!/bin/bash
#
# written by Christian Schwamborn
# bugs and suggestions to:
# christian.schwamborn[you-know-what-comes-here]nswit.de
#
# published under GNU General Public License v.2
# version 1.0.1 (2006-11-21)
#
# You are using this scrip at your own risk, the author is not
responsible
# for data damage or losses in any way.
#
# What this is:
# You can use this script to create and manage snapshots for the Samba
# VFS module shadow_copy.
#
# How to use:
# The script provides some commanline parameters which are usefull for
# start/stop scrips (i.e. mount and unmount). Other parameters are
usefull
# for cronjobs - add this, for a usual snapshot scenario (without
trailing #)
# to your crontab:
#
# 0 12 * * 1-5 root /usr/local/sbin/smbsnap autosnap 0 0
# 0 7 * * 2-5 root /usr/local/sbin/smbsnap autosnap 0 1
# 0 7 * * 1 root /usr/local/sbin/smbsnap autosnap 0 2
# 3,33 * * * * root /usr/local/sbin/smbsnap autoresize all
#
# This takes snapshots at 7:00 and 12:00 every workday and checks every
hour
# if a snapshot needs to be resized.
#
# The script has some flaws:
#   -This script currently works only with LVM2, no EVMS support yet
#   -XFS should be easy to implement, but it isn't yet
#   -You must not use dashes in your volumegroups or logical volumes
#   -Be carefull with the configuration, the parameters are not
completely
#    checked right now, as the same for the command line parameters
#   -You have to keep track of the freespace of your volumegroups
#   -Be aware, that if your snapshots grow faster than you assumed, they
will
#    become unusable. With the configuration shown above, this script
checks
#    every 30 minutes if the snapshots are in the need of a resize. If
#    someone has a better idea how to check the snapshots than
periodical,
#    let me know plaese.
#
# This script is written for the bash, other shells might work, it also
uses
# some external commands: mount, umount, grep, date, bc, logger,
lvcreate,
# lvremove, lvresize
#
# There are currently three variables that have to be configured:
#   -SnapVolumes is an array, every element of that array represents a
logical
#    volume that is configured for snapshots. Each element is a comma
seperated
#    list, which consists of the logical volume itself
(i.e. /dev/GROUP1/foo),
#    the start size of the snapshot (in megabytes), the freespace which
should
#    be maintained (in megabytes) and the space added, when a snapshot
is
#    resized (also in megabytes).
#    The number of an element is used as a reference when calling the
script
#   -SnapSets is also an array, currently every element just represents
the
#    age (in days) of a snapshot of the specific snapshot-set.
#   -OffDays is a simple string with the none work days.
#
# The script will figure out by itself where to mount the snapshots, but
the
# original logical volumes has to be mounted fist.
#
# Copy and adjust the following three variables (without #) to a blank
file in
# /etc/samba and name it smbsnap.conf. If you place the configuration
file
# elsewhere, make sure to adjust the path below.
#
# SnapVolumes=('/dev/GROUP/foo,2000,500,1000'
'/dev/GROUP/bar,3000,1000,2000')
# SnapSets=(3 5 25)
# OffDays="Sat Sun"
#
###############################################################################

        . /etc/samba/smbsnap.conf

        export LANG=en_US.UTF-8
        export LANGUAGE=en_US:en
        SnapDate=$(date +%Y.%m.%d-%H.%M).00

        [ -z "${1}" ] || Command=${1}
        [ -z "${2}" ] || LVolume=${2}
        [ -z "${3}" ] || SnapSet=${3}


        # process a single snapshot
        # arguments: Command
        # needs:     SnapShot, VolumePath, SnapSets, OffDays, FreeSize, ReSize
        # provides:  na.
        # local:     cmd, SnapShotPath, CurrSnapSets, Count, Expire,
Parameters, SnapState, CurrSize, FillPercet, CurrFreeSize
        function DoSnap()
        {
                cmd=${1}
                SnapShotPath=${VolumePath}/@GMT-$(echo ${SnapShot##*/} | cut 
-f3-4 -d
\-)

                case ${cmd} in
                        # to mount snapshots
                        mount)
                                [ -d ${SnapShotPath} ] || mkdir ${SnapShotPath} 
|| \
                                        logger "${0}: ***error*** - unable to 
create mountpoint for
${SnapShot}"
                                if mount | grep -q ${SnapShotPath}; then
                                        logger "${0}: ***error*** - snapshot 
${SnapShot} is allready
mounted to ${SnapShotPath}"
                                else
                                        mount ${SnapShot} ${SnapShotPath} -o ro 
>/dev/null 2>&1 || \
                                                logger "${0}: ***error*** - can 
not mount ${SnapShot} to
${SnapShotPath}"
                                fi
                        ;;

                        # to unmount a snapshots
                        umount)
                                if mount | grep -q ${SnapShotPath}; then
                                        umount -f -l ${SnapShotPath} >/dev/null 
2>&1 || \
                                                logger "${0}: ***error*** - can 
not unmount ${SnapShot} mounted to
${SnapShotPath}"
                                else
                                        logger "${0}: ***error*** - snapshot 
${SnapShot} is not mounted to
${SnapShotPath}"
                                fi
                        ;;

                        # to remove expired snapshots
                        clean)
                                CurrSnapSet=$(echo ${SnapShot##*/} | cut -f2 
-d\-)
                                if [ ${CurrSnapSet} -ge 0 ] && [ ${CurrSnapSet} 
-lt
[EMAIL PROTECTED] ]; then                               
                                        Expire=$(echo 
${SnapSets[${CurrSnapSet}]} | cut -f1 -d,)

                                        # add off-days, if any, to the expire 
time; we just count work-days
                                        declare -i Count=1
                                        while [ ${Expire} -ge ${Count} ];do
                                                echo ${OffDays} | grep -q 
$(date -d "-${Count} day" +%a) &&
Expire=$((${Expire} + 1))
                                                Count=$((${Count} + 1))
                                        done

                                        # compare date now minus expire-time 
with the snapshot-date
                                        if [ $(( $(date +%s) - 
${Expire}*24*60*60 - 12*60*60)) -gt \
                                                        $(date -d "$(echo 
${SnapShot##*/} | cut -f3 -d\- |  tr \. \-) \
                                                        $(echo ${SnapShot##*/} 
| cut -f4 -d\- |  tr \. \:)" +%s) ]; then
                                                # unmount snapshot
                                                if mount | grep -q 
${SnapShotPath}; then
                                                        umount -f 
${SnapShotPath} >/dev/null 2>&1 || \
                                                                logger "${0}: 
***error*** - can not unmount ${SnapShot} mounted
to ${SnapShotPath}"
                                                fi
                                                if ! mount | grep -q 
${SnapShotPath}; then
                                                        # remove mount-directory
                                                        if [ -d ${SnapShotPath} 
]; then
                                                                rmdir 
${SnapShotPath} || \
                                                                        logger 
"${0}: ***error*** - unable to remove mountpoint for
${SnapShot}"
                                                        fi
                                                        # finally remove 
snapshot
                                                        if lvremove -f 
${SnapShot} >/dev/null 2>&1;then
                                                                logger "${0}: 
successfully removed outdated snapshot
${SnapShot}"
                                                        else
                                                                logger "${0}: 
***error*** - can not remove logical volume
${SnapShot}"
                                                        fi
                                                fi
                                        fi
                                else
                                        logger "${0}: ***error*** - 
snapshot-set #${CurrSnapSet} of snaphot
${SnapShot} is not configured"
                                fi
                        ;;

                        # to check periodical if the snapshots have to be 
resized
                        autoresize)
                                Parameters="--options lv_size,snap_percent 
--noheadings --nosuffix
--separator , --unbuffered --units m"
                                SnapState=$(lvs ${Parameters} ${SnapShot})
                                CurrSize=$(echo ${SnapState} | cut -f1 -d,)
                                FillPercet=$(echo ${SnapState} | cut -f2 -d,)
                                CurrFreeSize=$(echo 
"${CurrSize}-${CurrSize}/100*${FillPercet}" |
bc)

                                if ! [ $(echo "${CurrFreeSize} > ${FreeSize}" | 
bc) -eq 1 ]; then
                                        if lvresize -L +${ReSize}M ${SnapShot} 
>/dev/null 2>&1; then
                                                logger "${0}: successfully 
resized snapshot ${SnapShot}"
                                        else
                                                logger "${0}: ***error*** - an 
error occurred while resizing
${SnapShot}"
                                        fi
                                fi
                        ;;
                esac
        }


        # invoked if all snapshots of a volume are processed
        # arguments: Command
        # needs:     VolumeDevice, VolumePath, SnapSet & functions: DoSnap
        # provides:  SnapShot
        # local:     snapset_tmp, cmd
        function DoAllSnaps()
        {
                cmd=${1}
                [ -z "${SnapSet}" ] || snapset_tmp="${SnapSet}-"
                # checkout if the configured volume exists and is mounted
                if [ -b ${VolumeDevice} ]; then
                        if mount | grep -q "${VolumePath} "; then
                                # process all snapshots of the volume and, if 
given, of a specific
snapshot-set
                                for SnapShot in 
${VolumeDevice}-${snapset_tmp}*; do
                                        if [ ${SnapShot} = 
"${VolumeDevice}-${snapset_tmp}*" ]; then
                                                logger "${0}: ***error*** - no 
backupset #${SnapSet} found for
${VolumeDevice}"
                                        else
                                                DoSnap ${cmd}
                                        fi
                                done
                        else
                                logger "${0}: ***error*** - logical volume 
${VolumeDevice} not
mounted to ${VolumePath}"
                        fi
                else
                        logger "${0}: ***error*** - logical volume 
${VolumeDevice} does not
exist"
                fi
        }


        # creates a new snapshot and mounts it
        # arguments: na.
        # needs:     VolumeDevice, VolumePath, SnapSet, SnapSize, SnapDate &
functions: DoAllSnaps, DoSnap
        # provides:  SnapShot
        # local:     na.
        function MakeSnap ()
        {
                case ${SnapSet} in

                        [0-9])
                                if [ "${Command}" = "autosnap" ]; then 
DoAllSnaps "clean"; fi
                                SnapShot=${VolumeDevice}-${SnapSet}-${SnapDate}
                                if lvcreate -L${SnapSize}M -s -n 
${SnapShot##*/} ${VolumeDevice}
>/dev/null 2>&1; then
                                        logger "${0}: successfully created new 
snapshot ${SnapShot}"
                                else
                                        logger "${0}: ***error*** - an error 
occurred while creating
snapshot ${SnapShot}"
                                fi
                                DoSnap "mount"
                        ;;

                        *)
                                echo "usage: ${0} snap|autosnap <LV number | 
all> <Snap-Set Number>"
                        ;;
                esac
        }


        # sets some variables and splits the way for certain commands
        # arguments: one object of the array SnapVolumes
        # needs:     Command, & functions: DoAllSnaps MakeSnap
        # provides:  SnapVolume, VolumeDevice, PVGroupName, LVolumeName,
VolumePath, SnapSize, FreeSize, ReSize
        # local:     na.
        function SecondChoice ()
        {
                SnapVolume=${1}
                VolumeDevice=$(echo ${SnapVolume} | cut -f1 -d,)
                PVGroupName=$(echo ${VolumeDevice} | cut -f3 -d/)
                LVolumeName=$(echo ${VolumeDevice} | cut -f4 -d/)
                VolumePath=$(mount | grep  ^/dev[[:alnum:]/]*
${PVGroupName}.${LVolumeName}[\ ] | cut -f3 -d' ')
                SnapSize=$(echo ${SnapVolume} | cut -f2 -d,)
                FreeSize=$(echo ${SnapVolume} | cut -f3 -d,)
                ReSize=$(echo ${SnapVolume} | cut -f4 -d,)

                case ${Command} in

                        mount|umount|clean|autoresize)
                                DoAllSnaps ${Command}
                        ;;

                        snap|autosnap)
                                MakeSnap
                        ;;
                esac
        }


# decides if all configured volumes are processed or just a specific one
# arguments: na.
# needs:     Command, LVolume, SnapVolumes & functions: SecondChoice
# provides:  na.
# local:     snp
case ${Command} in

        mount|umount|snap|clean|autosnap|autoresize)
                case ${LVolume} in

                        all)
                                for snp in [EMAIL PROTECTED]; do
                                        SecondChoice ${snp}
                                done
                        ;;

                        [0-9])
                                if [ ${LVolume} -ge 0 ] && [ ${LVolume} -lt 
[EMAIL PROTECTED] ];
then
                                        SecondChoice ${SnapVolumes[LVolume]}
                                else
                                        logger "${0}: ***error*** - there is no 
configured logical volume #
${LVolume} for snapshots"
                                fi
                        ;;

                        *)
                        echo "usage: ${0} <command> <LV number | all> 
[<Snap-Set Number>]"
                        ;;
                esac
        ;;

        *)
                echo "usage: ${0} <command> <LV number | all> [<Snap-Set 
Number>]"
                echo
                echo "       valid commands are:"
                echo "       mount      - to mount snapshots"
                echo "       umount     - to unmount snapshots"
                echo "       snap       - to make a new snapshot"
                echo "       clean      - to cleanup outdated snapshots"
                echo "       autosnap   - normally used for cronjobs to cleanup"
                echo "                    outdates snapshots an create a new 
one"
                echo "       autoresize - for a periodical check if snapshots"
                echo "                    needs to be resized"
                echo
                echo "       <LV number> is the number of a logical volume, 
configured
for"
                echo "         snapshots in SnapVolumes, or simply 'all' for all
volumes"
                echo "       <Snap-Set Number> is the number of the 
snapshot-set,
configured"
                echo "         in SnapSet. It is optional, except for the 
commands
'snap' and"
                echo "         'autosnap'"
                echo
        ;;
esac


-- 
To unsubscribe from this list go to the following URL and read the
instructions:  https://lists.samba.org/mailman/listinfo/samba

Reply via email to