diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 18addcaf14..5d95c5bdb0 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 * $action 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 d3cb05be6f..10c6aeadcd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -270,6 +270,7 @@ virDomainDefHasDeviceAddress; virDomainDefHasMemballoon; virDomainDefHasMemoryHotplug; virDomainDefHasVcpusOffline; +virDomainDefLifecycleActionAllowed; virDomainDefMaybeAddController; virDomainDefMaybeAddInput; virDomainDefNeedsPlacementAdvice; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 502b5b5fcd..b241b98336 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -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 */ };