Bhyve supports ACPI shutdown by issuing SIGTERM signal to the bhyve
process. Add the bhyveDomainShutdown() function and
virBhyveProcessShutdown() helper function that just sends SIGTERM to
VM's bhyve process. If a guest supports ACPI shutdown then process
will be terminated and this event will be noticed by the bhyve monitor
code that will handle setting proper status and clean up VM's resources.
Also, remove a warning in domainDestroy in case if
virProcessKillPainfully() returns 1, meaning that it killed process
using SIGKILL. This behavior should be expected when using 'destroy'.
---
src/bhyve/bhyve_driver.c | 27 +++++++++++++++++++++++++++
src/bhyve/bhyve_process.c | 30 ++++++++++++++++++++++++++----
src/bhyve/bhyve_process.h | 2 ++
3 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index 9219890..b9eacb9 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -1018,6 +1018,32 @@ bhyveDomainDestroy(virDomainPtr dom)
}
static int
+bhyveDomainShutdown(virDomainPtr dom)
+{
+ virDomainObjPtr vm;
+ int ret = -1;
+
+ if (!(vm = bhyveDomObjFromDomain(dom)))
+ goto cleanup;
+
+ if (virDomainShutdownEnsureACL(dom->conn, vm->def) < 0)
+ goto cleanup;
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("Domain is not running"));
+ goto cleanup;
+ }
+
+ ret = virBhyveProcessShutdown(vm);
+
+ cleanup:
+ if (vm)
+ virObjectUnlock(vm);
+ return ret;
+}
+
+static int
bhyveDomainOpenConsole(virDomainPtr dom,
const char *dev_name ATTRIBUTE_UNUSED,
virStreamPtr st,
@@ -1507,6 +1533,7 @@ static virHypervisorDriver bhyveHypervisorDriver = {
.domainCreateWithFlags = bhyveDomainCreateWithFlags, /* 1.2.3 */
.domainCreateXML = bhyveDomainCreateXML, /* 1.2.4 */
.domainDestroy = bhyveDomainDestroy, /* 1.2.2 */
+ .domainShutdown = bhyveDomainShutdown, /* 1.3.3 */
.domainLookupByUUID = bhyveDomainLookupByUUID, /* 1.2.2 */
.domainLookupByName = bhyveDomainLookupByName, /* 1.2.2 */
.domainLookupByID = bhyveDomainLookupByID, /* 1.2.3 */
diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c
index 14588a9..fba3896 100644
--- a/src/bhyve/bhyve_process.c
+++ b/src/bhyve/bhyve_process.c
@@ -282,10 +282,9 @@ virBhyveProcessStop(bhyveConnPtr driver,
bhyveMonitorClose(priv->mon);
/* First, try to kill 'bhyve' process */
- if (virProcessKillPainfully(vm->pid, true) != 0)
- VIR_WARN("Failed to gracefully stop bhyve VM '%s' (pid: %d)",
- vm->def->name,
- (int)vm->pid);
+ if (virProcessKillPainfully(vm->pid, true) == -1)
+ VIR_WARN("Failed to kill bhyve process for VM '%s': %s",
+ vm->def->name, virGetLastErrorMessage());
/* Cleanup network interfaces */
bhyveNetCleanup(vm);
@@ -317,6 +316,29 @@ virBhyveProcessStop(bhyveConnPtr driver,
}
int
+virBhyveProcessShutdown(virDomainObjPtr vm)
+{
+ if (vm->pid <= 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid PID %d for VM"),
+ (int)vm->pid);
+ return -1;
+ }
+
+ /* Bhyve tries to perform ACPI shutdown when it receives
+ * SIGTERM signal. So we just issue SIGTERM here and rely
+ * on the bhyve monitor to clean things up if process disappears.
+ */
+ if (virProcessKill(vm->pid, SIGTERM) != 0) {
+ VIR_WARN("Failed to terminate bhyve process for VM '%s': %s",
+ vm->def->name, virGetLastErrorMessage());
+ return -1;
+ }
+
+ return 0;
+}
+
+int
virBhyveGetDomainTotalCpuStats(virDomainObjPtr vm,
unsigned long long *cpustats)
{
diff --git a/src/bhyve/bhyve_process.h b/src/bhyve/bhyve_process.h
index cfa80af..ebabe17 100644
--- a/src/bhyve/bhyve_process.h
+++ b/src/bhyve/bhyve_process.h
@@ -34,6 +34,8 @@ int virBhyveProcessStop(bhyveConnPtr driver,
virDomainObjPtr vm,
virDomainShutoffReason reason);
+int virBhyveProcessShutdown(virDomainObjPtr vm);
+
int virBhyveGetDomainTotalCpuStats(virDomainObjPtr vm,
unsigned long long *cpustats);
--
2.7.4