Blame SOURCES/libvirt-storage-rbd-qemu-Add-support-for-specifying-internal-RBD-snapshots.patch

9119d9
From b7945d7e44a533d7a9cc26d493f7abb9ebccaae4 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <b7945d7e44a533d7a9cc26d493f7abb9ebccaae4@dist-git>
9119d9
From: Peter Krempa <pkrempa@redhat.com>
9119d9
Date: Fri, 21 Nov 2014 15:04:11 +0100
9119d9
Subject: [PATCH] storage: rbd: qemu: Add support for specifying internal RBD
9119d9
 snapshots
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=1164528
9119d9
9119d9
Some storage systems have internal support for snapshots. Libvirt should
9119d9
be able to select a correct snapshot when starting a VM.
9119d9
9119d9
This patch adds a XML element to select a storage source snapshot for
9119d9
the RBD protocol which supports this feature.
9119d9
9119d9
(cherry picked from commit 02556606584ef6c065eae6e36c311250fa7a24f4)
9119d9
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 docs/formatdomain.html.in                          | 16 +++++++--
9119d9
 docs/schemas/domaincommon.rng                      |  8 +++++
9119d9
 src/conf/domain_conf.c                             | 38 +++++++++++++++++++---
9119d9
 src/conf/domain_conf.h                             |  1 +
9119d9
 src/conf/snapshot_conf.c                           |  6 ++--
9119d9
 src/qemu/qemu_command.c                            |  3 ++
9119d9
 src/util/virstoragefile.c                          |  8 +++++
9119d9
 src/util/virstoragefile.h                          |  1 +
9119d9
 .../qemuxml2argv-disk-drive-network-rbd.args       |  4 +++
9119d9
 .../qemuxml2argv-disk-drive-network-rbd.xml        | 17 ++++++++++
9119d9
 10 files changed, 93 insertions(+), 9 deletions(-)
9119d9
9119d9
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
9119d9
index a458067..789f6ee 100644
9119d9
--- a/docs/formatdomain.html.in
9119d9
+++ b/docs/formatdomain.html.in
9119d9
@@ -1661,6 +1661,7 @@
9119d9
       <driver name="qemu" type="raw"/>
9119d9
       <source protocol="rbd" name="image_name2">
9119d9
         <host name="hostname" port="7000"/>
9119d9
+        <snapshot name="snapname"/>
9119d9
       </source>
9119d9
       <target dev="hdc" bus="ide"/>
9119d9
       <auth username='myuser'>
9119d9
@@ -1934,15 +1935,17 @@
9119d9
         is only valid when the specified storage volume is of 'file' or
9119d9
         'block' type).
9119d9
         

9119d9
-        When the disk type is "network", the source
9119d9
-        may have zero or more host sub-elements used to
9119d9
-        specify the hosts to connect.
9119d9
+        The source element may contain the following sub elements:
9119d9
         

9119d9
 
9119d9
         
9119d9
           
host
9119d9
           
9119d9
             

9119d9
+            When the disk type is "network", the source
9119d9
+            may have zero or more host sub-elements used to
9119d9
+            specify the hosts to connect.
9119d9
+
9119d9
             The host element supports 4 attributes, viz.  "name",
9119d9
             "port", "transport" and "socket", which specify the hostname,
9119d9
             the port number, transport type and path to socket, respectively.
9119d9
@@ -1995,6 +1998,13 @@
9119d9
             AF_UNIX socket.
9119d9
             

9119d9
           
9119d9
+          
snapshot
9119d9
+          
9119d9
+            The name attribute of snapshot element can
9119d9
+            optionally specify an internal snapshot name to be used as the
9119d9
+            source for storage protocols.
9119d9
+            Supported for 'rbd' since 1.2.11 (QEMU only).
9119d9
+          
9119d9
         
9119d9
 
9119d9
         

9119d9
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
9119d9
index c010c45..fa17494 100644
9119d9
--- a/docs/schemas/domaincommon.rng
9119d9
+++ b/docs/schemas/domaincommon.rng
9119d9
@@ -1447,6 +1447,14 @@
9119d9
             </choice>
9119d9
           </element>
9119d9
         </zeroOrMore>
9119d9
+        <optional>
9119d9
+          <element name="snapshot">
9119d9
+            <attribute name="name">
9119d9
+              <ref name="genericName"/>
9119d9
+            </attribute>
9119d9
+            <empty/>
9119d9
+          </element>
9119d9
+        </optional>
9119d9
         <empty/>
