qemu: implement virDomainSetLifecycleAction() API

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>
This commit is contained in:
Pavel Hrdina 2017-10-11 16:09:49 +02:00
parent e859da6f42
commit d66fc71d31
5 changed files with 103 additions and 2 deletions

View File

@ -5612,7 +5612,7 @@ virDomainDefCheckDuplicateDriveAddresses(const virDomainDef *def)
}
static bool
bool
virDomainDefLifecycleActionAllowed(virDomainLifecycle type,
virDomainLifecycleAction action)
{

View File

@ -3409,4 +3409,8 @@ virDomainNetTypeSharesHostView(const virDomainNetDef *net)
return false;
}
bool
virDomainDefLifecycleActionAllowed(virDomainLifecycle type,
virDomainLifecycleAction action);
#endif /* __DOMAIN_CONF_H */

View 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,

View File

@ -270,6 +270,7 @@ virDomainDefHasDeviceAddress;
virDomainDefHasMemballoon;
virDomainDefHasMemoryHotplug;
virDomainDefHasVcpusOffline;
virDomainDefLifecycleActionAllowed;
virDomainDefMaybeAddController;
virDomainDefMaybeAddInput;
virDomainDefNeedsPlacementAdvice;

View 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 */
};