Save My VMs
So what about saving a whole VM and then you know, forget about it ?
Virtual Machines are the coolest thing in the.. data centre (after the actual cooling system). To add to it's refreshingness, a script that will can backup your virtual machines. For this script to work they need to be LVM based. You will also now need rsync
Use it, break it, mend it, distribute it, fork it. Just don't sell it or you will put a curse on your server and any VM it may contain (for as long as 3 generations).
Update/upgrade: We can rebuild it. We have the technology (rsync). We can make it better than it was. Better...stronger...faster. So yeah, now with rsync copies are a bit more optimal and the whole process is much faster (once your backups are already setup).
Direct download: Save My VMs v.0.2
#!/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