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>
...
<devices>
- <disk type='file'>
+ <disk type='file' snapshot='external'>
<driver name="tap" type="aio"
cache="default"/>
<source file='/var/lib/xen/images/fv0'/>
<target dev='hda' bus='ide'/>
@@ -910,8 +910,14 @@
</source>
<target dev="hdb" bus="ide"/>
<boot order='1'/>
+ <transient/>
<address type='drive' controller='0' bus='1'
unit='0'/>
</disk>
+ <disk type='block' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <target def='hdc' bus='ide'/>
+ <readonly/>
+ </disk>
</devices>
...</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