For many years, I’ve been immersed in the world of Citrix XenServer, managing a fleet of XenServers via XenCenter on a dedicated Windows machine. Traditionally, our approach to VM backup has been a manual process, always necessitating a shutdown of the VM. This practice has understandably led to some frustration among VM owners due to the extended downtime. However, a recent search revealed a more efficient method that allows for backing up VMs without the need to shut them down, thereby eliminating downtime.
In this tutorial, we’re going to guide you through the process of backing up active VMs step by step. Additionally, we’ll introduce you to a shell script that automates the backup of all VMs or specific ones of your choice. This script can be easily integrated into a crontab to schedule regular backups, making the process seamless and efficient.
Method 1: Manual Backup of Running VM
For those who prefer the command line over using XenCenter, especially Linux enthusiasts, here are the steps to manage your VM backups using terminal commands.
1.1. Identifying VM UUIDs
To begin, locate the UUIDs of all your VMs, which are essential for the following steps. Execute the command below to list all VMs, noting their UUIDs and other details:
xe vm-list is-control-domain=false is-a-snapshot=false
Example output might look like this:
uuid ( RO) : 8ac95696-94f3-83c1-bc89-8bb2603f832b name-label ( RW): test-vm power-state ( RO): running
From the output, you can see the UUID for test-vm is 8ac95696-94f3-83c1-bc89-8bb2603f832b, though yours will vary.
1.2. Creating a VM Snapshot
Next, create a snapshot of the VM using its UUID from the previous step. Ensure the UUID is accurate:
xe vm-snapshot uuid=8ac95696-94f3-83c1-bc89-8bb2603f832b new-name-label=testvmsnapshot
This command will return a snapshot UUID. Use this new UUID to set the snapshot as a non-template VM, preparing it for export:
xe template-param-set is-a-template=false ha-always-run=false uuid=b15c0531-88a5-98a4-e484-01bc89131561
1.3. Exporting Snapshot to File
With the snapshot prepared, export it to an .xva file, which can be restored later via command line or XenCenter:
xe vm-export vm=b15c0531-88a5-98a4-e484-01bc89131561 filename=vm-backup.xva
1.4. Deleting the Snapshot
After backing up the VM, you can safely remove the snapshot from the XenServer:
xe vm-uninstall uuid=b15c0531-88a5-98a4-e484-01bc89131561 force=true
Method 2: Using Script for Backup Running VMs
To automate backups for all running VMs on XenServer, consider using a shell script. This approach involves mounting a remote filesystem shared via NFS. While the following script has been effective in my experience, its performance may vary for you. Proceed with caution and understand the risks involved.
#!/bin/bash
# Script for backing up running Virtual Machines in XenServer
# Written by: Mr. Rahul Kumar
# Creation date: Jun 14, 2014
# Last updated: Mar 14, 2024
# Version: 1.3
# More information at: https://tecadmin.net/backup-running-virtual-machine-in-xenserver/
DATE=$(date +%d%b%Y)
XS_HOSTNAME=$(hostname)
UUIDFILE="/tmp/xen-uuids.txt"
NFS_SERVER_IP="192.168.10.100"
MOUNTPOINT="/xenmnt"
FILE_LOCATION_ON_NFS="/backup/citrix/vms"
# Create mount point
mkdir -p "${MOUNTPOINT}"
# Mounting remote NFS share backup drive
if [ ! -d "${MOUNTPOINT}" ]; then
echo "No mount point found, kindly check"
exit 1
fi
mount -F nfs "${NFS_SERVER_IP}:${FILE_LOCATION_ON_NFS}" "${MOUNTPOINT}"
BACKUPPATH="${MOUNTPOINT}/${XS_HOSTNAME}/${DATE}"
mkdir -p "${BACKUPPATH}"
if [ ! -d "${BACKUPPATH}" ]; then
echo "No backup directory found"
exit 1
fi
# Fetching list UUIDs of all VMs running on XenServer
xe vm-list is-control-domain=false is-a-snapshot=false | grep uuid | cut -d":" -f2 | tr -d ' ' > "${UUIDFILE}"
if [ ! -f "${UUIDFILE}" ]; then
echo "No UUID list file found"
exit 1
fi
while IFS= read -r VMUUID; do
VMNAME=$(xe vm-list uuid="$VMUUID" | grep "name-label" | cut -d":" -f2 | sed 's/^ *//g')
SNAPUUID=$(xe vm-snapshot uuid="$VMUUID" new-name-label="SNAPSHOT-$VMUUID-$DATE")
xe template-param-set is-a-template=false ha-always-run=false uuid="${SNAPUUID}"
xe vm-export vm="${SNAPUUID}" filename="${BACKUPPATH}/${VMNAME}-${DATE}.xva"
xe vm-uninstall uuid="${SNAPUUID}" force=true
done < "${UUIDFILE}"
# Unmount the mount point
umount "${MOUNTPOINT}"
Download this script directly from Github.com
Conclusion
In conclusion, backing up virtual machines without shutting them down is not only possible but also efficient and practical. This guide and the provided script make it easy to regularly backup your VMs, reducing downtime and keeping your data safe. With these tools, you can automate the backup process, ensuring your VMs are always protected with minimal disruption. This method marks a significant improvement in managing VM backups, offering a solution that is both user-friendly and highly effective.
24 Comments
Protect your XEN VM with Spectrum Protect using SPFS
=================================================
Mount your Spectrum Protect filespace anywhere on your XEN server
# mount -t spfs /backup
Backup the XEN VM nodes using above example
You could also use the script from here https://www.baculasystems.com/products/bacula-enterprise-data-backup-tools/citrix-xenserver-backup-software with Bacula Community Edition for free.
On Xen 7.2 the fix for the
[ ! -d ${BACKUPPATH} ] && echo “No backup directory found”; exit 0
is
[ ! -d ${BACKUPPATH} ] && (echo “No backup directory found”; exit 0)
I ran into situations where customers did not have enough bandwidth on their storage hardware to complete a backup in a nightly backup. However they still needed some level of protection in the event of malware or admin error. I modified the backup script to only create snapshots of the running VM, and only keep the last 15 days of snapshots. I changed the SNAPSHOT name variable format so that it would not conflict with their existing backup script, so that it could be used in conjunction to the backup script. Just another layer of protection . I installed it into the crontab using * */4 * * * so that it runs every four hours. I hope some will find this useful
DATE=`date +%F`
XSNAME=`echo $HOSTNAME`
MOUNTPOINT=/xenmnt
UUIDFILE=”/tmp/xen-uuids.txt”
NFS_SERVER_IP=”10.10.20.230″
xe vm-list is-control-domain=false is-a-snapshot=false | grep uuid | cut -d”:” -f2 > ${UUIDFILE}
while read VMUUID
do
VMNAME=`xe vm-list uuid=$VMUUID | grep name-label | cut -d”:” -f2 | sed ‘s/^ *//g’`
SNAPUUID=`xe vm-snapshot uuid=$VMUUID new-name-label=”SNAPSHOT-$DATE”`
xe template-param-set is-a-template=false ha-always-run=false uuid=${SNAPUUID}
done ${UUIDFILE}
while read VMUUID
do
xe snapshot-uninstall uuid=$VMUUID –force
done < ${UUIDFILE}
Please find below sample instructions for restoring using my modified backup script. If anyone would like to help automate this that would be greatly appreciated.
Contained in the VM backup set you will find several files, an xva file and a VHD image of the hard drives. The XVA file is the definition and or metadata of the vm itself without the VHD or Hard disk.
Get list of SR
xe sr-list
record the sr-uuid you will be using
example:
uuid ( RO) : 0c67c214-5041-2d9e-14db-2d2b7e92a8a2
name-label ( RW): XENSR1
name-description ( RW): iSCSI SR [10.10.20.221 (iqn.1992-04.com.emc:cx.apm00155221699.b5; LUN 2: APM00155221699: 10240 GB (DGC))]
host ( RO):
type ( RO): lvmoiscsi
content-type ( RO):
Import Metadata of VM
xe vm-import preservce=false filename=hylafax-12Mar2017.xva –force sr-uuid=0c67c214-5041-2d9e-14db-2d2b7e92a8a2
Get uuid of imported vm
[root@xenbl460-1 hylafax]# xe vm-list name-label=hylafax
uuid ( RO) : b2fb074f-b024-6d1d-364c-8ac2c73c90b8
name-label ( RW): hylafax
power-state ( RO): haltedGet list of snapshots of MV
Get list of snapshot of vm
[root@xenbl460-1 hylafax]# xe snapshot-list snapshot-of=b2fb074f-b024-6d1d-364c-8ac2c73c90b8
uuid ( RO) : 002ad76c-c281-5ef8-e1dd-afa637c63822
name-label ( RW): SNAPSHOT-6edb308d-4cb7-e16e-f565-fbe95609ab79-12Mar2017
name-description ( RW):
Destroy Snapshot of VM
[root@xenbl460-1 hylafax]# xe snapshot-destroy uuid=002ad76c-c281-5ef8-e1dd-afa637c63822
get list of VBD for VM
[root@xenbl460-1 hylafax]# xe vbd-list vm-uuid=b2fb074f-b024-6d1d-364c-8ac2c73c90b8
uuid ( RO) : e8c9b02a-f73d-907b-b717-ed19b6d5e751
vm-uuid ( RO): b2fb074f-b024-6d1d-364c-8ac2c73c90b8
vm-name-label ( RO): hylafax
vdi-uuid ( RO): a2eea760-6131-4afa-ac7e-87faec69a818
empty ( RO): false
device ( RO):
uuid ( RO) : 893b1267-d3bf-6520-2416-3e7bbadd61d9
vm-uuid ( RO): b2fb074f-b024-6d1d-364c-8ac2c73c90b8
vm-name-label ( RO): hylafax
vdi-uuid ( RO): 53a07b39-eac0-4e72-b0c0-69702474bd4d
empty ( RO): false
device ( RO):
uuid ( RO) : aae311d1-847a-b67c-056c-fd367136889e
vm-uuid ( RO): b2fb074f-b024-6d1d-364c-8ac2c73c90b8
vm-name-label ( RO): hylafax
vdi-uuid ( RO):
empty ( RO): true
device ( RO):
Get VDI info for each VBD
xe vdi-list uuid=53a07b39-eac0-4e72-b0c0-69702474bd4d
xe vdi-list uuid=a2eea760-6131-4afa-ac7e-87faec69a818
Pay attention to the size of the output
[root@xenbl460-1 hylafax]# xe vdi-list uuid=a2eea760-6131-4afa-ac7e-87faec69a818
uuid ( RO) : a2eea760-6131-4afa-ac7e-87faec69a818
name-label ( RW): hylafax_1
name-description ( RW): hylafax_1
sr-uuid ( RO): 0c67c214-5041-2d9e-14db-2d2b7e92a8a2
virtual-size ( RO): 17179869184
sharable ( RO): false
read-only ( RO): false
Import VDI
Now you will import each vhd file that matches the size of the vdi. if your unsure of the size use the following command as an example
Get VHD file information
[root@xenbl460-1 hylafax]# vhd-util scan -f -p -m *.vhd
vhd=hylafax_0-d9d6c6ff-f862-44ca-afc9-48b29c4b4c31.vhd capacity=5368709120 size=365006336 hidden=0 parent=none
vhd=hylafax_1-d487610b-12dc-4d9a-9981-9a97c33fa74b.vhd capacity=17179869184 size=12214732800 hidden=0 parent=none
Manually match the VHD to the VDI based on size or name label of the filename and or VDI
example: xe vdi-import format=VHD filename=hylafax_0-d9d6c6ff-f862-44ca-afc9-48b29c4b4c31.vhd uuid=53a07b39-eac0-4e72-b0c0-69702474bd4d
Do this for each VDI / VHD
Start VM
xe vm-start uuid=b2fb074f-b024-6d1d-364c-8ac2c73c90b8
or
xe vm-start name-label=hylafax
Repeat this process for each VM
Hi,
thanks for the script, but I got some problems with it so here are some questions:
On what Xenserver Version this script is running?
I tried that script on Xenserver 7.1 and there are a few serious problems:
your script says ‘mount -F nfs’ -> “mount” on my Xenserver says “-F = fork off for each device” Wrong paramter???
your script says ‘[ ! -d ${MOUNTPOINT} ] && echo “No mount point found, kindly check”; exit 0’ maybe I am wrong but doesnt this ALWAYS mean that your scripts ends at this line? “;” just seperates two commands?! What system are you using? Greetings
Hi,
The script will only exist if mount point directory is not created already.
You can also use the script given by REVERSEARP in the comments section box.
This is a simple bash script. So if required you can modify it as per your requirements.
Hi Rahul,
thanks for your quick response.
I will try the script of REVERSEARP, (he uses mount -t nfs).
Ofcourse exiting the script when the Mount point directory is not created makes sense. I see ur goal here. But please have a closer look to this line:
‘[ ! -d ${MOUNTPOINT} ] && echo “No mount point found, kindly check”; exit 0’
I did some tests:
[root@xenhost ~]# false && echo “ok” —> nothing happens
[root@xenhost ~]# true && echo “ok” —> shell outputs “ok” (makes sense)
[root@xenhost ~]# false && echo “ok”; exit 0 –> Shell closes
[root@xenhost ~]# true && echo “ok”; exit 0 –> Shell closes
To my mind this script cant work because you always exit the script no matter the mount point directory exist or not… Sorry, just wanna verify this line. I am just wondering why this script works for you?? Where is my mistake …
I had the same problem. I ended up changing this line to :
if [ ! -d “$MOUNTPOINT” ] ; then echo “Mount point ${MOUNTPOINT} not found, kindly check”; exit 0; fi
A little wordier, but it works on my system. I changed the other ‘if exists’ type statements as well to explicit if’s and it all works as expected.
And the VMUUID variable where is initialize?
thank you for sharing your script,
I am trying to use it
#########################################################
#Ubuntu-server-1 Backup
TDY=`date +%Y%m%d%H-%M`
SNAPUUID=`xe vm-snapshot uuid=$384b41b6-eaac-c2d9-48e5-c169c2be5968 new-name-label=Ubuntu-server-1`
xe template-param-set is-a-template=false ha-always-run=false uuid=${SNAPUUID}
xe vm-export vm=${SNAPUUID} filename=”Ubuntu-server-1-$TDY”.xva
xe vm-uninstall uuid=${SNAPUUID} force=true
#########################################################
restored backup
xe vm-import filename=/media/xen-vm-backup/Ubuntu-server-1-11-9-2016.xva
#########################################################
The problem is when import the VM, It works fine but it does not have all the files.
can you help me please
I saw this, and tried it, and I like it, thank you for sharing its very useful. Only problem was that in my environment is that it took 16.3 hours to complete . So I got to thinking, there needs to be a faster way to do this. Forgive the syntax and formatting , I am not a bash programmer by any standpoint. Basically this modification takes a snapshot, grabs the metadata, of the actual vm and does a vdi-export on the snapshot. then uninstalls the snapshot. In my environment it took 6 hours to run. (4.7TB) I am dumping my VM’s to a ZFS based san , I highly recommend some sort of compressed FS ( I like zfs), as the vhd’s are large however they are highly compressible. I am going to test the dedupe ratio on an EMC Datadomain to see what type of ratios I get, as I would like to keep 3 months of weekly snapshots at a minimum on site and replicated to our DR.
To restore you will need to do a vm-import on the metadata, then import the individual vhd’s . Which means creating new vdi and then doing the vdi-import to that vdi. If you don’t know the size of the vdi you will need to query the vhd using vhd-util.
#!/bin/bash
#
# Written By: Mr Rahul Kumar
# Created date: Jun 14, 2014
# Last Updated: Jan 22, 2016
# Version: 1.2
# Visit: http://tecadmin.net
#
DATE=`date +%d%b%Y`
XSNAME=`echo $HOSTNAME`
MOUNTPOINT=/xenmnt
UUIDFILE=”/tmp/xen-uuids.txt”
NFS_SERVER_IP=”10.10.20.212″
### Create mount point
mkdir -p ${MOUNTPOINT}
### Mounting remote nfs share backup drive
# [ ! -d ${MOUNTPOINT} ] && echo “No mount point found, kindly check”; exit 0
mount -t nfs ${NFS_SERVER_IP}:/mnt/pool1/vm_backups ${MOUNTPOINT} -o async,rsize=32768,wsize=32768,soft
BACKUPPATH=${MOUNTPOINT}/${XSNAME}/${DATE}
mkdir -p ${BACKUPPATH}
# [ ! -d ${BACKUPPATH} ] && echo “No backup directory found”; exit 0
# Fetching list UUIDs of all VMs running on XenServer
xe vm-list is-control-domain=false is-a-snapshot=false | grep uuid | cut -d”:” -f2 > ${UUIDFILE}
# [ ! -f ${UUIDFILE} ] && echo “No UUID list file found”; exit 0
while read VMUUID
do
VMNAME=`xe vm-list uuid=$VMUUID | grep name-label | cut -d”:” -f2 | sed ‘s/^ *//g’`
SNAPUUID=`xe vm-snapshot uuid=$VMUUID new-name-label=”SNAPSHOT-$VMUUID-$DATE”`
xe template-param-set is-a-template=false ha-always-run=false uuid=${SNAPUUID}
NEWPATH=${BACKUPPATH}/${VMNAME}
mkdir “${NEWPATH}”
echo “${NEWPATH}/$VMNAME-$DATE.xva”
xe vm-export metadata=true vm=${VMUUID} filename=”${NEWPATH}/${VMNAME}-${DATE}.xva”
#######GET VBD######
for VBDUUID in $(xe vbd-list vm-uuid=${SNAPUUID} empty=false –minimal | sed “s/,/ /g” );
do
VDIUUID=$( xe vdi-list vbd-uuids=$VBDUUID –minimal)
VDINAME=$( xe vdi-param-get param-name=name-label uuid=$VDIUUID )
xe vdi-export progress=true uuid=$VDIUUID format=vhd filename=$NEWPATH/$VDINAME-$VDIUUID.vhd
done
xe vm-uninstall uuid=${SNAPUUID} force=true
done < ${UUIDFILE}
umount ${MOUNTPOINT}
I would like to know if the snapshots would also backup the disks that are attached to the VM. I have few VM that have 4TB and 2TB disks attached for file storage and those don’t need to be on the snapshots. If the attached disks are also on the snapshots, is there a way to ignore them? Thanks for the great tutorial.
I’m with Joe…Curious about the answer.
This is kinda like the blind leading the deaf, but since nobody else answered:
The line
#######GET VBD######
for VBDUUID in $(xe vbd-list vm-uuid=${SNAPUUID} empty=false –minimal | sed “s/,/ /g” );
is what controls which volumes are backed up. You can run it “by hand” to see what exactly is include, for example:
# get a list of the VM UUIDS
xe vm-list
# Show the volues attached to the VM you want to look at
xe vbd-list uuid=(enter the UUID you got from the previous command)
So, yes it can be done, but would take some hacking of the script – particularly to have it deal with different situations for different VM’s
So after some testing – the script will backup any size hard drive or VHD that it has access to. However upon doing a restore of that VHD it will fail. It appears that the VHD has to be less than 2000G. The way I overcame this limitation was to use smaller VHD’s and use LVM in linux or in windows spanned disks. If you absolutely need to use a disk that large, create a new SR via nfs and move the vid
s that SR (via mv or cp from cli). them rename the VHD with a valid GUID keeping the VHD extension. Then you can do a SRscan and then attach the disk to the VM. It is literally the only way to deal with restoring VHD’s of that size
I have to question
1 you have,t specify the path for the backup file
2 if i want the backup over network then what should be the procedure
Thanks
Hi everyone
i am just confuse because where is the location of backup file.
Secondly if i want to do the backup over the network then what will be the procedure for that.
If possible please give the reply on my mail
Thanks
ihsan
The information I search for – thanks.
But on a XenServer 6.2.0 you don’t need to create a file with the uuids. It can done with a for-loop.
Here a little loop to list the uuids and name-labels:
for vmuuid in $(xe vm-list is-control-domain=false is-a-snapshot=false is-a-template=false params=uuid –minimal | tr ‘,’ ‘ ‘)
do echo “UUID: $vmuuid – Name-Label: $(xe vm-list uuid=$vmuuid params=name-label –minimal)”
done
@BIOS: perfect, thank you!
@Cuong Nguyen Viet
xe vm-import filename=vm-backup.xva
Nice!
But how can I do restore VM with the xva file?
Interesting….
Glynn
———————————————————————————-
1º – LISTAR VMS para encontra a identificação ( UUID ) da maquina que será exportada
COMANDO: xe vm-list is-control-domain=false
———————————————————————————-
———————————————————————————-
##### CRIAR SNAPSHOT DA MAQINA QUE DESEJA EXPORTAR
COMANDO: xe vm-snapshot uuid= AQUI VOCE COLOCA O UUID DA MAQUINA QUE SERA EXPORTADA new-name-label=bkp_vm_xp
———————————————————————————-
———————————————————————————-
##### APOS CRIAR O SNAPSHOT ESSE COMANDO TRANSFORMA O SNAPSHOT EM vm
COMANDO: xe template-param-set is-a-template=false ha-always-run=false uuid=AQUI VOCE COLOCA O UUID DO SNAPSHOT
———————————————————————————-
———————————————————————————-
##### CRIAR PASTA PARA BACKUP DA VM
COMANDO: mkdir /mnt/pasta_bkp
———————————————————————————-
———————————————————————————-
##### COLOQUE AQUI OS DADOS DA PASTA COMPARTILHADA EM REDE
COMANDO: mount -t cifs “//10.0.0.45/bkp-vm/BKP-SCRIPT/windows-xp” -o username=”dominiousuario”,password=”senha” “/mnt/pasta_bkp”
———————————————————————————-
———————————————————————————-
##### ESSE COMANDO COPIA A VM PARA SUA PASTA NA REDE
COMANDO: xe vm-export vm=AQUI VOCE COLOCA O UUID DO SNAPSHOT filename=/mnt/pasta_bkp/win_xp_bkp.xva
———————————————————————————-
———————————————————————————-
##### ESSE COMANDO Remover VM Snapeshot
COMANDO: xe vm-uninstall uuid=b759625c-eab5-4e0f-be5e-a05bcbad869a force=true
———————————————————————————-