#!/bin/bash
# To restore a machine from backup-server

# Use: restore.sh server.fqdn mountpoint

SERV=$1
MNT=$2

if [ -z $MNT ] ; then
 echo Use: $0 server.fqdn mountpoint
 exit 1
fi

function ismounted() {
 MNT=$1
 mount | awk ' $3 == "'$MNT'" { print "OK" ; } ' | grep -q OK
}

function yesorno() {
 PROMPT=$1
 DEF=$2
 if echo $DEF | egrep -q -i Y ; then
  PROMPT="$PROMPT (Y/n)"
 fi
 if echo $DEF | egrep -q -i N ; then
  PROMPT="$PROMPT (y/N)"
 fi
 while [ "$A" != y ] && [ "$A" != Y ] && [ "$A" != n ] && [ "$A" != N ] ; do
  read -p "$PROMPT " -n 1 A
  echo 
  if [ -z $A ] ; then
   A=$DEF
  fi
 done
 [ "$A" = "y" ] || [ "$A" = "Y" ]
}

if ! ismounted $MNT ; then
 echo $MNT is not mounted: mount something there before continuing
fi

# Check to see that we have something to restore

STAMP=`ssh backup-server ls -lrtd /rsnapshots/*/$SERV/var/adm/backup/debconf | tail -1 | awk ' { print $6" "$7 ; } '`
if [ -z "$STAMP" ] ; then
 echo Cannot find any backups for $SERV - have you got the right name?
 exit 2
fi
DIR=`ssh backup-server ls -lrtd /rsnapshots/*/$SERV/var/adm/backup/debconf | tail -1 | awk ' { print $8 ; } '`
DIR=`echo $DIR | sed sZ$SERV/var/adm/backup/debconfZZ`

echo "Restoring from snapshot in $DIR taken at $STAMP"
if ! yesorno "Good to go?" "N" ; then
 echo Halting
 exit
fi

# Step 1: debootstrap the base system
debootstrap lenny $MNT
SSH="ssh -l root backup-server"
SCP="scp root@backup-server"
set -xv
# Step 1.5: copy existing password (and shadow) entries into the mount
# so that when packages see if their UIDs exist, we keep the same number
$SCP:$DIR/$SERV/etc/passwd $MNT/etc/passwd-old
$SCP:$DIR/$SERV/etc/shadow $MNT/etc/shadow-old
$SCP:$DIR/$SERV/etc/group  $MNT/etc/group-old
./fix-uids-and-gids.pl $MNT $MNT/etc/passwd-old $MNT/etc/passwd $MNT/etc/group-old $MNT/etc/group
for FILE in passwd shadow group ; do
 mv $MNT/etc/$FILE     $MNT/etc/$FILE-original
 mv $MNT/etc/$FILE-old $MNT/etc/$FILE
done

# Prepare the mount point for chrooting
mount -t proc proc $MNT/proc
# Install packages
$SSH "cd /etc && tar --numeric-owner -cf - apt " | (cd $MNT/etc && tar -xvf -)
# Copy the package list
$SCP:$DIR/$SERV/var/adm/backup/packages $MNT/tmp/packages
# Hacky way of ensuring that locales actually gets installed
echo locales >> $MNT/tmp/packages
# Copy the debconf database
$SCP:$DIR/$SERV/var/adm/backup/debconf $MNT/tmp/debconf
# Divert start-stop-daemon
chroot $MNT dpkg-divert --add /sbin/start-stop-daemon
# Preconfigure
chroot $MNT debconf-set-selections <$MNT/tmp/debconf
# Install the packages
chroot $MNT aptitude install udev `cat $MNT/tmp/packages`
# Cancel diversion
chroot $MNT dpkg-divert --remove /sbin/start-stop-daemon
# Restore MySQL
if $SSH [ -f $DIR/$SERV/var/adm/backup/mysql ] ; then
 echo -e Restoring MySQL database ... \\c
 chroot $MNT /etc/init.d/mysql start
 $SSH cat $DIR/$SERV/var/adm/backup/mysql | chroot $MNT mysql >/tmp/restore-$SERV-mysql.log 2>/tmp/restore-$SERV-mysql.err
 chroot $MNT /etc/init.d/mysql stop
 echo restored.
fi
# Restore Postgres
if $SSH [ -f $DIR/$SERV/var/adm/backup/postgres ] ; then
 STARTCMD=`(cd /mnt/etc/init.d/ ; ls postgres* )`
 echo -e Restoring Postgres database ... \\c
 chroot $MNT /etc/init.d/$STARTCMD start
 $SSH cat $DIR/$SERV/var/adm/backup/postgres | chroot $MNT su -c 'psql -f - template1' postgres >/tmp/restore-$SERV-postgres.log 2>/tmp/restore-$SERV-postgres.err
 chroot $MNT /etc/init.d/$STARTCMD stop
 echo restored.
fi
# Restore LDAP data
if $SSH [ -f $DIR/$SERV/var/adm/backup/ldap ] ; then
 echo -e Restoring SLAP data ... \\c
 chroot $MNT chsh -s /bin/bash openldap
 $SSH cat $DIR/$SERV/var/adm/backup/ldap | awk ' BEGIN { skip=2} NF == 0 && skip>0 { skip=skip-1 } skip==0 {print;} ' | chroot $MNT su -c slapadd openldap
 chroot $MNT chsh -s /bin/false openldap
 echo restored
fi
# Hmm: now we have to go through and adjust the ownership of all files:
# Restore the remainder of the files
$SSH "cd $DIR/$SERV && tar --numeric-owner -cf - ." | chroot $MNT tar --numeric-owner -xf - --exclude=./boot --exclude=./lib --exclude=./bin --exclude=./cdrom --exclude=./initrd* --exclude=./lost+found --exclude=./media --exclude=./mnt --exclude=./sbin --exclude=./selinux --exclude=./usr/bin --exclude=./usr/sbin --exclude=./vmlinuz\* --exclude=./var/lib/postgresql --exclude=./var/lib/mysql --exclude=./var/lib/dpkg --exclude=./var/lib/ldap --exclude=/etc/passwd
mv $MNT/etc/fstab $MNT/etc/fstab.manual
mv $MNT/etc/network/interfaces $MNT/etc/network/interfaces.manual
HN=`cat $MNT/etc/hostname`-rebuild
echo $HN >$MNT/etc/hostname
echo Creating a bare fstab - you might want to update this
cat <<EOF >$MNT/etc/fstab
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
/dev/sda1       /               ext3    defaults,errors=remount-ro 0       1
EOF
echo You will, no doubt, want to edit /etc/network/interfaces too.
if grep -q xen.independent_wallclock=1 /etc/sysctl.conf ; then 
 echo xen.independent_wallclock=1 >>$MNT/etc/sysctl.conf
fi

# Kill off all old processes
echo -e Killing any remaining processes in $MNT ... \\c
lsof $MNT | awk ' { print $2 ; } ' | sort -u | grep -v PID | xargs kill
echo killed.

# Umount /proc
echo -e Unmounting [proc] ... \\c
umount $MNT/proc
echo -e OK. $MNT ... \\c
umount $MNT
echo -e OK

