Blame SOURCES/libvirt-snapshot-Add-support-for-specifying-snapshot-disk-backing-type.patch

c401cc
From 7e5acfbcb67f2afbc32d2d1371bccc0c96ca475f Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <7e5acfbcb67f2afbc32d2d1371bccc0c96ca475f@dist-git>
c401cc
From: Peter Krempa <pkrempa@redhat.com>
c401cc
Date: Wed, 26 Feb 2014 14:55:22 +0100
c401cc
Subject: [PATCH] snapshot: Add support for specifying snapshot disk backing
c401cc
 type
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
c401cc
c401cc
Add support for specifying various types when doing snapshots. This will
c401cc
later allow to do snapshots on network backed volumes. Disks of type
c401cc
'volume' are not supported by snapshots (yet).
c401cc
c401cc
Also amend the test suite to check parsing of the various new disk
c401cc
types that can now be specified.
c401cc
c401cc
(cherry picked from commit 7076b4b72ce65c43a88af6b11558ed37893af692)
c401cc
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 docs/formatsnapshot.html.in                        | 15 ++++++
c401cc
 docs/schemas/domainsnapshot.rng                    | 60 ++++++++++++++++++----
c401cc
 src/conf/snapshot_conf.c                           | 43 +++++++++-------
c401cc
 src/conf/snapshot_conf.h                           | 15 +++---
c401cc
 src/qemu/qemu_conf.c                               |  3 --
c401cc
 src/qemu/qemu_driver.c                             | 58 +++++++++++++--------
c401cc
 tests/domainsnapshotxml2xmlin/disk_snapshot.xml    | 18 +++++++
c401cc
 .../disk_driver_name_null.xml                      |  2 +-
c401cc
 tests/domainsnapshotxml2xmlout/disk_snapshot.xml   | 22 +++++++-
c401cc
 .../disk_snapshot_redefine.xml                     |  6 +--
c401cc
 10 files changed, 178 insertions(+), 64 deletions(-)
c401cc
c401cc
diff --git a/docs/formatsnapshot.html.in b/docs/formatsnapshot.html.in
c401cc
index 76689cb..44ed4fd 100644
c401cc
--- a/docs/formatsnapshot.html.in
c401cc
+++ b/docs/formatsnapshot.html.in
c401cc
@@ -170,6 +170,21 @@
c401cc
             snapshots, the original file name becomes the read-only
c401cc
             snapshot, and the new file name contains the read-write
c401cc
             delta of all disk changes since the snapshot.
c401cc
+
c401cc
+            Since 1.2.2 the disk element
c401cc
+            supports an optional attribute type if the
c401cc
+            snapshot attribute is set to external.
c401cc
+            This attribute specifies the snapshot target storage type and allows
c401cc
+            to overwrite the default file type. The type
c401cc
+            attribute along with the format of the source
c401cc
+            sub-element is identical to the source element used in
c401cc
+            domain disk definitions. See the
c401cc
+            disk devices section
c401cc
+            documentation for further information.
c401cc
+
c401cc
+            Libvirt currently supports the type element in the qemu
c401cc
+            driver and supported values are file and
c401cc
+            block (since 1.2.2).
c401cc
           
c401cc
         
c401cc
       
c401cc
diff --git a/docs/schemas/domainsnapshot.rng b/docs/schemas/domainsnapshot.rng
c401cc
index 169fcfb..824a186 100644
c401cc
--- a/docs/schemas/domainsnapshot.rng
c401cc
+++ b/docs/schemas/domainsnapshot.rng
c401cc
@@ -123,19 +123,57 @@
c401cc
               <value>external</value>
c401cc
             </attribute>
c401cc
           </optional>
c401cc
-          <interleave>
c401cc
-            <ref name='disksnapshotdriver'/>
c401cc
-            <optional>
c401cc
-              <element name='source'>
c401cc
+          <choice>
c401cc
+            <group>
c401cc
+              <optional>
c401cc
+                <attribute name='type'>
c401cc
+                  <value>file</value>
c401cc
+                </attribute>
c401cc
+              </optional>
c401cc
+              <interleave>
c401cc
                 <optional>
