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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list