1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

bhyve: monitor: Make bhyveMonitor a virClass

This makes lifecycle management a bit easier thanks to ref counting, and
it is closer to what the qemu driver does.

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Ryan Moeller <ryan@iXsystems.com>
This commit is contained in:
Ryan Moeller 2020-02-24 01:46:16 -05:00 committed by Daniel P. Berrangé
parent fd54da1ef2
commit 30ab31a902

View File

@ -32,24 +32,51 @@
#include "virerror.h" #include "virerror.h"
#include "virfile.h" #include "virfile.h"
#include "virlog.h" #include "virlog.h"
#include "virobject.h"
#define VIR_FROM_THIS VIR_FROM_BHYVE #define VIR_FROM_THIS VIR_FROM_BHYVE
VIR_LOG_INIT("bhyve.bhyve_monitor"); VIR_LOG_INIT("bhyve.bhyve_monitor");
struct _bhyveMonitor { struct _bhyveMonitor {
virObject parent;
int kq; int kq;
int watch; int watch;
bhyveConnPtr driver; bhyveConnPtr driver;
virDomainObjPtr vm;
}; };
static virClassPtr bhyveMonitorClass;
static void
bhyveMonitorDispose(void *obj)
{
bhyveMonitorPtr mon = obj;
VIR_FORCE_CLOSE(mon->kq);
virObjectUnref(mon->vm);
}
static int
bhyveMonitorOnceInit(void)
{
if (!VIR_CLASS_NEW(bhyveMonitor, virClassForObject()))
return -1;
return 0;
}
VIR_ONCE_GLOBAL_INIT(bhyveMonitor);
static void static void
bhyveMonitorIO(int watch, int kq, int events G_GNUC_UNUSED, void *opaque) bhyveMonitorIO(int watch, int kq, int events G_GNUC_UNUSED, void *opaque)
{ {
const struct timespec zerowait = { 0, 0 }; const struct timespec zerowait = { 0, 0 };
virDomainObjPtr vm = opaque; bhyveMonitorPtr mon = opaque;
bhyveDomainObjPrivatePtr priv = vm->privateData; virDomainObjPtr vm = mon->vm;
bhyveMonitorPtr mon = priv->mon; bhyveConnPtr driver = mon->driver;
const char *name;
struct kevent kev; struct kevent kev;
int rc, status; int rc, status;
@ -82,60 +109,49 @@ bhyveMonitorIO(int watch, int kq, int events G_GNUC_UNUSED, void *opaque)
return; return;
} }
name = vm->def->name;
status = kev.data; status = kev.data;
if (WIFSIGNALED(status) && WCOREDUMP(status)) { if (WIFSIGNALED(status) && WCOREDUMP(status)) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Guest %s got signal %d and crashed"), _("Guest %s got signal %d and crashed"),
vm->def->name, name, WTERMSIG(status));
WTERMSIG(status)); virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED);
virBhyveProcessStop(mon->driver, vm,
VIR_DOMAIN_SHUTOFF_CRASHED);
} else if (WIFEXITED(status)) { } else if (WIFEXITED(status)) {
if (WEXITSTATUS(status) == 0) { if (WEXITSTATUS(status) == 0) {
/* 0 - reboot */ /* 0 - reboot */
/* TODO: Implementing reboot is a little more complicated. */ /* TODO: Implementing reboot is a little more complicated. */
VIR_INFO("Guest %s rebooted; destroying domain.", VIR_INFO("Guest %s rebooted; destroying domain.", name);
vm->def->name); virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
virBhyveProcessStop(mon->driver, vm,
VIR_DOMAIN_SHUTOFF_SHUTDOWN);
} else if (WEXITSTATUS(status) < 3) { } else if (WEXITSTATUS(status) < 3) {
/* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */ /* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */
VIR_INFO("Guest %s shut itself down; destroying domain.", VIR_INFO("Guest %s shut itself down; destroying domain.", name);
vm->def->name); virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
virBhyveProcessStop(mon->driver, vm,
VIR_DOMAIN_SHUTOFF_SHUTDOWN);
} else { } else {
VIR_INFO("Guest %s had an error and exited with status %d; destroying domain.", VIR_INFO("Guest %s had an error and exited with status %d; destroying domain.",
vm->def->name, WEXITSTATUS(status)); name, WEXITSTATUS(status));
virBhyveProcessStop(mon->driver, vm, virBhyveProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN);
VIR_DOMAIN_SHUTOFF_UNKNOWN);
} }
} }
} }
} }
static void static bhyveMonitorPtr
bhyveMonitorRelease(void *opaque) bhyveMonitorOpenImpl(virDomainObjPtr vm, bhyveConnPtr driver)
{ {
virDomainObjPtr vm = opaque; bhyveMonitorPtr mon;
bhyveDomainObjPrivatePtr priv = vm->privateData;
bhyveMonitorPtr mon = priv->mon;
VIR_FORCE_CLOSE(mon->kq);
VIR_FREE(mon);
}
bhyveMonitorPtr
bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver)
{
bhyveMonitorPtr mon = NULL;
struct kevent kev; struct kevent kev;
if (VIR_ALLOC(mon) < 0) if (bhyveMonitorInitialize() < 0)
return NULL;
if (!(mon = virObjectNew(bhyveMonitorClass)))
return NULL; return NULL;
mon->driver = driver; mon->driver = driver;
virObjectRef(vm);
mon->vm = vm;
mon->kq = kqueue(); mon->kq = kqueue();
if (mon->kq < 0) { if (mon->kq < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR, "%s", virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
@ -150,14 +166,17 @@ bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver)
goto cleanup; goto cleanup;
} }
virObjectRef(mon);
mon->watch = virEventAddHandle(mon->kq, mon->watch = virEventAddHandle(mon->kq,
VIR_EVENT_HANDLE_READABLE | VIR_EVENT_HANDLE_READABLE |
VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_HANGUP, VIR_EVENT_HANDLE_HANGUP,
bhyveMonitorIO, bhyveMonitorIO,
vm, mon,
bhyveMonitorRelease); virObjectFreeCallback);
if (mon->watch < 0) { if (mon->watch < 0) {
VIR_DEBUG("failed to add event handle for mon %p", mon);
virObjectUnref(mon);
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("unable to register monitor events")); _("unable to register monitor events"));
goto cleanup; goto cleanup;
@ -166,18 +185,35 @@ bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver)
return mon; return mon;
cleanup: cleanup:
bhyveMonitorRelease(mon); bhyveMonitorClose(mon);
return NULL; return NULL;
} }
bhyveMonitorPtr
bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver)
{
bhyveMonitorPtr mon;
virObjectRef(vm);
mon = bhyveMonitorOpenImpl(vm, driver);
virObjectUnref(vm);
return mon;
}
void void
bhyveMonitorClose(bhyveMonitorPtr mon) bhyveMonitorClose(bhyveMonitorPtr mon)
{ {
if (mon == NULL) if (mon == NULL)
return; return;
if (mon->watch > 0) VIR_DEBUG("cleaning up bhyveMonitor %p", mon);
virEventRemoveHandle(mon->watch);
else if (mon->watch < 0)
bhyveMonitorRelease(mon); return;
virEventRemoveHandle(mon->watch);
mon->watch = -1;
virObjectUnref(mon);
} }