Offline internal snapshots can be rolled back with just a little
bit of refactoring, meaning that we are now automatically atomic.
* src/qemu/qemu_domain.c (qemuDomainSnapshotForEachQcow2): Move
guts...
(qemuDomainSnapshotForEachQcow2Raw): ...to new helper, to allow
rollbacks.
* src/qemu/qemu_driver.c (qemuDomainSnapshotCreateXML): Offline
snapshots are now atomic.
---
v2: new patch.
src/qemu/qemu_domain.c | 55 ++++++++++++++++++++++++++++++-----------------
src/qemu/qemu_driver.c | 6 -----
2 files changed, 35 insertions(+), 26 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 625c595..a845480 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1,7 +1,7 @@
/*
* qemu_domain.h: QEMU domain private state
*
- * Copyright (C) 2006-2011 Red Hat, Inc.
+ * Copyright (C) 2006-2012 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -1489,24 +1489,17 @@ cleanup:
/* The domain is expected to be locked and inactive. Return -1 on normal
* failure, 1 if we skipped a disk due to try_all. */
-int
-qemuDomainSnapshotForEachQcow2(struct qemud_driver *driver,
- virDomainObjPtr vm,
- virDomainSnapshotObjPtr snap,
- const char *op,
- bool try_all)
+static int
+qemuDomainSnapshotForEachQcow2Raw(struct qemud_driver *driver,
+ virDomainDefPtr def,
+ const char *name,
+ const char *op,
+ bool try_all,
+ int ndisks)
{
const char *qemuimgarg[] = { NULL, "snapshot", NULL, NULL, NULL, NULL };
int i;
bool skipped = false;
- virDomainDefPtr def;
-
- /* Prefer action on the disks in use at the time the snapshot was
- * created; but fall back to current definition if dealing with a
- * snapshot created prior to libvirt 0.9.5. */
- def = snap->def->dom;
- if (!def)
- def = vm->def;
qemuimgarg[0] = qemuFindQemuImgBinary(driver);
if (qemuimgarg[0] == NULL) {
@@ -1515,13 +1508,10 @@ qemuDomainSnapshotForEachQcow2(struct qemud_driver *driver,
}
qemuimgarg[2] = op;
- qemuimgarg[3] = snap->def->name;
+ qemuimgarg[3] = name;
- for (i = 0; i < def->ndisks; i++) {
+ for (i = 0; i < ndisks; i++) {
/* FIXME: we also need to handle LVM here */
- /* FIXME: if we fail halfway through this loop, we are in an
- * inconsistent state. I'm not quite sure what to do about that
- */
if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
if (!def->disks[i]->driverType ||
STRNEQ(def->disks[i]->driverType, "qcow2")) {
@@ -1533,6 +1523,11 @@ qemuDomainSnapshotForEachQcow2(struct qemud_driver *driver,
def->disks[i]->dst);
skipped = true;
continue;
+ } else if (STREQ(op, "-c") && i) {
+ /* We must roll back partial creation by deleting
+ * all earlier snapshots. */
+ qemuDomainSnapshotForEachQcow2Raw(driver, def, name,
+ "-d", false, i);
}
qemuReportError(VIR_ERR_OPERATION_INVALID,
_("Disk device '%s' does not support"
@@ -1558,6 +1553,26 @@ qemuDomainSnapshotForEachQcow2(struct qemud_driver *driver,
return skipped ? 1 : 0;
}
+/* The domain is expected to be locked and inactive. Return -1 on normal
+ * failure, 1 if we skipped a disk due to try_all. */
+int
+qemuDomainSnapshotForEachQcow2(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ virDomainSnapshotObjPtr snap,
+ const char *op,
+ bool try_all)
+{
+ /* Prefer action on the disks in use at the time the snapshot was
+ * created; but fall back to current definition if dealing with a
+ * snapshot created prior to libvirt 0.9.5. */
+ virDomainDefPtr def = snap->def->dom;
+
+ if (!def)
+ def = vm->def;
+ return qemuDomainSnapshotForEachQcow2Raw(driver, def, snap->def->name,
+ op, try_all, def->ndisks);
+}
+
/* Discard one snapshot (or its metadata), without reparenting any children. */
int
qemuDomainSnapshotDiscard(struct qemud_driver *driver,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9e62738..4bbfabd 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10295,12 +10295,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
&vm, snap, flags) < 0)
goto cleanup;
} else if (!virDomainObjIsActive(vm)) {
- if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC) {
- qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("atomic snapshots of inactive domains not "
- "implemented yet"));
- goto cleanup;
- }
if (qemuDomainSnapshotCreateInactive(driver, vm, snap) < 0)
goto cleanup;
} else {
--
1.7.7.6