[libvirt] [PATCH libvirt-tck] bhyve: reconnect to domains after libvirtd restart

Roman Bogorodskiy bogorodskiy at gmail.com
Sun Jun 29 16:06:47 UTC 2014


Try to reconnect to the running domains after libvirtd restart. To
achieve that, do:

 * Save domain state
  - Modify virBhyveProcessStart() to save domain state to the state
    dir
  - Modify virBhyveProcessStop() to cleanup the pidfile and the state

 * Detect if the state information loaded from the driver's state
   dir matches the actual state. Consider domain active if:
    - PID it points to exist
    - Process title of this PID matches the expected one with the
      domain name

   Otherwise, mark the domain as shut off.

Note: earlier development bhyve versions before FreeBSD 10.0-RELEASE
didn't set proctitle we expect, so the current code will not detect
it. I don't plan adding support for this unless somebody requests
this.
---
 src/bhyve/bhyve_driver.c  | 18 ++++++++++
 src/bhyve/bhyve_process.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++
 src/bhyve/bhyve_process.h |  2 ++
 3 files changed, 111 insertions(+)

diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index eb5fc95..4c7596e 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -1151,6 +1151,8 @@ bhyveStateInitialize(bool priveleged ATTRIBUTE_UNUSED,
                      virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                      void *opaque ATTRIBUTE_UNUSED)
 {
+    virConnectPtr conn = NULL;
+
     if (!priveleged) {
         VIR_INFO("Not running priveleged, disabling driver");
         return 0;
@@ -1199,6 +1201,15 @@ bhyveStateInitialize(bool priveleged ATTRIBUTE_UNUSED,
     }
 
     if (virDomainObjListLoadAllConfigs(bhyve_driver->domains,
+                                       BHYVE_STATE_DIR,
+                                       NULL, 1,
+                                       bhyve_driver->caps,
+                                       bhyve_driver->xmlopt,
+                                       1 << VIR_DOMAIN_VIRT_BHYVE,
+                                       NULL, NULL) < 0)
+        goto cleanup;
+
+    if (virDomainObjListLoadAllConfigs(bhyve_driver->domains,
                                        BHYVE_CONFIG_DIR,
                                        BHYVE_AUTOSTART_DIR, 0,
                                        bhyve_driver->caps,
@@ -1207,9 +1218,16 @@ bhyveStateInitialize(bool priveleged ATTRIBUTE_UNUSED,
                                        NULL, NULL) < 0)
         goto cleanup;
 
+    conn = virConnectOpen("bhyve:///system");
+
+    virBhyveProcessReconnectAll(conn, bhyve_driver);
+
+    virObjectUnref(conn);
+
     return 0;
 
  cleanup:
+    virObjectUnref(conn);
     bhyveStateCleanup();
     return -1;
 }
diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c
index f3898f5..ea5ac9b 100644
--- a/src/bhyve/bhyve_process.c
+++ b/src/bhyve/bhyve_process.c
@@ -185,6 +185,11 @@ virBhyveProcessStart(virConnectPtr conn,
     vm->def->id = vm->pid;
     virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
 
+    if (virDomainSaveStatus(driver->xmlopt,
+                            BHYVE_STATE_DIR,
+                            vm) < 0)
+        goto cleanup;
+
     ret = 0;
 
  cleanup:
@@ -257,6 +262,10 @@ virBhyveProcessStop(bhyveConnPtr driver,
 
  cleanup:
     virCommandFree(cmd);
+
+    virPidFileDelete(BHYVE_STATE_DIR, vm->def->name);
+    virDomainDeleteConfig(BHYVE_STATE_DIR, NULL, vm);
+
     return ret;
 }
 
@@ -295,3 +304,85 @@ virBhyveGetDomainTotalCpuStats(virDomainObjPtr vm,
 
     return ret;
 }
+
+struct bhyveProcessReconnectData {
+    virConnectPtr conn;
+    bhyveConnPtr driver;
+    kvm_t *kd;
+};
+
+static int
+virBhyveProcessReconnect(virDomainObjPtr vm,
+                         void *opaque)
+{
+    struct bhyveProcessReconnectData *data = opaque;
+    struct kinfo_proc *kp;
+    int nprocs;
+    char **proc_argv;
+    char *expected_proctitle = NULL;
+    int ret = -1;
+
+    if (!virDomainObjIsActive(vm))
+        return 0;
+
+    if (!vm->pid)
+        return 0;
+
+    virObjectLock(vm);
+
+    kp = kvm_getprocs(data->kd, KERN_PROC_PID, vm->pid, &nprocs);
+    if (kp == NULL || nprocs != 1)
+        goto cleanup;
+
+    if (virAsprintf(&expected_proctitle, "bhyve: %s", vm->def->name) < 0)
+        goto cleanup;
+
+    proc_argv = kvm_getargv(data->kd, kp, 0);
+    if (proc_argv && proc_argv[0])
+         if (STREQ(expected_proctitle, proc_argv[0]))
+             ret = 0;
+
+ cleanup:
+    if (ret < 0) {
+        /* If VM is reported to be in active state, but we cannot find
+         * its PID, then we clear information about the PID and
+         * set state to 'shutdown' */
+        vm->pid = 0;
+        vm->def->id = -1;
+        virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
+                             VIR_DOMAIN_SHUTOFF_UNKNOWN);
+        ignore_value(virDomainSaveStatus(data->driver->xmlopt,
+                                         BHYVE_STATE_DIR,
+                                         vm));
+    }
+
+    virObjectUnlock(vm);
+    VIR_FREE(expected_proctitle);
+
+    return ret;
+}
+
+void
+virBhyveProcessReconnectAll(virConnectPtr conn,
+                            bhyveConnPtr driver)
+{
+    kvm_t *kd;
+    struct bhyveProcessReconnectData data;
+    char errbuf[_POSIX2_LINE_MAX];
+
+    if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) {
+        virReportError(VIR_ERR_SYSTEM_ERROR,
+                       _("Unable to get kvm descriptor: %s"),
+                       errbuf);
+        return;
+
+    }
+
+    data.conn = conn;
+    data.driver = driver;
+    data.kd = kd;
+
+    virDomainObjListForEach(driver->domains, virBhyveProcessReconnect, &data);
+
+    kvm_close(kd);
+}
diff --git a/src/bhyve/bhyve_process.h b/src/bhyve/bhyve_process.h
index 3049ad0..006a5ae 100644
--- a/src/bhyve/bhyve_process.h
+++ b/src/bhyve/bhyve_process.h
@@ -37,6 +37,8 @@ int virBhyveProcessStop(bhyveConnPtr driver,
 int virBhyveGetDomainTotalCpuStats(virDomainObjPtr vm,
                                    unsigned long long *cpustats);
 
+void virBhyveProcessReconnectAll(virConnectPtr conn, bhyveConnPtr driver);
+
 typedef enum {
     VIR_BHYVE_PROCESS_START_AUTODESTROY = 1 << 0,
 } bhyveProcessStartFlags;
-- 
1.9.0




More information about the libvir-list mailing list