#!/bin/sh

# virt-backup script, version 0.7.1
# (c) 2008-2009 Jan ONDREJ (SAL) <ondrejj(at)salstar.sk>
# Lincensed under GPLv2+

SOURCE_VG="vg1"
TARGET_VG="vg1"
ROOT_VS="xen2"
BACKUP_VS="backup@$ROOT_VS"
SNAP_SIZE="10g"
EXCLUDE="--exclude BACKUP/OLD"
DD_PARAMS="bs=10485760"
RSYNC="rsync -aHe ssh --delete-before --numeric-ids"
PATH="$PATH:/sbin:/usr/sbin"
export LANG=C
if [ "$TERM" = "dumb" ]; then
  # more quiet in cron
  PV="" # leave empty, set later
  LOGFILE="/var/log/xen/backup.log"
  debug() {
    echo "`date`: $@" >> $LOGFILE
  }
else
  RSYNC="$RSYNC -vP"
  PV="pv --size"
  LOGFILE="/dev/tty" # log to stdout
  debug() {
    echo "$@"
  }
fi

modprobe dm-snapshot 2>/dev/null

configbackup() {
  CONFIG_BACKUP_DONE=1
  debug "Local config backup."
  $RSYNC --no-times /etc $BACKUP_VS: --no-progress -q >> $LOGFILE 2>&1
}

start_snap() {
  # Usage: start_snap virt_machine vg_disk

  # try to backup config, if it has been not done
  if [ -z "$CONFIG_BACKUP_DONE" ]; then
    configbackup
  fi

  if [ -x /usr/sbin/xm ]; then
    # sync disks
    xm sysrq $1 s
    # pause xen host
    xm pause $1
    # sync disks
    xm sysrq $1 s
  fi
  sync
  # create snapshot
  lvcreate --autobackup n --quiet -s --size $SNAP_SIZE \
           --name snap /dev/$SOURCE_VG/$2 >> $LOGFILE 2>&1
  if [ -x /usr/sbin/xm ]; then
    # unpause domain
    xm unpause $1
  fi
}

stop_snap() {
  # remove snapshot
  umount /mnt/snap >/dev/null 2>&1 || true
  loopdev="`losetup -a | grep /dev/[a-z0-9]*/snap | cut -d: -f1`"
  [ "$loopdev" ] && losetup -d "$loopdev"
  lvremove --autobackup n --quiet -f /dev/$SOURCE_VG/snap >> $LOGFILE 2>&1
}

backup() {
  # backup virt_machine vg_disk
  start_snap $1 $2
  debug "Full backup for /dev/$SOURCE_VG/$2 using dd"
  # get image size
  TARGET="/dev/mapper/$TARGET_VG-$2"
  if [ "$PV" ]; then
    img_size=`lvs /dev/$SOURCE_VG/$2 --noheadings -o lv_size --units b | tr -d "B "`
    PVCMD="$PV $img_size"
  else
    PVCMD="cat"
  fi
  dd if=/dev/$SOURCE_VG/snap $DD_PARAMS 2>/dev/null \
    | $PVCMD \
    | ssh $BACKUP_VS "dd of=$TARGET $DD_PARAMS 2> /dev/null"
  stop_snap
}

rsdisk() {
  # rsdisk virt_machine vg_disk
  start_snap $1 $2
  debug "Disk backup for /dev/$SOURCE_VG/$2 using rsync"
  mkdir -p /mnt/snap
  umount /mnt/snap 2>/dev/null || true
  mount -r /dev/$SOURCE_VG/snap /mnt/snap
  ssh $ROOT_VS "mkdir -p /mnt/$2; mount /mnt/$2 2>/dev/null \
                || mount /dev/$TARGET_VG/$2 /mnt/$2"
  $RSYNC /mnt/snap/ $ROOT_VS:/mnt/$2/ $EXCLUDE >> $LOGFILE 2>&1
  ssh $ROOT_VS umount /mnt/$2
  umount /mnt/snap
  stop_snap
}

rspart() {
  # rspart virt_machine vg_disk part1 [part2 ...]
  disk="$2"
  start_snap $1 $disk
  debug "Partition backup for /dev/$SOURCE_VG/$2 using rsync"
  shift 2
  mkdir -p /mnt/snap
  umount /mnt/snap 2>/dev/null || true
  for part in "$@"; do
    # mount local partition
    lomount -diskimage /dev/$SOURCE_VG/snap -partition $part /mnt/snap
    # mount remote partition, skip on fail
    ssh $ROOT_VS lomount -diskimage /dev/$TARGET_VG/$disk -partition $part \
        /mnt/$disk$part || break
    # rsync data
    $RSYNC /mnt/snap/ $ROOT_VS:/mnt/$disk$part/ $EXCLUDE >> $LOGFILE 2>&1
    # umount remote partition
    ssh $ROOT_VS umount /mnt/$disk$part
    # umount local partition
    umount /mnt/snap
  done
  stop_snap
}

fsbackup() {
  # fsdump virt_machine vg_disk part1 [part2 ...]
  disk="$2"
  start_snap $1 $disk
  debug "Partition backup for /dev/$SOURCE_VG/$2 using partimage"
  shift 2
  mkdir -p /mnt/snap
  umount /mnt/snap 2>/dev/null || true
  delim="__virt-backup__"
  for part in "$@"; do
    # create access to local partition
    kpartx -a -p $delim /dev/$SOURCE_VG/snap
    # kpartx remote partition
    ssh $ROOT_VS "kpartx -a -p $delim /dev/$TARGET_VG/$disk"
    # partimage data
set -x
sleep 1m
    /usr/sbin/partimage --allowmnt -b -d -B gui=no save \
          /dev/mapper/snap$delim$part stdout \
      | ssh $BACKUP_VS \
          "TERM=$TERM /usr/sbin/partimage -b -B gui=no restore /dev/mapper/$disk$delim$part stdin"
set +x
    # umount remote partition
    ssh $ROOT_VS "kpartx -d -p $delim /dev/$TARGET_VG/$disk"
    # umount local partition
    kpartx -d -p $delim /dev/$SOURCE_VG/snap
  done
  stop_snap
}

if [ "$1" ]; then
  . $1
else
  . /etc/sysconfig/virt-backup
fi

#backup stats stats_hda
#backup voip voip_hda
#backup webmail webmail_hda
#backup kecom kecom_hda
#backup kecom kecom_home
#fsbackup vpn vpn_hda 1
#rsdisk ns1 www1_home
#rspart ns1 www1_var 1
