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:
<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.
---
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 ++
5 files changed, 100 insertions(+), 6 deletions(-)
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 ade8a02..d2800d2 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;
@@ -8643,8 +8667,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) {
@@ -8718,6 +8747,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 93bb7c8..7dbf353 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;
};
@@ -1689,6 +1700,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 0d8aa99..6e313a9 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -286,6 +286,8 @@ virDomainDiskIoTypeFromString;
virDomainDiskIoTypeToString;
virDomainDiskRemove;
virDomainDiskRemoveByName;
+virDomainDiskSnapshotTypeFromString;
+virDomainDiskSnapshotTypeToString;
virDomainDiskTypeFromString;
virDomainDiskTypeToString;
virDomainFSDefFree;
--
1.7.4.4