9119d9
       </element>
9119d9
     </interleave>
9119d9
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
9119d9
index 0e977fc..82d321a 100644
9119d9
--- a/src/conf/domain_conf.c
9119d9
+++ b/src/conf/domain_conf.c
9119d9
@@ -3157,6 +3157,22 @@ virDomainDeviceDefPostParseInternal(virDomainDeviceDefPtr dev,
9119d9
             return -1;
9119d9
     }
9119d9
 
9119d9
+    /* verify disk source */
9119d9
+    if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
9119d9
+        virDomainDiskDefPtr disk = dev->data.disk;
9119d9
+
9119d9
+        /* internal snapshots are currently supported only with rbd: */
9119d9
+        if (virStorageSourceGetActualType(disk->src) != VIR_STORAGE_TYPE_NETWORK &&
9119d9
+            disk->src->protocol != VIR_STORAGE_NET_PROTOCOL_RBD) {
9119d9
+            if (disk->src->snapshot) {
9119d9
+                virReportError(VIR_ERR_XML_ERROR, "%s",
9119d9
+                               _("<snapshot> element is currently supported "
9119d9
+                                 "only with 'rbd' disks"));
9119d9
+                return -1;
9119d9
+            }
9119d9
+        }
9119d9
+    }
9119d9
+
9119d9
     return 0;
9119d9
 }
9119d9
 
9119d9
@@ -5301,10 +5317,14 @@ virDomainDiskSourcePoolDefParse(xmlNodePtr node,
9119d9
 
9119d9
 int
9119d9
 virDomainDiskSourceParse(xmlNodePtr node,
9119d9
+                         xmlXPathContextPtr ctxt,
9119d9
                          virStorageSourcePtr src)
9119d9
 {
9119d9
     int ret = -1;
9119d9
     char *protocol = NULL;
9119d9
+    xmlNodePtr saveNode = ctxt->node;
9119d9
+
9119d9
+    ctxt->node = node;
9119d9
 
9119d9
     switch ((virStorageType)src->type) {
9119d9
     case VIR_STORAGE_TYPE_FILE:
9119d9
@@ -5357,6 +5377,9 @@ virDomainDiskSourceParse(xmlNodePtr node,
9119d9
             tmp[0] = '\0';
9119d9
         }
9119d9
 
9119d9
+        /* snapshot currently works only for remote disks */
9119d9
+        src->snapshot = virXPathString("string(./snapshot/@name)", ctxt);
9119d9
+
9119d9
         if (virDomainStorageHostParse(node, &src->hosts, &src->nhosts) < 0)
9119d9
             goto cleanup;
9119d9
         break;
9119d9
@@ -5382,6 +5405,7 @@ virDomainDiskSourceParse(xmlNodePtr node,
9119d9
 
9119d9
  cleanup:
9119d9
     VIR_FREE(protocol);
9119d9
+    ctxt->node = saveNode;
9119d9
     return ret;
9119d9
 }
9119d9
 
9119d9
@@ -5437,7 +5461,7 @@ virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt,
9119d9
         goto cleanup;
9119d9
     }
9119d9
 
9119d9
-    if (virDomainDiskSourceParse(source, backingStore) < 0 ||
9119d9
+    if (virDomainDiskSourceParse(source, ctxt, backingStore) < 0 ||
9119d9
         virDomainDiskBackingStoreParse(ctxt, backingStore) < 0)
9119d9
         goto cleanup;
9119d9
 
9119d9
@@ -5547,7 +5571,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
9119d9
                 xmlStrEqual(cur->name, BAD_CAST "source")) {
9119d9
                 sourceNode = cur;
9119d9
 
9119d9
-                if (virDomainDiskSourceParse(cur, def->src) < 0)
9119d9
+                if (virDomainDiskSourceParse(cur, ctxt, def->src) < 0)
9119d9
                     goto error;
9119d9
                 source = def->src->path;
9119d9
 
9119d9
@@ -5713,7 +5737,8 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
9119d9
                                        _("mirror requires source element"));
9119d9
                         goto error;
9119d9
                     }
9119d9
-                    if (virDomainDiskSourceParse(mirrorNode, def->mirror) < 0)
9119d9
+                    if (virDomainDiskSourceParse(mirrorNode, ctxt,
9119d9
+                                                 def->mirror) < 0)
9119d9
                         goto error;
9119d9
                 }
9119d9
                 ready = virXMLPropString(cur, "ready");
