[PATCH 11/16] Add reboot support for bhyve backend

Ryan Moeller posted 16 patches 4 years, 9 months ago
There is a newer version of this series
[PATCH 11/16] Add reboot support for bhyve backend
Posted by Ryan Moeller 4 years, 9 months ago
Signed-off-by: Ryan Moeller <ryan@iXsystems.com>
---
 src/bhyve/bhyve_driver.c  | 30 ++++++++++++++++++++++
 src/bhyve/bhyve_monitor.c | 19 +++++++++-----
 src/bhyve/bhyve_monitor.h |  2 ++
 src/bhyve/bhyve_process.c | 52 ++++++++++++++++++++++++++++-----------
 src/bhyve/bhyve_process.h |  3 +++
 5 files changed, 85 insertions(+), 21 deletions(-)

diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index 625dc0ec22..05ffc2f050 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -1013,6 +1013,35 @@ bhyveDomainShutdown(virDomainPtr dom)
     return bhyveDomainShutdownFlags(dom, 0);
 }
 
+static int
+bhyveDomainReboot(virDomainPtr dom, unsigned int flags)
+{
+    virConnectPtr conn = dom->conn;
+    virDomainObjPtr vm;
+    bhyveDomainObjPrivatePtr priv;
+    int ret = -1;
+
+    virCheckFlags(VIR_DOMAIN_REBOOT_ACPI_POWER_BTN, -1);
+
+    if (!(vm = bhyveDomObjFromDomain(dom)))
+        goto cleanup;
+
+    if (virDomainRebootEnsureACL(conn, vm->def, flags) < 0)
+        goto cleanup;
+
+    if (virDomainObjCheckActive(vm) < 0)
+        goto cleanup;
+
+    priv = vm->privateData;
+    bhyveMonitorSetReboot(priv->mon);
+
+    ret = virBhyveProcessShutdown(vm);
+
+ cleanup:
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
+
 static int
 bhyveDomainOpenConsole(virDomainPtr dom,
                        const char *dev_name G_GNUC_UNUSED,
@@ -1657,6 +1686,7 @@ static virHypervisorDriver bhyveHypervisorDriver = {
     .domainDestroyFlags = bhyveDomainDestroyFlags, /* 5.6.0 */
     .domainShutdown = bhyveDomainShutdown, /* 1.3.3 */
     .domainShutdownFlags = bhyveDomainShutdownFlags, /* 5.6.0 */
+    .domainReboot = bhyveDomainReboot, /* TBD */
     .domainLookupByUUID = bhyveDomainLookupByUUID, /* 1.2.2 */
     .domainLookupByName = bhyveDomainLookupByName, /* 1.2.2 */
     .domainLookupByID = bhyveDomainLookupByID, /* 1.2.3 */
diff --git a/src/bhyve/bhyve_monitor.c b/src/bhyve/bhyve_monitor.c
index a1b1a21a6f..e5cd39a086 100644
--- a/src/bhyve/bhyve_monitor.c
+++ b/src/bhyve/bhyve_monitor.c
@@ -41,10 +41,11 @@ VIR_LOG_INIT("bhyve.bhyve_monitor");
 struct _bhyveMonitor {
     virObject parent;
 
-    int kq;
-    int watch;
     bhyveConnPtr driver;
     virDomainObjPtr vm;
+    int kq;
+    int watch;
+    bool reboot;
 };
 
 static virClassPtr bhyveMonitorClass;
@@ -100,6 +101,12 @@ bhyveMonitorUnregister(bhyveMonitorPtr mon)
     mon->watch = -1;
 }
 
+void
+bhyveMonitorSetReboot(bhyveMonitorPtr mon)
+{
+    mon->reboot = true;
+}
+
 static void
 bhyveMonitorIO(int watch, int kq, int events G_GNUC_UNUSED, void *opaque)
 {
@@ -148,11 +155,10 @@ bhyveMonitorIO(int watch, int kq, int events G_GNUC_UNUSED, void *opaque)
                            name, WTERMSIG(status));
             virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED);
         } else if (WIFEXITED(status)) {
-            if (WEXITSTATUS(status) == 0) {
+            if (WEXITSTATUS(status) == 0 || mon->reboot) {
                 /* 0 - reboot */
-                /* TODO: Implementing reboot is a little more complicated. */
-                VIR_INFO("Guest %s rebooted; destroying domain.", name);
-                virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
+                VIR_INFO("Guest %s rebooted; restarting domain.", name);
+                virBhyveProcessRestart(driver, vm);
             } else if (WEXITSTATUS(status) < 3) {
                 /* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */
                 VIR_INFO("Guest %s shut itself down; destroying domain.", name);
@@ -179,6 +185,7 @@ bhyveMonitorOpenImpl(virDomainObjPtr vm, bhyveConnPtr driver)
         return NULL;
 
     mon->driver = driver;
+    mon->reboot = false;
 
     virObjectRef(vm);
     mon->vm = vm;
diff --git a/src/bhyve/bhyve_monitor.h b/src/bhyve/bhyve_monitor.h
index 226866e6d9..175cc87192 100644
--- a/src/bhyve/bhyve_monitor.h
+++ b/src/bhyve/bhyve_monitor.h
@@ -29,3 +29,5 @@ typedef bhyveMonitor *bhyveMonitorPtr;
 
 bhyveMonitorPtr bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver);
 void bhyveMonitorClose(bhyveMonitorPtr mon);
+
+void bhyveMonitorSetReboot(bhyveMonitorPtr mon);
diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c
index 45162503d4..060018bc70 100644
--- a/src/bhyve/bhyve_process.c
+++ b/src/bhyve/bhyve_process.c
@@ -110,11 +110,10 @@ bhyveProcessStopHook(virDomainObjPtr vm, virHookBhyveOpType op)
                     VIR_HOOK_SUBOP_END, NULL, NULL, NULL);
 }
 
