mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
bhyve: add a basic driver
At this point it has a limited functionality and is highly experimental. Supported domain operations are: * define * start * destroy * dumpxml * dominfo It's only possible to have only one disk device and only one network, which should be of type bridge.
This commit is contained in:
parent
cffa51b81d
commit
0eb4a5f4f1
@ -1047,6 +1047,12 @@ if test "$with_parallels" = "yes"; then
|
|||||||
fi
|
fi
|
||||||
AM_CONDITIONAL([WITH_PARALLELS], [test "$with_parallels" = "yes"])
|
AM_CONDITIONAL([WITH_PARALLELS], [test "$with_parallels" = "yes"])
|
||||||
|
|
||||||
|
dnl
|
||||||
|
dnl Checks for bhyve driver
|
||||||
|
dnl
|
||||||
|
|
||||||
|
LIBVIRT_DRIVER_CHECK_BHYVE
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl check for shell that understands <> redirection without truncation,
|
dnl check for shell that understands <> redirection without truncation,
|
||||||
dnl needed by src/qemu/qemu_monitor_{text,json}.c.
|
dnl needed by src/qemu/qemu_monitor_{text,json}.c.
|
||||||
@ -2705,6 +2711,7 @@ AC_MSG_NOTICE([ PHYP: $with_phyp])
|
|||||||
AC_MSG_NOTICE([ ESX: $with_esx])
|
AC_MSG_NOTICE([ ESX: $with_esx])
|
||||||
AC_MSG_NOTICE([ Hyper-V: $with_hyperv])
|
AC_MSG_NOTICE([ Hyper-V: $with_hyperv])
|
||||||
AC_MSG_NOTICE([Parallels: $with_parallels])
|
AC_MSG_NOTICE([Parallels: $with_parallels])
|
||||||
|
LIBVIRT_DRIVER_RESULT_BHYVE
|
||||||
AC_MSG_NOTICE([ Test: $with_test])
|
AC_MSG_NOTICE([ Test: $with_test])
|
||||||
AC_MSG_NOTICE([ Remote: $with_remote])
|
AC_MSG_NOTICE([ Remote: $with_remote])
|
||||||
AC_MSG_NOTICE([ Network: $with_network])
|
AC_MSG_NOTICE([ Network: $with_network])
|
||||||
|
@ -77,6 +77,9 @@
|
|||||||
# ifdef WITH_VBOX
|
# ifdef WITH_VBOX
|
||||||
# include "vbox/vbox_driver.h"
|
# include "vbox/vbox_driver.h"
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef WITH_BHYVE
|
||||||
|
# include "bhyve/bhyve_driver.h"
|
||||||
|
# endif
|
||||||
# ifdef WITH_NETWORK
|
# ifdef WITH_NETWORK
|
||||||
# include "network/bridge_driver.h"
|
# include "network/bridge_driver.h"
|
||||||
# endif
|
# endif
|
||||||
@ -405,6 +408,9 @@ static void daemonInitialize(void)
|
|||||||
# ifdef WITH_VBOX
|
# ifdef WITH_VBOX
|
||||||
virDriverLoadModule("vbox");
|
virDriverLoadModule("vbox");
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef WITH_BHYVE
|
||||||
|
virDriverLoadModule("bhyve");
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
# ifdef WITH_NETWORK
|
# ifdef WITH_NETWORK
|
||||||
networkRegister();
|
networkRegister();
|
||||||
@ -442,6 +448,9 @@ static void daemonInitialize(void)
|
|||||||
# ifdef WITH_VBOX
|
# ifdef WITH_VBOX
|
||||||
vboxRegister();
|
vboxRegister();
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef WITH_BHYVE
|
||||||
|
bhyveRegister();
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +120,7 @@ typedef enum {
|
|||||||
|
|
||||||
VIR_FROM_ACCESS = 55, /* Error from access control manager */
|
VIR_FROM_ACCESS = 55, /* Error from access control manager */
|
||||||
VIR_FROM_SYSTEMD = 56, /* Error from systemd code */
|
VIR_FROM_SYSTEMD = 56, /* Error from systemd code */
|
||||||
|
VIR_FROM_BHYVE = 57, /* Error from bhyve driver */
|
||||||
|
|
||||||
# ifdef VIR_ENUM_SENTINELS
|
# ifdef VIR_ENUM_SENTINELS
|
||||||
VIR_ERR_DOMAIN_LAST
|
VIR_ERR_DOMAIN_LAST
|
||||||
|
57
m4/virt-driver-bhyve.m4
Normal file
57
m4/virt-driver-bhyve.m4
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
dnl The bhyve driver
|
||||||
|
dnl
|
||||||
|
dnl Copyright (C) 2014 Roman Bogorodskiy
|
||||||
|
dnl
|
||||||
|
dnl This library is free software; you can redistribute it and/or
|
||||||
|
dnl modify it under the terms of the GNU Lesser General Public
|
||||||
|
dnl License as published by the Free Software Foundation; either
|
||||||
|
dnl version 2.1 of the License, or (at your option) any later version.
|
||||||
|
dnl
|
||||||
|
dnl This library is distributed in the hope that it will be useful,
|
||||||
|
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
dnl Lesser General Public License for more details.
|
||||||
|
dnl
|
||||||
|
dnl You should have received a copy of the GNU Lesser General Public
|
||||||
|
dnl License along with this library. If not, see
|
||||||
|
dnl <http://www.gnu.org/licenses/>.
|
||||||
|
dnl
|
||||||
|
|
||||||
|
AC_DEFUN([LIBVIRT_DRIVER_CHECK_BHYVE],[
|
||||||
|
AC_ARG_WITH([bhyve],
|
||||||
|
[AS_HELP_STRING([--with-bhyve],
|
||||||
|
[add BHyVe support @<:@default=check@:>@])])
|
||||||
|
m4_divert_text([DEFAULTS], [with_bhyve=check])
|
||||||
|
|
||||||
|
if test "$with_bhyve" != "no"; then
|
||||||
|
AC_PATH_PROG([BHYVE], [bhyve], [], [$PATH:/usr/sbin])
|
||||||
|
AC_PATH_PROG([BHYVECTL], [bhyvectl], [], [$PATH:/usr/sbin])
|
||||||
|
AC_PATH_PROG([BHYVELOAD], [bhyveload], [], [$PATH:/usr/sbin/])
|
||||||
|
|
||||||
|
if test -z "$BHYVE" || test -z "$BHYVECTL" \
|
||||||
|
test -z "$BHYVELOAD" || test "$with_freebsd" = "no"; then
|
||||||
|
if test "$with_bhyve" = "check"; then
|
||||||
|
with_bhyve="no"
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR([The bhyve driver cannot be enabled])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
with_bhyve="yes"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$with_bhyve" = "yes"; then
|
||||||
|
AC_DEFINE_UNQUOTED([WITH_BHYVE], 1, [whether bhyve driver is enabled])
|
||||||
|
AC_DEFINE_UNQUOTED([BHYVE], ["$BHYVE"],
|
||||||
|
[Location of the bhyve tool])
|
||||||
|
AC_DEFINE_UNQUOTED([BHYVECTL], ["$BHYVECTL"],
|
||||||
|
[Location of the bhyvectl tool])
|
||||||
|
AC_DEFINE_UNQUOTED([BHYVELOAD], ["$BHYVELOAD"],
|
||||||
|
[Location of the bhyveload tool])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL([WITH_BHYVE], [test "$with_bhyve" = "yes"])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([LIBVIRT_DRIVER_RESULT_BHYVE],[
|
||||||
|
AC_MSG_NOTICE([ Bhyve: $with_bhyve])
|
||||||
|
])
|
@ -8,6 +8,9 @@ gnulib/lib/gai_strerror.c
|
|||||||
gnulib/lib/regcomp.c
|
gnulib/lib/regcomp.c
|
||||||
src/access/viraccessdriverpolkit.c
|
src/access/viraccessdriverpolkit.c
|
||||||
src/access/viraccessmanager.c
|
src/access/viraccessmanager.c
|
||||||
|
src/bhyve/bhyve_command.c
|
||||||
|
src/bhyve/bhyve_driver.c
|
||||||
|
src/bhyve/bhyve_process.c
|
||||||
src/conf/capabilities.c
|
src/conf/capabilities.c
|
||||||
src/conf/cpu_conf.c
|
src/conf/cpu_conf.c
|
||||||
src/conf/device_conf.c
|
src/conf/device_conf.c
|
||||||
|
@ -512,6 +512,7 @@ DRIVER_SOURCE_FILES = \
|
|||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
STATEFUL_DRIVER_SOURCE_FILES = \
|
STATEFUL_DRIVER_SOURCE_FILES = \
|
||||||
|
$(BHYVE_DRIVER_SOURCES) \
|
||||||
$(INTERFACE_DRIVER_SOURCES) \
|
$(INTERFACE_DRIVER_SOURCES) \
|
||||||
$(LIBXL_DRIVER_SOURCES) \
|
$(LIBXL_DRIVER_SOURCES) \
|
||||||
$(LXC_DRIVER_SOURCES) \
|
$(LXC_DRIVER_SOURCES) \
|
||||||
@ -772,6 +773,16 @@ PARALLELS_DRIVER_SOURCES = \
|
|||||||
parallels/parallels_storage.c \
|
parallels/parallels_storage.c \
|
||||||
parallels/parallels_network.c
|
parallels/parallels_network.c
|
||||||
|
|
||||||
|
BHYVE_DRIVER_SOURCES = \
|
||||||
|
bhyve/bhyve_command.c \
|
||||||
|
bhyve/bhyve_command.h \
|
||||||
|
bhyve/bhyve_driver.h \
|
||||||
|
bhyve/bhyve_driver.c \
|
||||||
|
bhyve/bhyve_process.c \
|
||||||
|
bhyve/bhyve_process.h \
|
||||||
|
bhyve/bhyve_utils.h \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
NETWORK_DRIVER_SOURCES = \
|
NETWORK_DRIVER_SOURCES = \
|
||||||
network/bridge_driver.h network/bridge_driver.c \
|
network/bridge_driver.h network/bridge_driver.c \
|
||||||
network/bridge_driver_platform.h \
|
network/bridge_driver_platform.h \
|
||||||
@ -1308,6 +1319,26 @@ libvirt_driver_parallels_la_CFLAGS = \
|
|||||||
libvirt_driver_parallels_la_SOURCES = $(PARALLELS_DRIVER_SOURCES)
|
libvirt_driver_parallels_la_SOURCES = $(PARALLELS_DRIVER_SOURCES)
|
||||||
endif WITH_PARALLELS
|
endif WITH_PARALLELS
|
||||||
|
|
||||||
|
if WITH_BHYVE
|
||||||
|
noinst_LTLIBRARIES += libvirt_driver_bhyve_impl.la
|
||||||
|
libvirt_driver_bhyve_la_SOURCES =
|
||||||
|
libvirt_driver_bhyve_la_LIBADD = libvirt_driver_bhyve_impl.la
|
||||||
|
if WITH_DRIVER_MODULES
|
||||||
|
mod_LTLIBRARIES += libvirt_driver_bhyve.la
|
||||||
|
libvirt_driver_bhyve_la_LIBADD += ../gnulib/lib/libgnu.la
|
||||||
|
libvirt_driver_bhyve_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
|
||||||
|
else ! WITH_DRIVER_MODULES
|
||||||
|
noinst_LTLIBRARIES += libvirt_driver_bhyve.la
|
||||||
|
endif ! WITH_DRIVER_MODULES
|
||||||
|
|
||||||
|
libvirt_driver_bhyve_impl_la_CFLAGS = \
|
||||||
|
-I$(top_srcdir)/src/access \
|
||||||
|
-I$(top_srcdir)/src/conf \
|
||||||
|
$(AM_CFLAGS)
|
||||||
|
libvirt_driver_bhyve_impl_la_LDFLAGS = $(AM_LDFLAGS)
|
||||||
|
libvirt_driver_bhyve_impl_la_SOURCES = $(BHYVE_DRIVER_SOURCES)
|
||||||
|
endif WITH_BHYVE
|
||||||
|
|
||||||
if WITH_NETWORK
|
if WITH_NETWORK
|
||||||
noinst_LTLIBRARIES += libvirt_driver_network_impl.la
|
noinst_LTLIBRARIES += libvirt_driver_network_impl.la
|
||||||
libvirt_driver_network_la_SOURCES =
|
libvirt_driver_network_la_SOURCES =
|
||||||
@ -1642,6 +1673,7 @@ EXTRA_DIST += \
|
|||||||
$(HYPERV_DRIVER_SOURCES) \
|
$(HYPERV_DRIVER_SOURCES) \
|
||||||
$(HYPERV_DRIVER_EXTRA_DIST) \
|
$(HYPERV_DRIVER_EXTRA_DIST) \
|
||||||
$(PARALLELS_DRIVER_SOURCES) \
|
$(PARALLELS_DRIVER_SOURCES) \
|
||||||
|
$(BHYVE_DRIVER_SOURCES) \
|
||||||
$(NETWORK_DRIVER_SOURCES) \
|
$(NETWORK_DRIVER_SOURCES) \
|
||||||
$(INTERFACE_DRIVER_SOURCES) \
|
$(INTERFACE_DRIVER_SOURCES) \
|
||||||
$(STORAGE_DRIVER_SOURCES) \
|
$(STORAGE_DRIVER_SOURCES) \
|
||||||
|
331
src/bhyve/bhyve_command.c
Normal file
331
src/bhyve/bhyve_command.c
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
/*
|
||||||
|
* bhyve_process.c: bhyve command generation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Roman Bogorodskiy
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_tap.h>
|
||||||
|
|
||||||
|
#include "bhyve_command.h"
|
||||||
|
#include "viralloc.h"
|
||||||
|
#include "virfile.h"
|
||||||
|
#include "virstring.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
#include "virnetdev.h"
|
||||||
|
#include "virnetdevbridge.h"
|
||||||
|
#include "virnetdevtap.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_BHYVE
|
||||||
|
|
||||||
|
static char*
|
||||||
|
virBhyveTapGetRealDeviceName(char *name)
|
||||||
|
{
|
||||||
|
/* This is an ugly hack, because if we rename
|
||||||
|
* tap device to vnet%d, its device name will be
|
||||||
|
* still /dev/tap%d, and bhyve tries to open /dev/tap%d,
|
||||||
|
* so we have to find the real name
|
||||||
|
*/
|
||||||
|
char *ret = NULL;
|
||||||
|
struct dirent *dp;
|
||||||
|
char *devpath = NULL;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
DIR *dirp = opendir("/dev");
|
||||||
|
if (dirp == NULL) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to opendir path '%s'"),
|
||||||
|
"/dev");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((dp = readdir(dirp)) != NULL) {
|
||||||
|
if (STRPREFIX(dp->d_name, "tap")) {
|
||||||
|
struct ifreq ifr;
|
||||||
|
if (virAsprintf(&devpath, "/dev/%s", dp->d_name) < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if ((fd = open(devpath, O_RDWR)) < 0) {
|
||||||
|
virReportSystemError(errno, _("Unable to open '%s'"), devpath);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, TAPGIFNAME, (void *)&ifr) < 0) {
|
||||||
|
virReportSystemError(errno, "%s",
|
||||||
|
_("Unable to query tap interface name"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STREQ(name, ifr.ifr_name)) {
|
||||||
|
/* we can ignore the return value
|
||||||
|
* because we still have nothing
|
||||||
|
* to do but return;
|
||||||
|
*/
|
||||||
|
ignore_value(VIR_STRDUP(ret, dp->d_name));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_FREE(devpath);
|
||||||
|
VIR_FORCE_CLOSE(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno != 0)
|
||||||
|
virReportSystemError(errno, "%s",
|
||||||
|
_("Unable to iterate over TAP devices"));
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(devpath);
|
||||||
|
VIR_FORCE_CLOSE(fd);
|
||||||
|
closedir(dirp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveBuildNetArgStr(const virDomainDef *def, virCommandPtr cmd)
|
||||||
|
{
|
||||||
|
virDomainNetDefPtr net = NULL;
|
||||||
|
char *brname = NULL;
|
||||||
|
char *realifname = NULL;
|
||||||
|
int *tapfd = NULL;
|
||||||
|
|
||||||
|
if (def->nnets != 1) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("domain should have one and only one net defined"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
net = def->nets[0];
|
||||||
|
|
||||||
|
if (net) {
|
||||||
|
int actualType = virDomainNetGetActualType(net);
|
||||||
|
|
||||||
|
if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
||||||
|
if (VIR_STRDUP(brname, virDomainNetGetActualBridgeName(net)) < 0)
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("Network type %d is not supported"),
|
||||||
|
virDomainNetGetActualType(net));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!net->ifname ||
|
||||||
|
STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) ||
|
||||||
|
strchr(net->ifname, '%')) {
|
||||||
|
VIR_FREE(net->ifname);
|
||||||
|
if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_PREFIX "%d") < 0) {
|
||||||
|
VIR_FREE(brname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac,
|
||||||
|
def->uuid, tapfd, 1,
|
||||||
|
virDomainNetGetActualVirtPortProfile(net),
|
||||||
|
virDomainNetGetActualVlan(net),
|
||||||
|
VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) {
|
||||||
|
VIR_FREE(net->ifname);
|
||||||
|
VIR_FREE(brname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
realifname = virBhyveTapGetRealDeviceName(net->ifname);
|
||||||
|
|
||||||
|
if (realifname == NULL) {
|
||||||
|
VIR_FREE(net->ifname);
|
||||||
|
VIR_FREE(brname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_DEBUG("%s -> %s", net->ifname, realifname);
|
||||||
|
/* hack on top of other hack: we need to set
|
||||||
|
* interface to 'UP' again after re-opening to find its
|
||||||
|
* name
|
||||||
|
*/
|
||||||
|
if (virNetDevSetOnline(net->ifname, true) != 0) {
|
||||||
|
VIR_FREE(net->ifname);
|
||||||
|
VIR_FREE(brname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL);
|
||||||
|
virCommandAddArg(cmd, "-s");
|
||||||
|
virCommandAddArgFormat(cmd, "1:0,virtio-net,%s", realifname);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveBuildDiskArgStr(const virDomainDef *def, virCommandPtr cmd)
|
||||||
|
{
|
||||||
|
virDomainDiskDefPtr disk;
|
||||||
|
|
||||||
|
if (def->ndisks != 1) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("domain should have one and only one disk defined"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
disk = def->disks[0];
|
||||||
|
|
||||||
|
if (disk->bus != VIR_DOMAIN_DISK_BUS_SATA) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("unsupported disk bus type"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("unsupported disk device"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disk->type != VIR_DOMAIN_DISK_TYPE_FILE) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("unsupported disk type"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virCommandAddArg(cmd, "-s");
|
||||||
|
virCommandAddArgFormat(cmd, "2:0,ahci-hd,%s", disk->src);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virCommandPtr
|
||||||
|
virBhyveProcessBuildBhyveCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED,
|
||||||
|
virDomainObjPtr vm)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* /usr/sbin/bhyve -c 2 -m 256 -AI -H -P \
|
||||||
|
* -s 0:0,hostbridge \
|
||||||
|
* -s 1:0,virtio-net,tap0 \
|
||||||
|
* -s 2:0,ahci-hd,${IMG} \
|
||||||
|
* -S 31,uart,stdio \
|
||||||
|
* vm0
|
||||||
|
*/
|
||||||
|
virCommandPtr cmd = virCommandNew(BHYVE);
|
||||||
|
|
||||||
|
/* CPUs */
|
||||||
|
virCommandAddArg(cmd, "-c");
|
||||||
|
virCommandAddArgFormat(cmd, "%d", vm->def->vcpus);
|
||||||
|
|
||||||
|
/* Memory */
|
||||||
|
virCommandAddArg(cmd, "-m");
|
||||||
|
virCommandAddArgFormat(cmd, "%llu",
|
||||||
|
VIR_DIV_UP(vm->def->mem.max_balloon, 1024));
|
||||||
|
|
||||||
|
/* Options */
|
||||||
|
if (vm->def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON)
|
||||||
|
virCommandAddArg(cmd, "-A"); /* Create an ACPI table */
|
||||||
|
if (vm->def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON)
|
||||||
|
virCommandAddArg(cmd, "-I"); /* Present ioapic to the guest */
|
||||||
|
|
||||||
|
/* Clarification about -H and -P flags from Peter Grehan:
|
||||||
|
* -H and -P flags force the guest to exit when it executes IA32 HLT and PAUSE
|
||||||
|
* instructions respectively.
|
||||||
|
*
|
||||||
|
* For the HLT exit, bhyve uses that to infer that the guest is idling and can
|
||||||
|
* be put to sleep until an external event arrives. If this option is not used,
|
||||||
|
* the guest will always use 100% of CPU on the host.
|
||||||
|
*
|
||||||
|
* The PAUSE exit is most useful when there are large numbers of guest VMs running,
|
||||||
|
* since it forces the guest to exit when it spins on a lock acquisition.
|
||||||
|
*/
|
||||||
|
virCommandAddArg(cmd, "-H"); /* vmexit from guest on hlt */
|
||||||
|
virCommandAddArg(cmd, "-P"); /* vmexit from guest on pause */
|
||||||
|
|
||||||
|
/* Devices */
|
||||||
|
if (bhyveBuildNetArgStr(vm->def, cmd) < 0)
|
||||||
|
goto error;
|
||||||
|
if (bhyveBuildDiskArgStr(vm->def, cmd) < 0)
|
||||||
|
goto error;
|
||||||
|
virCommandAddArg(cmd, vm->def->name);
|
||||||
|
|
||||||
|
return cmd;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virCommandFree(cmd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virCommandPtr
|
||||||
|
virBhyveProcessBuildDestroyCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED,
|
||||||
|
virDomainObjPtr vm)
|
||||||
|
{
|
||||||
|
virCommandPtr cmd = virCommandNew(BHYVECTL);
|
||||||
|
|
||||||
|
virCommandAddArg(cmd, "--destroy");
|
||||||
|
virCommandAddArgPair(cmd, "--vm", vm->def->name);
|
||||||
|
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
virCommandPtr
|
||||||
|
virBhyveProcessBuildLoadCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED,
|
||||||
|
virDomainObjPtr vm)
|
||||||
|
{
|
||||||
|
virCommandPtr cmd;
|
||||||
|
virDomainDiskDefPtr disk;
|
||||||
|
|
||||||
|
if (vm->def->ndisks != 1) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("domain should have one and only one disk defined"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
disk = vm->def->disks[0];
|
||||||
|
|
||||||
|
if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("unsupported disk device"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disk->type != VIR_DOMAIN_DISK_TYPE_FILE) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("unsupported disk type"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = virCommandNew(BHYVELOAD);
|
||||||
|
|
||||||
|
/* Memory */
|
||||||
|
virCommandAddArg(cmd, "-m");
|
||||||
|
virCommandAddArgFormat(cmd, "%llu",
|
||||||
|
VIR_DIV_UP(vm->def->mem.max_balloon, 1024));
|
||||||
|
|
||||||
|
/* Image path */
|
||||||
|
virCommandAddArg(cmd, "-d");
|
||||||
|
virCommandAddArg(cmd, disk->src);
|
||||||
|
|
||||||
|
/* VM name */
|
||||||
|
virCommandAddArg(cmd, vm->def->name);
|
||||||
|
|
||||||
|
return cmd;
|
||||||
|
}
|
41
src/bhyve/bhyve_command.h
Normal file
41
src/bhyve/bhyve_command.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* bhyve_process.c: bhyve command generation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Roman Bogorodskiy
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BHYVE_COMMAND_H__
|
||||||
|
# define __BHYVE_COMMAND_H__
|
||||||
|
|
||||||
|
# include "bhyve_utils.h"
|
||||||
|
|
||||||
|
# include "domain_conf.h"
|
||||||
|
# include "vircommand.h"
|
||||||
|
|
||||||
|
virCommandPtr virBhyveProcessBuildBhyveCmd(bhyveConnPtr,
|
||||||
|
virDomainObjPtr vm);
|
||||||
|
|
||||||
|
virCommandPtr
|
||||||
|
virBhyveProcessBuildDestroyCmd(bhyveConnPtr driver,
|
||||||
|
virDomainObjPtr vm);
|
||||||
|
|
||||||
|
virCommandPtr
|
||||||
|
virBhyveProcessBuildLoadCmd(bhyveConnPtr driver,
|
||||||
|
virDomainObjPtr vm);
|
||||||
|
|
||||||
|
#endif /* __BHYVE_COMMAND_H__ */
|
612
src/bhyve/bhyve_driver.c
Normal file
612
src/bhyve/bhyve_driver.c
Normal file
@ -0,0 +1,612 @@
|
|||||||
|
/*
|
||||||
|
* bhyve_driver.c: core driver methods for managing bhyve guests
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Roman Bogorodskiy
|
||||||
|
*
|
||||||
|
* 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: Roman Bogorodskiy
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
|
#include "virerror.h"
|
||||||
|
#include "datatypes.h"
|
||||||
|
#include "virbuffer.h"
|
||||||
|
#include "viruuid.h"
|
||||||
|
#include "capabilities.h"
|
||||||
|
#include "configmake.h"
|
||||||
|
#include "viralloc.h"
|
||||||
|
#include "network_conf.h"
|
||||||
|
#include "interface_conf.h"
|
||||||
|
#include "domain_audit.h"
|
||||||
|
#include "domain_conf.h"
|
||||||
|
#include "snapshot_conf.h"
|
||||||
|
#include "fdstream.h"
|
||||||
|
#include "storage_conf.h"
|
||||||
|
#include "node_device_conf.h"
|
||||||
|
#include "virxml.h"
|
||||||
|
#include "virthread.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
#include "virfile.h"
|
||||||
|
#include "virtypedparam.h"
|
||||||
|
#include "virrandom.h"
|
||||||
|
#include "virstring.h"
|
||||||
|
#include "cpu/cpu.h"
|
||||||
|
#include "viraccessapicheck.h"
|
||||||
|
|
||||||
|
#include "bhyve_driver.h"
|
||||||
|
#include "bhyve_process.h"
|
||||||
|
#include "bhyve_utils.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_BHYVE
|
||||||
|
|
||||||
|
bhyveConnPtr bhyve_driver = NULL;
|
||||||
|
|
||||||
|
void
|
||||||
|
bhyveDriverLock(bhyveConnPtr driver)
|
||||||
|
{
|
||||||
|
virMutexLock(&driver->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bhyveDriverUnlock(bhyveConnPtr driver)
|
||||||
|
{
|
||||||
|
virMutexUnlock(&driver->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static virCapsPtr
|
||||||
|
bhyveBuildCapabilities(void)
|
||||||
|
{
|
||||||
|
virCapsPtr caps;
|
||||||
|
virCapsGuestPtr guest;
|
||||||
|
|
||||||
|
if ((caps = virCapabilitiesNew(virArchFromHost(),
|
||||||
|
0, 0)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((guest = virCapabilitiesAddGuest(caps, "hvm",
|
||||||
|
VIR_ARCH_X86_64,
|
||||||
|
"bhyve",
|
||||||
|
NULL, 0, NULL)) == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (virCapabilitiesAddGuestDomain(guest,
|
||||||
|
"bhyve", NULL, NULL, 0, NULL) == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virObjectUnref(caps);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
bhyveConnectGetCapabilities(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
char *xml;
|
||||||
|
|
||||||
|
if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL)
|
||||||
|
virReportOOMError();
|
||||||
|
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
static virDomainObjPtr
|
||||||
|
bhyveDomObjFromDomain(virDomainPtr domain)
|
||||||
|
{
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
bhyveConnPtr privconn = domain->conn->privateData;
|
||||||
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
|
||||||
|
vm = virDomainObjListFindByUUID(privconn->domains, domain->uuid);
|
||||||
|
if (!vm) {
|
||||||
|
virUUIDFormat(domain->uuid, uuidstr);
|
||||||
|
virReportError(VIR_ERR_NO_DOMAIN,
|
||||||
|
_("no domain with matching uuid '%s' (%s)"),
|
||||||
|
uuidstr, domain->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static virDrvOpenStatus
|
||||||
|
bhyveConnectOpen(virConnectPtr conn,
|
||||||
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
|
||||||
|
|
||||||
|
if (conn->uri == NULL) {
|
||||||
|
if (bhyve_driver == NULL)
|
||||||
|
return VIR_DRV_OPEN_DECLINED;
|
||||||
|
|
||||||
|
if (!(conn->uri = virURIParse("bhyve:///system")))
|
||||||
|
return VIR_DRV_OPEN_ERROR;
|
||||||
|
} else {
|
||||||
|
if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "bhyve"))
|
||||||
|
return VIR_DRV_OPEN_DECLINED;
|
||||||
|
|
||||||
|
if (conn->uri->server)
|
||||||
|
return VIR_DRV_OPEN_DECLINED;
|
||||||
|
|
||||||
|
if (!STREQ_NULLABLE(conn->uri->path, "/system")) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Unexpected bhyve URI path '%s', try bhyve:///system"),
|
||||||
|
conn->uri->path);
|
||||||
|
return VIR_DRV_OPEN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bhyve_driver == NULL) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("bhyve state driver is not active"));
|
||||||
|
return VIR_DRV_OPEN_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virConnectOpenEnsureACL(conn) < 0)
|
||||||
|
return VIR_DRV_OPEN_ERROR;
|
||||||
|
|
||||||
|
conn->privateData = bhyve_driver;
|
||||||
|
|
||||||
|
return VIR_DRV_OPEN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveConnectClose(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
conn->privateData = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
bhyveConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
if (virConnectGetHostnameEnsureACL(conn) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return virGetHostname();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *version)
|
||||||
|
{
|
||||||
|
struct utsname ver;
|
||||||
|
|
||||||
|
if (virConnectGetVersionEnsureACL(conn) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uname(&ver);
|
||||||
|
|
||||||
|
if (virParseVersionString(ver.release, version, true) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Unknown release: %s"), ver.release);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
||||||
|
{
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!(vm = bhyveDomObjFromDomain(domain)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainGetInfoEnsureACL(domain->conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
info->state = virDomainObjGetState(vm, NULL);
|
||||||
|
info->maxMem = vm->def->mem.max_balloon;
|
||||||
|
info->nrVirtCpu = vm->def->vcpus;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnlock(vm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveDomainGetState(virDomainPtr domain,
|
||||||
|
int *state,
|
||||||
|
int *reason,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
virCheckFlags(0, -1);
|
||||||
|
|
||||||
|
if (!(vm = bhyveDomObjFromDomain(domain)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainGetStateEnsureACL(domain->conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
*state = virDomainObjGetState(vm, reason);
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnlock(vm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
bhyveDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
||||||
|
{
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
char *ret = NULL;
|
||||||
|
|
||||||
|
if (!(vm = bhyveDomObjFromDomain(domain)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainGetXMLDescEnsureACL(domain->conn, vm->def, flags) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = virDomainDefFormat(vm->def, flags);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnlock(vm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static virDomainPtr
|
||||||
|
bhyveDomainDefineXML(virConnectPtr conn, const char *xml)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
virDomainPtr dom = NULL;
|
||||||
|
virDomainDefPtr def = NULL;
|
||||||
|
virDomainDefPtr oldDef = NULL;
|
||||||
|
virDomainObjPtr vm = NULL;
|
||||||
|
|
||||||
|
if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
|
||||||
|
1 << VIR_DOMAIN_VIRT_BHYVE,
|
||||||
|
VIR_DOMAIN_XML_INACTIVE)) == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainDefineXMLEnsureACL(conn, def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(vm = virDomainObjListAdd(privconn->domains, def,
|
||||||
|
privconn->xmlopt,
|
||||||
|
0, &oldDef)))
|
||||||
|
goto cleanup;
|
||||||
|
def = NULL;
|
||||||
|
|
||||||
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||||
|
if (dom)
|
||||||
|
dom->id = vm->def->id;
|
||||||
|
|
||||||
|
if (virDomainSaveConfig(BHYVE_CONFIG_DIR, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virDomainDefFree(def);
|
||||||
|
virObjectUnlock(vm);
|
||||||
|
|
||||||
|
return dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveConnectListDomains(virConnectPtr conn, int *ids, int maxids)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (virConnectListDomainsEnsureACL(conn) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
n = virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
|
||||||
|
virConnectListDomainsCheckACL, conn);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveConnectNumOfDomains(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
if (virConnectNumOfDomainsEnsureACL(conn) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
count = virDomainObjListNumOfDomains(privconn->domains, true,
|
||||||
|
virConnectNumOfDomainsCheckACL, conn);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveConnectListDefinedDomains(virConnectPtr conn, char **const names,
|
||||||
|
int maxnames)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memset(names, 0, sizeof(*names) * maxnames);
|
||||||
|
n = virDomainObjListGetInactiveNames(privconn->domains, names,
|
||||||
|
maxnames, virConnectListDefinedDomainsCheckACL, conn);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveConnectNumOfDefinedDomains(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
count = virDomainObjListNumOfDomains(privconn->domains, false,
|
||||||
|
virConnectNumOfDefinedDomainsCheckACL, conn);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveConnectListAllDomains(virConnectPtr conn,
|
||||||
|
virDomainPtr **domains,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
|
||||||
|
|
||||||
|
if (virConnectListAllDomainsEnsureACL(conn) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = virDomainObjListExport(privconn->domains, conn, domains,
|
||||||
|
virConnectListAllDomainsCheckACL, flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static virDomainPtr
|
||||||
|
bhyveDomainLookupByUUID(virConnectPtr conn,
|
||||||
|
const unsigned char *uuid)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
virDomainPtr dom = NULL;
|
||||||
|
|
||||||
|
vm = virDomainObjListFindByUUID(privconn->domains, uuid);
|
||||||
|
|
||||||
|
if (!vm) {
|
||||||
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||||
|
virUUIDFormat(uuid, uuidstr);
|
||||||
|
virReportError(VIR_ERR_NO_DOMAIN,
|
||||||
|
_("No domain with matching uuid '%s'"), uuidstr);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||||
|
if (dom)
|
||||||
|
dom->id = vm->def->id;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnlock(vm);
|
||||||
|
return dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static virDomainPtr bhyveDomainLookupByName(virConnectPtr conn,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
virDomainPtr dom = NULL;
|
||||||
|
|
||||||
|
vm = virDomainObjListFindByName(privconn->domains, name);
|
||||||
|
|
||||||
|
if (!vm) {
|
||||||
|
virReportError(VIR_ERR_NO_DOMAIN,
|
||||||
|
_("no domain with matching name '%s'"), name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||||
|
if (dom)
|
||||||
|
dom->id = vm->def->id;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnlock(vm);
|
||||||
|
return dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveDomainCreate(virDomainPtr dom)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = dom->conn->privateData;
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!(vm = bhyveDomObjFromDomain(dom)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainCreateEnsureACL(dom->conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainObjIsActive(vm)) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||||
|
"%s", _("Domain is already running"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = virBhyveProcessStart(dom->conn, privconn, vm,
|
||||||
|
VIR_DOMAIN_RUNNING_BOOTED);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnlock(vm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveDomainDestroy(virDomainPtr dom)
|
||||||
|
{
|
||||||
|
bhyveConnPtr privconn = dom->conn->privateData;
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (!(vm = bhyveDomObjFromDomain(dom)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainDestroyEnsureACL(dom->conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = virBhyveProcessStop(privconn, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virObjectUnlock(vm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveStateCleanup(void)
|
||||||
|
{
|
||||||
|
VIR_DEBUG("bhyve state cleanup");
|
||||||
|
|
||||||
|
if (bhyve_driver == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
virObjectUnref(bhyve_driver->domains);
|
||||||
|
virObjectUnref(bhyve_driver->caps);
|
||||||
|
virObjectUnref(bhyve_driver->xmlopt);
|
||||||
|
|
||||||
|
virMutexDestroy(&bhyve_driver->lock);
|
||||||
|
VIR_FREE(bhyve_driver);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bhyveStateInitialize(bool priveleged ATTRIBUTE_UNUSED,
|
||||||
|
virStateInhibitCallback callback ATTRIBUTE_UNUSED,
|
||||||
|
void *opaque ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
if (!priveleged) {
|
||||||
|
VIR_INFO("Not running priveleged, disabling driver");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VIR_ALLOC(bhyve_driver) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virMutexInit(&bhyve_driver->lock) < 0) {
|
||||||
|
VIR_FREE(bhyve_driver);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(bhyve_driver->caps = bhyveBuildCapabilities()))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(bhyve_driver->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(bhyve_driver->domains = virDomainObjListNew()))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virFileMakePath(BHYVE_LOG_DIR) < 0) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to mkdir %s"),
|
||||||
|
BHYVE_LOG_DIR);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virFileMakePath(BHYVE_STATE_DIR) < 0) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to mkdir %s"),
|
||||||
|
BHYVE_LOG_DIR);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virDomainObjListLoadAllConfigs(bhyve_driver->domains,
|
||||||
|
BHYVE_CONFIG_DIR,
|
||||||
|
NULL, 0,
|
||||||
|
bhyve_driver->caps,
|
||||||
|
bhyve_driver->xmlopt,
|
||||||
|
1 << VIR_DOMAIN_VIRT_BHYVE,
|
||||||
|
NULL, NULL) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
bhyveStateCleanup();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virDriver bhyveDriver = {
|
||||||
|
.no = VIR_DRV_BHYVE,
|
||||||
|
.name = "bhyve",
|
||||||
|
.connectOpen = bhyveConnectOpen, /* 1.2.2 */
|
||||||
|
.connectClose = bhyveConnectClose, /* 1.2.2 */
|
||||||
|
.connectGetVersion = bhyveConnectGetVersion, /* 1.2.2 */
|
||||||
|
.connectGetHostname = bhyveConnectGetHostname, /* 1.2.2 */
|
||||||
|
.domainGetInfo = bhyveDomainGetInfo, /* 1.2.2 */
|
||||||
|
.domainGetState = bhyveDomainGetState, /* 1.2.2 */
|
||||||
|
.connectGetCapabilities = bhyveConnectGetCapabilities, /* 1.2.2 */
|
||||||
|
.connectListDomains = bhyveConnectListDomains, /* 1.2.2 */
|
||||||
|
.connectNumOfDomains = bhyveConnectNumOfDomains, /* 1.2.2 */
|
||||||
|
.connectListAllDomains = bhyveConnectListAllDomains, /* 1.2.2 */
|
||||||
|
.connectListDefinedDomains = bhyveConnectListDefinedDomains, /* 1.2.2 */
|
||||||
|
.connectNumOfDefinedDomains = bhyveConnectNumOfDefinedDomains, /* 1.2.2 */
|
||||||
|
.domainCreate = bhyveDomainCreate, /* 1.2.2 */
|
||||||
|
.domainDestroy = bhyveDomainDestroy, /* 1.2.2 */
|
||||||
|
.domainLookupByUUID = bhyveDomainLookupByUUID, /* 1.2.2 */
|
||||||
|
.domainLookupByName = bhyveDomainLookupByName, /* 1.2.2 */
|
||||||
|
.domainDefineXML = bhyveDomainDefineXML, /* 1.2.2 */
|
||||||
|
.domainGetXMLDesc = bhyveDomainGetXMLDesc, /* 1.2.2 */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static virStateDriver bhyveStateDriver = {
|
||||||
|
.name = "bhyve",
|
||||||
|
.stateInitialize = bhyveStateInitialize,
|
||||||
|
.stateCleanup = bhyveStateCleanup,
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
bhyveRegister(void)
|
||||||
|
{
|
||||||
|
virRegisterDriver(&bhyveDriver);
|
||||||
|
virRegisterStateDriver(&bhyveStateDriver);
|
||||||
|
return 0;
|
||||||
|
}
|
28
src/bhyve/bhyve_driver.h
Normal file
28
src/bhyve/bhyve_driver.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* bhyve_driver.h: core driver methods for managing bhyve guests
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Roman Bogorodskiy
|
||||||
|
*
|
||||||
|
* 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: Roman Bogorodskiy <bogorodskiy@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BHYVE_DRIVER_H__
|
||||||
|
# define __BHYVE_DRIVER_H__
|
||||||
|
|
||||||
|
int bhyveRegister(void);
|
||||||
|
|
||||||
|
#endif /* __BHYVE_DRIVER_H__ */
|
224
src/bhyve/bhyve_process.c
Normal file
224
src/bhyve/bhyve_process.c
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
* bhyve_process.c: bhyve process management
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Roman Bogorodskiy
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_tap.h>
|
||||||
|
|
||||||
|
#include "bhyve_process.h"
|
||||||
|
#include "bhyve_command.h"
|
||||||
|
#include "datatypes.h"
|
||||||
|
#include "virerror.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
#include "virfile.h"
|
||||||
|
#include "viralloc.h"
|
||||||
|
#include "vircommand.h"
|
||||||
|
#include "virstring.h"
|
||||||
|
#include "virpidfile.h"
|
||||||
|
#include "virprocess.h"
|
||||||
|
#include "virnetdev.h"
|
||||||
|
#include "virnetdevbridge.h"
|
||||||
|
#include "virnetdevtap.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_BHYVE
|
||||||
|
|
||||||
|
int
|
||||||
|
virBhyveProcessStart(virConnectPtr conn,
|
||||||
|
bhyveConnPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virDomainRunningReason reason)
|
||||||
|
{
|
||||||
|
char *logfile = NULL;
|
||||||
|
int logfd = -1;
|
||||||
|
off_t pos = -1;
|
||||||
|
char ebuf[1024];
|
||||||
|
virCommandPtr cmd = NULL;
|
||||||
|
virCommandPtr load_cmd = NULL;
|
||||||
|
bhyveConnPtr privconn = conn->privateData;
|
||||||
|
int ret = -1, status;
|
||||||
|
|
||||||
|
if (virAsprintf(&logfile, "%s/%s.log",
|
||||||
|
BHYVE_LOG_DIR, vm->def->name) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT,
|
||||||
|
S_IRUSR | S_IWUSR)) < 0) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to open '%s'"),
|
||||||
|
logfile);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_FREE(privconn->pidfile);
|
||||||
|
if (!(privconn->pidfile = virPidFileBuildPath(BHYVE_STATE_DIR,
|
||||||
|
vm->def->name))) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
"%s", _("Failed to build pidfile path"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlink(privconn->pidfile) < 0 &&
|
||||||
|
errno != ENOENT) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Cannot remove state PID file %s"),
|
||||||
|
privconn->pidfile);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call bhyve to start the VM */
|
||||||
|
if (!(cmd = virBhyveProcessBuildBhyveCmd(driver,
|
||||||
|
vm)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
virCommandSetOutputFD(cmd, &logfd);
|
||||||
|
virCommandSetErrorFD(cmd, &logfd);
|
||||||
|
virCommandWriteArgLog(cmd, logfd);
|
||||||
|
virCommandSetPidFile(cmd, privconn->pidfile);
|
||||||
|
virCommandDaemonize(cmd);
|
||||||
|
|
||||||
|
/* Now bhyve command is constructed, meaning the
|
||||||
|
* domain is ready to be started, so we can build
|
||||||
|
* and execute bhyveload command */
|
||||||
|
if (!(load_cmd = virBhyveProcessBuildLoadCmd(driver, vm)))
|
||||||
|
goto cleanup;
|
||||||
|
virCommandSetOutputFD(load_cmd, &logfd);
|
||||||
|
virCommandSetErrorFD(load_cmd, &logfd);
|
||||||
|
|
||||||
|
/* Log generated command line */
|
||||||
|
virCommandWriteArgLog(load_cmd, logfd);
|
||||||
|
if ((pos = lseek(logfd, 0, SEEK_END)) < 0)
|
||||||
|
VIR_WARN("Unable to seek to end of logfile: %s",
|
||||||
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
||||||
|
|
||||||
|
VIR_DEBUG("Loading domain '%s'", vm->def->name);
|
||||||
|
if (virCommandRun(load_cmd, &status) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (status != 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Guest failed to load: %d"), status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we can start the domain */
|
||||||
|
VIR_DEBUG("Starting domain '%s'", vm->def->name);
|
||||||
|
ret = virCommandRun(cmd, NULL);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
if (virPidFileReadPath(privconn->pidfile, &vm->pid) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Domain %s didn't show up"), vm->def->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->def->id = vm->pid;
|
||||||
|
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
|
||||||
|
} else {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (ret < 0) {
|
||||||
|
virCommandPtr destroy_cmd;
|
||||||
|
if ((destroy_cmd = virBhyveProcessBuildDestroyCmd(driver, vm)) != NULL) {
|
||||||
|
virCommandSetOutputFD(load_cmd, &logfd);
|
||||||
|
virCommandSetErrorFD(load_cmd, &logfd);
|
||||||
|
ignore_value(virCommandRun(destroy_cmd, NULL));
|
||||||
|
virCommandFree(destroy_cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virCommandFree(load_cmd);
|
||||||
|
virCommandFree(cmd);
|
||||||
|
VIR_FREE(logfile);
|
||||||
|
VIR_FORCE_CLOSE(logfd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
virBhyveProcessStop(bhyveConnPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virDomainShutoffReason reason ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
int ret = -1;
|
||||||
|
int status;
|
||||||
|
virCommandPtr cmd = NULL;
|
||||||
|
|
||||||
|
if (!virDomainObjIsActive(vm)) {
|
||||||
|
VIR_DEBUG("VM '%s' not active", vm->def->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm->pid <= 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Invalid PID %d for VM"),
|
||||||
|
(int)vm->pid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First, try to kill 'bhyve' process */
|
||||||
|
if (virProcessKillPainfully(vm->pid, true) != 0)
|
||||||
|
VIR_WARN("Failed to gracefully stop bhyve VM '%s' (pid: %d)",
|
||||||
|
vm->def->name,
|
||||||
|
(int)vm->pid);
|
||||||
|
|
||||||
|
for (i = 0; i < vm->def->nnets; i++) {
|
||||||
|
virDomainNetDefPtr net = vm->def->nets[i];
|
||||||
|
int actualType = virDomainNetGetActualType(net);
|
||||||
|
|
||||||
|
if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
||||||
|
ignore_value(virNetDevBridgeRemovePort(
|
||||||
|
virDomainNetGetActualBridgeName(net),
|
||||||
|
net->ifname));
|
||||||
|
ignore_value(virNetDevTapDelete(net->ifname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No matter if shutdown was successful or not, we
|
||||||
|
* need to unload the VM */
|
||||||
|
if (!(cmd = virBhyveProcessBuildDestroyCmd(driver, vm)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virCommandRun(cmd, &status) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (status != 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Guest failed to stop: %d"), status);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
|
||||||
|
vm->pid = -1;
|
||||||
|
vm->def->id = -1;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virCommandFree(cmd);
|
||||||
|
return ret;
|
||||||
|
}
|
36
src/bhyve/bhyve_process.h
Normal file
36
src/bhyve/bhyve_process.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* bhyve_process.h: bhyve process management
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Roman Bogorodskiy
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BHYVE_PROCESS_H__
|
||||||
|
# define __BHYVE_PROCESS_H__
|
||||||
|
|
||||||
|
# include "bhyve_utils.h"
|
||||||
|
|
||||||
|
int virBhyveProcessStart(virConnectPtr conn,
|
||||||
|
bhyveConnPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virDomainRunningReason reason);
|
||||||
|
|
||||||
|
int virBhyveProcessStop(bhyveConnPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virDomainShutoffReason reason);
|
||||||
|
|
||||||
|
#endif /* __BHYVE_PROCESS_H__ */
|
48
src/bhyve/bhyve_utils.h
Normal file
48
src/bhyve/bhyve_utils.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* bhyve_utils.h: bhyve utils
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Roman Bogorodskiy
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BHYVE_UTILS_H__
|
||||||
|
# define __BHYVE_UTILS_H__
|
||||||
|
|
||||||
|
# include "driver.h"
|
||||||
|
# include "domain_conf.h"
|
||||||
|
# include "configmake.h"
|
||||||
|
# include "virthread.h"
|
||||||
|
|
||||||
|
# define BHYVE_CONFIG_DIR SYSCONFDIR "/libvirt/bhyve"
|
||||||
|
# define BHYVE_STATE_DIR LOCALSTATEDIR "/run/libvirt/bhyve"
|
||||||
|
# define BHYVE_LOG_DIR LOCALSTATEDIR "/log/libvirt/bhyve"
|
||||||
|
|
||||||
|
struct _bhyveConn {
|
||||||
|
virMutex lock;
|
||||||
|
virDomainObjListPtr domains;
|
||||||
|
virCapsPtr caps;
|
||||||
|
virDomainXMLOptionPtr xmlopt;
|
||||||
|
char *pidfile;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _bhyveConn bhyveConn;
|
||||||
|
typedef struct _bhyveConn *bhyveConnPtr;
|
||||||
|
|
||||||
|
void bhyveDriverLock(bhyveConnPtr driver);
|
||||||
|
void bhyveDriverUnlock(bhyveConnPtr driver);
|
||||||
|
|
||||||
|
#endif /* __BHYVE_UTILS_H__ */
|
@ -123,7 +123,8 @@ VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST,
|
|||||||
"hyperv",
|
"hyperv",
|
||||||
"vbox",
|
"vbox",
|
||||||
"phyp",
|
"phyp",
|
||||||
"parallels")
|
"parallels",
|
||||||
|
"bhyve")
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST,
|
VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST,
|
||||||
"fd",
|
"fd",
|
||||||
|
@ -196,6 +196,7 @@ enum virDomainVirtType {
|
|||||||
VIR_DOMAIN_VIRT_VBOX,
|
VIR_DOMAIN_VIRT_VBOX,
|
||||||
VIR_DOMAIN_VIRT_PHYP,
|
VIR_DOMAIN_VIRT_PHYP,
|
||||||
VIR_DOMAIN_VIRT_PARALLELS,
|
VIR_DOMAIN_VIRT_PARALLELS,
|
||||||
|
VIR_DOMAIN_VIRT_BHYVE,
|
||||||
|
|
||||||
VIR_DOMAIN_VIRT_LAST
|
VIR_DOMAIN_VIRT_LAST
|
||||||
};
|
};
|
||||||
|
@ -47,6 +47,7 @@ typedef enum {
|
|||||||
VIR_DRV_LIBXL = 14,
|
VIR_DRV_LIBXL = 14,
|
||||||
VIR_DRV_HYPERV = 15,
|
VIR_DRV_HYPERV = 15,
|
||||||
VIR_DRV_PARALLELS = 16,
|
VIR_DRV_PARALLELS = 16,
|
||||||
|
VIR_DRV_BHYVE = 17,
|
||||||
} virDrvNo;
|
} virDrvNo;
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,6 +96,9 @@
|
|||||||
#ifdef WITH_PARALLELS
|
#ifdef WITH_PARALLELS
|
||||||
# include "parallels/parallels_driver.h"
|
# include "parallels/parallels_driver.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WITH_BHYVE
|
||||||
|
# include "bhyve/bhyve_driver.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_NONE
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
||||||
|
|
||||||
|
@ -124,6 +124,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
|
|||||||
|
|
||||||
"Access Manager", /* 55 */
|
"Access Manager", /* 55 */
|
||||||
"Systemd",
|
"Systemd",
|
||||||
|
"Bhyve",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user