diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 825babd4a69aae515e81c4cafd43cc62ae68f2a1..d40b5d5467dd9efb58005955b2d1587cd9005bd5 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1702,40 +1702,40 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { virDomainObjPtr vm; int ret = -1; qemuDomainObjPrivatePtr priv; - bool useAgent = false; + bool useAgent = false, agentRequested, acpiRequested; virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN | VIR_DOMAIN_SHUTDOWN_GUEST_AGENT, -1); - /* At most one of these two flags should be set. */ - if ((flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) && - (flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT)) { - virReportInvalidArg(flags, "%s", - _("flags for acpi power button and guest agent are mutually exclusive")); - return -1; - } - if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; priv = vm->privateData; + agentRequested = flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT; + acpiRequested = flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN; - if ((flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT) || - (!(flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) && - priv->agent)) + /* Prefer agent unless we were requested to not to. */ + if (agentRequested || (!flags && priv->agent)) useAgent = true; - if (useAgent) { - if (priv->agentError) { + if (priv->agentError) { + if (agentRequested && !acpiRequested) { virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s", _("QEMU guest agent is not " "available due to an error")); goto cleanup; + } else { + useAgent = false; } - if (!priv->agent) { + } + + if (!priv->agent) { + if (agentRequested && !acpiRequested) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("QEMU guest agent is not configured")); goto cleanup; + } else { + useAgent = false; } } @@ -1752,7 +1752,13 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { qemuDomainObjEnterAgent(vm); ret = qemuAgentShutdown(priv->agent, QEMU_AGENT_SHUTDOWN_POWERDOWN); qemuDomainObjExitAgent(vm); - } else { + } + + /* If we are not enforced to use just an agent, try ACPI + * shutdown as well in case agent did not succeed. + */ + if (!useAgent || + (ret < 0 && (acpiRequested || !flags))) { qemuDomainSetFakeReboot(driver, vm, false); qemuDomainObjEnterMonitor(driver, vm);