
On 14.11.2014 17:03, Conrad Meyer wrote:
Reboot requires more sophistication and is left as a future work item -- but at least part of the plumbing is in place. --- Looking for feedback. I'm pretty unfamiliar with libvirt; maybe this isn't quite the right way to do this. Sorry. If you want me to rework it in some way, just let me know.
I tried to model this off of DrvQEMU, which I knew to support this behavior.
Reboot should probably be processed on a threadpool thread outside of the event loop, so I omitted it for now.
P.S., the 'read-non-seekable' check test seems to just hang forever on FreeBSD. I haven't dug into it, but POSIX FIFO behavior is pretty weird. --- src/Makefile.am | 2 + src/bhyve/bhyve_monitor.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++ src/bhyve/bhyve_monitor.h | 36 +++++++++ src/bhyve/bhyve_process.c | 14 +++- 4 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 src/bhyve/bhyve_monitor.c create mode 100644 src/bhyve/bhyve_monitor.h
diff --git a/src/Makefile.am b/src/Makefile.am index d8fe624..b6c1701 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -833,6 +833,8 @@ BHYVE_DRIVER_SOURCES = \ bhyve/bhyve_domain.h \ bhyve/bhyve_driver.h \ bhyve/bhyve_driver.c \ + bhyve/bhyve_monitor.c \ + bhyve/bhyve_monitor.h \ bhyve/bhyve_process.c \ bhyve/bhyve_process.h \ bhyve/bhyve_utils.h \ diff --git a/src/bhyve/bhyve_monitor.c b/src/bhyve/bhyve_monitor.c new file mode 100644 index 0000000..cd3cf6e --- /dev/null +++ b/src/bhyve/bhyve_monitor.c @@ -0,0 +1,184 @@ +/* + * bhyve_monitor.c: Tear-down or reboot bhyve domains on guest shutdown + * + * Copyright (C) 2014 Conrad Meyer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Conrad Meyer <cse.cem@gmail.com> + */ + +#include <config.h> + +#include <sys/types.h> +#include <sys/event.h> +#include <sys/time.h> +#include <sys/wait.h> + +#include "bhyve_monitor.h" +#include "bhyve_process.h" +#include "viralloc.h" +#include "virerror.h" +#include "virfile.h" +#include "virlog.h" + +#define VIR_FROM_THIS VIR_FROM_BHYVE + +VIR_LOG_INIT("bhyve.bhyve_monitor"); + +struct _bhyveMonitor { + int kq; + int watch; + virDomainObjPtr vm; + bhyveConnPtr driver; +}; + +static void +bhyveMonitorIO(int watch, int kq, int events ATTRIBUTE_UNUSED, void *opaque) +{ + const struct timespec zerowait = {}; + bhyveMonitorPtr mon = opaque; + struct kevent kev; + int rc, status; + + if (watch != mon->watch || kq != mon->kq) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("event from unexpected fd %d!=%d / watch %d!=%d"), + mon->kq, kq, mon->watch, watch); + return; + } + + rc = kevent(kq, NULL, 0, &kev, 1, &zerowait); + if (rc < 0) { + virReportSystemError(errno, "%s", _("Unable to query kqueue")); + return; + } + + if (rc == 0) + return; + + if ((kev.flags & EV_ERROR) != 0) { + virReportSystemError(kev.data, "%s", _("Unable to query kqueue")); + return; + } + + if (kev.filter == EVFILT_PROC && (kev.fflags & NOTE_EXIT) != 0) { + if ((pid_t)kev.ident != mon->vm->pid) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("event from unexpected proc %ju!=%ju"), + (uintmax_t)mon->vm->pid, (uintmax_t)kev.ident); + return; + } + + status = kev.data; + if (WIFSIGNALED(status) && WCOREDUMP(status)) { + VIR_ERROR("Guest %s got signal %d and crashed", mon->vm->def->name, + WTERMSIG(status));
This needs to be virReportError(). And since you're doing gettext translations _() you need to change po/POTFILES.in too.
+ virBhyveProcessStop(mon->driver, mon->vm, + VIR_DOMAIN_SHUTOFF_CRASHED); + } else if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == 0) { + /* 0 - reboot */ + /* TODO: Implementing reboot is a little more complicated. */ + VIR_INFO("Guest %s rebooted; destroying domain.", + mon->vm->def->name); + virBhyveProcessStop(mon->driver, mon->vm, + VIR_DOMAIN_SHUTOFF_SHUTDOWN); + } else if (WEXITSTATUS(status) < 3) { + /* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */ + VIR_INFO("Guest %s shut itself down; destroying domain.", + mon->vm->def->name); + virBhyveProcessStop(mon->driver, mon->vm, + VIR_DOMAIN_SHUTOFF_SHUTDOWN); + } else { + VIR_INFO("Guest %s had an error and exited with status %d; destroying domain.", + mon->vm->def->name, WEXITSTATUS(status)); + virBhyveProcessStop(mon->driver, mon->vm, + VIR_DOMAIN_SHUTOFF_UNKNOWN); + } + } + } +}
ACKed with this squashed in: diff --git a/po/POTFILES.in b/po/POTFILES.in index f17b35f..d07b75a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -11,6 +11,7 @@ src/access/viraccessmanager.c src/bhyve/bhyve_command.c src/bhyve/bhyve_device.c src/bhyve/bhyve_driver.c +src/bhyve/bhyve_monitor.c src/bhyve/bhyve_process.c src/conf/capabilities.c src/conf/cpu_conf.c diff --git a/src/bhyve/bhyve_monitor.c b/src/bhyve/bhyve_monitor.c index cd3cf6e..7f19c6e 100644 --- a/src/bhyve/bhyve_monitor.c +++ b/src/bhyve/bhyve_monitor.c @@ -84,8 +84,10 @@ bhyveMonitorIO(int watch, int kq, int events ATTRIBUTE_UNUSED, void *opaque) status = kev.data; if (WIFSIGNALED(status) && WCOREDUMP(status)) { - VIR_ERROR("Guest %s got signal %d and crashed", mon->vm->def->name, - WTERMSIG(status)); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Guest %s got signal %d and crashed"), + mon->vm->def->name, + WTERMSIG(status)); virBhyveProcessStop(mon->driver, mon->vm, VIR_DOMAIN_SHUTOFF_CRASHED); } else if (WIFEXITED(status)) { Fixed and pushed. Michal