diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index aa64fa5948..765488413f 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2596,7 +2596,8 @@ int virDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, /* Delete a snapshot */ typedef enum { - VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN = (1 << 0), + VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN = (1 << 0), /* Also delete children */ + VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY = (1 << 1), /* Delete just metadata */ } virDomainSnapshotDeleteFlags; int virDomainSnapshotDelete(virDomainSnapshotPtr snapshot, diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index e6033994e5..846a777b96 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4543,7 +4543,8 @@ esxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags) esxVI_TaskInfoState taskInfoState; char *taskInfoErrorMessage = NULL; - virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, -1); + virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN | + VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, -1); if (esxVI_EnsureSession(priv->primary) < 0) { return -1; @@ -4561,6 +4562,13 @@ esxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags) goto cleanup; } + /* ESX snapshots do not require any libvirt metadata, making this + * flag trivial once we know we have a valid snapshot. */ + if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) { + result = 0; + goto cleanup; + } + if (esxVI_RemoveSnapshot_Task(priv->primary, snapshotTree->snapshot, removeChildren, &task) < 0 || esxVI_WaitForTaskCompletion(priv->primary, task, snapshot->domain->uuid, diff --git a/src/libvirt.c b/src/libvirt.c index 8e569ab8bd..0f3399c822 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -15962,14 +15962,18 @@ error: /** * virDomainSnapshotDelete: * @snapshot: a domain snapshot object - * @flags: flag parameters + * @flags: bitwise-or of supported virDomainSnapshotDeleteFlags * * Delete the snapshot. * * If @flags is 0, then just this snapshot is deleted, and changes from * this snapshot are automatically merged into children snapshots. If - * flags is VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, then this snapshot - * and any children snapshots are deleted. + * @flags includes VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, then this snapshot + * and any children snapshots are deleted. If @flags includes + * VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, then any snapshot metadata + * tracked by libvirt is removed while keeping the snapshot contents + * intact; if a hypervisor does not require any libvirt metadata to + * track snapshots, then this flag is silently ignored. * * Returns 0 if the snapshot was successfully deleted, -1 on error. */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 822e8992b3..8de2bae8ce 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -6361,7 +6361,8 @@ vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, PRUint32 state; nsresult rc; - virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, -1); + virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN | + VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, -1); vboxIIDFromUUID(&domiid, dom->uuid); rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine); @@ -6382,6 +6383,13 @@ vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, goto cleanup; } + /* VBOX snapshots do not require any libvirt metadata, making this + * flag trivial once we know we have a valid snapshot. */ + if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY) { + ret = 0; + goto cleanup; + } + if (state >= MachineState_FirstOnline && state <= MachineState_LastOnline) { vboxError(VIR_ERR_OPERATION_INVALID, "%s",