]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: implement virDomainSetLifecycleAction() API
authorPavel Hrdina <phrdina@redhat.com>
Wed, 11 Oct 2017 14:09:49 +0000 (16:09 +0200)
committerPavel Hrdina <phrdina@redhat.com>
Thu, 19 Oct 2017 09:52:38 +0000 (11:52 +0200)
There is one limitation for using this API, when the guest is started
with all actions set to "destroy" we put "-no-reboot" on the QEMU
command line.  That cannot be changed while QEMU is running and
the QEMU process is always terminated no matter what is configured
for any action.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1460677

Reviewed-by: John Ferlan <jferlan@redhat.com>
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt-domain.c
src/libvirt_private.syms
src/qemu/qemu_driver.c

index 18addcaf14fba051746a15f203abb6718f9d37f1..5d95c5bdb0a5e735346e6126cddbcbc79bad5cb8 100644 (file)
@@ -5612,7 +5612,7 @@ virDomainDefCheckDuplicateDriveAddresses(const virDomainDef *def)
 }
 
 
-static bool
+bool
 virDomainDefLifecycleActionAllowed(virDomainLifecycle type,
                                    virDomainLifecycleAction action)
 {
index 8240433611a007649da9fc4f011e44994d551de0..354b7adfa557fcc6f3ff932f28263ca092b46b30 100644 (file)
@@ -3409,4 +3409,8 @@ virDomainNetTypeSharesHostView(const virDomainNetDef *net)
     return false;
 }
 
+bool
+virDomainDefLifecycleActionAllowed(virDomainLifecycle type,
+                                   virDomainLifecycleAction action);
+
 #endif /* __DOMAIN_CONF_H */
index a51d8e3820760be2c5511a706bc692acc3fde7e0..eaec0979ad49e13633872625465ed59122b4ddfd 100644 (file)
@@ -12047,6 +12047,10 @@ virDomainSetBlockThreshold(virDomainPtr domain,
  * Changes the actions of lifecycle events for domain represented as
  * <on_$type>$action</on_$type> in the domain XML.
  *
+ * QEMU driver has a limitation that if all lifecycle events are set
+ * to destroy when the domain is started, it's not possible to change
+ * any action for running domain.
+ *
  * Returns 0 on success, -1 on failure.
  */
 int virDomainSetLifecycleAction(virDomainPtr domain,
index d3cb05be6f6fb527ac41c195eda84e3b8bf15144..10c6aeadcdcf113ca21537d7008dc5d4302b0a6f 100644 (file)
@@ -270,6 +270,7 @@ virDomainDefHasDeviceAddress;
 virDomainDefHasMemballoon;
 virDomainDefHasMemoryHotplug;
 virDomainDefHasVcpusOffline;
+virDomainDefLifecycleActionAllowed;
 virDomainDefMaybeAddController;
 virDomainDefMaybeAddInput;
 virDomainDefNeedsPlacementAdvice;
index 502b5b5fcdbfa8d54746b42e6c63b4fb497c654a..b241b9833680b17c6afb18a2c9bb60fb259d5847 100644 (file)
@@ -20944,6 +20944,97 @@ qemuDomainSetBlockThreshold(virDomainPtr dom,
 }
 
 
+static void
+qemuDomainModifyLifecycleAction(virDomainDefPtr def,
+                                virDomainLifecycle type,
+                                virDomainLifecycleAction action)
+{
+    switch (type) {
+    case VIR_DOMAIN_LIFECYCLE_POWEROFF:
+        def->onPoweroff = action;
+        break;
+    case VIR_DOMAIN_LIFECYCLE_REBOOT:
+        def->onReboot = action;
+        break;
+    case VIR_DOMAIN_LIFECYCLE_CRASH:
+        def->onCrash = action;
+        break;
+    case VIR_DOMAIN_LIFECYCLE_LAST:
+        break;
+    }
+}
+
+
+
+static int
+qemuDomainSetLifecycleAction(virDomainPtr dom,
+                             unsigned int type,
+                             unsigned int action,
+                             unsigned int flags)
+{
+    virQEMUDriverPtr driver = dom->conn->privateData;
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    qemuDomainObjPrivatePtr priv;
+    virDomainObjPtr vm = NULL;
+    virDomainDefPtr def = NULL;
+    virDomainDefPtr persistentDef = NULL;
+    int ret = -1;
+
+    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+                  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+    if (!virDomainDefLifecycleActionAllowed(type, action))
+        goto cleanup;
+
+    if (!(vm = qemuDomObjFromDomain(dom)))
+        goto cleanup;
+
+    priv = vm->privateData;
+
+    if (virDomainSetLifecycleActionEnsureACL(dom->conn, vm->def) < 0)
+        goto cleanup;
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+        goto cleanup;
+
+    if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+        goto endjob;
+
+    if (def) {
+        if (priv->allowReboot == VIR_TRISTATE_BOOL_NO) {
+            virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                           _("cannot update lifecycle action because QEMU "
+                             "was started with -no-reboot option"));
+            goto endjob;
+        }
+
+        qemuDomainModifyLifecycleAction(def, type, action);
+
+        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir,
+                                vm, driver->caps) < 0)
+            goto endjob;
+    }
+
+    if (persistentDef) {
+        qemuDomainModifyLifecycleAction(persistentDef, type, action);
+
+        if (virDomainSaveConfig(cfg->configDir, driver->caps,
+                                persistentDef) < 0)
+            goto endjob;
+    }
+
+    ret = 0;
+
+ endjob:
+    qemuDomainObjEndJob(driver, vm);
+
+ cleanup:
+    virDomainObjEndAPI(&vm);
+    virObjectUnref(cfg);
+    return ret;
+}
+
+
 static virHypervisorDriver qemuHypervisorDriver = {
     .name = QEMU_DRIVER_NAME,
     .connectOpen = qemuConnectOpen, /* 0.2.0 */
@@ -21161,7 +21252,8 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainGetGuestVcpus = qemuDomainGetGuestVcpus, /* 2.0.0 */
     .domainSetGuestVcpus = qemuDomainSetGuestVcpus, /* 2.0.0 */
     .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */
-    .domainSetBlockThreshold = qemuDomainSetBlockThreshold /* 3.2.0 */
+    .domainSetBlockThreshold = qemuDomainSetBlockThreshold, /* 3.2.0 */
+    .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
 };