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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list