]> xenbits.xensource.com Git - libvirt.git/commitdiff
Allow automatic kill of guests when a connection is closed
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 23 Jun 2011 10:41:57 +0000 (11:41 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 24 Jun 2011 11:15:10 +0000 (12:15 +0100)
If an application is using libvirt + KVM as a piece of its
internal infrastructure to perform a specific task, it can
be desirable to guarentee the VM dies when the virConnectPtr
disconnects from libvirtd. This ensures the app can't leak
any VMs it was using. Adding VIR_DOMAIN_START_AUTOKILL as
a flag when starting guests enables this to be done.

* include/libvirt/libvirt.h.in: All VIR_DOMAIN_START_AUTOKILL
* src/qemu/qemu_driver.c: Support automatic killing of guests
  upon connection close
* tools/virsh.c: Add --autokill flag to 'start' and 'create'
  commands

include/libvirt/libvirt.h.in
src/libvirt.c
src/qemu/qemu_driver.c
src/qemu/qemu_migration.c
src/qemu/qemu_process.c
src/qemu/qemu_process.h
tools/virsh.c
tools/virsh.pod

index 3f634e683fbd023ccb5414da432aec62b4035231..edf876ef48a23c8cabd6a4dc64a5274460266b90 100644 (file)
@@ -234,6 +234,7 @@ typedef virDomainInfo *virDomainInfoPtr;
 typedef enum {
     VIR_DOMAIN_NONE         = 0,      /* Default behavior */
     VIR_DOMAIN_START_PAUSED = 1 << 0, /* Launch guest in paused state */
+    VIR_DOMAIN_START_AUTODESTROY = 1 << 1, /* Automatically kill guest when virConnectPtr is closed */
 } virDomainCreateFlags;
 
 
index 69e0ea89bacc3cb1ea025521e2efc71fc92baef9..8a2988c0f7c1ce89ec86b05f69c079de0c09b48d 100644 (file)
@@ -1793,6 +1793,17 @@ virDomainGetConnect (virDomainPtr dom)
  * is destroyed, or if the host is restarted (see virDomainDefineXML() to
  * define persistent domains).
  *
+ * If the VIR_DOMAIN_START_PAUSED flag is set, the guest domain
+ * will be started, but its CPUs will remain paused. The CPUs
+ * can later be manually started using virDomainResume.
+ *
+ * If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest
+ * domain will be automatically destroyed when the virConnectPtr
+ * object is finally released. This will also happen if the
+ * client application crashes / looses its connection to the
+ * libvirtd daemon. Any domains marked for auto destroy will
+ * block attempts at migration or save-to-file
+ *
  * Returns a new domain object or NULL in case of failure
  */
 virDomainPtr
@@ -6522,6 +6533,17 @@ error:
  * Launch a defined domain. If the call succeeds the domain moves from the
  * defined to the running domains pools.
  *
+ * If the VIR_DOMAIN_START_PAUSED flag is set, the guest domain
+ * will be started, but its CPUs will remain paused. The CPUs
+ * can later be manually started using virDomainResume.
+ *
+ * If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest
+ * domain will be automatically destroyed when the virConnectPtr
+ * object is finally released. This will also happen if the
+ * client application crashes / looses its connection to the
+ * libvirtd daemon. Any domains marked for auto destroy will
+ * block attempts at migration or save-to-file
+ *
  * Returns 0 in case of success, -1 in case of error
  */
 int
index e73f0d715afba594872d2e7c9e4a6dc6ea3aa4ca..32a5ba17436672dd7f9e660cb84afaa8c237d654 100644 (file)
@@ -119,7 +119,8 @@ static int qemudShutdown(void);
 static int qemudDomainObjStart(virConnectPtr conn,
                                struct qemud_driver *driver,
                                virDomainObjPtr vm,
-                               bool start_paused);
+                               bool start_paused,
+                               bool autodestroy);
 
 static int qemudDomainGetMaxVcpus(virDomainPtr dom);
 