c401cc
-                  <attribute name='file'>
c401cc
-                    <ref name='absFilePath'/>
c401cc
-                  </attribute>
c401cc
+                  <element name='source'>
c401cc
+                    <optional>
c401cc
+                      <attribute name='file'>
c401cc
+                        <ref name='absFilePath'/>
c401cc
+                      </attribute>
c401cc
+                    </optional>
c401cc
+                    <empty/>
c401cc
+                  </element>
c401cc
                 </optional>
c401cc
-                <empty/>
c401cc
-              </element>
c401cc
-            </optional>
c401cc
-          </interleave>
c401cc
+                <ref name='disksnapshotdriver'/>
c401cc
+              </interleave>
c401cc
+            </group>
c401cc
+            <group>
c401cc
+              <attribute name='type'>
c401cc
+                <value>block</value>
c401cc
+              </attribute>
c401cc
+              <interleave>
c401cc
+                <optional>
c401cc
+                  <element name="source">
c401cc
+                    <attribute name="dev">
c401cc
+                      <ref name="absFilePath"/>
c401cc
+                    </attribute>
c401cc
+                    <empty/>
c401cc
+                  </element>
c401cc
+                </optional>
c401cc
+                <ref name='disksnapshotdriver'/>
c401cc
+              </interleave>
c401cc
+            </group>
c401cc
+            <group>
c401cc
+              <attribute name="type">
c401cc
+                <value>network</value>
c401cc
+              </attribute>
c401cc
+              <interleave>
c401cc
+                <optional>
c401cc
+                  <element name="source">
c401cc
+                    <ref name='diskSourceNetwork'/>
c401cc
+                  </element>
c401cc
+                </optional>
c401cc
+                <ref name='disksnapshotdriver'/>
c401cc
+              </interleave>
c401cc
+            </group>
c401cc
+          </choice>
c401cc
         </group>
c401cc
       </choice>
c401cc
     </element>
c401cc
diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
c401cc
index 3a7ed5d..3510677 100644
c401cc
--- a/src/conf/snapshot_conf.c
c401cc
+++ b/src/conf/snapshot_conf.c
c401cc
@@ -108,6 +108,7 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
c401cc
 {
c401cc
     int ret = -1;
c401cc
     char *snapshot = NULL;
c401cc
+    char *type = NULL;
c401cc
     xmlNodePtr cur;
c401cc
 
c401cc
     def->name = virXMLPropString(node, "name");
c401cc
@@ -128,7 +129,17 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
c401cc
         }
c401cc
     }
c401cc
 
c401cc
-    def->type = -1;
c401cc
+    if ((type = virXMLPropString(node, "type"))) {
c401cc
+        if ((def->type = virDomainDiskTypeFromString(type)) < 0 ||
c401cc
+            def->type == VIR_DOMAIN_DISK_TYPE_VOLUME ||
c401cc
+            def->type == VIR_DOMAIN_DISK_TYPE_DIR) {
c401cc
+            virReportError(VIR_ERR_XML_ERROR,
c401cc
+                           _("unknown disk snapshot type '%s'"), type);
c401cc
+            goto cleanup;
c401cc
+        }
c401cc
+    } else {
c401cc
+        def->type = VIR_DOMAIN_DISK_TYPE_FILE;
c401cc
+    }
c401cc
 
