<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'/>
</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>
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
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
<empty/>
</element>
</optional>
+ <optional>
+ <element name="transient">
+ <empty/>
+ </element>
+ </optional>
<optional>
<element name="serial">
<ref name="diskSerial"/>
<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">
</choice>
</attribute>
</optional>
+ <optional>
+ <ref name="snapshot"/>
+ </optional>
<choice>
<group>
<attribute name="type">
"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",
xmlNodePtr cur, host;
char *type = NULL;
char *device = NULL;
+ char *snapshot = NULL;
char *driverName = NULL;
char *driverType = NULL;
char *source = NULL;
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
}
+ snapshot = virXMLPropString(node, "snapshot");
+
cur = node->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE) {
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 */
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,
cleanup:
VIR_FREE(bus);
VIR_FREE(type);
+ VIR_FREE(snapshot);
VIR_FREE(target);
VIR_FREE(source);
while (nhosts > 0) {
no_memory:
virReportOOMError();
- error:
+error:
virDomainDiskDefFree(def);
def = NULL;
goto cleanup;
}
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) {
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);
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;
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;
};
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)
virDomainDiskIoTypeToString;
virDomainDiskRemove;
virDomainDiskRemoveByName;
+virDomainDiskSnapshotTypeFromString;
+virDomainDiskSnapshotTypeToString;
virDomainDiskTypeFromString;
virDomainDiskTypeToString;
virDomainFSDefFree;
--- /dev/null
+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
--- /dev/null
+<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>
--- /dev/null
+<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>
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,