#!/bin/bash # # Backup VM # if [ $# -ne 1 ]; then echo "Usage for $0 : VM Name required as argument." exit 1 fi # if [ $UID -eq 0 ]; then echo "This script should NOT be run as root." exit 1 fi # # Source config file if [ ! -f ~/.vbconfig ]; then echo "Config File ~/.vbconfig not found!" echo "Run: set-folders to create .vbconfig" exit 1 fi . ~/.vbconfig # VB_VM_NAME=$1 # # Configuration parameters # # Backup Type # offline first takes the VM to savestate before backup # online does a live backup # offline is faster, safer but has slight downtime # online is slower but keeps system live #VB_VM_BACKUP_TYPE="online" # Or offline VB_VM_BACKUP_TYPE="offline" # # Fix number of levels of Backup # 2 Levels are minimal and sufficient # 3 is Optimal but you can have as many as desired VB_VM_MAX_LEVEL=3 # # Indicate snapshot name prefix. # Create multiple sets by changing LEVELNAME LEVELNAME="Level" # VB_VM_BUSY_CHK="Y" # or N # # Begin Backup processing # VM_POWERED_ON=`VBoxManage list runningvms|grep -c '^"'${VB_VM_NAME}'"'` if [ $VM_POWERED_ON -eq 0 ]; then echo "Non-running VMs don't require snapshot for backups. Exiting." exit fi # # Check if VM is idle or busy if [[ $VB_VM_BUSY_CHK == "Y" ]]; then VM_STATE=`$VB_BIN_LOC/400-busy-chk-vm.bash $VB_VM_NAME` if [[ $VM_STATE == "busy" ]]; then echo "VM is busy. Not doing shapshot. Exiting." exit 1 fi fi # # Backup Day of Week, Date, Moth # Day of Week (e.g. Sunday) VB_VM_BK_DOW="Sunday" # Date of the Month (e.g. 16th) VB_VM_BK_DOM="16" # Date and Month of the Year (e.g. 25th, November) VB_VM_BK_DOY="25" VB_VM_BK_MOY="11" # if [ $VB_VM_BK_DOM -eq $VB_VM_BK_DOY ]; then echo "Warning:" echo "Montly backup date is same as Yearly date" echo "Avoid the same date to NOT skip one" echo "Monthly backup each year" fi # # Start with the smallest incremental backup # # For daily backups VB_VM_BACKUP_LEVEL=$VB_VM_MAX_LEVEL # # For weekly backups (Sunday) dayofweek=`date +"%A"` if [[ $VB_VM_MAX_LEVEL -gt 1 ]]; then if [[ $dayofweek == $VB_VM_BK_DOW ]]; then let VB_VM_BACKUP_LEVEL=$VB_VM_MAX_LEVEL-1 fi fi # # For monthly backups (16th day) daynumber=`date +"%d"` if [[ $VB_VM_MAX_LEVEL -gt 2 ]]; then if [[ $daynumber == $VB_VM_BK_DOM ]]; then let VB_VM_BACKUP_LEVEL=$VB_VM_MAX_LEVEL-2 fi fi # For yearly backups (Nov 25th) # Annual will only kick in if we have VB_VM_MAX_LEVEL > 3 if [[ $VB_VM_MAX_LEVEL -gt 3 ]]; then if [[ $daynumber == $VB_VM_BK_DOY ]]; then monthnumber=`date +"%m"` if [[ $monthnumber == $VB_VM_BK_MOY ]]; then let VB_VM_BACKUP_LEVEL=$VB_VM_MAX_LEVEL-3 fi fi fi # Check to make sure VB_VM_MAX_LEVEL is not set too low # Alternatively remove higher level options (yearly) if [ $VB_VM_BACKUP_LEVEL -lt 1 ]; then echo "Config error. Inc Max Level" exit 1 fi # # Check current Snapshot Level # There should always be all level from 1 to VB_VM_MAX_LEVEL CUR_SS=`VBoxManage snapshot "${VB_VM_NAME}" list --machinereadable \ | grep CurrentSnapshotName|cut -d"\"" -f2` MAX_SS=${LEVELNAME}_${VB_VM_MAX_LEVEL} if [[ $MAX_SS != $CUR_SS ]]; then # Max Level does not exit in SS. This may be the 1st run, so reset echo "Detecting 1st run ..." VB_VM_BACKUP_LEVEL=1 else echo "At Level $VB_VM_BACKUP_LEVEL / $VB_VM_MAX_LEVEL" fi # # Save State if [[ $VB_VM_BACKUP_TYPE == "offline" ]]; then echo "Sending VM to savestate ..." VBoxManage controlvm "${VB_VM_NAME}" savestate fi # echo "Deleting (Merging) Old snapshots ..." for i in $(eval echo "{${VB_VM_MAX_LEVEL}..${VB_VM_BACKUP_LEVEL}..-1}") do SS_NAME=${LEVELNAME}_${i} # Ignore errors with delete on use the redirect to prevent display #VBoxManage snapshot "${VB_VM_NAME}" delete $SS_NAME 2> /dev/null SS_EXISTS=`VBoxManage snapshot "${VB_VM_NAME}" list|grep -c "Name: ${SS_NAME} "` if [ $SS_EXISTS -gt 0 ]; then echo "Deleting snapshot $SS_NAME ..." VBoxManage snapshot "${VB_VM_NAME}" delete $SS_NAME else echo "Snapshot $SS_NAME to be deleted does not exist!" fi done # echo "Taking New snapshots ..." for i in $(eval echo "{${VB_VM_BACKUP_LEVEL}..${VB_VM_MAX_LEVEL}}") do SS_NAME=${LEVELNAME}_${i} echo "Taking snapshot $SS_NAME ..." VBoxManage snapshot "${VB_VM_NAME}" take $SS_NAME --live done # if [[ $VB_VM_BACKUP_TYPE == "offline" ]]; then echo "Powering VM back on ..." VBoxManage startvm "${VB_VM_NAME}" --type headless fi # exit