Implement domain reboot using the guest agent.
Implementation is very similar to the domain shutdown
added earlier.

Also, change the VIR_DOMAIN_REBOOT_ACPI_POWER_BTN flag
to VIR_DOMAIN_REBOOT_SIGNAL. Even though bhyve emulates
the ACPI button, it's triggered by sending a signal to the
bhyve process, so VIR_DOMAIN_REBOOT_SIGNAL looks like
a more accurate description of communication between
libvirt and bhyve.

Signed-off-by: Roman Bogorodskiy <[email protected]>
---
 src/bhyve/bhyve_driver.c | 38 +++++++++++++++++++++++++++++++++++---
 1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index 4b28c698e7..45e8aad5b5 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -1085,6 +1085,12 @@ bhyveDomainShutdownFlagsAgent(virDomainObj *vm,
     return ret;
 }
 
+static int
+bhyveDomainRebootAgent(virDomainObj *vm, bool isReboot, bool reportError)
+{
+    return bhyveDomainShutdownFlagsAgent(vm, isReboot, reportError);
+}
+
 static int
 bhyveDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
 {
@@ -1160,10 +1166,15 @@ bhyveDomainReboot(virDomainPtr dom, unsigned int flags)
 {
     virConnectPtr conn = dom->conn;
     virDomainObj *vm;
-    bool isReboot = true;
+    bhyveDomainObjPrivate *priv;
     int ret = -1;
+    bool isReboot = true;
+    bool useAgent = false;
+    bool agentRequested, signalRequested;
+    bool agentForced;
 
-    virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN, -1);
+    virCheckFlags(VIR_DOMAIN_REBOOT_SIGNAL |
+                  VIR_DOMAIN_REBOOT_GUEST_AGENT, -1);
 
     if (!(vm = bhyveDomObjFromDomain(dom)))
         goto cleanup;
@@ -1174,13 +1185,34 @@ bhyveDomainReboot(virDomainPtr dom, unsigned int flags)
         VIR_INFO("Domain on_reboot setting overridden, shutting down");
     }
 
+    priv = vm->privateData;
+    agentRequested = flags & VIR_DOMAIN_REBOOT_GUEST_AGENT;
+    signalRequested = flags & VIR_DOMAIN_REBOOT_SIGNAL;
+
+    /* Prefer agent unless we were requested to not to. */
+    if (agentRequested || !flags)
+        useAgent = true;
+
     if (virDomainRebootEnsureACL(conn, vm->def, flags) < 0)
         goto cleanup;
 
     if (virDomainObjCheckActive(vm) < 0)
         goto cleanup;
 
-    ret = bhyveDomainShutdownSignal(vm, isReboot);
+    agentForced = agentRequested && !signalRequested;
+    if (useAgent) {
+        ret = bhyveDomainRebootAgent(vm, isReboot, agentForced);
+        if (((ret < 0) || (priv->agent != NULL)) && agentForced)
+            goto cleanup;
+    }
+
+    /* If we are not enforced to use just an agent, try signal
+     * reboot as well in case agent did not succeed.
+     */
+    if (!useAgent || (((ret < 0) ||
+        (priv->agent != NULL)) && (signalRequested || !flags))) {
+        ret = bhyveDomainShutdownSignal(vm, isReboot);
+    }
 
  cleanup:
     virDomainObjEndAPI(&vm);
-- 
2.52.0

Reply via email to