First cut at allowing snapshot branch creation. For now, the code
requires that the snapshot be created but not activated (thus leaving
the user on the original branch); this is because activating the
new branch will require shared code with revert. Of course, until
we allow reverting to a snapshot branch, this functionality feels
more like a write-only interface (we can create the snapshot but not
use it); but one thing at a time.
* src/qemu/qemu_driver.c (qemuDomainSnapshotCreateXML): Support
new flag.
(qemuDomainSnapshotPrepare): Likewise.
---
src/qemu/qemu_driver.c | 47 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 41 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f5bbc52..a17ab62 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10901,7 +10901,8 @@ qemuDomainSnapshotPrepare(virDomainObjPtr vm,
virDomainSnapshotDefPtr def,
qemuDomainObjPrivatePtr priv = vm->privateData;
if (def->state == VIR_DOMAIN_DISK_SNAPSHOT &&
- reuse && !qemuCapsGet(priv->caps, QEMU_CAPS_TRANSACTION)) {
+ reuse && !qemuCapsGet(priv->caps, QEMU_CAPS_TRANSACTION) &&
+ !(*flags & VIR_DOMAIN_SNAPSHOT_CREATE_BRANCH)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("reuse is not supported with this QEMU binary"));
goto cleanup;
@@ -11015,7 +11016,8 @@ qemuDomainSnapshotPrepare(virDomainObjPtr vm,
virDomainSnapshotDefPtr def,
if (external && !active)
*flags |= VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY;
- if (def->state != VIR_DOMAIN_DISK_SNAPSHOT && active) {
+ if (def->state != VIR_DOMAIN_DISK_SNAPSHOT && active &&
+ !(*flags & VIR_DOMAIN_SNAPSHOT_CREATE_BRANCH)) {
if (external == 1 ||
qemuCapsGet(priv->caps, QEMU_CAPS_TRANSACTION)) {
*flags |= VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC;
@@ -11464,7 +11466,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT |
VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE |
VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC |
- VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, NULL);
+ VIR_DOMAIN_SNAPSHOT_CREATE_LIVE |
+ VIR_DOMAIN_SNAPSHOT_CREATE_BRANCH, NULL);
if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY)) {
@@ -11473,12 +11476,15 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
return NULL;
}
- if (((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
+ if (((flags & (VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
+ VIR_DOMAIN_SNAPSHOT_CREATE_BRANCH)) &&
!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) ||
(flags & VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA))
update_current = false;
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)
parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE;
+ else if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_BRANCH)
+ parse_flags |= VIR_DOMAIN_SNAPSHOT_PARSE_BRANCH;
qemuDriverLock(driver);
virUUIDFormat(domain->uuid, uuidstr);
@@ -11519,7 +11525,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE &&
(!virDomainObjIsActive(vm) ||
def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL ||
- flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
+ flags & (VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
+ VIR_DOMAIN_SNAPSHOT_CREATE_BRANCH))) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("live snapshot creation is supported only "
"with external checkpoints"));
@@ -11636,6 +11643,22 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
align_match) < 0)
goto cleanup;
}
+ } else if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_BRANCH) {
+ /* XXX For now, we require that the new branch is not current
+ * (getting that to work will require sharing code with
+ * snapshot revert for (re-)starting the domain with correct
+ * events). */
+ if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("branch snapshot creation does not yet support "
+ "the current flag"));
+ goto cleanup;
+ }
+ /* def->dom was already populated, and the disks aligned; but
+ * we still need to check that we can create the new disk
+ * wrappers. */
+ if (qemuDomainSnapshotPrepare(vm, def, &flags) < 0)
+ goto cleanup;
} else {
/* Easiest way to clone inactive portion of vm->def is via
* conversion in and back out of xml. */
@@ -11678,7 +11701,8 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
if (update_current)
snap->def->current = true;
if (vm->current_snapshot) {
- if (!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
+ if (!(flags & (VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
+ VIR_DOMAIN_SNAPSHOT_CREATE_BRANCH))) {
snap->def->parent = strdup(vm->current_snapshot->def->name);
if (snap->def->parent == NULL) {
virReportOOMError();
@@ -11699,6 +11723,17 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
/* XXX Should we validate that the redefined snapshot even
* makes sense, such as checking that qemu-img recognizes the
* snapshot name in at least one of the domain's disks? */
+ } else if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_BRANCH) {
+ /* Whether or not the domain is online or the snapshot was
+ * from a running state, we reuse the offline creation code to
+ * create the new qcow2 files. */
+ bool reuse = !!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT);
+
+ if (qemuDomainSnapshotCreateInactiveExternal(driver, vm, snap,
+ reuse) < 0)
+ goto cleanup;
+ /* XXX Figure out how to support _CURRENT by reusing code from
+ * revert to swap over to the just-created snapshot. */
} else if (virDomainObjIsActive(vm)) {
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY ||
snap->def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
--
1.7.11.7