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
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
src/conf/domain_conf.c | 2 +-
src/conf/domain_conf.h | 4 +++
src/libvirt-domain.c | 4 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_driver.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 103 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f69bcc2530..feea8523a7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5612,7 +5612,7 @@ virDomainDefCheckDuplicateDriveAddresses(const virDomainDef *def)
}
-static bool
+bool
virDomainDefLifecycleActionAllowed(virDomainLifecycle type,
virDomainLifecycleAction action)
{
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8240433611..354b7adfa5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3409,4 +3409,8 @@ virDomainNetTypeSharesHostView(const virDomainNetDef *net)
return false;
}
+bool
+virDomainDefLifecycleActionAllowed(virDomainLifecycle type,
+ virDomainLifecycleAction action);
+
#endif /* __DOMAIN_CONF_H */
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index a51d8e3820..eaec0979ad 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -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,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4cd328eded..a8983f2246 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -269,6 +269,7 @@ virDomainDefHasDeviceAddress;
virDomainDefHasMemballoon;
virDomainDefHasMemoryHotplug;
virDomainDefHasVcpusOffline;
+virDomainDefLifecycleActionAllowed;
virDomainDefMaybeAddController;
virDomainDefMaybeAddInput;
virDomainDefNeedsPlacementAdvice;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f7d713ab59..58a1c7d94e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20914,6 +20914,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 */
@@ -21131,7 +21222,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 */
};
--
2.13.6