#!/bin/bash -eu
#set -x
# Backup Script
#label tapes, so overwriting not posible (tar --list | head -1) maybe
#tar --create --blocking-factor 128 --rsh-command=/usr/bin/ssh --verbose \
#       --file backup@diamond:/dev/nst0

partition=/srv/jade.backup
tapedev=/dev/nst0
remotehost=""
dump="/ /home /usr/local"
exclude='--exclude '/var/cache/swap' --exclude '/usr/local/vms/*' --exclude '/home/thomas/azureus/*' --exclude '/home/thomas/dvdrip/*''
nofind=no
mountpartition=yes

umask 066
hostname=`hostname | awk -F. '{print $1}'`
dateparms="+%Y%m%d-%H%M%S"
date=`date $dateparms`
remoteuser=backup
mailfrom="backupmaster@$hostname"
mailto="root@$hostname"

base=$partition/backup
lock=$base/$hostname-lock
rsyncstore="$base/rsync"
snaps="$base/snap"
findall="$base/findall"
logs="$base/log"
masterlog="$base/$hostname-master.log"

if [ `uname -a | grep -i linux | wc -l` -gt 0 ]; then
        sendmail=/usr/lib/sendmail
        mt=/bin/mt-gnu
        tar=/bin/tar
        rsync=/usr/bin/rsync
        gfind=/usr/bin/find
        gzip=/bin/gzip
        gunzip=/bin/gunzip
        ssh=/usr/bin/ssh
fi
if [ `uname -a | grep -i sunos | wc -l` -gt 0 ]; then
        sendmail=/usr/lib/sendmail
        mt=/bin/mt
        tar=/opt/csw/bin/gtar
        rsync=/opt/csw/bin/rsync
        gfind=/opt/csw/bin/gfind
        gzip=/opt/csw/bin/gzip
        gunzip=/opt/csw/bin/gunzip
        ssh=/opt/csw/bin/ssh
fi

tapeuri=$tapedev
if [ "$remotehost" != "" ]; then
       tapeuri="$remoteuser@$remotehost:$tapedev" 
       mt="ssh $remoteuser@$remotehost $mt"
fi

if [ `basename $0` = "nvs" ]; then
        $mt -f $tapedev offline
        echo "`date $dateparms` $hostname backup: $date $tapeuri offline" >> \
                        $masterlog
        sleep 30
        while true; do
                result=`$mt -f $tapedev status 2> /dev/null | tail -1 | \
                                grep -v DR_OPEN | grep -v WR_PROT | \
                                grep BOT | grep ONLINE | wc -l`
                if [ $result -eq 1 ]; then
                        echo -n "`date $dateparms` $hostname backup: " \
                                        >> $masterlog
                        echo "$date $tapeuri online" \
                                        >> $masterlog
                        sleep 30
                        exit
                fi
                sleep 300 #5min
        done
        exit 1
fi

if [ $# -lt 1 ]; then
        cmd=help
else
        cmd=$1
fi
case "$cmd" in
        cronwrapper)
                #Monthly Full, tape in last day of month
                #Weekly Incr, tape in each sunday night
                #Daily Incr, each morning to hd

                #m h dom mon dow user command
                #0 3 0   *   *   root /usr/local/bin/backup cronwrapper

                if [ `date +%d` = "01" ]; then
                        $0 rsync
                        $0 full
                        exit
                fi
                
                if [ `date +%w` = "1"  ]; then
                        $0 rsync
                        $0 weekly
                        exit
                fi
                
                $0 rsync
                exit ;;

        full)   backuptype=full   ;;
        weekly) backuptype=weekly ;;
        daily)  backuptype=daily  ;;
        rsync)  backuptype=rsync  ;;
        
        mp3)    dump="/srv/mp3"
                backuptype=full ;;

        preprmt)
                if [ ! -f /root/.ssh/id_dsa ]; then
                        ssh-keygen -t dsa -f /root/.ssh/id_dsa
                        ln -s /root/.ssh/id_dsa.pub /root/.ssh/identity.pub
                        ssh root@$remotehost "mkdir ~$remoteuser/.ssh && chown $remoteuser ~$remoteuser/.ssh && chmod 700 ~$remoteuser/.ssh"
                        ssh-copy-id  backup@$remotehost
                fi
                ssh $remoteuser@$remotehost hostname
                exit ;;

        maptape)
                $mt -f $tapedev rewind
                while [ `$mt -f $tapedev status | grep EOD | wc -l` -eq 0 ]; do
                        $tar --list --rsh-command=$ssh --verbose \
                                        --file $tapedev --blocking-factor 64 \
                                        | head -1
                        result=`$mt -f $tapedev status | grep EOD | wc -l`
                        if [ $result -eq 0 ]; then
                                $mt -f $tapedev fsf
                        fi
                done
                $mt -f $tapedev rewind
                exit ;;

        blanktape)
                echo -n "Blanking tape in drive: $tapeuri "
                echo "(10 seconds to abort with ctrl-c) "
                for c in `seq 1 10`; do
                        sleep 1
                        echo -n "."
                done
                $tar --create --blocking-factor 64 --directory=/ \
                                --rsh-command=$ssh --file $tapeuri dev/null
                echo "done."
                exit ;;

        writelabel)
                echo -n "Writing label: \"$2\" to tape in drive: $tapeuri "
                echo "(10 seconds to abort with ctrl-c) "
                for c in `seq 1 10`; do
                        sleep 1
                        echo -n "."
                done
                $mt -f $tapedev rewind
                echo "$2" > $tapedev
                echo "done."
                exit ;;

        readlabel)
                $mt -f $tapedev rewind
                cat $tapedev
                exit ;;
                
        oldlogs)
                #e.g. mv `backup oldlogs | xargs` /mnt/backup/backup/oldlogs/
                #Only for fsen in $dump
                for fs in $dump; do
                        fsname=`echo "$fs" | sed 's/\///g'`
                        if [ "$fsname" = "" ]; then
                                fsname="root"
                        fi

                        #rsync's older then last weekly
                        $gfind $logs/ -not -newer $logs/$hostname-$fsname-weekly.log.gz | grep $hostname-$fsname | grep rsync
                        #weeky's older than last full
                        $gfind $logs/ -not -newer $logs/$hostname-$fsname-full.log.gz   | grep $hostname-$fsname | grep weekly | grep -v $hostname-$fsname-weekly
                done
                exit ;;

        oldsnaps)
                #cd $snaps
                for fs in $dump; do
                        fsname=`echo "$fs" | sed 's/\///g'`
                        if [ "$fsname" = "" ]; then
                                fsname="root"
                        fi

                        #weeky's older than last full
                        $gfind $snaps/ -not -newer $snaps/$hostname-$fsname-full.snap | grep $hostname-$fsname | grep weekly | grep -v $hostname-$fsname-weekly
                done
                exit ;;

        verify) $tar --compare --blocking-factor 128 --directory=/ --multi-volume --file $tapeuri --rsh-command=$ssh; exit ;;
        
        restore) echo "$tar --extract --verbose --preserve-permissions --numeric-owner --label hostname-fs-date-type --rsh-command=$ssh --file $tapeuri --blocking-factor 64 --multi-volume --file $tapeuri (--listed-incremental=$snaps/hostname-fs-date-type.snap)"
                 exit ;;

        settings)
                echo "dump: $dump" 
                echo "remoteuser: $remoteuser" 
                echo "remotehost: $remotehost" 
                echo "tapedev: $tapedev" 
                echo "exclude: $exclude" 
                exit ;;

        *)      echo "Backup Usage: backup usage"
                echo "  cronwrapper - examine date and run correct backup type"
                echo "  full|weekly|daily|rsync - run specifyed backup type"
                echo "  mp3 - full mp3 backup to tape"
                echo "  preprmt - prepare rmt"
                echo "  maptape - list whats on a tape"
                echo "  blanktape - wipes tape in drive"
                echo "  writelabel- write label to tape in drive"
                echo "  readlabel- read label to tape in drive"
                echo "  oldlogs - prints list of old logs"
                echo "  oldsnaps - prints list of old snaps"
                echo "  verify - verify tape against disk"
                echo "  restore - restore information"
                echo "  settings - print local settings"
                exit 1 ;;
esac

if [ "$remotehost" == "" ]; then
        if [ ! -c $tapedev ]; then
                echo "$tapedev does not exist"
                exit 1
        fi
fi
if [ "$remotehost" != "" ]; then
        if ssh $remoteuser@$remotehost [ ! -c $tapedev ]; then
                echo "$remoteuser@$remotehost:$tapedev does not exist"
                exit 1
        fi
fi

if [ "$backuptype" == "full" \
                -o "$backuptype" == "weekly" \
                -o "$backuptype" == "daily" ]; then
        if [ "$tapedev" == "" ]; then
                exit
        fi
        status=`$mt -f $tapedev status 2> /dev/null | tail -1 | grep -v DR_OPEN | grep -v WR_PROT | grep BOT | grep ONLINE | wc -l`
        if [ $status -ne 1 ]; then
                echo "$tapeuri not ready"
                exit 1
        fi
fi

if [ "`mount | grep $partition | wc -l | awk '{print $1}'`" = "0" ]; then
        mount $partition
fi

if [ -f $lock ]; then
        echo "$lock exists, backup allready running or backup premeturly died?"
        exit 1
fi
touch $lock

if [ -f $snaps/$hostname-current.snap ]; then
        echo "$snaps/$hostname-current.snap exists, backup allready runing?"
        exit 1
fi

case "$backuptype" in
        full)   $mt -f $tapedev rewind ;;
        weekly) $mt -f $tapedev eom ;;
        daily)  $mt -f $tapedev eom ;;
esac

for dir in $base $rsyncstore $snaps $logs $findall; do
        if [ ! -d $dir ]; then
                mkdir -p $dir
        fi
done

echo $date >> $base/$hostname-parttable
fdisk -l   >> $base/$hostname-parttable

if [ "$nofind" != "yes" ]; then
        $gfind / -printf "%p %s\n" | $gzip > $findall/$hostname-$date.gz
fi
cp $0 $base/$hostname-`basename $0`

echo "`date $dateparms` $hostname backup: $date $backuptype started" >> \
                $masterlog
backupstatus=""
for fs in $dump; do
        fsname=`echo "$fs" | sed 's/\///g'`
        if [ "$fsname" = "" ]; then
                fsname="root"
        fi

        label=$hostname-$fsname-$date-$backuptype
        snap=$snaps/$label.snap
        log=$logs/$label.log

        tarparms="--create --listed-incremental=$snaps/$hostname-current.snap --file $tapeuri --rsh-command=$ssh --multi-volume --new-volume-script=nvs --blocking-factor 128 --record-size=262144 --label=$label --directory=$fs $exclude --one-file-system --verbose "
        rsyncparms="-vaux --delete $exclude"

        echo "`date $dateparms` $hostname backup: $date $backuptype $fs" >> $masterlog

        case "$backuptype" in
                full)   rm -f $snaps/$hostname-$fsname.full.snap ;;
                weekly) cp $snaps/$hostname-$fsname-full.snap \
                                        $snaps/$hostname-current.snap ;;
                daily)  cp $snaps/$hostname-$fsname-weekly.snap \
                                        $snaps/$hostname-current.snap ;;
        esac
        
        set -f #turn off globbing for excludes
        set +e #want to catch return vars
        case "$backuptype" in
                full)   $tar $tarparms $fs &> $log ;;
                weekly) $tar $tarparms $fs &> $log ;;
                daily)  $tar $tarparms $fs &> $log ;;
                rsync)  mkdir -p $rsyncstore/$hostname.$fsname || true
                        $rsync $rsyncparms $fs $rsyncstore/$hostname.$fsname \
                                        &> $log ;;
        esac
        backupstatus="$backupstatus $fsname=$?\n"
        set -e
        set +f

        $gzip $log
        cp $log.gz $logs/$hostname-$fsname-$backuptype.log.gz
        if [ "$backuptype" != "rsync" ]; then
                mv $snaps/$hostname-current.snap $snap
                cp $snap $snaps/$hostname-$fsname-$backuptype.snap
        fi

        echo "`date $dateparms` $hostname backup: $date $backuptype $fs done" \
                        >> $masterlog
done

if [ "$backuptype" = "full" -o "$backuptype" = "weekly" ]; then
        label=$hostname-$date-$backuptype
        log=$logs/$label.log
        tarparms="--create --file $tapeuri --blocking-factor 64 --label=$label --directory=$base --one-file-system --verbose"

        echo "`date $dateparms` $hostname backup: $date $backuptype meta" \
                        >> $masterlog
        $tar $tarparms $snaps $findall $logs $masterlog &> $log || true
        echo "`date $dateparms` $hostname backup: $date $backuptype meta done" \
                        >> $masterlog

        $mt -f $tapedev offline
fi
echo "`date $dateparms` $hostname backup: $date $backuptype finished" >> \
                $masterlog

df=`df -h $base | tail -1`
mail=/tmp/backup.$date.$$
cat << EOF > $mail
From: $mailfrom
To: $mailto
Subject: Backup Completed
MIME-Version: 1.0
Content-Disposition: inline
Content-Type: Multipart/Mixed;
  boundary="Boundary-00=_aOVpAKnX+Ugowa1"


--Boundary-00=_aOVpAKnX+Ugowa1
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Subject: 

Host: $hostname, Date: $date, Type: $backuptype
Device: `echo $df | awk '{print $1}'`, Size: `echo $df | awk '{print $2}'`, Used: `echo $df | awk '{print $3}'`, Avail: `echo $df | awk '{print $4}'`, Use%: `echo $df | awk '{print $5}'`
Backup Status:
`echo -en "$backupstatus"`

Master Log:
`cat $masterlog | grep $date`

Errors:
`$gunzip -c $logs/$hostname-*-$date-$backuptype.log.gz | grep "^tar:" | grep -v "Directory is new$" | grep -v "Directory has been renamed$" | grep -v "socket ignored$" | grep -v "from member names$" | head -1000`

EOF

for fs in $dump; do
        fsname=`echo "$fs" | sed 's/\///g'`
        if [ "$fsname" = "" ]; then
                fsname="root"
        fi

        label=$hostname-$fsname-$date-$backuptype
        logfilename=$label.log
        logfile=$logs/$label.log.gz

        cat << EOF >> $mail
--Boundary-00=_aOVpAKnX+Ugowa1
Content-Type: text/plain;
  charset="us-ascii";
  name="$logfilename"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="$logfilename"

`$gunzip -c $logfile`

EOF
done

echo -en "--Boundary-00=_aOVpAKnX+Ugowa1\n\n" >> $mail

cat $mail | $sendmail $mailto
rm -f $mail
rm -f $lock

if [ "$mountpartition" == "yes" ]; then
        $(
        while [ "`mount | grep $partition | wc -l | awk '{print $1}'`" = "1" ]; do
                umount $partition || true
                sleep 1
        done ) &
fi