c401cc
     for (cur = node->children; cur; cur = cur->next) {
c401cc
         if (cur->type != XML_ELEMENT_NODE)
c401cc
@@ -137,17 +148,12 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
c401cc
         if (!def->file &&
c401cc
             xmlStrEqual(cur->name, BAD_CAST "source")) {
c401cc
 
c401cc
-            int backingtype = def->type;
c401cc
-
c401cc
-            if (backingtype < 0)
c401cc
-                backingtype = VIR_DOMAIN_DISK_TYPE_FILE;
c401cc
-
c401cc
             if (virDomainDiskSourceDefParse(cur,
c401cc
-                                            backingtype,
c401cc
+                                            def->type,
c401cc
                                             &def->file,
c401cc
-                                            NULL,
c401cc
-                                            NULL,
c401cc
-                                            NULL,
c401cc
+                                            &def->protocol,
c401cc
+                                            &def->nhosts,
c401cc
+                                            &def->hosts,
c401cc
                                             NULL) < 0)
c401cc
                 goto cleanup;
c401cc
 
c401cc
@@ -174,6 +180,7 @@ virDomainSnapshotDiskDefParseXML(xmlNodePtr node,
c401cc
     ret = 0;
c401cc
 cleanup:
c401cc
     VIR_FREE(snapshot);
c401cc
+    VIR_FREE(type);
c401cc
     if (ret < 0)
c401cc
         virDomainSnapshotDiskDefClear(def);
c401cc
     return ret;
c401cc
@@ -495,7 +502,7 @@ virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,
c401cc
             goto cleanup;
c401cc
         disk->index = i;
c401cc
         disk->snapshot = def->dom->disks[i]->snapshot;
c401cc
-        disk->type = -1;
c401cc
+        disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
c401cc
         if (!disk->snapshot)
c401cc
             disk->snapshot = default_snapshot;
c401cc
     }
c401cc
@@ -513,8 +520,7 @@ virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,
c401cc
             const char *tmp;
c401cc
             struct stat sb;
c401cc
 
c401cc
-            if (disk->type != VIR_DOMAIN_DISK_TYPE_FILE &&
c401cc
-                disk->type != -1) {
c401cc
+            if (disk->type != VIR_DOMAIN_DISK_TYPE_FILE) {
c401cc
                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
c401cc
                                _("cannot generate external snapshot name "
c401cc
                                  "for disk '%s' on a '%s' device"),
c401cc
@@ -577,15 +583,12 @@ virDomainSnapshotDiskDefFormat(virBufferPtr buf,
c401cc
         virBufferAsprintf(buf, " snapshot='%s'",
c401cc
                           virDomainSnapshotLocationTypeToString(disk->snapshot));
c401cc
 
c401cc
-    if (type < 0)
c401cc
-        type = VIR_DOMAIN_DISK_TYPE_FILE;
c401cc
-
c401cc
     if (!disk->file && disk->format == 0) {
c401cc
         virBufferAddLit(buf, "/>\n");
c401cc
         return;
c401cc
     }
c401cc
 
c401cc
-    virBufferAddLit(buf, ">\n");
c401cc
+    virBufferAsprintf(buf, " type='%s'>\n", virDomainDiskTypeToString(type));
c401cc
 
c401cc
     if (disk->format > 0)
c401cc
         virBufferEscapeString(buf, "      <driver type='%s'/>\n",
c401cc
@@ -593,7 +596,11 @@ virDomainSnapshotDiskDefFormat(virBufferPtr buf,
c401cc
     virDomainDiskSourceDefFormatInternal(buf,
c401cc
                                          type,
c401cc
                                          disk->file,
c401cc
-                                         0, 0, 0, NULL, 0, NULL, NULL, 0);
c401cc
+                                         0,
c401cc
+                                         disk->protocol,
c401cc
+                                         disk->nhosts,
c401cc
+                                         disk->hosts,
c401cc
+                                         0, NULL, NULL, 0);
c401cc
 
c401cc
     virBufferAddLit(buf, "    </disk>\n");
c401cc
 }
c401cc
diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h
c401cc
index 9ed80b2..12ece0c 100644
c401cc
--- a/src/conf/snapshot_conf.h
c401cc
+++ b/src/conf/snapshot_conf.h
c401cc
@@ -48,12 +48,15 @@ enum virDomainSnapshotState {
c401cc
 typedef struct _virDomainSnapshotDiskDef virDomainSnapshotDiskDef;
c401cc
 typedef virDomainSnapshotDiskDef *virDomainSnapshotDiskDefPtr;
c401cc
 struct _virDomainSnapshotDiskDef {
c401cc
-    char *name; /* name matching the 
c401cc
-    int index; /* index within snapshot->dom->disks that matches name */
c401cc
-    int snapshot; /* enum virDomainSnapshotLocation */
c401cc
-    int type; /* enum virDomainDiskType */
c401cc
-    char *file; /* new source file when snapshot is external */
c401cc
-    int format; /* enum virStorageFileFormat */
c401cc
+    char *name;     /* name matching the 
c401cc
+    int index;      /* index within snapshot->dom->disks that matches name */
c401cc
+    int snapshot;   /* enum virDomainSnapshotLocation */
c401cc
+    int type;       /* enum virDomainDiskType */
c401cc
+    char *file;     /* new source file when snapshot is external */
c401cc
+    int format;     /* enum virStorageFileFormat */
c401cc
+    int protocol;   /* network source protocol */
c401cc
+    size_t nhosts;  /* network source hosts count */
c401cc
+    virDomainDiskHostDefPtr hosts; /* network source hosts */
c401cc
 };
c401cc
 
c401cc
 /* Stores the complete snapshot metadata */
c401cc
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
c401cc
index 1f25675..af1e3be 100644
c401cc
--- a/src/qemu/qemu_conf.c
c401cc
+++ b/src/qemu/qemu_conf.c
c401cc
@@ -1442,9 +1442,6 @@ cleanup:
c401cc
 int
c401cc
 qemuSnapshotDiskGetActualType(virDomainSnapshotDiskDefPtr def)
c401cc
 {
c401cc
-    if (def->type == -1)
c401cc
-        return VIR_DOMAIN_DISK_TYPE_FILE;
c401cc
-
c401cc
     return def->type;
c401cc
 }
c401cc
 
c401cc
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
c401cc
index 1c9b190..641d118 100644
c401cc
--- a/src/qemu/qemu_driver.c
c401cc
+++ b/src/qemu/qemu_driver.c
c401cc
@@ -12529,33 +12529,47 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
c401cc
     }
c401cc
 
c401cc
     if (virAsprintf(&device, "drive-%s", disk->info.alias) < 0 ||
c401cc
-        VIR_STRDUP(source, snap->file) < 0 ||
c401cc
         (persistDisk && VIR_STRDUP(persistSource, source) < 0))
c401cc
         goto cleanup;
c401cc
 
c401cc
-    /* create the stub file and set selinux labels; manipulate disk in
c401cc
-     * place, in a way that can be reverted on failure. */
c401cc
-    if (!reuse) {
c401cc
-        fd = qemuOpenFile(driver, vm, source, O_WRONLY | O_TRUNC | O_CREAT,
c401cc
-                          &need_unlink, NULL);
c401cc
-        if (fd < 0)
c401cc
-            goto cleanup;
c401cc
-        VIR_FORCE_CLOSE(fd);
c401cc
-    }
c401cc
-
c401cc
     /* XXX Here, we know we are about to alter disk->backingChain if
c401cc
-     * successful, so we nuke the existing chain so that future
c401cc
-     * commands will recompute it.  Better would be storing the chain
c401cc
-     * ourselves rather than reprobing, but this requires modifying
c401cc
-     * domain_conf and our XML to fully track the chain across
c401cc
-     * libvirtd restarts.  */
c401cc
+     * successful, so we nuke the existing chain so that future commands will
c401cc
+     * recompute it.  Better would be storing the chain ourselves rather than
c401cc
+     * reprobing, but this requires modifying domain_conf and our XML to fully
c401cc
+     * track the chain across libvirtd restarts.  */
c401cc
     virStorageFileFreeMetadata(disk->backingChain);
c401cc
     disk->backingChain = NULL;
c401cc
 
c401cc
-    if (qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
c401cc
-                                          VIR_DISK_CHAIN_READ_WRITE) < 0) {
c401cc
-        qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
c401cc
-                                          VIR_DISK_CHAIN_NO_ACCESS);
c401cc
+    switch (snap->type) {
c401cc
+    case VIR_DOMAIN_DISK_TYPE_BLOCK:
c401cc
+        reuse = true;
c401cc
+        /* fallthrough */
c401cc
+    case VIR_DOMAIN_DISK_TYPE_FILE:
c401cc
+        if (VIR_STRDUP(source, snap->file) < 0)
c401cc
+            goto cleanup;
c401cc
+
c401cc
+        /* create the stub file and set selinux labels; manipulate disk in
c401cc
+         * place, in a way that can be reverted on failure. */
c401cc
+        if (!reuse) {
c401cc
+            fd = qemuOpenFile(driver, vm, source, O_WRONLY | O_TRUNC | O_CREAT,
c401cc
+                              &need_unlink, NULL);
c401cc
+            if (fd < 0)
c401cc
+                goto cleanup;
c401cc
+            VIR_FORCE_CLOSE(fd);
c401cc
+        }
c401cc
+
c401cc
+        if (qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
c401cc
+                                              VIR_DISK_CHAIN_READ_WRITE) < 0) {
c401cc
+            qemuDomainPrepareDiskChainElement(driver, vm, disk, source,
c401cc
+                                              VIR_DISK_CHAIN_NO_ACCESS);
c401cc
+            goto cleanup;
c401cc
+        }
c401cc
+        break;
c401cc
+
c401cc
+    default:
c401cc
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
c401cc
+                       _("snapshots are not supported on '%s' volumes"),
c401cc
+                       virDomainDiskTypeToString(snap->type));
c401cc
         goto cleanup;
c401cc
     }
c401cc
 
c401cc
@@ -12591,11 +12605,13 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
c401cc
     disk->src = source;
c401cc
     source = NULL;
c401cc
     disk->format = format;
c401cc
+    disk->type = snap->type;
c401cc
     if (persistDisk) {
c401cc
         VIR_FREE(persistDisk->src);
c401cc
         persistDisk->src = persistSource;
c401cc
         persistSource = NULL;
c401cc
         persistDisk->format = format;
c401cc
+        persistDisk->type = snap->type;
c401cc
     }
c401cc
 
c401cc
 cleanup:
c401cc
@@ -12637,11 +12653,13 @@ qemuDomainSnapshotUndoSingleDiskActive(virQEMUDriverPtr driver,
c401cc
     disk->src = source;
c401cc
     source = NULL;
c401cc
     disk->format = origdisk->format;
c401cc
+    disk->type = origdisk->type;
c401cc
     if (persistDisk) {
c401cc
         VIR_FREE(persistDisk->src);
c401cc
         persistDisk->src = persistSource;
c401cc
         persistSource = NULL;
c401cc
         persistDisk->format = origdisk->format;
c401cc
+        persistDisk->type = origdisk->type;
c401cc
     }
c401cc
 
c401cc
 cleanup:
c401cc
diff --git a/tests/domainsnapshotxml2xmlin/disk_snapshot.xml b/tests/domainsnapshotxml2xmlin/disk_snapshot.xml
c401cc
index ee6b46a..aa1522a 100644
c401cc
--- a/tests/domainsnapshotxml2xmlin/disk_snapshot.xml
c401cc
+++ b/tests/domainsnapshotxml2xmlin/disk_snapshot.xml
c401cc
@@ -12,5 +12,23 @@
c401cc
     <disk name='hde' snapshot='external'>
c401cc
       <source file='/path/to/new'/>
c401cc
     </disk>
c401cc
+    <disk name='hde' snapshot='external' type='file'>
c401cc
+      <source file='/path/to/new2'/>
c401cc
+    </disk>
c401cc
+    <disk name='hdf' snapshot='external' type='block'>
c401cc
+      <source dev='/path/to/new3'/>
c401cc
+    </disk>
c401cc
+    <disk name='hdg' snapshot='external' type='network'>
c401cc
+      <source protocol='gluster' name='volume/path'>
c401cc
+        <host name='host' port='1234'/>
c401cc
+      </source>
c401cc
+    </disk>
c401cc
+    <disk name='hdh' snapshot='external' type='network'>
c401cc
+      <source protocol='rbd' name='name'>
c401cc
+        <host name='host' port='1234'/>
c401cc
+        <host name='host2' port='1234' transport='rdma'/>
c401cc
+        <host name='host3' port='1234'/>
c401cc
+      </source>
c401cc
+    </disk>
c401cc
   </disks>
c401cc
 </domainsnapshot>
c401cc
diff --git a/tests/domainsnapshotxml2xmlout/disk_driver_name_null.xml b/tests/domainsnapshotxml2xmlout/disk_driver_name_null.xml
c401cc
index 41961f1..ddd350d 100644
c401cc
--- a/tests/domainsnapshotxml2xmlout/disk_driver_name_null.xml
c401cc
+++ b/tests/domainsnapshotxml2xmlout/disk_driver_name_null.xml
c401cc
@@ -2,7 +2,7 @@
c401cc
   <name>asdf</name>
c401cc
   <description>adsf</description>
c401cc
   <disks>
c401cc
-    <disk name='vda' snapshot='external'>
c401cc
+    <disk name='vda' snapshot='external' type='file'>
c401cc
       <source file='/tmp/foo'/>
c401cc
     </disk>
c401cc
   </disks>
c401cc
diff --git a/tests/domainsnapshotxml2xmlout/disk_snapshot.xml b/tests/domainsnapshotxml2xmlout/disk_snapshot.xml
c401cc
index 1a1fc02..c2e77d7 100644
c401cc
--- a/tests/domainsnapshotxml2xmlout/disk_snapshot.xml
c401cc
+++ b/tests/domainsnapshotxml2xmlout/disk_snapshot.xml
c401cc
@@ -5,11 +5,29 @@
c401cc
     <disk name='/dev/HostVG/QEMUGuest1'/>
c401cc
     <disk name='hdb' snapshot='no'/>
c401cc
     <disk name='hdc' snapshot='internal'/>
c401cc
-    <disk name='hdd' snapshot='external'>
c401cc
+    <disk name='hdd' snapshot='external' type='file'>
c401cc
       <driver type='qed'/>
c401cc
     </disk>
c401cc
-    <disk name='hde' snapshot='external'>
c401cc
+    <disk name='hde' snapshot='external' type='file'>
c401cc
       <source file='/path/to/new'/>
c401cc
     </disk>
c401cc
+    <disk name='hde' snapshot='external' type='file'>
c401cc
+      <source file='/path/to/new2'/>
c401cc
+    </disk>
c401cc
+    <disk name='hdf' snapshot='external' type='block'>
c401cc
+      <source dev='/path/to/new3'/>
c401cc
+    </disk>
c401cc
+    <disk name='hdg' snapshot='external' type='network'>
c401cc
+      <source protocol='gluster' name='volume/path'>
c401cc
+        <host name='host' port='1234'/>
c401cc
+      </source>
c401cc
+    </disk>
c401cc
+    <disk name='hdh' snapshot='external' type='network'>
c401cc
+      <source protocol='rbd' name='name'>
c401cc
+        <host name='host' port='1234'/>
c401cc
+        <host name='host2' port='1234' transport='rdma'/>
c401cc
+        <host name='host3' port='1234'/>
c401cc
+      </source>
c401cc
+    </disk>
c401cc
   </disks>
c401cc
 </domainsnapshot>
c401cc
diff --git a/tests/domainsnapshotxml2xmlout/disk_snapshot_redefine.xml b/tests/domainsnapshotxml2xmlout/disk_snapshot_redefine.xml
c401cc
index 5f42bf5..c267db5 100644
c401cc
--- a/tests/domainsnapshotxml2xmlout/disk_snapshot_redefine.xml
c401cc
+++ b/tests/domainsnapshotxml2xmlout/disk_snapshot_redefine.xml
c401cc
@@ -11,15 +11,15 @@
c401cc
     <disk name='hda' snapshot='no'/>
c401cc
     <disk name='hdb' snapshot='no'/>
c401cc
     <disk name='hdc' snapshot='internal'/>
c401cc
-    <disk name='hdd' snapshot='external'>
c401cc
+    <disk name='hdd' snapshot='external' type='file'>
c401cc
       <driver type='qed'/>
c401cc
       <source file='/path/to/generated4'/>
c401cc
     </disk>
c401cc
-    <disk name='hde' snapshot='external'>
c401cc
+    <disk name='hde' snapshot='external' type='file'>
c401cc
       <driver type='qcow2'/>
c401cc
       <source file='/path/to/new'/>
c401cc
     </disk>
c401cc
-    <disk name='hdf' snapshot='external'>
c401cc
+    <disk name='hdf' snapshot='external' type='file'>
c401cc
       <driver type='qcow2'/>
c401cc
       <source file='/path/to/generated5'/>
c401cc
     </disk>
c401cc
-- 
c401cc
1.9.0
c401cc