├── README ├── snapback-xva.sh └── snapback.sh /README: -------------------------------------------------------------------------------- 1 | Xenserver snapshot and template based backup script 2 | https://github.com/markround/XenServer-snapshot-backup 3 | Mark Round, github@markround.com 4 | 5 | This README was copied from the text at http://www.markround.com/snapback 6 | 7 | Please visit this page for the full HTML version of the README, along with 8 | screenshots which may make this a little clearer! 9 | 10 | We have recently started using Citrix Xenserver in 11 | production at work (fantastic product, see my review at 12 | http://www.markround.com/archives/63-Citrix-XenServer-5.6-Review.html for 13 | more information) and needed a simple backup solution. Our VMs run from an 14 | iSCSI SAN and are backed up daily through various methods - e.g. Bacula for 15 | the Unix/Linux systems. However, we wanted the ability to quickly roll back 16 | to a previous VM snapshot, and get up and running quickly if our SAN failed 17 | for whatever reason. 18 | 19 | Our solution was to create a large shared NFS storage repository, and 20 | periodically snapshot VMs and copy the templates over to this SR. Doing 21 | this means that if the SAN fails, we can create a new VM quickly from this 22 | NFS store (using the Xenserver's local disks, or even the NFS SR itself as 23 | storage). Once up and running, we can bring VMs back up to date by restoring 24 | the latest backup to them. 25 | 26 | In order to automate this, I wrote a quick script which I thought may prove 27 | useful to someone else, so decided to post it here. 28 | 29 | It is very simple, and although it may serve well as your only backup 30 | solution, it's really intended as an image-level compliment to your primary 31 | file-system based backup system such as Bacula, Amanda, Netbackup etc. It 32 | also has not had much testing, and I fully appreciate the scripting is pretty 33 | rudimentary and could do with some optimisation - there's no error checking, 34 | for instance. I kept it pretty verbose on purpose though, so you can get a 35 | good idea of exactly what it's doing at each step; it may be better to think 36 | of this as a template you can base your own scripts off! 37 | 38 | * Note * There is now a snapback-xva.sh script, which has modifications by 39 | Luis Davim, which support the creation of additional XVA snapshots on 40 | an independant schedule. This is a great addition to the script, but as it 41 | may not be suitable for all users, it's included as a separate script. 42 | Thanks, Luis! 43 | 44 | Overview 45 | ======== 46 | 47 | The script creates a snapshot of a running VM on a configurable schedule, 48 | and then creates a template from this snapshot. It will copy all these 49 | backup templates over to a configurable storage repository, and then clean 50 | up any old backups according to a specified retention policy. These backups 51 | are full backups, so if you have a 10GB VM and keep 7 previous copies you 52 | will need a total of 80GB disk space on your backup VM. Non-running VMs, 53 | and those not configured (as detailed below) will be skipped. 54 | 55 | Important: See http://support.citrix.com/article/CTX123400. After backing 56 | up each VM, you will end up with a new VDI, so you may need to manually 57 | coalesce your VDIs again to reclaim disk space. This appears to have been 58 | fixed in 5.6FP1, however. 59 | 60 | Installation and usage 61 | ===================== 62 | 63 | First, copy the script to your Xenserver pool master, and make it executable. A 64 | good location for this is 65 | 66 | /usr/local/bin/snapback.sh. 67 | 68 | Next, create a cron entry for the script - to make it run daily just after 69 | 1AM, you'd create /etc/cron.d/backup with the following contents : 70 | 71 | 2 1 * * * root /usr/local/bin/snapback.sh > /var/log/snapback.log 2>&1 72 | 73 | This will also record a log of it's actions to /var/log/snapback.log. You 74 | now need to edit the script and change the DEST_SR variable to the UUID 75 | of your backup storage repository. You can find this value by clicking 76 | on the SR in Xencenter; the UUID will be displayed as a value like 77 | "2c01dc26-f525-70d6-dedf-00baaec76645". 78 | 79 | Lastly, you need to configure your backup and retention policy for your VMs. In 80 | Xencenter, right click your VM, and select "Properties". Click on "Custom 81 | Fields", and then "Edit Custom Fields". You should add two text fields : 82 | 83 | 84 | backup : Can be one of "daily", "weekly", or "monthly". If it is set to 85 | weekly, it will by default run on a Sunday, and if it set to monthly, it 86 | will run on the first Sunday of the month. This day can be changed at the 87 | top of the script - see the WEEKLY_ON and MONTHLY_ON variables. 88 | 89 | retain : How many previous backups (in addition to the currently running 90 | backup) to keep. So, setting this to a value of "2" would mean that after 91 | a backup has run, you would end up with 3 backups in total. 92 | 93 | 94 | The script will look for these fields when it is run, and will skip any VM 95 | that doesn't have them set. You can also see them in the Xencenter summary 96 | and properties for the VM. 97 | 98 | You can now either run the script manually, or wait until the cron job 99 | kicks off. It will produce a detailed log to the console (or log file if 100 | run through cron), and when it's finished, you'll see your template backup 101 | VMs listed in Xencenter. 102 | 103 | If you find that this clutters up the Xencenter view a little, you can always 104 | hide them (View->Server View->Custom Templates). 105 | 106 | To restore a VM from a backup, just right click, and choose "New template 107 | from backup". Anyway, I hope this helps someone else! 108 | 109 | -------------------------------------------------------------------------------- /snapback-xva.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # snapback.sh 1.4 3 | # Simple script to create regular snapshot-based backups for Citrix Xenserver 4 | # Mark Round, scripts@markround.com 5 | # http://www.markround.com/snapback 6 | # 7 | # 1.4 : Modifications by Luis Davim to support XVA backups with independent scheduling 8 | # 1.3 : Added basic lockfile 9 | # 1.2 : Tidied output, removed VDIs before deleting snapshots and templates 10 | # 1.1 : Added missing force=true paramaters to snapshot uninstall calls. 11 | 12 | # 13 | # Variables 14 | # 15 | 16 | # Temporary snapshots will be use this as a suffix 17 | SNAPSHOT_SUFFIX=snapback 18 | # Temporary backup templates will use this as a suffix 19 | TEMP_SUFFIX=newbackup 20 | # Backup templates will use this as a suffix, along with the date 21 | BACKUP_SUFFIX=backup 22 | # What day to run weekly backups on 23 | WEEKLY_ON="Sun" 24 | # What day to run monthly backups on. These will run on the first day 25 | # specified below of the month. 26 | MONTHLY_ON="Sun" 27 | # Temporary file 28 | TEMP=/tmp/snapback.$$ 29 | # UUID of the destination SR for backups 30 | TEMPLATE_SR=81548d46-4f0e-fada-927c-e2177eb49943 31 | # UUID of the destination SR for XVA files it must be an NFS SR 32 | XVA_SR=557dec09-333c-37be-6c1f-0e6d787b905a 33 | 34 | LOCKFILE=/tmp/snapback.lock 35 | 36 | #Cicle control flags 37 | SKIP_TEMPLATE=1 38 | SKIP_XVA=1 39 | 40 | if [ -f $LOCKFILE ]; then 41 | echo "Lockfile $LOCKFILE exists, exiting!" 42 | exit 1 43 | fi 44 | 45 | touch $LOCKFILE 46 | 47 | # 48 | # Don't modify below this line 49 | # 50 | 51 | # Date format must be %Y%m%d so we can sort them 52 | BACKUP_DATE=$(date +"%Y%m%d") 53 | 54 | # Quick hack to grab the required paramater from the output of the xe command 55 | function xe_param() 56 | { 57 | PARAM=$1 58 | while read DATA; do 59 | LINE=$(echo $DATA | egrep "$PARAM") 60 | if [ $? -eq 0 ]; then 61 | echo "$LINE" | awk 'BEGIN{FS=": "}{print $2}' 62 | fi 63 | done 64 | } 65 | 66 | # Deletes a snapshot's VDIs before uninstalling it. This is needed as 67 | # snapshot-uninstall seems to sometimes leave "stray" VDIs in SRs 68 | function delete_snapshot() 69 | { 70 | DELETE_SNAPSHOT_UUID=$1 71 | for VDI_UUID in $(xe vbd-list vm-uuid=$DELETE_SNAPSHOT_UUID empty=false | xe_param "vdi-uuid"); do 72 | echo "Deleting snapshot VDI : $VDI_UUID" 73 | xe vdi-destroy uuid=$VDI_UUID 74 | done 75 | 76 | # Now we can remove the snapshot itself 77 | echo "Removing snapshot with UUID : $DELETE_SNAPSHOT_UUID" 78 | xe snapshot-uninstall uuid=$DELETE_SNAPSHOT_UUID force=true 79 | } 80 | 81 | # See above - templates also seem to leave stray VDIs around... 82 | function delete_template() 83 | { 84 | DELETE_TEMPLATE_UUID=$1 85 | for VDI_UUID in $(xe vbd-list vm-uuid=$DELETE_TEMPLATE_UUID empty=false | xe_param "vdi-uuid"); do 86 | echo "Deleting template VDI : $VDI_UUID" 87 | xe vdi-destroy uuid=$VDI_UUID 88 | done 89 | 90 | # Now we can remove the template itself 91 | echo "Removing template with UUID : $DELETE_TEMPLATE_UUID" 92 | xe template-uninstall template-uuid=$DELETE_TEMPLATE_UUID force=true 93 | } 94 | 95 | 96 | echo " " 97 | echo "=== Snapshot backup started at $(date) ===" 98 | echo " " 99 | 100 | # Get all running VMs 101 | # todo: Need to check this works across a pool 102 | RUNNING_VMS=$(xe vm-list power-state=running is-control-domain=false | xe_param uuid) 103 | 104 | for VM in $RUNNING_VMS; do 105 | VM_NAME="$(xe vm-list uuid=$VM | xe_param name-label)" 106 | 107 | # Useful for testing, if we only want to process one VM 108 | #if [ "$VM_NAME" != "testvm" ]; then 109 | # continue 110 | #fi 111 | 112 | echo " " 113 | echo "== Backup for $VM_NAME started at $(date) ==" 114 | echo "= Retrieving backup paramaters =" 115 | #Template backups 116 | SCHEDULE=$(xe vm-param-get uuid=$VM param-name=other-config param-key=XenCenter.CustomFields.backup) 117 | RETAIN=$(xe vm-param-get uuid=$VM param-name=other-config param-key=XenCenter.CustomFields.retain) 118 | #XVA Backups 119 | XVA_SCHEDULE=$(xe vm-param-get uuid=$VM param-name=other-config param-key=XenCenter.CustomFields.xva_backup) 120 | XVA_RETAIN=$(xe vm-param-get uuid=$VM param-name=other-config param-key=XenCenter.CustomFields.xva_retain) 121 | 122 | # Not using this yet, as there are some bugs to be worked out... 123 | # QUIESCE=$(xe vm-param-get uuid=$VM param-name=other-config param-key=XenCenter.CustomFields.quiesce) 124 | 125 | ##############################check Template schedule########################### 126 | if [[ "$SCHEDULE" == "" || "$RETAIN" == "" ]]; then 127 | echo "No schedule or retention set for template backup, skipping this VM" 128 | SKIP_TEMPLATE=1 129 | else 130 | echo "VM template backup schedule : $SCHEDULE" 131 | echo "VM template retention : $RETAIN previous snapshots" 132 | 133 | if [ "$SCHEDULE" == "daily" ]; then 134 | SKIP_TEMPLATE=0 135 | else 136 | # If weekly, see if this is the correct day 137 | if [ "$SCHEDULE" == "weekly" ]; then 138 | if [ "$(date +'%a')" == "$WEEKLY_ON" ]; then 139 | echo "On correct day for weekly backups, running..." 140 | SKIP_TEMPLATE=0 141 | else 142 | echo "Weekly backups scheduled on $WEEKLY_ON, skipping..." 143 | SKIP_TEMPLATE=1 144 | fi 145 | else 146 | # If monthly, see if this is the correct day 147 | if [ "$SCHEDULE" == "monthly" ]; then 148 | if [[ "$(date +'%a')" == "$MONTHLY_ON" && $(date '+%e') -le 7 ]]; then 149 | echo "On correct day for monthly backups, running..." 150 | SKIP_TEMPLATE=0 151 | else 152 | echo "Monthly backups scheduled on 1st $MONTHLY_ON, skipping..." 153 | SKIP_TEMPLATE=1 154 | fi 155 | fi 156 | fi 157 | fi 158 | fi 159 | ##############################check XVA schedule################################ 160 | if [[ "$XVA_SCHEDULE" == "" || "$XVA_RETAIN" == "" ]]; then 161 | echo "No schedule or retention set for XVA backup, skipping this VM" 162 | SKIP_XVA=1 163 | else 164 | echo "VM XVA backup schedule : $XVA_SCHEDULE" 165 | echo "VM XVA retention : $XVA_RETAIN previous snapshots" 166 | 167 | if [ "$XVA_SCHEDULE" == "daily" ]; then 168 | SKIP_XVA=0 169 | else 170 | # If weekly, see if this is the correct day 171 | if [ "$XVA_SCHEDULE" == "weekly" ]; then 172 | if [ "$(date +'%a')" == "$WEEKLY_ON" ]; then 173 | echo "On correct day for weekly backups, running..." 174 | SKIP_XVA=0 175 | else 176 | echo "Weekly backups scheduled on $WEEKLY_ON, skipping..." 177 | SKIP_XVA=1 178 | fi 179 | else 180 | # If monthly, see if this is the correct day 181 | if [ "$XVA_SCHEDULE" == "monthly" ]; then 182 | if [[ "$(date +'%a')" == "$MONTHLY_ON" && $(date '+%e') -le 7 ]]; then 183 | echo "On correct day for monthly backups, running..." 184 | SKIP_XVA=0 185 | else 186 | echo "Monthly backups scheduled on 1st $MONTHLY_ON, skipping..." 187 | SKIP_XVA=1 188 | fi 189 | fi 190 | fi 191 | fi 192 | fi 193 | ################################################################################ 194 | 195 | if [[ "$SKIP_TEMPLATE" == "0" && "$SKIP_XVA" == "0" ]]; then 196 | echo "Nothing to do for this VM!..." 197 | continue 198 | fi 199 | 200 | echo "= Checking snapshots for $VM_NAME =" 201 | VM_SNAPSHOT_CHECK=$(xe snapshot-list name-label="$VM_NAME-$SNAPSHOT_SUFFIX" | xe_param uuid) 202 | if [ "$VM_SNAPSHOT_CHECK" != "" ]; then 203 | echo "Found old backup snapshot : $VM_SNAPSHOT_CHECK" 204 | echo "Deleting..." 205 | delete_snapshot $VM_SNAPSHOT_CHECK 206 | fi 207 | echo "Done." 208 | 209 | echo "= Creating snapshot backup =" 210 | 211 | # Select appropriate snapshot command 212 | # See above - not using this yet, as have to work around failures 213 | #if [ "$QUIESCE" == "true" ]; then 214 | # echo "Using VSS plugin" 215 | # SNAPSHOT_CMD="vm-snapshot-with-quiesce" 216 | #else 217 | # echo "Not using VSS plugin, disks will not be quiesced" 218 | # SNAPSHOT_CMD="vm-snapshot" 219 | #fi 220 | SNAPSHOT_CMD="vm-snapshot" 221 | 222 | SNAPSHOT_UUID=$(xe $SNAPSHOT_CMD vm="$VM_NAME" new-name-label="$VM_NAME-$SNAPSHOT_SUFFIX") 223 | echo "Created snapshot with UUID : $SNAPSHOT_UUID" 224 | 225 | #Backup to template 226 | if [ "$SKIP_TEMPLATE" == "0" ]; then 227 | echo "= Copying snapshot to SR =" 228 | # Check there isn't a stale template with TEMP_SUFFIX name hanging around from a failed job 229 | TEMPLATE_TEMP="$(xe template-list name-label="$VM_NAME-$TEMP_SUFFIX" | xe_param uuid)" 230 | if [ "$TEMPLATE_TEMP" != "" ]; then 231 | echo "Found a stale temporary template, removing UUID $TEMPLATE_TEMP" 232 | delete_template $TEMPLATE_TEMP 233 | fi 234 | TEMPLATE_UUID=$(xe snapshot-copy uuid=$SNAPSHOT_UUID sr-uuid=$TEMPLATE_SR new-name-description="Snapshot created on $(date)" new-name-label="$VM_NAME-$TEMP_SUFFIX") 235 | echo "Done." 236 | 237 | # List templates for all VMs, grep for $VM_NAME-$BACKUP_SUFFIX 238 | # Sort -n, head -n -$RETAIN 239 | # Loop through and remove each one 240 | echo "= Removing old template backups =" 241 | xe template-list | grep "$VM_NAME-$BACKUP_SUFFIX" | xe_param name-label | sort -n | head -n-$RETAIN > $TEMP 242 | while read OLD_TEMPLATE; do 243 | OLD_TEMPLATE_UUID=$(xe template-list name-label="$OLD_TEMPLATE" | xe_param uuid) 244 | echo "Removing : $OLD_TEMPLATE with UUID $OLD_TEMPLATE_UUID" 245 | delete_template $OLD_TEMPLATE_UUID 246 | done < $TEMP 247 | 248 | # Also check there is no template with the current timestamp. 249 | # Otherwise, you would not be able to backup more than once a day if you needed... 250 | TODAYS_TEMPLATE="$(xe template-list name-label="$VM_NAME-$BACKUP_SUFFIX-$BACKUP_DATE" | xe_param uuid)" 251 | if [ "$TODAYS_TEMPLATE" != "" ]; then 252 | echo "Found a template already for today, removing UUID $TODAYS_TEMPLATE" 253 | delete_template $TODAYS_TEMPLATE 254 | fi 255 | 256 | echo "= Renaming template =" 257 | xe template-param-set name-label="$VM_NAME-$BACKUP_SUFFIX-$BACKUP_DATE" uuid=$TEMPLATE_UUID 258 | echo "Done." 259 | fi 260 | 261 | #Backup to XVA 262 | if [ "$SKIP_XVA" == "0" ]; then 263 | echo "= Exporting VM to file =" 264 | #Creates a XVA file from the snapshot 265 | EXPORT_CMD="vm-export" 266 | xe $EXPORT_CMD vm=$SNAPSHOT_UUID filename="/var/run/sr-mount/$XVA_SR/$VM_NAME-$BACKUP_SUFFIX-$BACKUP_DATE.xva" 267 | echo "Done." 268 | 269 | # List XVA files for all VMs, grep for $VM_NAME-$BACKUP_SUFFIX 270 | # Sort -n, head -n -$RETAIN 271 | # Loop through and remove each one 272 | echo "= Removing old XVA files =" 273 | ls -1 /var/run/sr-mount/$XVA_SR/*.xva | grep "$VM_NAME-$BACKUP_SUFFIX" | sort -n | head -n-$XVA_RETAIN > $TEMP 274 | while read OLD_TEMPLATE; do 275 | echo "Removing : $OLD_TEMPLATE" 276 | rm $OLD_TEMPLATE 277 | done < $TEMP 278 | fi 279 | 280 | echo "= Removing temporary snapshot backup =" 281 | delete_snapshot $SNAPSHOT_UUID 282 | echo "Done." 283 | 284 | echo "== Backup for $VM_NAME finished at $(date) ==" 285 | echo " " 286 | done 287 | 288 | xe vdi-list sr-uuid=$TEMPLATE_SR > /var/run/sr-mount/$TEMPLATE_SR/mapping.txt 289 | xe vbd-list > /var/run/sr-mount/$TEMPLATE_SR/vbd-mapping.txt 290 | 291 | echo "=== Snapshot backup finished at $(date) ===" 292 | echo " " 293 | echo "=== Metadata backup started at $(date) ===" 294 | echo " " 295 | #Backup Pool meta-data: 296 | xe-backup-metadata -c -k 10 -u $TEMPLATE_SR 297 | 298 | echo "=== Metadata backup finished at $(date) ===" 299 | echo " " 300 | 301 | rm $TEMP 302 | rm $LOCKFILE 303 | -------------------------------------------------------------------------------- /snapback.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # snapback.sh 1.3 3 | # Simple script to create regular snapshot-based backups for Citrix Xenserver 4 | # Mark Round, scripts@markround.com 5 | # http://www.markround.com/snapback 6 | # 7 | # 1.3 : Added basic lockfile 8 | # 1.2 : Tidied output, removed VDIs before deleting snapshots and templates 9 | # 1.1 : Added missing force=true paramaters to snapshot uninstall calls. 10 | 11 | # 12 | # Variables 13 | # 14 | 15 | # Temporary snapshots will be use this as a suffix 16 | SNAPSHOT_SUFFIX=snapback 17 | # Temporary backup templates will use this as a suffix 18 | TEMP_SUFFIX=newbackup 19 | # Backup templates will use this as a suffix, along with the date 20 | BACKUP_SUFFIX=backup 21 | # What day to run weekly backups on 22 | WEEKLY_ON="Sun" 23 | # What day to run monthly backups on. These will run on the first day 24 | # specified below of the month. 25 | MONTHLY_ON="Sun" 26 | # Temporary file 27 | TEMP=/tmp/snapback.$$ 28 | # UUID of the destination SR for backups 29 | DEST_SR=e871f2df-a195-9c50-5377-be55e749c003 30 | 31 | LOCKFILE=/tmp/snapback.lock 32 | 33 | if [ -f $LOCKFILE ]; then 34 | echo "Lockfile $LOCKFILE exists, exiting!" 35 | exit 1 36 | fi 37 | 38 | touch $LOCKFILE 39 | 40 | # 41 | # Don't modify below this line 42 | # 43 | 44 | # Date format must be %Y%m%d so we can sort them 45 | BACKUP_DATE=$(date +"%Y%m%d") 46 | 47 | # Quick hack to grab the required paramater from the output of the xe command 48 | function xe_param() 49 | { 50 | PARAM=$1 51 | while read DATA; do 52 | LINE=$(echo $DATA | egrep "$PARAM") 53 | if [ $? -eq 0 ]; then 54 | echo "$LINE" | awk 'BEGIN{FS=": "}{print $2}' 55 | fi 56 | done 57 | 58 | } 59 | 60 | # Deletes a snapshot's VDIs before uninstalling it. This is needed as 61 | # snapshot-uninstall seems to sometimes leave "stray" VDIs in SRs 62 | function delete_snapshot() 63 | { 64 | DELETE_SNAPSHOT_UUID=$1 65 | for VDI_UUID in $(xe vbd-list vm-uuid=$DELETE_SNAPSHOT_UUID empty=false | xe_param "vdi-uuid"); do 66 | echo "Deleting snapshot VDI : $VDI_UUID" 67 | xe vdi-destroy uuid=$VDI_UUID 68 | done 69 | 70 | # Now we can remove the snapshot itself 71 | echo "Removing snapshot with UUID : $DELETE_SNAPSHOT_UUID" 72 | xe snapshot-uninstall uuid=$DELETE_SNAPSHOT_UUID force=true 73 | } 74 | 75 | # See above - templates also seem to leave stray VDIs around... 76 | function delete_template() 77 | { 78 | DELETE_TEMPLATE_UUID=$1 79 | for VDI_UUID in $(xe vbd-list vm-uuid=$DELETE_TEMPLATE_UUID empty=false | xe_param "vdi-uuid"); do 80 | echo "Deleting template VDI : $VDI_UUID" 81 | xe vdi-destroy uuid=$VDI_UUID 82 | done 83 | 84 | # Now we can remove the template itself 85 | echo "Removing template with UUID : $DELETE_TEMPLATE_UUID" 86 | xe template-uninstall template-uuid=$DELETE_TEMPLATE_UUID force=true 87 | } 88 | 89 | 90 | 91 | echo "=== Snapshot backup started at $(date) ===" 92 | echo " " 93 | 94 | # Get all running VMs 95 | # todo: Need to check this works across a pool 96 | RUNNING_VMS=$(xe vm-list power-state=running is-control-domain=false | xe_param uuid) 97 | 98 | for VM in $RUNNING_VMS; do 99 | VM_NAME="$(xe vm-list uuid=$VM | xe_param name-label)" 100 | 101 | # Useful for testing, if we only want to process one VM 102 | #if [ "$VM_NAME" != "testvm" ]; then 103 | # continue 104 | #fi 105 | 106 | echo " " 107 | echo "== Backup for $VM_NAME started at $(date) ==" 108 | echo "= Retrieving backup paramaters =" 109 | SCHEDULE=$(xe vm-param-get uuid=$VM param-name=other-config param-key=XenCenter.CustomFields.backup) 110 | RETAIN=$(xe vm-param-get uuid=$VM param-name=other-config param-key=XenCenter.CustomFields.retain) 111 | # Not using this yet, as there are some bugs to be worked out... 112 | # QUIESCE=$(xe vm-param-get uuid=$VM param-name=other-config param-key=XenCenter.CustomFields.quiesce) 113 | 114 | if [[ "$SCHEDULE" == "" || "$RETAIN" == "" ]]; then 115 | echo "No schedule or retention set, skipping this VM" 116 | continue 117 | fi 118 | echo "VM backup schedule : $SCHEDULE" 119 | echo "VM retention : $RETAIN previous snapshots" 120 | 121 | # If weekly, see if this is the correct day 122 | if [ "$SCHEDULE" == "weekly" ]; then 123 | if [ "$(date +'%a')" == "$WEEKLY_ON" ]; then 124 | echo "On correct day for weekly backups, running..." 125 | else 126 | echo "Weekly backups scheduled on $WEEKLY_ON, skipping..." 127 | continue 128 | fi 129 | fi 130 | 131 | # If monthly, see if this is the correct day 132 | if [ "$SCHEDULE" == "monthly" ]; then 133 | if [[ "$(date +'%a')" == "$MONTHLY_ON" && $(date '+%e') -le 7 ]]; then 134 | echo "On correct day for monthly backups, running..." 135 | else 136 | echo "Monthly backups scheduled on 1st $MONTHLY_ON, skipping..." 137 | continue 138 | fi 139 | fi 140 | 141 | echo "= Checking snapshots for $VM_NAME =" 142 | VM_SNAPSHOT_CHECK=$(xe snapshot-list name-label=$VM_NAME-$SNAPSHOT_SUFFIX | xe_param uuid) 143 | if [ "$VM_SNAPSHOT_CHECK" != "" ]; then 144 | echo "Found old backup snapshot : $VM_SNAPSHOT_CHECK" 145 | echo "Deleting..." 146 | delete_snapshot $VM_SNAPSHOT_CHECK 147 | fi 148 | echo "Done." 149 | 150 | echo "= Creating snapshot backup =" 151 | 152 | # Select appropriate snapshot command 153 | # See above - not using this yet, as have to work around failures 154 | #if [ "$QUIESCE" == "true" ]; then 155 | # echo "Using VSS plugin" 156 | # SNAPSHOT_CMD="vm-snapshot-with-quiesce" 157 | #else 158 | # echo "Not using VSS plugin, disks will not be quiesced" 159 | # SNAPSHOT_CMD="vm-snapshot" 160 | #fi 161 | SNAPSHOT_CMD="vm-snapshot" 162 | 163 | SNAPSHOT_UUID=$(xe $SNAPSHOT_CMD vm="$VM_NAME" new-name-label="$VM_NAME-$SNAPSHOT_SUFFIX") 164 | echo "Created snapshot with UUID : $SNAPSHOT_UUID" 165 | 166 | echo "= Copying snapshot to SR =" 167 | # Check there isn't a stale template with TEMP_SUFFIX name hanging around from a failed job 168 | TEMPLATE_TEMP="$(xe template-list name-label="$VM_NAME-$TEMP_SUFFIX" | xe_param uuid)" 169 | if [ "$TEMPLATE_TEMP" != "" ]; then 170 | echo "Found a stale temporary template, removing UUID $TEMPLATE_TEMP" 171 | delete_template $TEMPLATE_TEMP 172 | fi 173 | TEMPLATE_UUID=$(xe snapshot-copy uuid=$SNAPSHOT_UUID sr-uuid=$DEST_SR new-name-description="Snapshot created on $(date)" new-name-label="$VM_NAME-$TEMP_SUFFIX") 174 | echo "Done." 175 | 176 | echo "= Removing temporary snapshot backup =" 177 | delete_snapshot $SNAPSHOT_UUID 178 | echo "Done." 179 | 180 | 181 | # List templates for all VMs, grep for $VM_NAME-$BACKUP_SUFFIX 182 | # Sort -n, head -n -$RETAIN 183 | # Loop through and remove each one 184 | echo "= Removing old backups =" 185 | xe template-list | grep "$VM_NAME-$BACKUP_SUFFIX" | xe_param name-label | sort -n | head -n-$RETAIN > $TEMP 186 | while read OLD_TEMPLATE; do 187 | OLD_TEMPLATE_UUID=$(xe template-list name-label="$OLD_TEMPLATE" | xe_param uuid) 188 | echo "Removing : $OLD_TEMPLATE with UUID $OLD_TEMPLATE_UUID" 189 | delete_template $OLD_TEMPLATE_UUID 190 | done < $TEMP 191 | 192 | # Also check there is no template with the current timestamp. 193 | # Otherwise, you would not be able to backup more than once a day if you needed... 194 | TODAYS_TEMPLATE="$(xe template-list name-label="$VM_NAME-$BACKUP_SUFFIX-$BACKUP_DATE" | xe_param uuid)" 195 | if [ "$TODAYS_TEMPLATE" != "" ]; then 196 | echo "Found a template already for today, removing UUID $TODAYS_TEMPLATE" 197 | delete_template $TODAYS_TEMPLATE 198 | fi 199 | 200 | echo "= Renaming template =" 201 | xe template-param-set name-label="$VM_NAME-$BACKUP_SUFFIX-$BACKUP_DATE" uuid=$TEMPLATE_UUID 202 | echo "Done." 203 | 204 | echo "== Backup for $VM_NAME finished at $(date) ==" 205 | echo " " 206 | done 207 | 208 | xe vdi-list sr-uuid=$DEST_SR > /var/run/sr-mount/$DEST_SR/mapping.txt 209 | xe vbd-list > /var/run/sr-mount/$DEST_SR/vbd-mapping.txt 210 | 211 | echo "=== Snapshot backup finished at $(date) ===" 212 | rm $TEMP 213 | rm $LOCKFILE 214 | --------------------------------------------------------------------------------