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.
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).
Direct download: Save My VMs v.0.1
#!/bin/bash
# save_my_vms.sh - Backup script for xen virtual machines
# Version 0.1.1
# (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 retention (in days)
DEFAULT_DAYS="3"
# default size of snapshot, unless it's crazy 10G is more than enough
SNAPSHOTSIZE="10G"
### VMs to save ###
# VMs settings (the important stuff)
# - space separated values
# - each VM to backup = unique ID, they don't have to follow
# - each VM should have: VM[id]="vmname" and LVMS[id]="partition1 partition2"
#
# example:
# VM[2]="name_of_vm"
# LVMS[2]="lvm-part1 lvm-part2"
# DAYS[2]="3" # optional, uses default if empty
### End of VMs ###
# Mail config
MAILDATE=$(date +%Y-%m-%d_%H:%M:%S)
SENDMAIL="/usr/lib/sendmail -t"
TO="wtbackup@example.com"
FROM="root@example.com"
SUBJECT="VM Backup ${MAILDATE} on `hostname -f`"
XMAILER="Save my VMs"
EMAIL="Save my VMs has (hopefully) done the following (correctly):\n"
# This is where things actualy happen
# for each VM
for INDEX in ${!VM[*]}; do
echo -e "\nVM: ${VM[$INDEX]}\t\tID: ${INDEX}"
echo "LVMS: ${LVMS[$INDEX]}"
EMAIL="${EMAIL}\n\n--> ${VM[$INDEX]} backup start: `date +%H:%M:%S`\n"
# Cleanup old backups
# define retention
if [[ ${DAYS[$INDEX]} -gt 0 ]]; then
RETENTION=${DAYS[$INDEX]}
else
RETENTION=$DEFAULT_DAYS
fi
echo "Keep data for $RETENTION days"
NOW=`date +%s`
for OLDDIR in `ls -1 ${BACKUPDIR}/${VM[$INDEX]}|cut -d "_" -f 1`; do
OLD=`date --utc --date $OLDDIR +%s`
DIFF=$(((NOW-OLD)/86400))
if [[ $DIFF -gt $RETENTION ]]; then
rm -rf ${BACKUPDIR}/${VM[$INDEX]}/${OLDDIR}*
fi
done
# Create a TMP dir for this VM
VMTMPDIR="${BACKUPDIR}/${VM[$INDEX]}/TMP"
mkdir -p ${VMTMPDIR}
# 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="${EMAIL}\n\t$LVM: `date +%H:%M:%S` start"
TMPLVM="${VM[$INDEX]}-${LVM}-BACKUP"
# create lvm snapshot
lvcreate -L${SNAPSHOTSIZE} -s -n ${TMPLVM} /dev/${LVGRP}/${LVM}
# create tmp dir to mount snapshot
TMPDIR="${VMTMPDIR}/${DATE}_${LVM}"
mkdir -p ${TMPDIR}
mount /dev/${LVGRP}/${TMPLVM} ${TMPDIR}
# create backup dir and copy data
LVMBACKUPDIR="${BACKUPDIR}/${VM[$INDEX]}/${DATE}/${LVM}"
mkdir -p ${LVMBACKUPDIR}
cp -a ${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="${EMAIL}\n\t$LVM: `date +%H:%M:%S` done\n"
done
# Remove TMP dir
rmdir ${VMTMPDIR}
EMAIL="${EMAIL}\n${VM[$INDEX]} backup done: `date +%H:%M:%S` <-"
done
# Send a little happy mail
echo -e "From: $FROM\nTo: $TO\nReply-To: $FROM\nSubject: $SUBJECT\nX-Mailer: $XMAILER\n$EMAIL" |$SENDMAIL
exit


rike
one should read the script just because of the funny comments :)