[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCHv4 35/51] snapshot: additions to domain xml for disks



As discussed here:
https://www.redhat.com/archives/libvir-list/2011-August/msg00361.html
https://www.redhat.com/archives/libvir-list/2011-August/msg00552.html

Adds snapshot attribute and transient sub-element:

<devices>
  <disk type=... snapshot='no|internal|external'>
    ...
    <transient/>
  </disk>
</devices>

* docs/schemas/domaincommon.rng (snapshot): New define.
(disk): Add snapshot and persistent attributes.
* docs/formatdomain.html.in: Document them.
* src/conf/domain_conf.h (virDomainDiskSnapshot): New enum.
(_virDomainDiskDef): New fields.
* tests/qemuxml2argvdata/qemuxml2argv-disk-transient.xml: New
test of rng, no args counterpart until qemu support is complete.
* tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.args: New
file, snapshot attribute does not affect args.
* tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.xml: Likewise.
* tests/qemuxml2argvtest.c (mymain): Run new test.
---
 docs/formatdomain.html.in                          |   40 ++++++++++++++++++--
 docs/schemas/domaincommon.rng                      |   17 ++++++++
 src/conf/domain_conf.c                             |   35 ++++++++++++++++-
 src/conf/domain_conf.h                             |   12 ++++++
 src/libvirt_private.syms                           |    2 +
 .../qemuxml2argv-disk-snapshot.args                |    7 +++
 .../qemuxml2argv-disk-snapshot.xml                 |   39 +++++++++++++++++++
 .../qemuxml2argv-disk-transient.xml                |   27 +++++++++++++
 tests/qemuxml2argvtest.c                           |    2 +
 9 files changed, 175 insertions(+), 6 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-transient.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index f46771d..911dee5 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -889,7 +889,7 @@
 <pre>
   ...
   &lt;devices&gt;
-    &lt;disk type='file'&gt;
+    &lt;disk type='file' snapshot='external'&gt;
       &lt;driver name="tap" type="aio" cache="default"/&gt;
       &lt;source file='/var/lib/xen/images/fv0'/&gt;
       &lt;target dev='hda' bus='ide'/&gt;
@@ -910,8 +910,14 @@
       &lt;/source&gt;
       &lt;target dev="hdb" bus="ide"/&gt;
       &lt;boot order='1'/&gt;
+      &lt;transient/&gt;
       &lt;address type='drive' controller='0' bus='1' unit='0'/&gt;
     &lt;/disk&gt;
+    &lt;disk type='block' device='cdrom'&gt;
+      &lt;driver name='qemu' type='raw'/&gt;
+      &lt;target def='hdc' bus='ide'/&gt;
+      &lt;readonly/&gt;
+    &lt;/disk&gt;
   &lt;/devices&gt;
   ...</pre>

@@ -923,9 +929,23 @@
         and refers to the underlying source for the disk. The optional
         <code>device</code> attribute indicates how the disk is to be exposed
         to the guest OS. Possible values for this attribute are "floppy", "disk"
-        and "cdrom", defaulting to "disk".
-        <span class="since">Since 0.0.3; "device" attribute since 0.1.4;
-        "network" attribute since 0.8.7</span></dd>
+        and "cdrom", defaulting to "disk".  The
+        optional <code>snapshot</code> attribute indicates the default
+        behavior of the disk during disk snapshots: "internal"
+        requires a file format such as qcow2 that can store both the
+        snapshot and the data changes since the snapshot;
+        "external" will separate the snapshot from the live data; and
+        "no" means the disk will not participate in snapshots.
+        Read-only disks default to "no", while the default for other
+        disks depends on the hypervisor's capabilities.  Some
+        hypervisors allow a per-snapshot choice as well,
+        during <a href="formatsnapshot.html">domain snapshot
+        creation</a>.  Not all snapshot modes are supported;
+        for example, <code>snapshot='yes'</code> with a transient disk
+        generally does not make sense.  <span class="since">Since 0.0.3;
+        "device" attribute since 0.1.4;
+        "network" attribute since 0.8.7; "snapshot" since
+        0.9.5</span></dd>
       <dt><code>source</code></dt>
       <dd>If the disk <code>type</code> is "file", then
         the <code>file</code> attribute specifies the fully-qualified
@@ -1032,11 +1052,23 @@
         the <a href="formatstorageencryption.html">Storage Encryption</a> page
         for more information.
       </dd>
+      <dt><code>readonly</code></dt>
+      <dd>If present, this indicates the device cannot be modified by
+        the guest.  For now, this is the default for disks with
+        attribute <code>type='cdrom'</code>.
+      </dd>
       <dt><code>shareable</code></dt>
       <dd>If present, this indicates the device is expected to be shared
           between domains (assuming the hypervisor and OS support this),
           which means that caching should be deactivated for that device.
       </dd>
