diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b960381c9f2e16c496658a856f4448fc6d1fa69f..b6e6de3994ee0a4a37b6e74030061a84f0cad54c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -889,7 +889,7 @@
   ...
   <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>
   ...
@@ -923,9 +929,23 @@ and refers to the underlying source for the disk. The optional device 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". - Since 0.0.3; "device" attribute since 0.1.4; - "network" attribute since 0.8.7 + and "cdrom", defaulting to "disk". The + optional snapshot 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 domain snapshot + creation. Not all snapshot modes are supported; + for example, snapshot='yes' with a transient disk + generally does not make sense. Since 0.0.3; + "device" attribute since 0.1.4; + "network" attribute since 0.8.7; "snapshot" since + 0.9.5
source
If the disk type is "file", then the file attribute specifies the fully-qualified @@ -1034,11 +1054,23 @@ the Storage Encryption page for more information.
+
readonly
+
If present, this indicates the device cannot be modified by + the guest. For now, this is the default for disks with + attribute type='cdrom'. +
shareable
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.
+
transient
+
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. Since 0.9.5 +
serial
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 8e7fd63de2237e68332dc5d267eac551c56da2c1..e622cede6fac4fef0c9b65e716a2b45a0e42ac14 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -616,6 +616,11 @@ + + + + + @@ -628,6 +633,15 @@ + + + + no + internal + external + + + @@ -667,6 +681,9 @@ + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index cce99556551e958c1fdd38195115b58d00c68b84..c9e6e38bfae5665fe2a4c8e64380725482d465eb 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -191,6 +191,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", @@ -2232,6 +2238,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; @@ -2265,6 +2272,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) { @@ -2366,6 +2375,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 */ @@ -2437,6 +2448,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, @@ -2582,6 +2605,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, cleanup: VIR_FREE(bus); VIR_FREE(type); + VIR_FREE(snapshot); VIR_FREE(target); VIR_FREE(source); while (nhosts > 0) { @@ -2607,7 +2631,7 @@ cleanup: no_memory: virReportOOMError(); - error: +error: virDomainDiskDefFree(def); def = NULL; goto cleanup; @@ -8996,8 +9020,13 @@ virDomainDiskDefFormat(virBufferPtr buf, } virBufferAsprintf(buf, - " \n", + " 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) { @@ -9071,6 +9100,8 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferAddLit(buf, " \n"); if (def->shared) virBufferAddLit(buf, " \n"); + if (def->transient) + virBufferAddLit(buf, " \n"); if (def->serial) virBufferEscapeString(buf, " %s\n", def->serial); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e218a302444ba1e6db332291de0bf9bc216044dd..7e09c0abb45aef8fbcedfa17d83eaefa97e5c790 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -244,6 +244,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; @@ -265,8 +274,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; }; @@ -1779,6 +1790,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 011f7522d0f2c378a30b7c28f0e58546265de93c..60e2f14e699eac9a65f8b4fb09e068b1ecb4c815 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -289,6 +289,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 0000000000000000000000000000000000000000..7e62942b6deea66f9f05163e3ec398ad1f1f0481 --- /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 0000000000000000000000000000000000000000..aeb2315caab9a3dac952f4fb932e0e013234a114 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-snapshot.xml @@ -0,0 +1,39 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + + +
+ + + + + + +
+ + + + + +
+ + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-transient.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-transient.xml new file mode 100644 index 0000000000000000000000000000000000000000..df49c4853dec92c74887e235a0034540b1433b4d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-transient.xml @@ -0,0 +1,27 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + + + +
+ + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 335af4a6b55f5a67dff1cbe8be1b849760a24008..fcb20bbd623f36b325a951f5529a53cd6ced59e0 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -362,6 +362,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,