-int
-virBhyveProcessStart(virConnectPtr conn,
-                     virDomainObjPtr vm,
-                     virDomainRunningReason reason,
-                     unsigned int flags)
+static int
+virBhyveProcessStartImpl(bhyveConnPtr driver,
+                         virDomainObjPtr vm,
+                         virDomainRunningReason reason)
 {
     char *devmap_file = NULL;
     char *devicemap = NULL;
@@ -122,7 +121,6 @@ virBhyveProcessStart(virConnectPtr conn,
     int logfd = -1;
     virCommandPtr cmd = NULL;
     virCommandPtr load_cmd = NULL;
-    bhyveConnPtr driver = conn->privateData;
     bhyveDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1, rc;
 
@@ -154,10 +152,6 @@ virBhyveProcessStart(virConnectPtr conn,
     if (bhyveDomainAssignAddresses(vm->def, NULL) < 0)
         goto cleanup;
 
-    /* Run an early hook to setup missing devices. */
-    if (bhyveProcessStartHook(vm, VIR_HOOK_BHYVE_OP_PREPARE) < 0)
-        goto cleanup;
-
     /* Call bhyve to start the VM */
     if (!(cmd = virBhyveProcessBuildBhyveCmd(driver, vm->def, false)))
         goto cleanup;
@@ -213,11 +207,6 @@ virBhyveProcessStart(virConnectPtr conn,
         goto cleanup;
     }
 
-    if (flags & VIR_BHYVE_PROCESS_START_AUTODESTROY &&
-        virCloseCallbacksSet(driver->closeCallbacks, vm,
-                             conn, bhyveProcessAutoDestroy) < 0)
-        goto cleanup;
-
     vm->def->id = vm->pid;
     virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
     priv->mon = bhyveMonitorOpen(vm, driver);
@@ -262,6 +251,26 @@ virBhyveProcessStart(virConnectPtr conn,
     return ret;
 }
 
+int
+virBhyveProcessStart(virConnectPtr conn,
+                     virDomainObjPtr vm,
+                     virDomainRunningReason reason,
+                     unsigned int flags)
+{
+    bhyveConnPtr driver = conn->privateData;
+
+    /* Run an early hook to setup missing devices. */
+    if (bhyveProcessStartHook(vm, VIR_HOOK_BHYVE_OP_PREPARE) < 0)
+        return -1;
+
+    if (flags & VIR_BHYVE_PROCESS_START_AUTODESTROY &&
+        virCloseCallbacksSet(driver->closeCallbacks, vm,
+                             conn, bhyveProcessAutoDestroy) < 0)
+        return -1;
+
+    return virBhyveProcessStartImpl(driver, vm, reason);
+}
+
 int
 virBhyveProcessStop(bhyveConnPtr driver,
                     virDomainObjPtr vm,
@@ -349,6 +358,19 @@ virBhyveProcessShutdown(virDomainObjPtr vm)
     return 0;
 }
 
+int
+virBhyveProcessRestart(bhyveConnPtr driver,
+                       virDomainObjPtr vm)
+{
+    if (virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN) < 0)
+        return -1;
+
+    if (virBhyveProcessStartImpl(driver, vm, VIR_DOMAIN_RUNNING_BOOTED) < 0)
+        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 8419e44faa..d7b4e0bd4e 100644
--- a/src/bhyve/bhyve_process.h
+++ b/src/bhyve/bhyve_process.h
@@ -32,6 +32,9 @@ int virBhyveProcessStop(bhyveConnPtr driver,
                         virDomainObjPtr vm,
                         virDomainShutoffReason reason);
 
+int virBhyveProcessRestart(bhyveConnPtr driver,
+                           virDomainObjPtr vm);
+
 int virBhyveProcessShutdown(virDomainObjPtr vm);
 
 int virBhyveGetDomainTotalCpuStats(virDomainObjPtr vm,
-- 
2.24.1