[libvirt] [PATCH] qemu: Don't fail to reboot domains with unresponsive agent

Michal Privoznik mprivozn at redhat.com
Thu Apr 23 08:37:17 UTC 2015


On 23.04.2015 05:40, zhang bo wrote:
> just as what b8e25c35d7f80a2fadc0e51e95318e39db3d1687 did,
> we fall back to the ACPI method when the guest agent is unresponsive in qemuDomainReboot.
> 
> Signed-off-by: YueWenyuan <yuewenyuan at huawei.com>
> Signed-off-by: Zhang Bo <oscar.zhangbo at huawei.com>
> 
> ---
>  src/qemu/qemu_driver.c | 67 +++++++++++++++++++++++++-------------------------
>  1 file changed, 34 insertions(+), 33 deletions(-)
> 
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 6fc9696..964a9c5 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -2002,21 +2002,14 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
>      virDomainObjPtr vm;
>      int ret = -1;
>      qemuDomainObjPrivatePtr priv;
> -    bool useAgent = false;
> +    bool useAgent = false, agentRequested, acpiRequested;
>      bool isReboot = true;
> +    bool agentForced;
>      int agentFlag = QEMU_AGENT_SHUTDOWN_REBOOT;
> 
>      virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN |
>                    VIR_DOMAIN_REBOOT_GUEST_AGENT, -1);
> 
> -    /* At most one of these two flags should be set.  */
> -    if ((flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN) &&
> -        (flags & VIR_DOMAIN_REBOOT_GUEST_AGENT)) {
> -        virReportInvalidArg(flags, "%s",
> -                            _("flags for acpi power button and guest agent are mutually exclusive"));
> -        return -1;
> -    }
> -
>      if (!(vm = qemuDomObjFromDomain(dom)))
>          goto cleanup;
> 
> @@ -2028,38 +2021,25 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
>      }
> 
>      priv = vm->privateData;
> +    agentRequested = flags & VIR_DOMAIN_REBOOT_GUEST_AGENT;
> +    acpiRequested  = flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN;
> 
>      if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
>          goto cleanup;
> 
> -    if ((flags & VIR_DOMAIN_REBOOT_GUEST_AGENT) ||
> -        (!(flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN) &&
> -         priv->agent))
> +    /* Prefer agent unless we were requested to not to. */
> +    if (agentRequested || (!flags && priv->agent))
>          useAgent = true;

Not that it would harm or anything, but this check can be made just before checkACL() like in shutdown.

> 
> -    if (!useAgent) {
> -#if WITH_YAJL
> -        if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON)) {
> -            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NO_SHUTDOWN)) {
> -                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> -                               _("Reboot is not supported with this QEMU binary"));
> -                goto cleanup;
> -            }
> -        } else {
> -#endif
> -            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> -                           _("Reboot is not supported without the JSON monitor"));
> -            goto cleanup;
> -#if WITH_YAJL
> -        }
> -#endif
> -    }
> -
>      if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
>          goto cleanup;
> 
> -    if (useAgent && !qemuDomainAgentAvailable(vm, true))
> -        goto endjob;
> +    agentForced = agentRequested && !acpiRequested;
> +    if (useAgent && !qemuDomainAgentAvailable(vm, true)) {

Or if (!qemuDomainAgentAvailable(vm, agentForced)) {}

> +        if (agentForced)
> +            goto endjob;
> +        useAgent = false;
> +    }
> 
>      if (!virDomainObjIsActive(vm)) {
>          virReportError(VIR_ERR_OPERATION_INVALID,

Not to be seen in the context, but this is the correct place to set fakeReboot.

> @@ -2071,7 +2051,28 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
>          qemuDomainObjEnterAgent(vm);
>          ret = qemuAgentShutdown(priv->agent, agentFlag);
>          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))) {
> +#if WITH_YAJL
> +        if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON)) {
> +            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NO_SHUTDOWN)) {
> +                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                               _("ACPI reboot is not supported with this QEMU binary"));
> +                goto endjob;
> +            }
> +        } else {
> +#endif
> +            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                           _("ACPI reboot is not supported without the JSON monitor"));
> +            goto endjob;
> +#if WITH_YAJL
> +        }
> +#endif
>          qemuDomainObjEnterMonitor(driver, vm);
>          ret = qemuMonitorSystemPowerdown(priv->mon);
>          if (qemuDomainObjExitMonitor(driver, vm) < 0)
> 

So, I'm squashing this in:

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 509ba94..82f34ec 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2024,18 +2024,18 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
     agentRequested = flags & VIR_DOMAIN_REBOOT_GUEST_AGENT;
     acpiRequested  = flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN;
 
+    /* Prefer agent unless we were requested to not to. */
+    if (agentRequested || (!flags && priv->agent))
+        useAgent = true;
+
     if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
         goto cleanup;
 
-    /* Prefer agent unless we were requested to not to. */
-    if (agentRequested || (!flags && priv->agent))
-        useAgent = true;
-
     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
         goto cleanup;
 
     agentForced = agentRequested && !acpiRequested;
-    if (useAgent && !qemuDomainAgentAvailable(vm, true)) {
+    if (!qemuDomainAgentAvailable(vm, agentForced)) {
         if (agentForced)
             goto endjob;
         useAgent = false;
@@ -2047,6 +2047,8 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
         goto endjob;
     }
 
+    qemuDomainSetFakeReboot(driver, vm, isReboot);
+
     if (useAgent) {
         qemuDomainObjEnterAgent(vm);
         ret = qemuAgentShutdown(priv->agent, agentFlag);
@@ -2077,9 +2079,6 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags)
         ret = qemuMonitorSystemPowerdown(priv->mon);
         if (qemuDomainObjExitMonitor(driver, vm) < 0)
             ret = -1;
-
-        if (ret == 0)
-            qemuDomainSetFakeReboot(driver, vm, isReboot);
     }
 
  endjob:

ACKing and pushing.

Michal




More information about the libvir-list mailing list