[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCHv4 24/51] snapshot: prevent stranding snapshot data on domain destruction



Just as leaving managed save metadata behind can cause problems
when creating a new domain that happens to collide with the name
of the just-deleted domain, the same is true of leaving any
snapshot metadata behind.  For safety sake, extend the semantic
change of commit b26a9fa9 to also cover snapshot metadata as a
reason to reject undefining an inactive domain.  A future patch
will make sure that shutdown of a transient domain automatically
deletes snapshot metadata (whether by destroy, shutdown, or
guest-initiated action).  Management apps of transient domains
should take care to capture xml of snapshots, if it is necessary
to recreate the snapshot metadata on a later transient domain
with the same name and uuid.

This also documents a new flag that hypervisors can choose to
support as a shortcut for taking care of the metadata as part of
the undefine process; however, nontrivial driver support for these
flags will be deferred to future patches.

Note that ESX and VBox can never be transient; therefore, they
do not have to worry about automatic cleanup after shutdown
(the persistent domain still remains); likewise they never
store snapshot metadata, so the undefine flag is trivial.
The nontrivial work remaining is thus in the qemu driver.

* include/libvirt/libvirt.h.in
(VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA): New flag.
* src/libvirt.c (virDomainUndefine, virDomainUndefineFlags):
Document new limitations and flag.
* src/esx/esx_driver.c (esxDomainUndefineFlags): Trivial
implementation.
* src/vbox/vbox_tmpl.c (vboxDomainUndefineFlags): Likewise.
* src/qemu/qemu_driver.c (qemuDomainUndefineFlags): Enforce
the limitations.
---
 include/libvirt/libvirt.h.in |    8 +++++++-
 src/esx/esx_driver.c         |    5 ++++-
 src/libvirt.c                |   35 ++++++++++++++++++++++++++++-------
 src/qemu/qemu_driver.c       |    9 +++++++++
 src/vbox/vbox_tmpl.c         |    5 ++++-
 5 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 00b8350..4a5dbff 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -923,10 +923,12 @@ virConnectPtr           virDomainGetConnect     (virDomainPtr domain);
  * Domain creation and destruction
  */

+
 /*
  * typedef enum {
  * } virDomainDestroyFlagsValues;
  */
+
 virDomainPtr            virDomainCreateXML      (virConnectPtr conn,
                                                  const char *xmlDesc,
                                                  unsigned int flags);