@@ -148,7 +149,7 @@ qemuAutostartDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaq
     } else {
         if (vm->autostart &&
             !virDomainObjIsActive(vm) &&
-            qemudDomainObjStart(data->conn, data->driver, vm, false) < 0) {
+            qemudDomainObjStart(data->conn, data->driver, vm, false, false) < 0) {
             err = virGetLastError();
             VIR_ERROR(_("Failed to autostart VM '%s': %s"),
                       vm->def->name,
@@ -1246,7 +1247,8 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
     virDomainPtr dom = NULL;
     virDomainEventPtr event = NULL;
 
-    virCheckFlags(VIR_DOMAIN_START_PAUSED, NULL);
+    virCheckFlags(VIR_DOMAIN_START_PAUSED |
+                  VIR_DOMAIN_START_AUTODESTROY, NULL);
 
     qemuDriverLock(driver);
     if (!(def = virDomainDefParseString(driver->caps, xml,
@@ -1277,7 +1279,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
 
     if (qemuProcessStart(conn, driver, vm, NULL,
                          (flags & VIR_DOMAIN_START_PAUSED) != 0,
-                         false,
+                         (flags & VIR_DOMAIN_START_AUTODESTROY) != 0,
                          -1, NULL, VIR_VM_OP_CREATE) < 0) {
         qemuAuditDomainStart(vm, "booted", false);
         if (qemuDomainObjEndJob(vm) > 0)
@@ -1333,6 +1335,12 @@ static int qemudDomainSuspend(virDomainPtr dom) {
         goto cleanup;
     }
 
+    if (qemuProcessAutoDestroyActive(driver, vm)) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is marked for auto destroy"));
+        goto cleanup;
+    }
+
     priv = vm->privateData;
 
     if (priv->jobActive == QEMU_JOB_MIGRATION_OUT) {
@@ -3882,7 +3890,8 @@ static int qemudNumDefinedDomains(virConnectPtr conn) {
 static int qemudDomainObjStart(virConnectPtr conn,
                                struct qemud_driver *driver,
                                virDomainObjPtr vm,
-                               bool start_paused)
+                               bool start_paused,
+                               bool autodestroy)
 {
     int ret = -1;
     char *managed_save;
@@ -3906,7 +3915,7 @@ static int qemudDomainObjStart(virConnectPtr conn,
     }
 
     ret = qemuProcessStart(conn, driver, vm, NULL, start_paused,
-                           false, -1, NULL, VIR_VM_OP_CREATE);
+                           autodestroy, -1, NULL, VIR_VM_OP_CREATE);
     qemuAuditDomainStart(vm, "booted", ret >= 0);
     if (ret >= 0) {
         virDomainEventPtr event =
@@ -3929,7 +3938,8 @@ qemudDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
     virDomainObjPtr vm;
     int ret = -1;
 
-    virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);
+    virCheckFlags(VIR_DOMAIN_START_PAUSED |
+                  VIR_DOMAIN_START_AUTODESTROY, -1);
 
     qemuDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -3951,8 +3961,12 @@ qemudDomainStartWithFlags(virDomainPtr dom, unsigned int flags)
         goto endjob;
     }
 
-    ret = qemudDomainObjStart(dom->conn, driver, vm,
-                              (flags & VIR_DOMAIN_START_PAUSED) != 0);
+    if (qemudDomainObjStart(dom->conn, driver, vm,
+                            (flags & VIR_DOMAIN_START_PAUSED) != 0,
+                            (flags & VIR_DOMAIN_START_AUTODESTROY) != 0) < 0)
+        goto endjob;
+
+    ret = 0;
 
 endjob:
     if (qemuDomainObjEndJob(vm) == 0)
index dcbc15889bd02006ee1b25483af44fb205493208..78acffb60f4c9f6aa2f92580bc83591fe87a10f5 100644 (file)
@@ -1000,6 +1000,12 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
         goto cleanup;
     }
 
+    if (qemuProcessAutoDestroyActive(driver, vm)) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is marked for auto destroy"));
+        goto cleanup;
+    }
+
     if (!qemuMigrationIsAllowed(vm->def))
         goto cleanup;
 
@@ -2288,6 +2294,12 @@ int qemuMigrationPerform(struct qemud_driver *driver,
         goto endjob;
     }
 
+    if (qemuProcessAutoDestroyActive(driver, vm)) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is marked for auto destroy"));
+        goto endjob;
+    }
+
     memset(&priv->jobInfo, 0, sizeof(priv->jobInfo));
     priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED;
 
index b4b745e3c926193c9923b903ed317b28d2a60822..2d2037b10071ddcb07be2b0ef79bb27b916523d6 100644 (file)
@@ -3158,3 +3158,14 @@ int qemuProcessAutoDestroyRemove(struct qemud_driver *driver,
         return -1;
     return 0;
 }
+
+bool qemuProcessAutoDestroyActive(struct qemud_driver *driver,
+                                  virDomainObjPtr vm)
+{
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    virUUIDFormat(vm->def->uuid, uuidstr);
+    VIR_DEBUG("vm=%s uuid=%s", vm->def->name, uuidstr);
+    if (virHashLookup(driver->autodestroy, uuidstr) != NULL)
+        return true;
+    return false;
+}
index 7c5e8e803a83ff41528515f5a0913bada9b26137..0e74d2a57a51d2da229bff91e9413b6ddc85d476 100644 (file)
@@ -67,6 +67,7 @@ int qemuProcessAutoDestroyAdd(struct qemud_driver *driver,
                               virConnectPtr conn);
 int qemuProcessAutoDestroyRemove(struct qemud_driver *driver,
                                  virDomainObjPtr vm);
-
+bool qemuProcessAutoDestroyActive(struct qemud_driver *driver,
+                                  virDomainObjPtr vm);
 
 #endif /* __QEMU_PROCESS_H__ */
index fcd254db7a66e6eff808077aa1e1c913e5b1ea6f..cafbb4bb9401b345d8e86e655e22cd2eb94cb410 100644 (file)
@@ -1305,6 +1305,7 @@ static const vshCmdOptDef opts_create[] = {
     {"console", VSH_OT_BOOL, 0, N_("attach to console after creation")},
 #endif
     {"paused", VSH_OT_BOOL, 0, N_("leave the guest paused after creation")},
+    {"autodestroy", VSH_OT_BOOL, 0, N_("automatically destroy the guest when virsh disconnects")},
     {NULL, 0, 0, NULL}
 };
 
@@ -1331,6 +1332,8 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd)
 
     if (vshCommandOptBool(cmd, "paused"))
         flags |= VIR_DOMAIN_START_PAUSED;
+    if (vshCommandOptBool(cmd, "autodestroy"))
+        flags |= VIR_DOMAIN_START_AUTODESTROY;
 
     dom = virDomainCreateXML(ctl->conn, buffer, flags);
     VIR_FREE(buffer);
@@ -1466,6 +1469,7 @@ static const vshCmdOptDef opts_start[] = {
     {"console", VSH_OT_BOOL, 0, N_("attach to console after creation")},
 #endif
     {"paused", VSH_OT_BOOL, 0, N_("leave the guest paused after creation")},
+    {"autodestroy", VSH_OT_BOOL, 0, N_("automatically destroy the guest when virsh disconnects")},
     {NULL, 0, 0, NULL}
 };
 
@@ -1494,6 +1498,8 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
 
     if (vshCommandOptBool(cmd, "paused"))
         flags |= VIR_DOMAIN_START_PAUSED;
+    if (vshCommandOptBool(cmd, "autodestroy"))
+        flags |= VIR_DOMAIN_START_AUTODESTROY;
 
     /* Prefer older API unless we have to pass a flag.  */
     if ((flags ? virDomainCreateWithFlags(dom, flags)
index 023ab42d4436099356c625e3eebfcdebc517d901..bdaea48e92c343dfa2a01ed81f749518324e62b9 100644 (file)
@@ -392,13 +392,16 @@ I<devname> parameter refers to the device alias of an alternate
 console, serial or parallel device configured for the guest.
 If omitted, the primary console will be opened.
 
-=item B<create> I<FILE> optional I<--console> I<--paused>
+=item B<create> I<FILE> optional I<--console> I<--paused> I<--autodestroy>
 
 Create a domain from an XML <file>. An easy way to create the XML
 <file> is to use the B<dumpxml> command to obtain the definition of a
 pre-existing guest.  The domain will be paused if the I<--paused> option
 is used and supported by the driver; otherwise it will be running.
 If I<--console> is requested, attach to the console after creation.
+If I<--autodestroy> is requested, then the guest will be automatically
+destroyed when virsh closes its connection to libvirt, or otherwise
+exits.
 
 B<Example>
 
@@ -786,13 +789,16 @@ services must be shutdown in the domain.
 The exact behavior of a domain when it shuts down is set by the
 I<on_shutdown> parameter in the domain's XML definition.
 
-=item B<start> I<domain-name> optional I<--console> I<--paused>
+=item B<start> I<domain-name> optional I<--console> I<--paused> I<--autodestroy>
 
 Start a (previously defined) inactive domain, either from the last
 B<managedsave> state, or via a fresh boot if no managedsave state is
 present.  The domain will be paused if the I<--paused> option is
 used and supported by the driver; otherwise it will be running.
 If I<--console> is requested, attach to the console after creation.
+If I<--autodestroy> is requested, then the guest will be automatically
+destroyed when virsh closes its connection to libvirt, or otherwise
+exits.
 
 =item B<suspend> I<domain-id>