#!/bin/bash

#   save_my_vms.sh - Backup script for xen virtual machines that use LVM
#   Version 0.2
#   (c) 2011 Emmanuel Revah - manu-at-manurevah.com

#   This script makes snapshots of Xen virtual machines, mounts them
#	and then copies their content to a backup directory on Dom0
#   You should test this script before using it, as always.
#	I WILL NOT BE RESPONSIBLE FOR ANY OF YOUR FUTURE MISFORTUNES.

#   This is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   save_my_vms.sh is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with save_my_vms.sh.  If not, see <http://www.gnu.org/licenses/>.


##################
# General config #
##################

# LVM group to use (later on in life might be added to per VM setting)
LVGRP="vga"

# global backup dir
BACKUPDIR="/home/backups"

# default number of copies the backup should reatain
DEFAULT_COPIES="3"

# default size of LVM snapshots, unless your systems read/write like crazy 10G should be more than enough
SNAPSHOTSIZE="10G"


###############
# VMs to save #
###############

# VMs settings (the important stuff):
#
#	- The configuration of VMs to backup uses arrays, so each VM should have a unique
#	  ID (that would be the number in the square brackets).
#	- VM:is the name you want to use to refer to the VM, it will become the name of the directory
#	  in which its backups are stored. Don't use spaces and other weird stuff, unless you like breakage.
#	- LVMS: are the names of the LVM partitions associated with the VM. These should be
#	  in /dev/$LVGRP/. You can add as many LVM partitions that should be backed up.
#	  Values should be space separated.
#	- COPIES: the amount of copies to keep. Every time you run the script a new copy is made.
#
# example:
# VM[2]="name_of_vm"
# LVMS[2]="vm-part1 vm-part2"
# COPIES[2]="3" # optional, uses default value of DEFAULT_COPIES if undefined


###############
# Mail config #
###############

TO="wtbackup@example.com"
FROM="root@example.com"

MAILDATE=$(date +%Y-%m-%d_%H:%M:%S)
SUBJECT="VM Backup ${MAILDATE} on `hostname -f`"
SENDMAIL="/usr/lib/sendmail -t"
XMAILER="Save my VMs"

### End of config ###


EMAIL="Save my VMs has (hopefully) done the following (correctly):"

# This is where things actually happen

# for each VM
for INDEX in ${!VM[*]}; do

	echo -e "\nVM: ${VM[$INDEX]}\t\tID: ${INDEX}"
	echo "LVMS: ${LVMS[$INDEX]}"
	EMAIL+="\n\n\n--> ${VM[$INDEX]} backup start: `date +%H:%M:%S`\n"

	# New report for each VM
	REPORT="Backup report for ${VM[$INDEX]} using 'save_my_ms.sh' on `date +%Y-%m-%d_%H:%M:%S`:"
	REPORT+="\n\n-> backup start: `date +%H:%M:%S`\n"

	# define retention
	if [[ ${COPIES[$INDEX]} -gt 0 ]]; then
		RETENTION=${COPIES[$INDEX]}
	else
		RETENTION=$DEFAULT_COPIES
	fi
	echo "Keep $RETENTION copies"


	# Move backups - Copy backups from previous... .. I mean.. .
	BACKUP_NUMBER=$RETENTION
	while [[ ${BACKUP_NUMBER} -gt 0  ]]; do
		BACKUP_PREV_NUMBER=`expr ${BACKUP_NUMBER} - 1`
		mkdir -p ${BACKUPDIR}/${VM[$INDEX]}/backup_${BACKUP_NUMBER}/
		rsync -avu --delete ${BACKUPDIR}/${VM[$INDEX]}/backup_${BACKUP_PREV_NUMBER}/ ${BACKUPDIR}/${VM[$INDEX]}/backup_${BACKUP_NUMBER}/
		BACKUP_NUMBER=`expr ${BACKUP_NUMBER} - 1`
	done


	# Create a TMP dir for this VM
	VMTMPDIR="${BACKUPDIR}/${VM[$INDEX]}/TMP"


	# For each LVM
	for LVM in ${LVMS[$INDEX]}; do

		DATE=$(date +%Y-%m-%d_%H-%M-%S)
		echo -e "\n  --> Backup $LVM date: ${DATE}.. ."
		EMAIL+="\n\t$LVM: `date +%H:%M:%S` start"
		REPORT+="\n\t$LVM: `date +%H:%M:%S` start"

		# create lvm snapshot
		TMPLVM="${VM[$INDEX]}-${LVM}-BACKUP"
		lvcreate -L${SNAPSHOTSIZE} -s -n ${TMPLVM} /dev/${LVGRP}/${LVM}

		# create tmp dir to mount snapshot
		TMPDIR="${VMTMPDIR}/${LVM}"
		mkdir -p ${TMPDIR}
		mount /dev/${LVGRP}/${TMPLVM} ${TMPDIR}

		# create backup dir and copy data
		LVMBACKUPDIR="${BACKUPDIR}/${VM[$INDEX]}/backup_0/${LVM}"
		mkdir -p ${LVMBACKUPDIR}
		ionice -c 3 rsync -avu --delete ${TMPDIR}/ ${LVMBACKUPDIR}/

		# umount and remove tmp dir and snapshot
		umount ${TMPDIR}
		rmdir ${TMPDIR}
		lvremove -f /dev/${LVGRP}/${TMPLVM}
		echo -e "  . ..Backup $LVM done <--\n"
		EMAIL+="\n\t$LVM: `date +%H:%M:%S` done\n"
		REPORT+="\n\t$LVM: `date +%H:%M:%S` done\n"

	done

	# Remove TMP dir
	rmdir ${VMTMPDIR}

	EMAIL+="\n${VM[$INDEX]} backup done: `date +%H:%M:%S` <-"
	REPORT+="\n${VM[$INDEX]} -> backup done: `date +%H:%M:%S`"

	# Post report (per VM)
	echo -e "${REPORT}" > ${BACKUPDIR}/${VM[$INDEX]}/backup_0/Backup_report
done

# Send email
echo -e "From: $FROM\nTo: $TO\nReply-To: $FROM\nSubject: $SUBJECT\nX-Mailer: $XMAILER\n$EMAIL" |$SENDMAIL


exit

