- Add support for the 'bhyve:///session' connection URL
for running in unprivileged mode.
- Use bhyve monitor mode ('-M') and a per-user runtime directory.
- Require monitor mode and VM PID query support for session mode.
- Use user configuration directories instead of system-wide directories.
Signed-off-by: Roman Bogorodskiy <[email protected]>
---
src/bhyve/bhyve_command.c | 7 ++++++
src/bhyve/bhyve_conf.c | 42 ++++++++++++++++++++++++++---------
src/bhyve/bhyve_conf.h | 2 +-
src/bhyve/bhyve_domain.c | 9 +++++++-
src/bhyve/bhyve_driver.c | 46 ++++++++++++++++++++++++++-------------
src/bhyve/bhyve_process.c | 2 +-
src/bhyve/bhyve_utils.h | 2 ++
tests/bhyvexml2argvtest.c | 4 +++-
tests/bhyvexml2xmltest.c | 2 +-
9 files changed, 86 insertions(+), 30 deletions(-)
diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c
index f0a87cffea..41c3767c3e 100644
--- a/src/bhyve/bhyve_command.c
+++ b/src/bhyve/bhyve_command.c
@@ -1100,6 +1100,13 @@ virBhyveProcessBuildBhyveCmd(struct _bhyveConn *driver,
virDomainDef *def,
unsigned nvcpus = virDomainDefGetVcpus(def);
size_t ncells = virDomainNumaGetNodeCount(def->numa);
+ /* Monitor mode */
+ if (!driver->privileged) {
+ virCommandAddArg(cmd, "-M");
+ virCommandAddArg(cmd, "-o");
+ virCommandAddArgFormat(cmd, "rundir=%s", driver->config->stateDir);
+ }
+
/* CPUs */
virCommandAddArg(cmd, "-c");
if (def->cpu && def->cpu->sockets) {
diff --git a/src/bhyve/bhyve_conf.c b/src/bhyve/bhyve_conf.c
index e0439af6fa..182dd24a60 100644
--- a/src/bhyve/bhyve_conf.c
+++ b/src/bhyve/bhyve_conf.c
@@ -25,6 +25,7 @@
#include "viralloc.h"
#include "virlog.h"
#include "virstring.h"
+#include "virutil.h"
#include "bhyve_conf.h"
#include "bhyve_domain.h"
#include "configmake.h"
@@ -47,7 +48,7 @@ static int virBhyveConfigOnceInit(void)
VIR_ONCE_GLOBAL_INIT(virBhyveConfig);
struct _virBhyveDriverConfig *
-virBhyveDriverConfigNew(void)
+virBhyveDriverConfigNew(bool privileged)
{
struct _virBhyveDriverConfig *cfg;
@@ -57,18 +58,39 @@ virBhyveDriverConfigNew(void)
if (!(cfg = virObjectNew(virBhyveDriverConfigClass)))
return NULL;
- cfg->configBaseDir = g_strdup(SYSCONFDIR "/libvirt");
+ if (privileged) {
+ cfg->configBaseDir = g_strdup(SYSCONFDIR "/libvirt");
- cfg->firmwareDir = g_strdup(DATADIR "/uefi-firmware");
- cfg->libDir = g_strdup_printf("%s/lib/libvirt/bhyve", LOCALSTATEDIR);
- cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
+ cfg->firmwareDir = g_strdup(DATADIR "/uefi-firmware");
+ cfg->libDir = g_strdup_printf("%s/lib/libvirt/bhyve", LOCALSTATEDIR);
+ cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
- cfg->ubootPath = g_strdup(DATADIR "/u-boot/u-boot-bhyve-arm64/u-boot.bin");
+ cfg->ubootPath = g_strdup(DATADIR
"/u-boot/u-boot-bhyve-arm64/u-boot.bin");
- cfg->configDir = g_strdup_printf("%s/bhyve", cfg->configBaseDir);
- cfg->autostartDir = g_strdup_printf("%s/bhyve/autostart",
cfg->configBaseDir);
- cfg->stateDir = g_strdup_printf("%s/libvirt/bhyve", RUNSTATEDIR);
- cfg->logDir = g_strdup_printf("%s/log/libvirt/bhyve", LOCALSTATEDIR);
+ cfg->configDir = g_strdup_printf("%s/bhyve", cfg->configBaseDir);
+ cfg->autostartDir = g_strdup_printf("%s/bhyve/autostart",
cfg->configBaseDir);
+ cfg->stateDir = g_strdup_printf("%s/libvirt/bhyve", RUNSTATEDIR);
+ cfg->logDir = g_strdup_printf("%s/log/libvirt/bhyve", LOCALSTATEDIR);
+ } else {
+ g_autofree char *rundir = NULL;
+ g_autofree char *cachedir = NULL;
+
+ cfg->configBaseDir = virGetUserConfigDirectory();
+
+ cachedir = virGetUserCacheDirectory();
+ rundir = virGetUserRuntimeDirectory();
+
+ cfg->firmwareDir = g_strdup(DATADIR "/uefi-firmware");
+ cfg->libDir = g_strdup_printf("%s/bhyve/lib", cfg->configBaseDir);
+ cfg->nvramDir = g_strdup_printf("%s/bhyve/nvram", cfg->configBaseDir);
+
+ cfg->ubootPath = g_strdup(DATADIR
"/u-boot/u-boot-bhyve-arm64/u-boot.bin");
+
+ cfg->configDir = g_strdup_printf("%s/bhyve", cfg->configBaseDir);
+ cfg->autostartDir = g_strdup_printf("%s/bhyve/autostart",
cfg->configBaseDir);
+ cfg->stateDir = g_strdup_printf("%s/bhyve/run", rundir);
+ cfg->logDir = g_strdup_printf("%s/bhyve/log", cachedir);
+ }
cfg->bhyveloadTimeout = 300;
cfg->bhyveloadTimeoutKill = 15;
diff --git a/src/bhyve/bhyve_conf.h b/src/bhyve/bhyve_conf.h
index d895f66bb7..70c6b1f6ed 100644
--- a/src/bhyve/bhyve_conf.h
+++ b/src/bhyve/bhyve_conf.h
@@ -23,7 +23,7 @@
#include "bhyve_utils.h"
-struct _virBhyveDriverConfig *virBhyveDriverConfigNew(void);
+struct _virBhyveDriverConfig *virBhyveDriverConfigNew(bool privileged);
struct _virBhyveDriverConfig *virBhyveDriverGetConfig(struct _bhyveConn
*driver);
int virBhyveLoadDriverConfig(struct _virBhyveDriverConfig *cfg,
const char *filename);
diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c
index 3588557979..2513573e98 100644
--- a/src/bhyve/bhyve_domain.c
+++ b/src/bhyve/bhyve_domain.c
@@ -555,9 +555,10 @@ bhyveValidateDomainLifecycleAction(const virDomainDef *def)
static int
bhyveDomainDefValidate(const virDomainDef *def,
- void *opaque G_GNUC_UNUSED,
+ void *opaque,
void *parseOpaque G_GNUC_UNUSED)
{
+ struct _bhyveConn *driver = opaque;
size_t i;
size_t ncells;
virStorageSource *src = NULL;
@@ -640,6 +641,12 @@ bhyveDomainDefValidate(const virDomainDef *def,
return -1;
}
+ if (!driver->privileged && !def->os.loader) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("only UEFI boot is supported in unprivileged mode"));
+ return -1;
+ }
+
if (bhyveValidateDomainLifecycleAction(def) < 0)
return -1;
diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index 7e8cc572e4..f48543e205 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -211,7 +211,8 @@ bhyveConnectURIProbe(char **uri)
if (bhyve_driver == NULL)
return 0;
- *uri = g_strdup("bhyve:///system");
+ *uri = g_strdup(bhyve_driver->privileged ?
+ "bhyve:///system" : "bhyve:///session");
return 1;
}
@@ -224,19 +225,17 @@ bhyveConnectOpen(virConnectPtr conn,
{
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
- if (STRNEQ(conn->uri->path, "/system")) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Unexpected bhyve URI path '%1$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 (!virConnectValidateURIPath(conn->uri->path,
+ "bhyve",
+ bhyve_driver->privileged))
+ return VIR_DRV_OPEN_ERROR;
+
if (virConnectOpenEnsureACL(conn) < 0)
return VIR_DRV_OPEN_ERROR;
@@ -1398,6 +1397,7 @@ bhyveStateInitialize(bool privileged,
void *opaque G_GNUC_UNUSED)
{
virDomainDriverAutoStartConfig autostartCfg;
+ g_autofree char *configFile = NULL;
virBhyveDriverConfig *cfg;
if (root != NULL) {
@@ -1406,13 +1406,9 @@ bhyveStateInitialize(bool privileged,
return -1;
}
- if (!privileged) {
- VIR_INFO("Not running privileged, disabling driver");
- return VIR_DRV_STATE_INIT_SKIPPED;
- }
-
bhyve_driver = g_new0(bhyveConn, 1);
+ bhyve_driver->privileged = privileged;
bhyve_driver->lockFD = -1;
if (virMutexInit(&bhyve_driver->lock) < 0) {
VIR_FREE(bhyve_driver);
@@ -1425,6 +1421,18 @@ bhyveStateInitialize(bool privileged,
if (virBhyveProbeCaps(&bhyve_driver->bhyvecaps) < 0)
goto cleanup;
+ if (!privileged && !(bhyveDriverGetBhyveCaps(bhyve_driver) &
BHYVE_CAP_MONITOR)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("bhyve does not support monitor mode, cannot run
unprivileged"));
+ goto cleanup;
+ }
+
+ if (!privileged && !(bhyveDriverGetBhyveCaps(bhyve_driver) &
BHYVE_CAP_GET_VMPID)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("bhyvectl does not support querying the VM PID,
cannot run unprivileged"));
+ goto cleanup;
+ }
+
if (virBhyveProbeGrubCaps(&bhyve_driver->grubcaps) < 0)
goto cleanup;
@@ -1443,10 +1451,11 @@ bhyveStateInitialize(bool privileged,
bhyve_driver->hostsysinfo = virSysinfoRead();
- if (!(bhyve_driver->config = cfg = virBhyveDriverConfigNew()))
+ if (!(bhyve_driver->config = cfg = virBhyveDriverConfigNew(privileged)))
goto cleanup;
- if (virBhyveLoadDriverConfig(bhyve_driver->config, SYSCONFDIR
"/libvirt/bhyve.conf") < 0)
+ configFile = g_build_filename(cfg->configBaseDir, "bhyve.conf", NULL);
+ if (virBhyveLoadDriverConfig(cfg, configFile) < 0)
goto cleanup;
if (g_mkdir_with_parents(cfg->logDir, 0777) < 0) {
@@ -1463,6 +1472,13 @@ bhyveStateInitialize(bool privileged,
goto cleanup;
}
+ if (g_mkdir_with_parents(cfg->nvramDir, 0777) < 0) {
+ virReportSystemError(errno,
+ _("Failed to mkdir %1$s"),
+ cfg->nvramDir);
+ goto cleanup;
+ }
+
if ((bhyve_driver->lockFD =
virPidFileAcquire(cfg->stateDir, "driver", getpid())) < 0)
goto cleanup;
diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c
index 4144f8230e..c42d9ec092 100644
--- a/src/bhyve/bhyve_process.c
+++ b/src/bhyve/bhyve_process.c
@@ -537,7 +537,7 @@ bhyvePrepareNVRAMFile(bhyveConn *driver G_GNUC_UNUSED,
if (virFileRewrite(loader->nvram->path,
S_IRUSR | S_IWUSR,
- 0, 0,
+ -1, -1,
bhyvePrepareNVRAMHelper,
&data) < 0) {
return -1;
diff --git a/src/bhyve/bhyve_utils.h b/src/bhyve/bhyve_utils.h
index 5d04b42195..8a6ca25b47 100644
--- a/src/bhyve/bhyve_utils.h
+++ b/src/bhyve/bhyve_utils.h
@@ -70,6 +70,8 @@ struct _bhyveConn {
unsigned bhyvecaps;
unsigned grubcaps;
+
+ bool privileged;
};
typedef struct _bhyveConn bhyveConn;
diff --git a/tests/bhyvexml2argvtest.c b/tests/bhyvexml2argvtest.c
index 95969a641b..06af9dec8a 100644
--- a/tests/bhyvexml2argvtest.c
+++ b/tests/bhyvexml2argvtest.c
@@ -162,7 +162,7 @@ mymain(void)
if (!(driver.remotePorts = virPortAllocatorRangeNew("display", 5900,
65535)))
return EXIT_FAILURE;
- if (!(driver.config = virBhyveDriverConfigNew()))
+ if (!(driver.config = virBhyveDriverConfigNew(true)))
return EXIT_FAILURE;
VIR_FREE(driver.config->firmwareDir);
@@ -174,6 +174,8 @@ mymain(void)
driver.config->bhyveloadTimeout = 0;
driver.config->bhyveloadTimeoutKill = 0;
+ driver.privileged = true;
+
# define DO_TEST_FULL(name, flags) \
do { \
static struct testInfo info = { \
diff --git a/tests/bhyvexml2xmltest.c b/tests/bhyvexml2xmltest.c
index 336278ce1c..92710b3f0f 100644
--- a/tests/bhyvexml2xmltest.c
+++ b/tests/bhyvexml2xmltest.c
@@ -67,7 +67,7 @@ mymain(void)
if ((driver.xmlopt = virBhyveDriverCreateXMLConf(&driver)) == NULL)
return EXIT_FAILURE;
- if (!(driver.config = virBhyveDriverConfigNew()))
+ if (!(driver.config = virBhyveDriverConfigNew(true)))
return EXIT_FAILURE;
VIR_FREE(driver.config->firmwareDir);
--
2.55.0