Blob Blame History Raw
From feb9d3652c97e848158cc22b5a6e28f0a90b6c8f Mon Sep 17 00:00:00 2001
Message-Id: <feb9d3652c97e848158cc22b5a6e28f0a90b6c8f@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 26 Feb 2014 14:55:30 +0100
Subject: [PATCH] qemu: snapshot: Add support for external active snapshots on
 gluster

https://bugzilla.redhat.com/show_bug.cgi?id=1032370

Add support for gluster backed images as sources for snapshots in the
qemu driver. This will also simplify adding further network backed
volumes as sources for snapshot in case qemu will support them.

(cherry picked from commit 3cf074ee40b4df4123732a1591aa3b4308e9c634)

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 docs/formatsnapshot.html.in |   5 +-
 src/qemu/qemu_command.c     |   2 +-
 src/qemu/qemu_command.h     |   9 ++++
 src/qemu/qemu_driver.c      | 108 +++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 114 insertions(+), 10 deletions(-)

diff --git a/docs/formatsnapshot.html.in b/docs/formatsnapshot.html.in
index 44ed4fd..1f9a6c6 100644
--- a/docs/formatsnapshot.html.in
+++ b/docs/formatsnapshot.html.in
@@ -183,8 +183,9 @@
             documentation for further information.
 
             Libvirt currently supports the <code>type</code> element in the qemu
-            driver and supported values are <code>file</code> and
-            <code>block</code> <span class="since">(since 1.2.2)</span>.
+            driver and supported values are <code>file</code>, <code>block</code>
+            and <code>network</code> with a protocol of <code>gluster</code>
+            <span class="since">(since 1.2.2)</span>.
           </dd>
         </dl>
       </dd>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8923b09..54c36e3 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3727,7 +3727,7 @@ cleanup:
 }
 
 
-static int
+int
 qemuGetDriveSourceString(int type,
                          const char *src,
                          int protocol,
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 22b7aa7..105389b 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -319,4 +319,13 @@ qemuParseKeywords(const char *str,
                   char ***retvalues,
                   int allowEmptyValue);
 
+int qemuGetDriveSourceString(int type,
+                             const char *src,
+                             int protocol,
+                             size_t nhosts,
+                             virDomainDiskHostDefPtr hosts,
+                             const char *username,
+                             const char *secret,
+                             char **path);
+
 #endif /* __QEMU_COMMAND_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 86f2775..cc6c133 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11816,6 +11816,24 @@ cleanup:
     return ret;
 }
 
+
+static int
+qemuDomainSnapshotDiskGetSourceString(virDomainSnapshotDiskDefPtr disk,
+                                      char **source)
+{
+    *source = NULL;
+
+    return qemuGetDriveSourceString(virDomainSnapshotDiskGetActualType(disk),
+                                    disk->file,
+                                    disk->protocol,
+                                    disk->nhosts,
+                                    disk->hosts,
+                                    NULL,
+                                    NULL,
+                                    source);
+}
+
+
 typedef enum {
     VIR_DISK_CHAIN_NO_ACCESS,
     VIR_DISK_CHAIN_READ_ONLY,
@@ -12208,6 +12226,24 @@ qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr d
         return 0;
 
     case VIR_DOMAIN_DISK_TYPE_NETWORK:
+        switch ((enum virDomainDiskProtocol) disk->protocol) {
+        case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER:
+            return 0;
+
+        case VIR_DOMAIN_DISK_PROTOCOL_NBD:
+        case VIR_DOMAIN_DISK_PROTOCOL_RBD:
+        case VIR_DOMAIN_DISK_PROTOCOL_SHEEPDOG:
+        case VIR_DOMAIN_DISK_PROTOCOL_ISCSI:
+        case VIR_DOMAIN_DISK_PROTOCOL_LAST:
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("external active snapshots are not supported on "
+                             "'network' disks using '%s' protocol"),
+                           virDomainDiskProtocolTypeToString(disk->protocol));
+            return -1;
+
+        }
+        break;
+
     case VIR_DOMAIN_DISK_TYPE_DIR:
     case VIR_DOMAIN_DISK_TYPE_VOLUME:
     case VIR_DOMAIN_DISK_TYPE_LAST:
@@ -12510,6 +12546,9 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     char *device = NULL;
     char *source = NULL;
+    char *newsource = NULL;
+    virDomainDiskHostDefPtr newhosts = NULL;
+    virDomainDiskHostDefPtr persistHosts = NULL;
     int format = snap->format;
     const char *formatStr = NULL;
     char *persistSource = NULL;
@@ -12524,8 +12563,7 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
         return -1;
     }
 