+      <dt><code>transient</code></dt>
+      <dd>If present, this indicates that changes to the device
+        contents should be reverted automatically when the guest
+        exits.  With some hypervisors, marking a disk transient
+        prevents the domain from participating in migration or
+        snapshots. <span class="since">Since 0.9.5</span>
+      </dd>
       <dt><code>serial</code></dt>
       <dd>If present, this specify serial number of virtual hard drive.
           For example, it may look
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 756e892..0af9e0f 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -617,6 +617,11 @@
       </element>
     </optional>
     <optional>
+      <element name="transient">
+        <empty/>
+      </element>
+    </optional>
+    <optional>
       <element name="serial">
         <ref name="diskSerial"/>
       </element>
@@ -628,6 +633,15 @@
       <ref name="address"/>
     </optional>
   </define>
+  <define name="snapshot">
+    <attribute name="snapshot">
+      <choice>
+        <value>no</value>
+        <value>internal</value>
+        <value>external</value>
+      </choice>
+    </attribute>
+  </define>

   <define name="lease">
     <element name="lease">
@@ -667,6 +681,9 @@
           </choice>
         </attribute>
       </optional>
+      <optional>
+        <ref name="snapshot"/>
+      </optional>
       <choice>
         <group>
           <attribute name="type">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d8f1a54..36a8252 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -187,6 +187,12 @@ VIR_ENUM_IMPL(virDomainVirtioEventIdx, VIR_DOMAIN_VIRTIO_EVENT_IDX_LAST,
               "on",
               "off")

+VIR_ENUM_IMPL(virDomainDiskSnapshot, VIR_DOMAIN_DISK_SNAPSHOT_LAST,
+              "default",
+              "no",
+              "internal",
+              "external")
+
 VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
               "ide",
               "fdc",
@@ -2073,6 +2079,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
     xmlNodePtr cur, host;
     char *type = NULL;
     char *device = NULL;
+    char *snapshot = NULL;
     char *driverName = NULL;
     char *driverType = NULL;
     char *source = NULL;
@@ -2106,6 +2113,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
         def->type = VIR_DOMAIN_DISK_TYPE_FILE;
     }

