]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
bhyve: implement reboot using agent
authorRoman Bogorodskiy <bogorodskiy@gmail.com>
Sat, 13 Jun 2026 06:03:27 +0000 (08:03 +0200)
committerRoman Bogorodskiy <bogorodskiy@gmail.com>
Sat, 20 Jun 2026 07:25:08 +0000 (09:25 +0200)
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 <bogorodskiy@gmail.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/bhyve/bhyve_driver.c

index 4b28c698e7f8e66e3c3341d7b978c21d0ae5ad66..45e8aad5b5277269a4608a1f0cf7e114cc5e5d9d 100644 (file)
@@ -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);