These functions mostly used from the qemu_snapshot.c and also semantically they belong to this source file. At the same time rename qemuDomainSnapshot* to qemuSnaphot*. Signed-off-by: Nikolay Shirokovskiy <nikolay.shirokovskiy@xxxxxxxxxx> --- src/qemu/qemu_domain.c | 241 +---------------------------------- src/qemu/qemu_domain.h | 19 --- src/qemu/qemu_driver.c | 8 +- src/qemu/qemu_snapshot.c | 268 ++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_snapshot.h | 10 ++ 5 files changed, 269 insertions(+), 277 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 18d403e099..56cf0c3f68 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -38,6 +38,7 @@ #include "qemu_checkpoint.h" #include "qemu_validate.h" #include "qemu_namespace.h" +#include "qemu_snapshot.h" #include "viralloc.h" #include "virlog.h" #include "virerror.h" @@ -64,7 +65,6 @@ #include "virsecret.h" #include "logging/log_manager.h" #include "locking/domain_lock.h" -#include "virdomainsnapshotobjlist.h" #include "virdomaincheckpointobjlist.h" #include "backup_conf.h" #include "virutil.h" @@ -7041,243 +7041,6 @@ qemuFindQemuImgBinary(virQEMUDriver *driver) return driver->qemuImgBinary; } -int -qemuDomainSnapshotWriteMetadata(virDomainObj *vm, - virDomainMomentObj *snapshot, - virDomainXMLOption *xmlopt, - const char *snapshotDir) -{ - g_autofree char *newxml = NULL; - g_autofree char *snapDir = NULL; - g_autofree char *snapFile = NULL; - char uuidstr[VIR_UUID_STRING_BUFLEN]; - unsigned int flags = VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE | - VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL; - virDomainSnapshotDef *def = virDomainSnapshotObjGetDef(snapshot); - - if (virDomainSnapshotGetCurrent(vm->snapshots) == snapshot) - flags |= VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT; - virUUIDFormat(vm->def->uuid, uuidstr); - newxml = virDomainSnapshotDefFormat(uuidstr, def, xmlopt, flags); - if (newxml == NULL) - return -1; - - snapDir = g_strdup_printf("%s/%s", snapshotDir, vm->def->name); - if (g_mkdir_with_parents(snapDir, 0777) < 0) { - virReportSystemError(errno, _("cannot create snapshot directory '%s'"), - snapDir); - return -1; - } - - snapFile = g_strdup_printf("%s/%s.xml", snapDir, def->parent.name); - - return virXMLSaveFile(snapFile, NULL, "snapshot-edit", newxml); -} - - -/* The domain is expected to be locked and inactive. Return -1 on normal - * failure, 1 if we skipped a disk due to try_all. */ -static int -qemuDomainSnapshotForEachQcow2Raw(virQEMUDriver *driver, - virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all, - int ndisks) -{ - virDomainSnapshotDef *snapdef = virDomainSnapshotObjGetDef(snap); - const char *qemuimgbin; - size_t i; - bool skipped = false; - - qemuimgbin = qemuFindQemuImgBinary(driver); - if (qemuimgbin == NULL) { - /* qemuFindQemuImgBinary set the error */ - return -1; - } - - for (i = 0; i < ndisks; i++) { - g_autoptr(virCommand) cmd = virCommandNewArgList(qemuimgbin, "snapshot", - op, snap->def->name, NULL); - int format = virDomainDiskGetFormat(def->disks[i]); - - /* FIXME: we also need to handle LVM here */ - if (def->disks[i]->device != VIR_DOMAIN_DISK_DEVICE_DISK || - snapdef->disks[i].snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL) - continue; - - if (!virStorageSourceIsLocalStorage(def->disks[i]->src)) { - virReportError(VIR_ERR_OPERATION_INVALID, - _("can't manipulate inactive snapshots of disk '%s'"), - def->disks[i]->dst); - return -1; - } - - if (format > 0 && format != VIR_STORAGE_FILE_QCOW2) { - if (try_all) { - /* Continue on even in the face of error, since other - * disks in this VM may have the same snapshot name. - */ - VIR_WARN("skipping snapshot action on %s", - 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, snap, - "-d", false, i); - } - virReportError(VIR_ERR_OPERATION_INVALID, - _("Disk device '%s' does not support snapshotting"), - def->disks[i]->dst); - return -1; - } - - virCommandAddArg(cmd, virDomainDiskGetSource(def->disks[i])); - - if (virCommandRun(cmd, NULL) < 0) { - if (try_all) { - VIR_WARN("skipping snapshot action on %s", - 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, snap, - "-d", false, i); - } - return -1; - } - } - - 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(virQEMUDriver *driver, - virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all) -{ - return qemuDomainSnapshotForEachQcow2Raw(driver, def, snap, - op, try_all, def->ndisks); -} - -/* Discard one snapshot (or its metadata), without reparenting any children. */ -int -qemuDomainSnapshotDiscard(virQEMUDriver *driver, - virDomainObj *vm, - virDomainMomentObj *snap, - bool update_parent, - bool metadata_only) -{ - g_autofree char *snapFile = NULL; - qemuDomainObjPrivate *priv; - virDomainMomentObj *parentsnap = NULL; - g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); - - if (!metadata_only) { - if (!virDomainObjIsActive(vm)) { - size_t i; - /* Ignore any skipped disks */ - - /* 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. */ - virDomainDef *def = snap->def->dom; - - if (!def) - def = vm->def; - - for (i = 0; i < def->ndisks; i++) { - if (virDomainDiskTranslateSourcePool(def->disks[i]) < 0) - return -1; - } - - if (qemuDomainSnapshotForEachQcow2(driver, def, snap, "-d", true) < 0) - return -1; - } else { - priv = vm->privateData; - qemuDomainObjEnterMonitor(driver, vm); - /* we continue on even in the face of error */ - qemuMonitorDeleteSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitor(vm); - } - } - - snapFile = g_strdup_printf("%s/%s/%s.xml", cfg->snapshotDir, vm->def->name, - snap->def->name); - - if (snap == virDomainSnapshotGetCurrent(vm->snapshots)) { - virDomainSnapshotSetCurrent(vm->snapshots, NULL); - if (update_parent && snap->def->parent_name) { - parentsnap = virDomainSnapshotFindByName(vm->snapshots, - snap->def->parent_name); - if (!parentsnap) { - VIR_WARN("missing parent snapshot matching name '%s'", - snap->def->parent_name); - } else { - virDomainSnapshotSetCurrent(vm->snapshots, parentsnap); - if (qemuDomainSnapshotWriteMetadata(vm, parentsnap, - driver->xmlopt, - cfg->snapshotDir) < 0) { - VIR_WARN("failed to set parent snapshot '%s' as current", - snap->def->parent_name); - virDomainSnapshotSetCurrent(vm->snapshots, NULL); - } - } - } - } - - if (unlink(snapFile) < 0) - VIR_WARN("Failed to unlink %s", snapFile); - if (update_parent) - virDomainMomentDropParent(snap); - virDomainSnapshotObjListRemove(vm->snapshots, snap); - - return 0; -} - -/* Hash iterator callback to discard multiple snapshots. */ -int qemuDomainMomentDiscardAll(void *payload, - const char *name G_GNUC_UNUSED, - void *data) -{ - virDomainMomentObj *moment = payload; - virQEMUMomentRemove *curr = data; - int err; - - if (!curr->found && curr->current == moment) - curr->found = true; - err = curr->momentDiscard(curr->driver, curr->vm, moment, false, - curr->metadata_only); - if (err && !curr->err) - curr->err = err; - return 0; -} - -int -qemuDomainSnapshotDiscardAllMetadata(virQEMUDriver *driver, - virDomainObj *vm) -{ - virQEMUMomentRemove rem = { - .driver = driver, - .vm = vm, - .metadata_only = true, - .momentDiscard = qemuDomainSnapshotDiscard, - }; - - virDomainSnapshotForEach(vm->snapshots, qemuDomainMomentDiscardAll, &rem); - virDomainSnapshotObjListRemoveAll(vm->snapshots); - - return rem.err; -} - static void qemuDomainRemoveInactiveCommon(virQEMUDriver *driver, @@ -7288,7 +7051,7 @@ qemuDomainRemoveInactiveCommon(virQEMUDriver *driver, g_autofree char *chkDir = NULL; /* Remove any snapshot metadata prior to removing the domain */ - if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0) { + if (qemuSnapshotDiscardAllMetadata(driver, vm) < 0) { VIR_WARN("unable to remove all snapshots for domain %s", vm->def->name); } else { diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index a41d8308e3..494a276212 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -633,22 +633,6 @@ int qemuDomainLogAppendMessage(virQEMUDriver *driver, const char *qemuFindQemuImgBinary(virQEMUDriver *driver); -int qemuDomainSnapshotWriteMetadata(virDomainObj *vm, - virDomainMomentObj *snapshot, - virDomainXMLOption *xmlopt, - const char *snapshotDir); - -int qemuDomainSnapshotForEachQcow2(virQEMUDriver *driver, - virDomainDef *def, - virDomainMomentObj *snap, - const char *op, - bool try_all); - -int qemuDomainSnapshotDiscard(virQEMUDriver *driver, - virDomainObj *vm, - virDomainMomentObj *snap, - bool update_current, - bool metadata_only); typedef struct _virQEMUMomentRemove virQEMUMomentRemove; struct _virQEMUMomentRemove { @@ -666,9 +650,6 @@ int qemuDomainMomentDiscardAll(void *payload, const char *name, void *data); -int qemuDomainSnapshotDiscardAllMetadata(virQEMUDriver *driver, - virDomainObj *vm); - void qemuDomainRemoveInactive(virQEMUDriver *driver, virDomainObj *vm); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 77012eb527..74bc2c7bf4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6568,7 +6568,7 @@ qemuDomainUndefineFlags(virDomainPtr dom, nsnapshots); goto endjob; } - if (qemuDomainSnapshotDiscardAllMetadata(driver, vm) < 0) + if (qemuSnapshotDiscardAllMetadata(driver, vm) < 0) goto endjob; } if (!virDomainObjIsActive(vm) && @@ -19132,9 +19132,9 @@ qemuDomainSnapshotWriteMetadataIter(void *payload, virQEMUDriverConfig *cfg = virQEMUDriverGetConfig(data->driver); int ret; - ret = qemuDomainSnapshotWriteMetadata(data->vm, payload, - data->driver->xmlopt, - cfg->snapshotDir); + ret = qemuSnapshotWriteMetadata(data->vm, payload, + data->driver->xmlopt, + cfg->snapshotDir); virObjectUnref(cfg); return ret; diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 5d622592c3..878a0abb34 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -49,6 +49,175 @@ VIR_LOG_INIT("qemu.qemu_snapshot"); +/* The domain is expected to be locked and inactive. Return -1 on normal + * failure, 1 if we skipped a disk due to try_all. */ +static int +qemuSnapshotForEachQcow2Raw(virQEMUDriver *driver, + virDomainDef *def, + virDomainMomentObj *snap, + const char *op, + bool try_all, + int ndisks) +{ + virDomainSnapshotDef *snapdef = virDomainSnapshotObjGetDef(snap); + const char *qemuimgbin; + size_t i; + bool skipped = false; + + qemuimgbin = qemuFindQemuImgBinary(driver); + if (qemuimgbin == NULL) { + /* qemuFindQemuImgBinary set the error */ + return -1; + } + + for (i = 0; i < ndisks; i++) { + g_autoptr(virCommand) cmd = virCommandNewArgList(qemuimgbin, "snapshot", + op, snap->def->name, NULL); + int format = virDomainDiskGetFormat(def->disks[i]); + + /* FIXME: we also need to handle LVM here */ + if (def->disks[i]->device != VIR_DOMAIN_DISK_DEVICE_DISK || + snapdef->disks[i].snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL) + continue; + + if (!virStorageSourceIsLocalStorage(def->disks[i]->src)) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("can't manipulate inactive snapshots of disk '%s'"), + def->disks[i]->dst); + return -1; + } + + if (format > 0 && format != VIR_STORAGE_FILE_QCOW2) { + if (try_all) { + /* Continue on even in the face of error, since other + * disks in this VM may have the same snapshot name. + */ + VIR_WARN("skipping snapshot action on %s", + def->disks[i]->dst); + skipped = true; + continue; + } else if (STREQ(op, "-c") && i) { + /* We must roll back partial creation by deleting + * all earlier snapshots. */ + qemuSnapshotForEachQcow2Raw(driver, def, snap, "-d", false, i); + } + virReportError(VIR_ERR_OPERATION_INVALID, + _("Disk device '%s' does not support snapshotting"), + def->disks[i]->dst); + return -1; + } + + virCommandAddArg(cmd, virDomainDiskGetSource(def->disks[i])); + + if (virCommandRun(cmd, NULL) < 0) { + if (try_all) { + VIR_WARN("skipping snapshot action on %s", + def->disks[i]->dst); + skipped = true; + continue; + } else if (STREQ(op, "-c") && i) { + /* We must roll back partial creation by deleting + * all earlier snapshots. */ + qemuSnapshotForEachQcow2Raw(driver, def, snap, "-d", false, i); + } + return -1; + } + } + + 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. */ +static int +qemuSnapshotForEachQcow2(virQEMUDriver *driver, + virDomainDef *def, + virDomainMomentObj *snap, + const char *op, + bool try_all) +{ + return qemuSnapshotForEachQcow2Raw(driver, def, snap, + op, try_all, def->ndisks); +} + + +/* Discard one snapshot (or its metadata), without reparenting any children. */ +static int +qemuSnapshotDiscard(virQEMUDriver *driver, + virDomainObj *vm, + virDomainMomentObj *snap, + bool update_parent, + bool metadata_only) +{ + g_autofree char *snapFile = NULL; + qemuDomainObjPrivate *priv; + virDomainMomentObj *parentsnap = NULL; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + + if (!metadata_only) { + if (!virDomainObjIsActive(vm)) { + size_t i; + /* Ignore any skipped disks */ + + /* 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. */ + virDomainDef *def = snap->def->dom; + + if (!def) + def = vm->def; + + for (i = 0; i < def->ndisks; i++) { + if (virDomainDiskTranslateSourcePool(def->disks[i]) < 0) + return -1; + } + + if (qemuSnapshotForEachQcow2(driver, def, snap, "-d", true) < 0) + return -1; + } else { + priv = vm->privateData; + qemuDomainObjEnterMonitor(driver, vm); + /* we continue on even in the face of error */ + qemuMonitorDeleteSnapshot(priv->mon, snap->def->name); + qemuDomainObjExitMonitor(vm); + } + } + + snapFile = g_strdup_printf("%s/%s/%s.xml", cfg->snapshotDir, vm->def->name, + snap->def->name); + + if (snap == virDomainSnapshotGetCurrent(vm->snapshots)) { + virDomainSnapshotSetCurrent(vm->snapshots, NULL); + if (update_parent && snap->def->parent_name) { + parentsnap = virDomainSnapshotFindByName(vm->snapshots, + snap->def->parent_name); + if (!parentsnap) { + VIR_WARN("missing parent snapshot matching name '%s'", + snap->def->parent_name); + } else { + virDomainSnapshotSetCurrent(vm->snapshots, parentsnap); + if (qemuSnapshotWriteMetadata(vm, parentsnap, + driver->xmlopt, + cfg->snapshotDir) < 0) { + VIR_WARN("failed to set parent snapshot '%s' as current", + snap->def->parent_name); + virDomainSnapshotSetCurrent(vm->snapshots, NULL); + } + } + } + } + + if (unlink(snapFile) < 0) + VIR_WARN("Failed to unlink %s", snapFile); + if (update_parent) + virDomainMomentDropParent(snap); + virDomainSnapshotObjListRemove(vm->snapshots, snap); + + return 0; +} + + /** * qemuSnapshotSetCurrent: Set currently active snapshot * @@ -73,7 +242,7 @@ qemuSnapshotSetCurrent(virDomainObj *vm, * 'active' property */ if (oldcurrent && oldcurrent != newcurrent) { - if (qemuDomainSnapshotWriteMetadata(vm, oldcurrent, driver->xmlopt, cfg->snapshotDir) < 0) + if (qemuSnapshotWriteMetadata(vm, oldcurrent, driver->xmlopt, cfg->snapshotDir) < 0) VIR_WARN("failed to update old current snapshot"); } } @@ -167,7 +336,7 @@ qemuSnapshotCreateInactiveInternal(virQEMUDriver *driver, virDomainObj *vm, virDomainMomentObj *snap) { - return qemuDomainSnapshotForEachQcow2(driver, vm->def, snap, "-c", false); + return qemuSnapshotForEachQcow2(driver, vm->def, snap, "-c", false); } @@ -1691,9 +1860,8 @@ qemuSnapshotCreateWriteMetadata(virDomainObj *vm, virQEMUDriver *driver, virQEMUDriverConfig *cfg) { - if (qemuDomainSnapshotWriteMetadata(vm, snap, - driver->xmlopt, - cfg->snapshotDir) < 0) { + if (qemuSnapshotWriteMetadata(vm, snap, driver->xmlopt, + cfg->snapshotDir) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to save metadata for snapshot %s"), snap->def->name); @@ -2005,9 +2173,8 @@ qemuSnapshotRevertWriteMetadata(virDomainObj *vm, bool defined) { qemuSnapshotSetCurrent(vm, snap); - if (qemuDomainSnapshotWriteMetadata(vm, snap, - driver->xmlopt, - cfg->snapshotDir) < 0) { + if (qemuSnapshotWriteMetadata(vm, snap, driver->xmlopt, + cfg->snapshotDir) < 0) { virDomainSnapshotSetCurrent(vm->snapshots, NULL); return -1; } @@ -2146,7 +2313,7 @@ qemuSnapshotInternalRevertInactive(virQEMUDriver *driver, } /* Try all disks, but report failure if we skipped any. */ - if (qemuDomainSnapshotForEachQcow2(driver, def, snap, "-a", true) != 0) + if (qemuSnapshotForEachQcow2(driver, def, snap, "-a", true) != 0) return -1; return 0; @@ -2415,7 +2582,7 @@ qemuSnapshotDelete(virDomainObj *vm, rem.err = 0; rem.current = virDomainSnapshotGetCurrent(vm->snapshots); rem.found = false; - rem.momentDiscard = qemuDomainSnapshotDiscard; + rem.momentDiscard = qemuSnapshotDiscard; virDomainMomentForEachDescendant(snap, qemuDomainMomentDiscardAll, &rem); if (rem.err < 0) @@ -2424,9 +2591,8 @@ qemuSnapshotDelete(virDomainObj *vm, qemuSnapshotSetCurrent(vm, snap); if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY) { - if (qemuDomainSnapshotWriteMetadata(vm, snap, - driver->xmlopt, - cfg->snapshotDir) < 0) { + if (qemuSnapshotWriteMetadata(vm, snap, driver->xmlopt, + cfg->snapshotDir) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to set snapshot '%s' as current"), snap->def->name); @@ -2441,7 +2607,7 @@ qemuSnapshotDelete(virDomainObj *vm, rep.vm = vm; rep.err = 0; rep.xmlopt = driver->xmlopt; - rep.writeMetadata = qemuDomainSnapshotWriteMetadata; + rep.writeMetadata = qemuSnapshotWriteMetadata; virDomainMomentForEachChild(snap, qemuSnapshotChildrenReparent, &rep); @@ -2454,7 +2620,7 @@ qemuSnapshotDelete(virDomainObj *vm, virDomainMomentDropChildren(snap); ret = 0; } else { - ret = qemuDomainSnapshotDiscard(driver, vm, snap, true, metadata_only); + ret = qemuSnapshotDiscard(driver, vm, snap, true, metadata_only); } endjob: @@ -2462,3 +2628,75 @@ qemuSnapshotDelete(virDomainObj *vm, return ret; } + + +int +qemuSnapshotWriteMetadata(virDomainObj *vm, + virDomainMomentObj *snapshot, + virDomainXMLOption *xmlopt, + const char *snapshotDir) +{ + g_autofree char *newxml = NULL; + g_autofree char *snapDir = NULL; + g_autofree char *snapFile = NULL; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + unsigned int flags = VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE | + VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL; + virDomainSnapshotDef *def = virDomainSnapshotObjGetDef(snapshot); + + if (virDomainSnapshotGetCurrent(vm->snapshots) == snapshot) + flags |= VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT; + virUUIDFormat(vm->def->uuid, uuidstr); + newxml = virDomainSnapshotDefFormat(uuidstr, def, xmlopt, flags); + if (newxml == NULL) + return -1; + + snapDir = g_strdup_printf("%s/%s", snapshotDir, vm->def->name); + if (g_mkdir_with_parents(snapDir, 0777) < 0) { + virReportSystemError(errno, _("cannot create snapshot directory '%s'"), + snapDir); + return -1; + } + + snapFile = g_strdup_printf("%s/%s.xml", snapDir, def->parent.name); + + return virXMLSaveFile(snapFile, NULL, "snapshot-edit", newxml); +} + + +/* Hash iterator callback to discard multiple snapshots. */ +int +qemuDomainMomentDiscardAll(void *payload, + const char *name G_GNUC_UNUSED, + void *data) +{ + virDomainMomentObj *moment = payload; + virQEMUMomentRemove *curr = data; + int err; + + if (!curr->found && curr->current == moment) + curr->found = true; + err = curr->momentDiscard(curr->driver, curr->vm, moment, false, + curr->metadata_only); + if (err && !curr->err) + curr->err = err; + return 0; +} + + +int +qemuSnapshotDiscardAllMetadata(virQEMUDriver *driver, + virDomainObj *vm) +{ + virQEMUMomentRemove rem = { + .driver = driver, + .vm = vm, + .metadata_only = true, + .momentDiscard = qemuSnapshotDiscard, + }; + + virDomainSnapshotForEach(vm->snapshots, qemuDomainMomentDiscardAll, &rem); + virDomainSnapshotObjListRemoveAll(vm->snapshots); + + return rem.err; +} diff --git a/src/qemu/qemu_snapshot.h b/src/qemu/qemu_snapshot.h index 0cc38c0039..016d18449a 100644 --- a/src/qemu/qemu_snapshot.h +++ b/src/qemu/qemu_snapshot.h @@ -81,3 +81,13 @@ qemuSnapshotDiskCreate(qemuSnapshotDiskContext *snapctxt); virDomainSnapshotDiskDef * qemuSnapshotGetTransientDiskDef(virDomainDiskDef *domdisk, const char *suffix); + +int +qemuSnapshotWriteMetadata(virDomainObj *vm, + virDomainMomentObj *snapshot, + virDomainXMLOption *xmlopt, + const char *snapshotDir); + +int +qemuSnapshotDiscardAllMetadata(virQEMUDriver *driver, + virDomainObj *vm); -- 2.35.1