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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list