src/bhyve/bhyve_driver.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-)
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>
---
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
Roman Bogorodskiy wrote: > 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> > --- > src/bhyve/bhyve_driver.c | 38 +++++++++++++++++++++++++++++++++++--- > 1 file changed, 35 insertions(+), 3 deletions(-) Sorry, I messed up with my patch directories and shell globs while sending this. This patch should be skipped. Patches 1/2 and 2/2 are valid. Roman
Implement shutdown using a guest agent.
Implementation and behaviour is very similar to the one
found in the qemu driver.
The bhyveDomainShutdownFlags() function now supports
the VIR_DOMAIN_SHUTDOWN_SIGNAL and VIR_DOMAIN_SHUTDOWN_GUEST_AGENT.
If flags were not specified, try the agent first, and if it does
not work, proceed with the signal.
As we do not expect a response from the agent shutdown command,
we do not check qemuAgentShutdown()'s return value. Assume that the
command failed if the agent did not receive EOF, thus "priv->agent"
is not NULL.
Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com>
---
src/bhyve/bhyve_driver.c | 69 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 67 insertions(+), 2 deletions(-)
diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index 35abf36877..4b28c698e7 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -1053,14 +1053,51 @@ bhyveDomainShutdownSignal(virDomainObj *vm,
return virBhyveProcessShutdown(vm);
}
+static int
+bhyveDomainShutdownFlagsAgent(virDomainObj *vm,
+ bool isReboot,
+ bool reportError)
+{
+ int ret = -1;
+ qemuAgent *agent;
+ int agentFlag = isReboot ? QEMU_AGENT_SHUTDOWN_REBOOT :
+ QEMU_AGENT_SHUTDOWN_POWERDOWN;
+
+ if (virDomainObjBeginAgentJob(vm, VIR_AGENT_JOB_MODIFY) < 0)
+ return -1;
+
+ if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto endjob;
+ }
+
+ if (bhyveDomainEnsureAgent(vm, reportError) < 0)
+ goto endjob;
+
+ agent = bhyveDomainObjEnterAgent(vm);
+ qemuAgentShutdown(agent, agentFlag);
+ bhyveDomainObjExitAgent(vm, agent);
+ ret = 0;
+
+ endjob:
+ virDomainObjEndAgentJob(vm);
+ return ret;
+}
+
static int
bhyveDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
{
virDomainObj *vm;
+ bhyveDomainObjPrivate *priv;
int ret = -1;
bool isReboot = false;
+ bool useAgent = false;
+ bool agentRequested, signalRequested;
+ bool agentForced;
- virCheckFlags(0, -1);
+ virCheckFlags(VIR_DOMAIN_SHUTDOWN_SIGNAL |
+ VIR_DOMAIN_SHUTDOWN_GUEST_AGENT, -1);
if (!(vm = bhyveDomObjFromDomain(dom)))
goto cleanup;
@@ -1071,13 +1108,41 @@ bhyveDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
VIR_INFO("Domain on_poweroff setting overridden, attempting reboot");
}
+ priv = vm->privateData;
+ agentRequested = flags & VIR_DOMAIN_SHUTDOWN_GUEST_AGENT;
+ signalRequested = flags & VIR_DOMAIN_SHUTDOWN_SIGNAL;
+
+ /* Prefer agent unless we were requested to not to. */
+ if (agentRequested || !flags)
+ useAgent = true;
+
if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;
if (virDomainObjCheckActive(vm) < 0)
goto cleanup;
- ret = bhyveDomainShutdownSignal(vm, isReboot);
+ agentForced = agentRequested && !signalRequested;
+ if (useAgent) {
+ ret = bhyveDomainShutdownFlagsAgent(vm, isReboot, agentForced);
+ if (((ret < 0) || (priv->agent != NULL)) && agentForced)
+ goto cleanup;
+ }
+
+ /* If we are not enforced to use just an agent, try signal
+ * shutdown as well in case agent did not succeed.
+ */
+ if (!useAgent || (((ret < 0) ||
+ (priv->agent != NULL)) && (signalRequested || !flags))) {
+ /* Even if agent failed, we have to check if guest went away
+ * by itself while our locks were down. */
+ if (useAgent && !virDomainObjIsActive(vm)) {
+ ret = 0;
+ goto cleanup;
+ }
+
+ ret = bhyveDomainShutdownSignal(vm, isReboot);
+ }
cleanup:
virDomainObjEndAPI(&vm);
--
2.52.0
On 6/14/26 08:56, Roman Bogorodskiy wrote: > Implement shutdown using a guest agent. > Implementation and behaviour is very similar to the one > found in the qemu driver. > > The bhyveDomainShutdownFlags() function now supports > the VIR_DOMAIN_SHUTDOWN_SIGNAL and VIR_DOMAIN_SHUTDOWN_GUEST_AGENT. > If flags were not specified, try the agent first, and if it does > not work, proceed with the signal. > > As we do not expect a response from the agent shutdown command, > we do not check qemuAgentShutdown()'s return value. Assume that the > command failed if the agent did not receive EOF, thus "priv->agent" > is not NULL. > > Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com> > --- > src/bhyve/bhyve_driver.c | 69 ++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 67 insertions(+), 2 deletions(-) Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
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>
---
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
On 6/14/26 08:56, Roman Bogorodskiy wrote: > 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> > --- > src/bhyve/bhyve_driver.c | 38 +++++++++++++++++++++++++++++++++++--- > 1 file changed, 35 insertions(+), 3 deletions(-) Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
© 2016 - 2026 Red Hat, Inc.