@@ -1247,7 +1249,11 @@ virDomainPtr            virDomainDefineXML      (virConnectPtr conn,
 int                     virDomainUndefine       (virDomainPtr domain);

 typedef enum {
-    VIR_DOMAIN_UNDEFINE_MANAGED_SAVE = (1 << 0),
+    VIR_DOMAIN_UNDEFINE_MANAGED_SAVE       = (1 << 0), /* Also remove any
+                                                          managed save */
+    VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA = (1 << 1), /* If last use of domain,
+                                                          then also remove any
+                                                          snapshot metadata */

     /* Future undefine control flags should come here. */
 } virDomainUndefineFlagsValues;
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index e004324..fb5b1a2 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -3309,7 +3309,10 @@ esxDomainUndefineFlags(virDomainPtr domain,
     esxVI_String *propertyNameList = NULL;
     esxVI_VirtualMachinePowerState powerState;

-    virCheckFlags(0, -1);
+    /* No managed save, so we explicitly reject
+     * VIR_DOMAIN_UNDEFINE_MANAGED_SAVE.  No snapshot metadata for
+     * ESX, so we can trivially ignore that flag.  */
+    virCheckFlags(VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);

     if (priv->vCenter != NULL) {
         ctx = priv->vCenter;
diff --git a/src/libvirt.c b/src/libvirt.c
index e3188b7..68d469f 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -2058,6 +2058,10 @@ error:
  * does not free the associated virDomainPtr object.
  * This function may require privileged access
  *
+ * If the domain is transient and has any snapshot metadata (see
+ * virDomainSnapshotNum()), then that metadata will automatically
+ * be deleted when the domain quits.
+ *
  * Returns 0 in case of success and -1 in case of failure.
  */
 int
@@ -2107,7 +2111,9 @@ error:
  * This function may require privileged access.
  *
  * Calling this function with no @flags set (equal to zero)
- * is equivalent to calling virDomainDestroy.
+ * is equivalent to calling virDomainDestroy.  Using virDomainShutdown()
+ * may produce cleaner results for the guest's disks, but depends on guest
+ * support.
  *
  * Returns 0 in case of success and -1 in case of failure.
  */
@@ -2912,12 +2918,17 @@ error:
  * virDomainShutdown:
  * @domain: a domain object
  *
- * Shutdown a domain, the domain object is still usable there after but
+ * Shutdown a domain, the domain object is still usable thereafter but
  * the domain OS is being stopped. Note that the guest OS may ignore the
- * request.
+ * request.  For guests that react to a shutdown request, the differences
+ * from virDomainDestroy() are that the guests disk storage will be in a
+ * stable state rather than having the (virtual) power cord pulled, and
+ * this command returns as soon as the shutdown request is issued rather
+ * than blocking until the guest is no longer running.
  *
- * TODO: should we add an option for reboot, knowing it may not be doable
- *       in the general case ?
+ * If the domain is transient and has any snapshot metadata (see
+ * virDomainSnapshotNum()), then that metadata will automatically
+ * be deleted when the domain quits.
  *
  * Returns 0 in case of success and -1 in case of failure.
  */
@@ -6879,8 +6890,9 @@ error:
  * the domain configuration is removed.
  *
  * If the domain has a managed save image (see
- * virDomainHasManagedSaveImage()), then the undefine will fail. See
- * virDomainUndefineFlags() for more control.
+ * virDomainHasManagedSaveImage()), or if it is inactive and has any
+ * snapshot metadata (see virDomainSnapshotNum()), then the undefine will
+ * fail. See virDomainUndefineFlags() for more control.
  *
  * Returns 0 in case of success, -1 in case of error
  */
@@ -6931,6 +6943,15 @@ error:
  * then including VIR_DOMAIN_UNDEFINE_MANAGED_SAVE in @flags will also remove
  * that file, and omitting the flag will cause the undefine process to fail.
  *
+ * If the domain is inactive and has any snapshot metadata (see
+ * virDomainSnapshotNum()), then including
+ * VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA in @flags will also remove
+ * that metadata.  Omitting the flag will cause the undefine of an
+ * inactive domain to fail.  Active snapshots will retain snapshot
+ * metadata until the (now-transient) domain halts, regardless of
+ * whether this flag is present.  On hypervisors where snapshots do
+ * not use libvirt metadata, this flag has no effect.
+ *
  * Returns 0 in case of success, -1 in case of error
  */
 int
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ac71b04..38a21db 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4838,6 +4838,7 @@ qemuDomainUndefineFlags(virDomainPtr dom,
     virDomainEventPtr event = NULL;
     char *name = NULL;
     int ret = -1;
+    int nsnapshots;

     virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);

@@ -4852,6 +4853,14 @@ qemuDomainUndefineFlags(virDomainPtr dom,
         goto cleanup;
     }

+    if (!virDomainObjIsActive(vm) &&
+        (nsnapshots = virDomainSnapshotObjListNum(&vm->snapshots, 0))) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        _("cannot delete inactive domain with %d snapshots"),
+                        nsnapshots);
+        goto cleanup;
+    }
+
     if (!vm->persistent) {
         qemuReportError(VIR_ERR_OPERATION_INVALID,
                         "%s", _("cannot undefine transient domain"));
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 636f5f2..ebed4d9 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -4982,7 +4982,10 @@ vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
 #if VBOX_API_VERSION >= 4000
     vboxArray media = VBOX_ARRAY_INITIALIZER;
 #endif
-    virCheckFlags(0, -1);
+    /* No managed save, so we explicitly reject
+     * VIR_DOMAIN_UNDEFINE_MANAGED_SAVE.  No snapshot metadata for
+     * VBox, so we can trivially ignore that flag.  */
+    virCheckFlags(VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1);

     vboxIIDFromUUID(&iid, dom->uuid);

-- 
1.7.4.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]