9119d9
@@ -15898,11 +15923,12 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf,
9119d9
 
9119d9
             VIR_FREE(path);
9119d9
 
9119d9
-            if (src->nhosts == 0) {
9119d9
+            if (src->nhosts == 0 && !src->snapshot) {
9119d9
                 virBufferAddLit(buf, "/>\n");
9119d9
             } else {
9119d9
                 virBufferAddLit(buf, ">\n");
9119d9
                 virBufferAdjustIndent(buf, 2);
9119d9
+
9119d9
                 for (n = 0; n < src->nhosts; n++) {
9119d9
                     virBufferAddLit(buf, "
9119d9
                     virBufferEscapeString(buf, " name='%s'",
9119d9
@@ -15919,6 +15945,10 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf,
9119d9
 
9119d9
                     virBufferAddLit(buf, "/>\n");
9119d9
                 }
9119d9
+
9119d9
+                virBufferEscapeString(buf, "<snapshot name='%s'/>\n",
9119d9
+                                      src->snapshot);
9119d9
+
9119d9
                 virBufferAdjustIndent(buf, -2);
9119d9
                 virBufferAddLit(buf, "</source>\n");
9119d9
             }
9119d9
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
9119d9
index 21d19cf..6768089 100644
9119d9
--- a/src/conf/domain_conf.h
9119d9
+++ b/src/conf/domain_conf.h
9119d9
@@ -2445,6 +2445,7 @@ virDomainDiskRemove(virDomainDefPtr def, size_t i);
9119d9
 virDomainDiskDefPtr
9119d9
 virDomainDiskRemoveByName(virDomainDefPtr def, const char *name);
9119d9
 int virDomainDiskSourceParse(xmlNodePtr node,
9119d9
+                             xmlXPathContextPtr ctxt,
9119d9
                              virStorageSourcePtr src);
9119d9
 
9119d9
 bool virDomainHasDiskMirror(virDomainObjPtr vm);
9119d9
diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
9119d9
index c53a66b..27882b8 100644
9119d9
--- a/src/conf/snapshot_conf.c
9119d9
+++ b/src/conf/snapshot_conf.c
9119d9
@@ -107,6 +107,7 @@ void virDomainSnapshotDefFree(virDomainSnapshotDefPtr def)
9119d9
 
9119d9
 static int
9119d9
 virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
9119d9
+                                 xmlXPathContextPtr ctxt,
9119d9
                                  virDomainSnapshotDiskDefPtr def)
9119d9
 {
9119d9
     int ret = -1;
9119d9
@@ -154,7 +155,7 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
9119d9
         if (!def->src->path &&
9119d9
             xmlStrEqual(cur->name, BAD_CAST "source")) {
9119d9
 
9119d9
-            if (virDomainDiskSourceParse(cur, def->src) < 0)
9119d9
+            if (virDomainDiskSourceParse(cur, ctxt, def->src) < 0)
9119d9
                 goto cleanup;
9119d9
 
9119d9
         } else if (!def->src->format &&
9119d9
@@ -352,7 +353,8 @@ virDomainSnapshotDefParse(xmlXPathContextPtr ctxt,
9119d9
             goto cleanup;
9119d9
         def->ndisks = n;
9119d9
         for (i = 0; i < def->ndisks; i++) {
9119d9
-            if (virDomainSnapshotDiskDefParseXML(nodes[i], &def->disks[i]) < 0)
9119d9
+            if (virDomainSnapshotDiskDefParseXML(nodes[i], ctxt,
9119d9
+                                                 &def->disks[i]) < 0)
9119d9
                 goto cleanup;
9119d9
         }
9119d9
         VIR_FREE(nodes);
9119d9
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
9119d9
index 93f02a9..5d34ba3 100644
9119d9
--- a/src/qemu/qemu_command.c
9119d9
+++ b/src/qemu/qemu_command.c
9119d9
@@ -2986,6 +2986,9 @@ qemuBuildNetworkDriveURI(virStorageSourcePtr src,
9119d9
 
9119d9
             virBufferStrcat(&buf, "rbd:", src->path, NULL);
9119d9
 
9119d9
+            if (src->snapshot)
9119d9
+                virBufferEscape(&buf, '\\', ":", "@%s", src->snapshot);
9119d9
+
9119d9
             if (username) {
9119d9
                 virBufferEscape(&buf, '\\', ":", ":id=%s", username);
9119d9
                 virBufferEscape(&buf, '\\', ":",
9119d9
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
9119d9
index ba4d830..6cdc5be 100644
9119d9
--- a/src/util/virstoragefile.c
9119d9
+++ b/src/util/virstoragefile.c
9119d9
@@ -1842,6 +1842,7 @@ virStorageSourceCopy(const virStorageSource *src,
9119d9
         VIR_STRDUP(ret->driverName, src->driverName) < 0 ||
9119d9
         VIR_STRDUP(ret->relPath, src->relPath) < 0 ||
9119d9
         VIR_STRDUP(ret->backingStoreRaw, src->backingStoreRaw) < 0 ||
9119d9
+        VIR_STRDUP(ret->snapshot, src->snapshot) < 0 ||
9119d9
         VIR_STRDUP(ret->compat, src->compat) < 0)
9119d9
         goto error;
9119d9
 
9119d9
@@ -2259,6 +2260,13 @@ virStorageSourceParseRBDColonString(const char *rbdstr,
9119d9
         *p = '\0';
9119d9
     }
9119d9
 
9119d9
+    /* snapshot name */
9119d9
+    if ((p = strchr(src->path, '@'))) {
9119d9
+        if (VIR_STRDUP(src->snapshot, p + 1) < 0)
9119d9
+            goto error;
9119d9
+        *p = '\0';
9119d9
+    }
9119d9
+
9119d9
     /* options */
9119d9
     if (!options)
9119d9
         return 0; /* all done */
9119d9
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
9119d9
index 3573ccd..74aa1a3 100644
9119d9
--- a/src/util/virstoragefile.h
9119d9
+++ b/src/util/virstoragefile.h
9119d9
@@ -236,6 +236,7 @@ struct _virStorageSource {
9119d9
     char *path;
9119d9
     int protocol; /* virStorageNetProtocol */
9119d9
     char *volume; /* volume name for remote storage */
9119d9
+    char *snapshot; /* for storage systems supporting internal snapshots */
9119d9
     size_t nhosts;
9119d9
     virStorageNetHostDefPtr hosts;
9119d9
     virStorageSourcePoolDefPtr srcpool;
9119d9
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd.args
9119d9
index 21d7b64..e4f1389 100644
9119d9
--- a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd.args
9119d9
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd.args
9119d9
@@ -5,4 +5,8 @@ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
9119d9
 -drive 'file=rbd:pool/image:auth_supported=none:\
9119d9
 mon_host=mon1.example.org\:6321\;mon2.example.org\:6322\;\
9119d9
 mon3.example.org\:6322,if=virtio,format=raw' \
9119d9
+-drive file=rbd:pool/image@asdf:auth_supported=none,if=virtio,format=raw \
9119d9
+-drive 'file=rbd:pool/image@foo:auth_supported=none:\
9119d9
+mon_host=mon1.example.org\:6321\;mon2.example.org\:6322\;\
9119d9
+mon3.example.org\:6322,if=virtio,format=raw' \
9119d9
 -net none -serial none -parallel none
9119d9
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd.xml
9119d9
index 37e9db5..f6accd8 100644
9119d9
--- a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd.xml
9119d9
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-rbd.xml
9119d9
@@ -29,6 +29,23 @@
9119d9
       </source>
9119d9
       <target dev='vda' bus='virtio'/>
9119d9
     </disk>
9119d9
+    <disk type='network' device='disk'>
9119d9
+      <driver name='qemu' type='raw'/>
9119d9
+      <source protocol='rbd' name='pool/image'>
9119d9
+        <snapshot name='asdf'/>
9119d9
+      </source>
9119d9
+      <target dev='vdb' bus='virtio'/>
9119d9
+    </disk>
9119d9
+    <disk type='network' device='disk'>
9119d9
+      <driver name='qemu' type='raw'/>
9119d9
+      <source protocol='rbd' name='pool/image'>
9119d9
+        <host name='mon1.example.org' port='6321'/>
9119d9
+        <host name='mon2.example.org' port='6322'/>
9119d9
+        <host name='mon3.example.org' port='6322'/>
9119d9
+        <snapshot name='foo'/>
9119d9
+      </source>
9119d9
+      <target dev='vdc' bus='virtio'/>
9119d9
+    </disk>
9119d9
     <controller type='usb' index='0'/>
9119d9
     <controller type='ide' index='0'/>
9119d9
     <controller type='pci' index='0' model='pci-root'/>
9119d9
-- 
9119d9
2.1.3
9119d9