+    snapshot = virXMLPropString(node, "snapshot");
+
     cur = node->children;
     while (cur != NULL) {
         if (cur->type == XML_ELEMENT_NODE) {
@@ -2207,6 +2216,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
                 def->readonly = 1;
             } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
                 def->shared = 1;
+            } else if (xmlStrEqual(cur->name, BAD_CAST "transient")) {
+                def->transient = 1;
             } else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
                        xmlStrEqual(cur->name, BAD_CAST "state")) {
                 /* Legacy back-compat. Don't add any more attributes here */
@@ -2278,6 +2289,18 @@ virDomainDiskDefParseXML(virCapsPtr caps,
         goto error;
     }

+    if (snapshot) {
+        def->snapshot = virDomainDiskSnapshotTypeFromString(snapshot);
+        if (def->snapshot <= 0) {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 _("unknown disk snapshot setting '%s'"),
+                                 snapshot);
+            goto error;
+        }
+    } else if (def->readonly) {
+        def->snapshot = VIR_DOMAIN_DISK_SNAPSHOT_NO;
+    }
+
     if (bus) {
         if ((def->bus = virDomainDiskBusTypeFromString(bus)) < 0) {
             virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -2423,6 +2446,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
 cleanup:
     VIR_FREE(bus);
     VIR_FREE(type);
+    VIR_FREE(snapshot);
     VIR_FREE(target);
     VIR_FREE(source);
     while (nhosts > 0) {
@@ -2448,7 +2472,7 @@ cleanup:
 no_memory:
     virReportOOMError();

- error:
+error:
     virDomainDiskDefFree(def);
     def = NULL;
     goto cleanup;
@@ -8638,8 +8662,13 @@ virDomainDiskDefFormat(virBufferPtr buf,
     }

     virBufferAsprintf(buf,
-                      "    <disk type='%s' device='%s'>\n",
+                      "    <disk type='%s' device='%s'",
                       type, device);
+    if (def->snapshot &&
+        !(def->snapshot == VIR_DOMAIN_DISK_SNAPSHOT_NO && def->readonly))
+        virBufferAsprintf(buf, " snapshot='%s'",
+                          virDomainDiskSnapshotTypeToString(def->snapshot));
+    virBufferAddLit(buf, ">\n");

     if (def->driverName || def->driverType || def->cachemode ||
         def->ioeventfd || def->event_idx) {
@@ -8713,6 +8742,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
         virBufferAddLit(buf, "      <readonly/>\n");
     if (def->shared)
         virBufferAddLit(buf, "      <shareable/>\n");
+    if (def->transient)
+        virBufferAddLit(buf, "      <transient/>\n");
     if (def->serial)
         virBufferEscapeString(buf, "      <serial>%s</serial>\n",
                               def->serial);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 54244be..1be7ed9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -217,6 +217,15 @@ enum virDomainVirtioEventIdx {
     VIR_DOMAIN_VIRTIO_EVENT_IDX_LAST
 };

+enum virDomainDiskSnapshot {
+    VIR_DOMAIN_DISK_SNAPSHOT_DEFAULT = 0,
+    VIR_DOMAIN_DISK_SNAPSHOT_NO,
+    VIR_DOMAIN_DISK_SNAPSHOT_INTERNAL,
+    VIR_DOMAIN_DISK_SNAPSHOT_EXTERNAL,
+
+    VIR_DOMAIN_DISK_SNAPSHOT_LAST
+};
+
 /* Stores the virtual disk configuration */
 typedef struct _virDomainDiskDef virDomainDiskDef;
 typedef virDomainDiskDef *virDomainDiskDefPtr;
@@ -238,8 +247,10 @@ struct _virDomainDiskDef {
     int iomode;
     int ioeventfd;
     int event_idx;
+    int snapshot; /* enum virDomainDiskSnapshot */
     unsigned int readonly : 1;
     unsigned int shared : 1;
+    unsigned int transient : 1;
     virDomainDeviceInfo info;
     virStorageEncryptionPtr encryption;
 };
@@ -1693,6 +1704,7 @@ VIR_ENUM_DECL(virDomainDiskCache)
 VIR_ENUM_DECL(virDomainDiskErrorPolicy)
 VIR_ENUM_DECL(virDomainDiskProtocol)
 VIR_ENUM_DECL(virDomainDiskIo)
+VIR_ENUM_DECL(virDomainDiskSnapshot)
 VIR_ENUM_DECL(virDomainIoEventFd)
 VIR_ENUM_DECL(virDomainVirtioEventIdx)
 VIR_ENUM_DECL(virDomainController)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 94e28e4..9f6c784 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -286,6 +286,8 @@ virDomainDiskIoTypeFromString;
 virDomainDiskIoTypeToString;
 virDomainDiskRemove;
 virDomainDiskRemoveByName;
+virDomainDiskSnapshotTypeFromString;
+virDomainDiskSnapshotTypeToString;
 virDomainDiskTypeFromString;
 virDomainDiskTypeToString;
 virDomainFSDefFree;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.args
new file mode 100644
index 0000000..7e62942
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.args
@@ -0,0 +1,7 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
+pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi -boot c \
+-drive file=/dev/HostVG/QEMUGuest1,if=ide,bus=0,unit=0,format=qcow2,cache=none \
+-drive file=/dev/HostVG/QEMUGuest3,if=ide,bus=2,unit=0,format=qcow2,cache=none \
+-drive file=/dev/HostVG/QEMUGuest2,if=ide,media=cdrom,bus=1,unit=0,format=raw \
+-net none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.xml
new file mode 100644
index 0000000..aeb2315
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.xml
@@ -0,0 +1,39 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk' snapshot='internal'>
+      <driver name='qemu' type='qcow2' cache='none'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <disk type='block' device='cdrom' snapshot='no'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest2'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+    <disk type='block' device='disk' snapshot='external'>
+      <driver name='qemu' type='qcow2' cache='none'/>
+      <source dev='/dev/HostVG/QEMUGuest3'/>
+      <target dev='hdb' bus='ide'/>
+      <address type='drive' controller='0' bus='2' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-transient.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-transient.xml
new file mode 100644
index 0000000..df49c48
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-transient.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <driver name='qemu' type='qcow2' cache='none'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <transient/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 6e8da5e..c7b1707 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -359,6 +359,8 @@ mymain(void)
     DO_TEST("disk-ioeventfd", false,
             QEMU_CAPS_DRIVE, QEMU_CAPS_VIRTIO_IOEVENTFD,
             QEMU_CAPS_VIRTIO_TX_ALG, QEMU_CAPS_DEVICE);
+    DO_TEST("disk-snapshot", false,
+            QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_CACHE_V2, QEMU_CAPS_DRIVE_FORMAT);
     DO_TEST("event_idx", false,
             QEMU_CAPS_DRIVE,
             QEMU_CAPS_VIRTIO_BLK_EVENT_IDX,
-- 
1.7.4.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]