• Москва +7 (495) 664 23 30
  • Санкт-Петербург +7 (812) 309 26 84

Xend patch for Xen 4.0 to create disk snapshots (for LVM devices) when saving VM snapshot

Use xm save or xm save -c. Disk snapshot will have the name based on the original name of the device with '-checkpoint-$timestamp' appended.

diff -ru /usr/lib/xen-4.0/lib/python/xen/xend/XendCheckpoint.py xen/xend/XendCheckpoint.py
--- /usr/lib/xen-4.0/lib/python/xen/xend/XendCheckpoint.py      2010-09-03 19:38:06.000000000 +0400
+++ xen/xend/XendCheckpoint.py  2012-04-12 02:40:31.000000000 +0400
@@ -11,6 +11,8 @@
 import string
 import threading
 import fcntl
+import time
+import subprocess
 from struct import pack, unpack, calcsize

 from xen.util.xpopen import xPopen3
@@ -94,6 +96,26 @@
             continue
         backend[1] = bkdominfo.getName()

+    if checkpoint:
+        disk_snapshots = dict() # will be used later to create the snapshots before domain resume
+        timestamp = str(time.time())
+        for device_sxp in sxp.children(sxprep, 'device'):
+            vbd_sxp = sxp.child(device_sxp, 'vbd')
+            if vbd_sxp == None:
+                continue
+            uname_sxp = sxp.child(vbd_sxp, 'uname')
+            if uname_sxp == None:
+                continue
+            uname = uname_sxp[1]
+            if uname.startswith('phy:'):
+                devpath = uname.split('phy:')[-1]
+                dirname, basename = os.path.split(devpath)
+                newname = basename + '-checkpoint-' + timestamp
+                disk_snapshots['devpath'] = newname
+                log.debug("Substitute %s with snapshot name %s", devpath, newname)
+                # update the disk name in the configuration
+                uname_sxp[1] = 'phy:' + dirname + '/' + newname
+
     config = sxp.to_string(sxprep)

     domain_name = dominfo.getName()
@@ -160,6 +182,13 @@
             os.remove("/var/lib/xen/qemu-save.%d" % dominfo.getDomid())

         if checkpoint:
+            # create LVM-snapshots for each disk device attached, assume all disks are LVM volumes
+            # default disk snapshot size is 1G, we can do lvresize later if needed
+            for origin, clone in disk_snapshots.iteritems():
+                try:
+                    subprocess.call(['/sbin/lvm', 'lvcreate', '-s', '-n', clone, '-L', '1G', origin])
+                except Exception exn:
+                    log.error("cannot create clone %s for %s", clone, origin)
             dominfo.resumeDomain()
         else:
             dominfo.destroy()