-    if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0 ||
-        (persistDisk && VIR_STRDUP(persistSource, source) < 0))
+    if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0)
         goto cleanup;
 
     /* XXX Here, we know we are about to alter disk->backingChain if
@@ -12539,13 +12577,21 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     if (!(snapfile = virStorageFileInitFromSnapshotDef(snap)))
         goto cleanup;
 
+    if (qemuDomainSnapshotDiskGetSourceString(snap, &source) < 0)
+        goto cleanup;
+
+    if (VIR_STRDUP(newsource, snap->file) < 0)
+        goto cleanup;
+
+    if (persistDisk &&
+        VIR_STRDUP(persistSource, snap->file) < 0)
+        goto cleanup;
+
     switch (snap->type) {
     case VIR_DOMAIN_DISK_TYPE_BLOCK:
         reuse = true;
         /* fallthrough */
     case VIR_DOMAIN_DISK_TYPE_FILE:
-        if (VIR_STRDUP(source, snap->file) < 0)
-            goto cleanup;
 
         /* create the stub file and set selinux labels; manipulate disk in
          * place, in a way that can be reverted on failure. */
@@ -12565,6 +12611,27 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
         }
         break;
 
+    case VIR_DOMAIN_DISK_TYPE_NETWORK:
+        switch (snap->protocol) {
+        case VIR_DOMAIN_DISK_PROTOCOL_GLUSTER:
+            if (!(newhosts = virDomainDiskHostDefCopy(snap->nhosts, snap->hosts)))
+                goto cleanup;
+
+            if (persistDisk &&
+                !(persistHosts = virDomainDiskHostDefCopy(snap->nhosts, snap->hosts)))
+                goto cleanup;
+
+            break;
+
+        default:
+            virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+                           _("snapshots on volumes using '%s' protocol "
+                             "are not supported"),
+                           virDomainDiskProtocolTypeToString(snap->protocol));
+            goto cleanup;
+        }
+        break;
+
     default:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("snapshots are not supported on '%s' volumes"),
@@ -12600,17 +12667,33 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
 
     /* Update vm in place to match changes.  */
     need_unlink = false;
+
     VIR_FREE(disk->src);
-    disk->src = source;
-    source = NULL;
+    virDomainDiskHostDefFree(disk->nhosts, disk->hosts);
+
+    disk->src = newsource;
     disk->format = format;
     disk->type = snap->type;
+    disk->protocol = snap->protocol;
+    disk->nhosts = snap->nhosts;
+    disk->hosts = newhosts;
+
+    newsource = NULL;
+    newhosts = NULL;
+
     if (persistDisk) {
         VIR_FREE(persistDisk->src);
+        virDomainDiskHostDefFree(persistDisk->nhosts, persistDisk->hosts);
+
         persistDisk->src = persistSource;
-        persistSource = NULL;
         persistDisk->format = format;
         persistDisk->type = snap->type;
+        persistDisk->protocol = snap->protocol;
+        persistDisk->nhosts = snap->nhosts;
+        persistDisk->hosts = persistHosts;
+
+        persistSource = NULL;
+        persistHosts = NULL;
     }
 
 cleanup:
@@ -12619,7 +12702,10 @@ cleanup:
     virStorageFileFree(snapfile);
     VIR_FREE(device);
     VIR_FREE(source);
+    VIR_FREE(newsource);
     VIR_FREE(persistSource);
+    virDomainDiskHostDefFree(snap->nhosts, newhosts);
+    virDomainDiskHostDefFree(snap->nhosts, persistHosts);
     return ret;
 }
 
@@ -12658,12 +12744,20 @@ qemuDomainSnapshotUndoSingleDiskActive(virQEMUDriverPtr driver,
     source = NULL;
     disk->format = origdisk->format;
     disk->type = origdisk->type;
+    disk->protocol = origdisk->protocol;
+    virDomainDiskHostDefFree(disk->nhosts, disk->hosts);
+    disk->nhosts = origdisk->nhosts;
+    disk->hosts = virDomainDiskHostDefCopy(origdisk->nhosts, origdisk->hosts);
     if (persistDisk) {
         VIR_FREE(persistDisk->src);
         persistDisk->src = persistSource;
         persistSource = NULL;
         persistDisk->format = origdisk->format;
         persistDisk->type = origdisk->type;
+        persistDisk->protocol = origdisk->protocol;
+        virDomainDiskHostDefFree(persistDisk->nhosts, persistDisk->hosts);
+        persistDisk->nhosts = origdisk->nhosts;
+        persistDisk->hosts = virDomainDiskHostDefCopy(origdisk->nhosts, origdisk->hosts);
     }
 
 cleanup:
-- 
1.9.0