[libvirt] [PATCH 2/3] snapshot: Add support for specifying snapshot disk backing type

Peter Krempa pkrempa at redhat.com
Fri Dec 6 14:47:28 UTC 2013


Add support for specifying various types when doing snapshots. This will
later allow to do snapshots on network backed volumes. Disks of type
'volume' are not supported by snapshots (yet).
---
 docs/schemas/domainsnapshot.rng | 76 +++++++++++++++++++++++++++++++++++------
 src/conf/snapshot_conf.c        | 25 +++++++++++---
 src/conf/snapshot_conf.h        | 15 ++++----
 src/qemu/qemu_driver.c          | 59 +++++++++++++++++++++-----------
 4 files changed, 134 insertions(+), 41 deletions(-)

diff --git a/docs/schemas/domainsnapshot.rng b/docs/schemas/domainsnapshot.rng
index 169fcfb..de9e788 100644
--- a/docs/schemas/domainsnapshot.rng
+++ b/docs/schemas/domainsnapshot.rng
@@ -123,19 +123,73 @@
               <value>external</value>
             </attribute>
           </optional>
-          <interleave>
-            <ref name='disksnapshotdriver'/>
-            <optional>
-              <element name='source'>
+          <choice>
+            <group>
+              <optional>
+                <attribute name='type'>
+                  <value>file</value>
+                </attribute>
+              </optional>
+              <interleave>
                 <optional>
-                  <attribute name='file'>
-                    <ref name='absFilePath'/>
-                  </attribute>
+                  <element name='source'>
+                    <optional>
+                      <attribute name='file'>
+                        <ref name='absFilePath'/>
+                      </attribute>
+                    </optional>
+                    <empty/>
+                  </element>
                 </optional>
-                <empty/>
-              </element>
-            </optional>
-          </interleave>
+                <ref name='disksnapshotdriver'/>
+              </interleave>
+            </group>
+            <group>
+              <attribute name='type'>
+                <value>block</value>
+              </attribute>
+              <interleave>
+                <optional>
+                  <element name="source">
+                    <attribute name="dev">
+                      <ref name="absFilePath"/>
+                    </attribute>
+                    <empty/>
+                  </element>
+                </optional>
+                <ref name='disksnapshotdriver'/>
+              </interleave>
+            </group>
+            <group>
+              <attribute name="type">
+                <value>dir</value>
+              </attribute>
+              <interleave>
+                <optional>
+                  <element name="source">
+                    <attribute name="dir">
+                      <ref name="absFilePath"/>
+                    </attribute>
+                    <empty/>
+                  </element>
+                </optional>
+                <ref name='disksnapshotdriver'/>
+              </interleave>
+            </group>
+            <group>
+              <attribute name="type">
+                <value>network</value>
+              </attribute>
+              <interleave>
+                <optional>
+                  <element name="source">
+                    <ref name='diskSourceNetwork'/>
+                  </element>
+                </optional>
+                <ref name='disksnapshotdriver'/>
+              </interleave>
+            </group>
+          </choice>
         </group>
       </choice>
     </element>
diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
index c18b99b..6ce65f6 100644
--- a/src/conf/snapshot_conf.c
+++ b/src/conf/snapshot_conf.c
@@ -108,6 +108,7 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
 {
     int ret = -1;
     char *snapshot = NULL;
+    char *type = NULL;
     xmlNodePtr cur;

     def->name = virXMLPropString(node, "name");
@@ -129,6 +130,14 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
     }

     def->type = -1;
+    if ((type = virXMLPropString(node, "type"))) {
+        if ((def->type = virDomainDiskTypeFromString(type)) < 0 ||
+            def->type == VIR_DOMAIN_DISK_TYPE_VOLUME) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("unknown disk snapshot type '%s'"), type);
+            goto cleanup;
+        }
+    }

     for (cur = node->children; cur; cur = cur->next) {
         if (cur->type != XML_ELEMENT_NODE)
@@ -145,9 +154,9 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
             if (virDomainDiskSourceDefParse(cur,
                                             backingtype,
                                             &def->file,
-                                            NULL,
-                                            NULL,
-                                            NULL,
+                                            &def->protocol,
+                                            &def->nhosts,
+                                            &def->hosts,
                                             NULL) < 0)
                 goto cleanup;

@@ -174,6 +183,7 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
     ret = 0;
 cleanup:
     VIR_FREE(snapshot);
+    VIR_FREE(type);
     if (ret < 0)
         virDomainSnapshotDiskDefClear(def);
     return ret;
@@ -616,6 +626,9 @@ virDomainSnapshotDiskDefFormat(virBufferPtr buf,

     if (type < 0)
         type = VIR_DOMAIN_DISK_TYPE_FILE;
+    else
+        virBufferAsprintf(buf, " type='%s'",
+                          virDomainDiskTypeToString(type));

     if (!disk->file && disk->format == 0) {
         virBufferAddLit(buf, "/>\n");
@@ -630,7 +643,11 @@ virDomainSnapshotDiskDefFormat(virBufferPtr buf,
     virDomainDiskSourceDefFormatInternal(buf,
                                          type,
                                          disk->file,
-                                         0, 0, 0, NULL, 0, NULL, NULL, 0);
+                                         0,
+                                         disk->protocol,
+                                         disk->nhosts,
+                                         disk->hosts,
+                                         0, NULL, NULL, 0);

     virBufferAddLit(buf, "    </disk>\n");
 }
diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h
index 241d63c..bcd92dc 100644
--- a/src/conf/snapshot_conf.h
+++ b/src/conf/snapshot_conf.h
@@ -48,12 +48,15 @@ enum virDomainSnapshotState {
 typedef struct _virDomainSnapshotDiskDef virDomainSnapshotDiskDef;
 typedef virDomainSnapshotDiskDef *virDomainSnapshotDiskDefPtr;
 struct _virDomainSnapshotDiskDef {
-    char *name; /* name matching the <target dev='...' of the domain */
-    int index; /* index within snapshot->dom->disks that matches name */
-    int snapshot; /* enum virDomainSnapshotLocation */
-    int type; /* enum virDomainDiskType */
-    char *file; /* new source file when snapshot is external */
-    int format; /* enum virStorageFileFormat */
+    char *name;     /* name matching the <target dev='...' of the domain */
+    int index;      /* index within snapshot->dom->disks that matches name */
+    int snapshot;   /* enum virDomainSnapshotLocation */
+    int type;       /* enum virDomainDiskType */
+    char *file;     /* new source file when snapshot is external */
+    int format;     /* enum virStorageFileFormat */
+    int protocol;   /* network source protocol */
+    size_t nhosts;  /* network source hosts count */
+    virDomainDiskHostDefPtr hosts; /* network source hosts */
 };

 /* Stores the complete snapshot metadata */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 66f2a0e..1afadcf 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12194,33 +12194,48 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     }

     if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0 ||
-        VIR_STRDUP(source, snap->file) < 0 ||
         (persistDisk && VIR_STRDUP(persistSource, source) < 0))
         goto cleanup;

-    /* create the stub file and set selinux labels; manipulate disk in
-     * place, in a way that can be reverted on failure. */
-    if (!reuse) {
-        fd = qemuOpenFile(driver, vm, source, O_WRONLY | O_TRUNC | O_CREAT,
-                          &need_unlink, NULL);
-        if (fd < 0)
-            goto cleanup;
-        VIR_FORCE_CLOSE(fd);
-    }
-
     /* XXX Here, we know we are about to alter disk->backingChain if
-     * successful, so we nuke the existing chain so that future
-     * commands will recompute it.  Better would be storing the chain
-     * ourselves rather than reprobing, but this requires modifying
-     * domain_conf and our XML to fully track the chain across
-     * libvirtd restarts.  */
+     * successful, so we nuke the existing chain so that future commands will
+     * recompute it.  Better would be storing the chain ourselves rather than
+     * reprobing, but this requires modifying domain_conf and our XML to fully
+     * track the chain across libvirtd restarts.  */
     virStorageFileFreeMetadata(disk->backingChain);
     disk->backingChain = NULL;

-    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
-                                          VIR_DISK_CHAIN_READ_WRITE) < 0) {
-        qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
-                                          VIR_DISK_CHAIN_NO_ACCESS);
+    switch (snap->type) {
+    case VIR_DOMAIN_DISK_TYPE_BLOCK:
+        reuse = true;
+        /* fallthrough */
+    case -1: /* type was not provided in snapshot conf */
+    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. */
+        if (!reuse) {
+            fd = qemuOpenFile(driver, vm, source, O_WRONLY | O_TRUNC | O_CREAT,
+                              &need_unlink, NULL);
+            if (fd < 0)
+                goto cleanup;
+            VIR_FORCE_CLOSE(fd);
+        }
+
+        if (qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
+                                              VIR_DISK_CHAIN_READ_WRITE) < 0) {
+            qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
+                                              VIR_DISK_CHAIN_NO_ACCESS);
+            goto cleanup;
+        }
+        break;
+
+    default:
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+                       _("snapshots are not supported on '%s' volumes"),
+                       virDomainDiskTypeToString(snap->type));
         goto cleanup;
     }

@@ -12239,11 +12254,13 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
     disk->src = source;
     source = NULL;
     disk->format = format;
+    disk->type = snap->type;
     if (persistDisk) {
         VIR_FREE(persistDisk->src);
         persistDisk->src = persistSource;
         persistSource = NULL;
         persistDisk->format = format;
+        persistDisk->type = snap->type;
     }

 cleanup:
@@ -12285,11 +12302,13 @@ qemuDomainSnapshotUndoSingleDiskActive(virQEMUDriverPtr driver,
     disk->src = source;
     source = NULL;
     disk->format = origdisk->format;
+    disk->type = origdisk->type;
     if (persistDisk) {
         VIR_FREE(persistDisk->src);
         persistDisk->src = persistSource;
         persistSource = NULL;
         persistDisk->format = origdisk->format;
+        persistDisk->type = origdisk->type;
     }

 cleanup:
-- 
1.8.4.3




More information about the libvir-list mailing list