libvirt/src/qemu/qemu_conf.c

1574 lines
50 KiB
C
Raw Normal View History

2007-02-14 01:40:09 +00:00
/*
* qemu_conf.c: QEMU configuration management
2007-02-14 01:40:09 +00:00
*
* Copyright (C) 2006-2014 Red Hat, Inc.
2007-02-14 01:40:09 +00:00
* Copyright (C) 2006 Daniel P. Berrange
*
* 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/>.
2007-02-14 01:40:09 +00:00
*/
#include <config.h>
2007-02-14 01:40:09 +00:00
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "virerror.h"
#include "qemu_conf.h"
#include "qemu_capabilities.h"
#include "qemu_domain.h"
#include "qemu_firmware.h"
#include "qemu_namespace.h"
#include "qemu_security.h"
2012-12-13 18:01:25 +00:00
#include "viruuid.h"
2012-12-12 16:35:35 +00:00
#include "virconf.h"
2012-12-12 18:06:53 +00:00
#include "viralloc.h"
2012-12-13 18:13:21 +00:00
#include "virxml.h"
2012-12-12 17:59:27 +00:00
#include "virlog.h"
#include "cpu/cpu.h"
#include "domain_driver.h"
#include "virfile.h"
#include "virstring.h"
#include "virutil.h"
maint: use gnulib configmake rather than open-coding things * bootstrap.conf (gnulib_modules): Add configmake. * daemon/Makefile.am (libvirtd_CFLAGS): Drop defines provided by gnulib. * src/Makefile.am (INCLUDES): Likewise. * tests/Makefile.am (INCLUDES): Likewise. * tools/Makefile.am (virsh_CFLAGS): Likewise. * daemon/libvirtd.c (qemudInitPaths, usage, main): Update clients. * src/cpu/cpu_map.c (CPUMAPFILE): Likewise. * src/driver.c (DEFAULT_DRIVER_DIR): Likewise. * src/internal.h (_): Likewise. * src/libvirt.c (virInitialize): Likewise. * src/lxc/lxc_conf.h (LXC_CONFIG_DIR, LXC_STATE_DIR, LXC_LOG_DIR): Likewise. * src/lxc/lxc_conf.c (lxcCapsInit, lxcLoadDriverConfig): Likewise. * src/network/bridge_driver.c (NETWORK_PID_DIR) (NETWORK_STATE_DIR, DNSMASQ_STATE_DIR, networkStartup): Likewise. * src/nwfilter/nwfilter_driver.c (nwfilterDriverStartup): Likewise. * src/qemu/qemu_conf.c (qemudLoadDriverConfig): Likewise. * src/qemu/qemu_driver.c (qemudStartup): Likewise. * src/remote/remote_driver.h (LIBVIRTD_PRIV_UNIX_SOCKET) (LIBVIRTD_PRIV_UNIX_SOCKET_RO, LIBVIRTD_CONFIGURATION_FILE) (LIBVIRT_PKI_DIR): Likewise. * src/secret/secret_driver.c (secretDriverStartup): Likewise. * src/security/security_apparmor.c (VIRT_AA_HELPER): Likewise. * src/security/virt-aa-helper.c (main): Likewise. * src/storage/storage_backend_disk.c (PARTHELPER): Likewise. * src/storage/storage_driver.c (storageDriverStartup): Likewise. * src/uml/uml_driver.c (TEMPDIR, umlStartup): Likewise. * src/util/hooks.c (LIBVIRT_HOOK_DIR): Likewise. * tools/virsh.c (main): Likewise. * docs/hooks.html.in: Likewise.
2010-11-16 14:54:17 +00:00
#include "configmake.h"
#include "security/security_util.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
VIR_LOG_INIT("qemu.qemu_conf");
/* These are only defaults, they can be changed now in qemu.conf and
* explicitly specified port is checked against these two (makes
* sense to limit the values).
*
* This limitation is mentioned in qemu.conf, so bear in mind that the
* configuration file should reflect any changes made to these values.
*/
#define QEMU_REMOTE_PORT_MIN 5900
#define QEMU_REMOTE_PORT_MAX 65535
#define QEMU_WEBSOCKET_PORT_MIN 5700
#define QEMU_WEBSOCKET_PORT_MAX 65535
#define QEMU_MIGRATION_PORT_MIN 49152
#define QEMU_MIGRATION_PORT_MAX 49215
static virClass *virQEMUDriverConfigClass;
static void virQEMUDriverConfigDispose(void *obj);
static int virQEMUConfigOnceInit(void)
{
if (!VIR_CLASS_NEW(virQEMUDriverConfig, virClassForObject()))
return -1;
return 0;
}
VIR_ONCE_GLOBAL_INIT(virQEMUConfig);
#ifndef DEFAULT_LOADER_NVRAM
# define DEFAULT_LOADER_NVRAM \
"/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd:" \
"/usr/share/OVMF/OVMF_CODE.secboot.fd:/usr/share/OVMF/OVMF_VARS.fd:" \
"/usr/share/AAVMF/AAVMF_CODE.fd:/usr/share/AAVMF/AAVMF_VARS.fd:" \
"/usr/share/AAVMF/AAVMF32_CODE.fd:/usr/share/AAVMF/AAVMF32_VARS.fd"
#endif
virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
qemu: add support for running QEMU driver in embedded mode This enables support for running QEMU embedded to the calling application process using a URI: qemu:///embed?root=/some/path Note that it is important to keep the path reasonably short to avoid risk of hitting the limit on UNIX socket path names which is 108 characters. When using the embedded mode with a root=/var/tmp/embed, the driver will use the following paths: logDir: /var/tmp/embed/log/qemu swtpmLogDir: /var/tmp/embed/log/swtpm configBaseDir: /var/tmp/embed/etc/qemu stateDir: /var/tmp/embed/run/qemu swtpmStateDir: /var/tmp/embed/run/swtpm cacheDir: /var/tmp/embed/cache/qemu libDir: /var/tmp/embed/lib/qemu swtpmStorageDir: /var/tmp/embed/lib/swtpm defaultTLSx509certdir: /var/tmp/embed/etc/pki/qemu These are identical whether the embedded driver is privileged or unprivileged. This compares with the system instance which uses logDir: /var/log/libvirt/qemu swtpmLogDir: /var/log/swtpm/libvirt/qemu configBaseDir: /etc/libvirt/qemu stateDir: /run/libvirt/qemu swtpmStateDir: /run/libvirt/qemu/swtpm cacheDir: /var/cache/libvirt/qemu libDir: /var/lib/libvirt/qemu swtpmStorageDir: /var/lib/libvirt/swtpm defaultTLSx509certdir: /etc/pki/qemu At this time all features present in the QEMU driver are available when running in embedded mode, availability matching whether the embedded driver is privileged or unprivileged. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:35:57 +00:00
const char *root)
{
g_autoptr(virQEMUDriverConfig) cfg = NULL;
if (virQEMUConfigInitialize() < 0)
return NULL;
if (!(cfg = virObjectNew(virQEMUDriverConfigClass)))
return NULL;
qemu: add support for running QEMU driver in embedded mode This enables support for running QEMU embedded to the calling application process using a URI: qemu:///embed?root=/some/path Note that it is important to keep the path reasonably short to avoid risk of hitting the limit on UNIX socket path names which is 108 characters. When using the embedded mode with a root=/var/tmp/embed, the driver will use the following paths: logDir: /var/tmp/embed/log/qemu swtpmLogDir: /var/tmp/embed/log/swtpm configBaseDir: /var/tmp/embed/etc/qemu stateDir: /var/tmp/embed/run/qemu swtpmStateDir: /var/tmp/embed/run/swtpm cacheDir: /var/tmp/embed/cache/qemu libDir: /var/tmp/embed/lib/qemu swtpmStorageDir: /var/tmp/embed/lib/swtpm defaultTLSx509certdir: /var/tmp/embed/etc/pki/qemu These are identical whether the embedded driver is privileged or unprivileged. This compares with the system instance which uses logDir: /var/log/libvirt/qemu swtpmLogDir: /var/log/swtpm/libvirt/qemu configBaseDir: /etc/libvirt/qemu stateDir: /run/libvirt/qemu swtpmStateDir: /run/libvirt/qemu/swtpm cacheDir: /var/cache/libvirt/qemu libDir: /var/lib/libvirt/qemu swtpmStorageDir: /var/lib/libvirt/swtpm defaultTLSx509certdir: /etc/pki/qemu At this time all features present in the QEMU driver are available when running in embedded mode, availability matching whether the embedded driver is privileged or unprivileged. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:35:57 +00:00
if (root) {
cfg->uri = g_strdup_printf("qemu:///embed?root=%s", root);
} else {
cfg->uri = g_strdup(privileged ? "qemu:///system" : "qemu:///session");
}
if (privileged) {
if (virGetUserID(QEMU_USER, &cfg->user) < 0)
return NULL;
if (virGetGroupID(QEMU_GROUP, &cfg->group) < 0)
return NULL;
} else {
cfg->user = (uid_t)-1;
cfg->group = (gid_t)-1;
}
cfg->dynamicOwnership = privileged;
if (privileged)
cfg->rememberOwner = virSecurityXATTRNamespaceDefined();
else
cfg->rememberOwner = false;
cfg->cgroupControllers = -1; /* -1 == auto-detect */
qemu: add support for running QEMU driver in embedded mode This enables support for running QEMU embedded to the calling application process using a URI: qemu:///embed?root=/some/path Note that it is important to keep the path reasonably short to avoid risk of hitting the limit on UNIX socket path names which is 108 characters. When using the embedded mode with a root=/var/tmp/embed, the driver will use the following paths: logDir: /var/tmp/embed/log/qemu swtpmLogDir: /var/tmp/embed/log/swtpm configBaseDir: /var/tmp/embed/etc/qemu stateDir: /var/tmp/embed/run/qemu swtpmStateDir: /var/tmp/embed/run/swtpm cacheDir: /var/tmp/embed/cache/qemu libDir: /var/tmp/embed/lib/qemu swtpmStorageDir: /var/tmp/embed/lib/swtpm defaultTLSx509certdir: /var/tmp/embed/etc/pki/qemu These are identical whether the embedded driver is privileged or unprivileged. This compares with the system instance which uses logDir: /var/log/libvirt/qemu swtpmLogDir: /var/log/swtpm/libvirt/qemu configBaseDir: /etc/libvirt/qemu stateDir: /run/libvirt/qemu swtpmStateDir: /run/libvirt/qemu/swtpm cacheDir: /var/cache/libvirt/qemu libDir: /var/lib/libvirt/qemu swtpmStorageDir: /var/lib/libvirt/swtpm defaultTLSx509certdir: /etc/pki/qemu At this time all features present in the QEMU driver are available when running in embedded mode, availability matching whether the embedded driver is privileged or unprivileged. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:35:57 +00:00
if (root != NULL) {
cfg->logDir = g_strdup_printf("%s/log/qemu", root);
cfg->swtpmLogDir = g_strdup_printf("%s/log/swtpm", root);
cfg->configBaseDir = g_strdup_printf("%s/etc", root);
cfg->stateDir = g_strdup_printf("%s/run/qemu", root);
cfg->swtpmStateDir = g_strdup_printf("%s/run/swtpm", root);
cfg->cacheDir = g_strdup_printf("%s/cache/qemu", root);
cfg->libDir = g_strdup_printf("%s/lib/qemu", root);
cfg->swtpmStorageDir = g_strdup_printf("%s/lib/swtpm", root);
cfg->saveDir = g_strdup_printf("%s/save", cfg->libDir);
cfg->snapshotDir = g_strdup_printf("%s/snapshot", cfg->libDir);
cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir);
cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir);
cfg->channelTargetDir = g_strdup_printf("%s/channel/target", cfg->libDir);
cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir);
} else if (privileged) {
cfg->logDir = g_strdup_printf("%s/log/libvirt/qemu", LOCALSTATEDIR);
cfg->swtpmLogDir = g_strdup_printf("%s/log/swtpm/libvirt/qemu",
LOCALSTATEDIR);
cfg->configBaseDir = g_strdup(SYSCONFDIR "/libvirt");
2007-10-12 16:05:44 +00:00
cfg->stateDir = g_strdup_printf("%s/libvirt/qemu", RUNSTATEDIR);
cfg->swtpmStateDir = g_strdup_printf("%s/libvirt/qemu/swtpm", RUNSTATEDIR);
cfg->cacheDir = g_strdup_printf("%s/cache/libvirt/qemu", LOCALSTATEDIR);
cfg->libDir = g_strdup_printf("%s/lib/libvirt/qemu", LOCALSTATEDIR);
cfg->saveDir = g_strdup_printf("%s/save", cfg->libDir);
cfg->snapshotDir = g_strdup_printf("%s/snapshot", cfg->libDir);
cfg->checkpointDir = g_strdup_printf("%s/checkpoint", cfg->libDir);
cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir);
cfg->channelTargetDir = g_strdup_printf("%s/channel/target", cfg->libDir);
cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir);
cfg->swtpmStorageDir = g_strdup_printf("%s/lib/libvirt/swtpm",
LOCALSTATEDIR);
if (!virDoesUserExist("tss") ||
virGetUserID("tss", &cfg->swtpm_user) < 0)
cfg->swtpm_user = 0; /* fall back to root */
if (!virDoesGroupExist("tss") ||
virGetGroupID("tss", &cfg->swtpm_group) < 0)
cfg->swtpm_group = 0; /* fall back to root */
} else {
g_autofree char *rundir = NULL;
g_autofree char *cachedir = NULL;
cachedir = virGetUserCacheDirectory();
cfg->logDir = g_strdup_printf("%s/qemu/log", cachedir);
cfg->swtpmLogDir = g_strdup_printf("%s/qemu/log", cachedir);
cfg->cacheDir = g_strdup_printf("%s/qemu/cache", cachedir);
rundir = virGetUserRuntimeDirectory();
cfg->stateDir = g_strdup_printf("%s/qemu/run", rundir);
cfg->swtpmStateDir = g_strdup_printf("%s/swtpm", cfg->stateDir);
cfg->configBaseDir = virGetUserConfigDirectory();
cfg->libDir = g_strdup_printf("%s/qemu/lib", cfg->configBaseDir);
cfg->saveDir = g_strdup_printf("%s/qemu/save", cfg->configBaseDir);
cfg->snapshotDir = g_strdup_printf("%s/qemu/snapshot", cfg->configBaseDir);
cfg->checkpointDir = g_strdup_printf("%s/qemu/checkpoint",
cfg->configBaseDir);
cfg->autoDumpPath = g_strdup_printf("%s/qemu/dump", cfg->configBaseDir);
cfg->channelTargetDir = g_strdup_printf("%s/qemu/channel/target",
cfg->configBaseDir);
cfg->nvramDir = g_strdup_printf("%s/qemu/nvram", cfg->configBaseDir);
cfg->memoryBackingDir = g_strdup_printf("%s/qemu/ram", cfg->configBaseDir);
cfg->swtpmStorageDir = g_strdup_printf("%s/qemu/swtpm",
cfg->configBaseDir);
qemu: add support for running QEMU driver in embedded mode This enables support for running QEMU embedded to the calling application process using a URI: qemu:///embed?root=/some/path Note that it is important to keep the path reasonably short to avoid risk of hitting the limit on UNIX socket path names which is 108 characters. When using the embedded mode with a root=/var/tmp/embed, the driver will use the following paths: logDir: /var/tmp/embed/log/qemu swtpmLogDir: /var/tmp/embed/log/swtpm configBaseDir: /var/tmp/embed/etc/qemu stateDir: /var/tmp/embed/run/qemu swtpmStateDir: /var/tmp/embed/run/swtpm cacheDir: /var/tmp/embed/cache/qemu libDir: /var/tmp/embed/lib/qemu swtpmStorageDir: /var/tmp/embed/lib/swtpm defaultTLSx509certdir: /var/tmp/embed/etc/pki/qemu These are identical whether the embedded driver is privileged or unprivileged. This compares with the system instance which uses logDir: /var/log/libvirt/qemu swtpmLogDir: /var/log/swtpm/libvirt/qemu configBaseDir: /etc/libvirt/qemu stateDir: /run/libvirt/qemu swtpmStateDir: /run/libvirt/qemu/swtpm cacheDir: /var/cache/libvirt/qemu libDir: /var/lib/libvirt/qemu swtpmStorageDir: /var/lib/libvirt/swtpm defaultTLSx509certdir: /etc/pki/qemu At this time all features present in the QEMU driver are available when running in embedded mode, availability matching whether the embedded driver is privileged or unprivileged. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:35:57 +00:00
}
if (privileged) {
if (!virDoesUserExist("tss") ||
virGetUserID("tss", &cfg->swtpm_user) < 0)
cfg->swtpm_user = 0; /* fall back to root */
if (!virDoesGroupExist("tss") ||
virGetGroupID("tss", &cfg->swtpm_group) < 0)
cfg->swtpm_group = 0; /* fall back to root */
} else {
cfg->swtpm_user = (uid_t)-1;
cfg->swtpm_group = (gid_t)-1;
}
cfg->configDir = g_strdup_printf("%s/qemu", cfg->configBaseDir);
cfg->autostartDir = g_strdup_printf("%s/qemu/autostart", cfg->configBaseDir);
cfg->slirpStateDir = g_strdup_printf("%s/slirp", cfg->stateDir);
cfg->dbusStateDir = g_strdup_printf("%s/dbus", cfg->stateDir);
/* Set the default directory to find TLS X.509 certificates.
* This will then be used as a fallback if the service specific
* directory doesn't exist (although we don't check if this exists).
*/
qemu: add support for running QEMU driver in embedded mode This enables support for running QEMU embedded to the calling application process using a URI: qemu:///embed?root=/some/path Note that it is important to keep the path reasonably short to avoid risk of hitting the limit on UNIX socket path names which is 108 characters. When using the embedded mode with a root=/var/tmp/embed, the driver will use the following paths: logDir: /var/tmp/embed/log/qemu swtpmLogDir: /var/tmp/embed/log/swtpm configBaseDir: /var/tmp/embed/etc/qemu stateDir: /var/tmp/embed/run/qemu swtpmStateDir: /var/tmp/embed/run/swtpm cacheDir: /var/tmp/embed/cache/qemu libDir: /var/tmp/embed/lib/qemu swtpmStorageDir: /var/tmp/embed/lib/swtpm defaultTLSx509certdir: /var/tmp/embed/etc/pki/qemu These are identical whether the embedded driver is privileged or unprivileged. This compares with the system instance which uses logDir: /var/log/libvirt/qemu swtpmLogDir: /var/log/swtpm/libvirt/qemu configBaseDir: /etc/libvirt/qemu stateDir: /run/libvirt/qemu swtpmStateDir: /run/libvirt/qemu/swtpm cacheDir: /var/cache/libvirt/qemu libDir: /var/lib/libvirt/qemu swtpmStorageDir: /var/lib/libvirt/swtpm defaultTLSx509certdir: /etc/pki/qemu At this time all features present in the QEMU driver are available when running in embedded mode, availability matching whether the embedded driver is privileged or unprivileged. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:35:57 +00:00
if (root == NULL) {
cfg->defaultTLSx509certdir = g_strdup(SYSCONFDIR "/pki/qemu");
qemu: add support for running QEMU driver in embedded mode This enables support for running QEMU embedded to the calling application process using a URI: qemu:///embed?root=/some/path Note that it is important to keep the path reasonably short to avoid risk of hitting the limit on UNIX socket path names which is 108 characters. When using the embedded mode with a root=/var/tmp/embed, the driver will use the following paths: logDir: /var/tmp/embed/log/qemu swtpmLogDir: /var/tmp/embed/log/swtpm configBaseDir: /var/tmp/embed/etc/qemu stateDir: /var/tmp/embed/run/qemu swtpmStateDir: /var/tmp/embed/run/swtpm cacheDir: /var/tmp/embed/cache/qemu libDir: /var/tmp/embed/lib/qemu swtpmStorageDir: /var/tmp/embed/lib/swtpm defaultTLSx509certdir: /var/tmp/embed/etc/pki/qemu These are identical whether the embedded driver is privileged or unprivileged. This compares with the system instance which uses logDir: /var/log/libvirt/qemu swtpmLogDir: /var/log/swtpm/libvirt/qemu configBaseDir: /etc/libvirt/qemu stateDir: /run/libvirt/qemu swtpmStateDir: /run/libvirt/qemu/swtpm cacheDir: /var/cache/libvirt/qemu libDir: /var/lib/libvirt/qemu swtpmStorageDir: /var/lib/libvirt/swtpm defaultTLSx509certdir: /etc/pki/qemu At this time all features present in the QEMU driver are available when running in embedded mode, availability matching whether the embedded driver is privileged or unprivileged. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2019-05-17 11:35:57 +00:00
} else {
cfg->defaultTLSx509certdir = g_strdup_printf("%s/etc/pki/qemu", root);
}
cfg->vncListen = g_strdup(VIR_LOOPBACK_IPV4_ADDR);
cfg->spiceListen = g_strdup(VIR_LOOPBACK_IPV4_ADDR);
cfg->remotePortMin = QEMU_REMOTE_PORT_MIN;
cfg->remotePortMax = QEMU_REMOTE_PORT_MAX;
cfg->webSocketPortMin = QEMU_WEBSOCKET_PORT_MIN;
cfg->webSocketPortMax = QEMU_WEBSOCKET_PORT_MAX;
cfg->migrationPortMin = QEMU_MIGRATION_PORT_MIN;
cfg->migrationPortMax = QEMU_MIGRATION_PORT_MAX;
/* For privileged driver, try and find hugetlbfs mounts automatically.
* Non-privileged driver requires admin to create a dir for the
* user, chown it, and then let user configure it manually. */
if (privileged &&
virFileFindHugeTLBFS(&cfg->hugetlbfs, &cfg->nhugetlbfs) < 0) {
/* This however is not implemented on all platforms. */
if (virGetLastErrorCode() != VIR_ERR_NO_SUPPORT)
return NULL;
}
cfg->bridgeHelperName = g_strdup(QEMU_BRIDGE_HELPER);
cfg->prHelperName = g_strdup(QEMU_PR_HELPER);
cfg->slirpHelperName = g_strdup(QEMU_SLIRP_HELPER);
cfg->dbusDaemonName = g_strdup(QEMU_DBUS_DAEMON);
cfg->securityDefaultConfined = true;
cfg->securityRequireConfined = false;
cfg->keepAliveInterval = 5;
cfg->keepAliveCount = 5;
cfg->seccompSandbox = -1;
cfg->logTimestamp = true;
cfg->glusterDebugLevel = 4;
cfg->stdioLogD = true;
cfg->namespaces = virBitmapNew(QEMU_DOMAIN_NS_LAST);
if (privileged &&
qemuDomainNamespaceAvailable(QEMU_DOMAIN_NS_MOUNT) &&
virBitmapSetBit(cfg->namespaces, QEMU_DOMAIN_NS_MOUNT) < 0)
return NULL;
if (virFirmwareParseList(DEFAULT_LOADER_NVRAM,
&cfg->firmwares,
&cfg->nfirmwares) < 0)
return NULL;
cfg->deprecationBehavior = g_strdup("none");
return g_steal_pointer(&cfg);
}
static void virQEMUDriverConfigDispose(void *obj)
{
virQEMUDriverConfig *cfg = obj;
virBitmapFree(cfg->namespaces);
g_strfreev(cfg->cgroupDeviceACL);
g_free(cfg->uri);
g_free(cfg->configBaseDir);
g_free(cfg->configDir);
g_free(cfg->autostartDir);
g_free(cfg->logDir);
g_free(cfg->swtpmLogDir);
g_free(cfg->stateDir);
g_free(cfg->swtpmStateDir);
g_free(cfg->slirpStateDir);
g_free(cfg->dbusStateDir);
g_free(cfg->libDir);
g_free(cfg->cacheDir);
g_free(cfg->saveDir);
g_free(cfg->snapshotDir);
g_free(cfg->checkpointDir);
g_free(cfg->channelTargetDir);
g_free(cfg->nvramDir);
g_free(cfg->defaultTLSx509certdir);
g_free(cfg->defaultTLSx509secretUUID);
g_free(cfg->vncTLSx509certdir);
g_free(cfg->vncTLSx509secretUUID);
g_free(cfg->vncListen);
g_free(cfg->vncPassword);
g_free(cfg->vncSASLdir);
g_free(cfg->spiceTLSx509certdir);
g_free(cfg->spiceListen);
g_free(cfg->spicePassword);
g_free(cfg->spiceSASLdir);
g_free(cfg->chardevTLSx509certdir);
g_free(cfg->chardevTLSx509secretUUID);
g_free(cfg->vxhsTLSx509certdir);
g_free(cfg->vxhsTLSx509secretUUID);
g_free(cfg->nbdTLSx509certdir);
g_free(cfg->nbdTLSx509secretUUID);
g_free(cfg->migrateTLSx509certdir);
g_free(cfg->migrateTLSx509secretUUID);
g_free(cfg->backupTLSx509certdir);
g_free(cfg->backupTLSx509secretUUID);
while (cfg->nhugetlbfs) {
cfg->nhugetlbfs--;
g_free(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir);
}
g_free(cfg->hugetlbfs);
g_free(cfg->bridgeHelperName);
g_free(cfg->prHelperName);
g_free(cfg->slirpHelperName);
g_free(cfg->dbusDaemonName);
g_free(cfg->saveImageFormat);
g_free(cfg->dumpImageFormat);
g_free(cfg->snapshotImageFormat);
g_free(cfg->autoDumpPath);
g_strfreev(cfg->securityDriverNames);
g_free(cfg->lockManagerName);
virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
g_free(cfg->memoryBackingDir);
g_free(cfg->swtpmStorageDir);
g_strfreev(cfg->capabilityfilters);
g_free(cfg->deprecationBehavior);
}
static int
virQEMUDriverConfigHugeTLBFSInit(virHugeTLBFS *hugetlbfs,
const char *path,
bool deflt)
{
hugetlbfs->mnt_dir = g_strdup(path);
if (virFileGetHugepageSize(path, &hugetlbfs->size) < 0)
return -1;
hugetlbfs->deflt = deflt;
return 0;
}
static int
virQEMUDriverConfigLoadDefaultTLSEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
int rv;
if ((rv = virConfGetValueString(conf, "default_tls_x509_cert_dir", &cfg->defaultTLSx509certdir)) < 0)
return -1;
cfg->defaultTLSx509certdirPresent = (rv == 1);
if ((rv = virConfGetValueBool(conf, "default_tls_x509_verify", &cfg->defaultTLSx509verify)) < 0)
return -1;
if (rv == 1)
cfg->defaultTLSx509verifyPresent = true;
if (virConfGetValueString(conf, "default_tls_x509_secret_uuid",
&cfg->defaultTLSx509secretUUID) < 0)
return -1;
return 0;
}
static int
virQEMUDriverConfigLoadVNCEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
int rv;
if (virConfGetValueBool(conf, "vnc_auto_unix_socket", &cfg->vncAutoUnixSocket) < 0)
return -1;
if (virConfGetValueBool(conf, "vnc_tls", &cfg->vncTLS) < 0)
return -1;
if ((rv = virConfGetValueBool(conf, "vnc_tls_x509_verify", &cfg->vncTLSx509verify)) < 0)
return -1;
if (rv == 1)
cfg->vncTLSx509verifyPresent = true;
if (virConfGetValueString(conf, "vnc_tls_x509_cert_dir", &cfg->vncTLSx509certdir) < 0)
return -1;
if (virConfGetValueString(conf, "vnc_tls_x509_secret_uuid", &cfg->vncTLSx509secretUUID) < 0)
return -1;
if (virConfGetValueString(conf, "vnc_listen", &cfg->vncListen) < 0)
return -1;
if (virConfGetValueString(conf, "vnc_password", &cfg->vncPassword) < 0)
return -1;
if (virConfGetValueBool(conf, "vnc_sasl", &cfg->vncSASL) < 0)
return -1;
if (virConfGetValueString(conf, "vnc_sasl_dir", &cfg->vncSASLdir) < 0)
return -1;
if (virConfGetValueBool(conf, "vnc_allow_host_audio", &cfg->vncAllowHostAudio) < 0)
return -1;
if (cfg->vncPassword &&
strlen(cfg->vncPassword) > 8) {
VIR_WARN("VNC password is %zu characters long, only 8 permitted, truncating",
strlen(cfg->vncPassword));
cfg->vncPassword[8] = '\0';
}
return 0;
}
static int
virQEMUDriverConfigLoadNographicsEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
return virConfGetValueBool(conf, "nographics_allow_host_audio", &cfg->nogfxAllowHostAudio);
}
static int
virQEMUDriverConfigLoadSPICEEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
if (virConfGetValueBool(conf, "spice_tls", &cfg->spiceTLS) < 0)
return -1;
if (virConfGetValueString(conf, "spice_tls_x509_cert_dir", &cfg->spiceTLSx509certdir) < 0)
return -1;
if (virConfGetValueBool(conf, "spice_sasl", &cfg->spiceSASL) < 0)
return -1;
if (virConfGetValueString(conf, "spice_sasl_dir", &cfg->spiceSASLdir) < 0)
return -1;
if (virConfGetValueString(conf, "spice_listen", &cfg->spiceListen) < 0)
return -1;
if (virConfGetValueString(conf, "spice_password", &cfg->spicePassword) < 0)
return -1;
if (virConfGetValueBool(conf, "spice_auto_unix_socket", &cfg->spiceAutoUnixSocket) < 0)
return -1;
return 0;
}
static int
virQEMUDriverConfigLoadSpecificTLSEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
int rv;
if (virConfGetValueBool(conf, "vxhs_tls", &cfg->vxhsTLS) < 0)
return -1;
if (virConfGetValueBool(conf, "nbd_tls", &cfg->nbdTLS) < 0)
return -1;
if (virConfGetValueBool(conf, "chardev_tls", &cfg->chardevTLS) < 0)
return -1;
if (virConfGetValueBool(conf, "migrate_tls_force", &cfg->migrateTLSForce) < 0)
return -1;
#define GET_CONFIG_TLS_CERTINFO_COMMON(val) \
do { \
if (virConfGetValueString(conf, #val "_tls_x509_cert_dir", \
&cfg->val## TLSx509certdir) < 0) \
return -1; \
if (virConfGetValueString(conf, \
#val "_tls_x509_secret_uuid", \
&cfg->val## TLSx509secretUUID) < 0) \
return -1; \
} while (0)
#define GET_CONFIG_TLS_CERTINFO_SERVER(val) \
do { \
if ((rv = virConfGetValueBool(conf, #val "_tls_x509_verify", \
&cfg->val## TLSx509verify)) < 0) \
return -1; \
if (rv == 1) \
cfg->val## TLSx509verifyPresent = true; \
} while (0)
GET_CONFIG_TLS_CERTINFO_COMMON(chardev);
GET_CONFIG_TLS_CERTINFO_SERVER(chardev);
GET_CONFIG_TLS_CERTINFO_COMMON(migrate);
GET_CONFIG_TLS_CERTINFO_SERVER(migrate);
GET_CONFIG_TLS_CERTINFO_COMMON(backup);
GET_CONFIG_TLS_CERTINFO_SERVER(backup);
GET_CONFIG_TLS_CERTINFO_COMMON(vxhs);
GET_CONFIG_TLS_CERTINFO_COMMON(nbd);
#undef GET_CONFIG_TLS_CERTINFO_COMMON
#undef GET_CONFIG_TLS_CERTINFO_SERVER
return 0;
}
static int
virQEMUDriverConfigLoadRemoteDisplayEntry(virQEMUDriverConfig *cfg,
virConf *conf,
const char *filename)
{
if (virConfGetValueUInt(conf, "remote_websocket_port_min", &cfg->webSocketPortMin) < 0)
return -1;
if (cfg->webSocketPortMin < QEMU_WEBSOCKET_PORT_MIN) {
/* if the port is too low, we can't get the display name
* to tell to vnc (usually subtract 5700, e.g. localhost:1
* for port 5701) */
virReportError(VIR_ERR_INTERNAL_ERROR,
_("%s: remote_websocket_port_min: port must be greater "
"than or equal to %d"),
filename, QEMU_WEBSOCKET_PORT_MIN);
return -1;
}
if (virConfGetValueUInt(conf, "remote_websocket_port_max", &cfg->webSocketPortMax) < 0)
return -1;
if (cfg->webSocketPortMax > QEMU_WEBSOCKET_PORT_MAX ||
cfg->webSocketPortMax < cfg->webSocketPortMin) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("%s: remote_websocket_port_max: port must be between "
"the minimal port and %d"),
filename, QEMU_WEBSOCKET_PORT_MAX);
return -1;
}
if (cfg->webSocketPortMin > cfg->webSocketPortMax) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("%s: remote_websocket_port_min: min port must not be "
"greater than max port"), filename);
return -1;
}
if (virConfGetValueUInt(conf, "remote_display_port_min", &cfg->remotePortMin) < 0)
return -1;
if (cfg->remotePortMin < QEMU_REMOTE_PORT_MIN) {
/* if the port is too low, we can't get the display name
* to tell to vnc (usually subtract 5900, e.g. localhost:1
* for port 5901) */
virReportError(VIR_ERR_INTERNAL_ERROR,
_("%s: remote_display_port_min: port must be greater "
"than or equal to %d"),
filename, QEMU_REMOTE_PORT_MIN);
return -1;
}
if (virConfGetValueUInt(conf, "remote_display_port_max", &cfg->remotePortMax) < 0)
return -1;
if (cfg->remotePortMax > QEMU_REMOTE_PORT_MAX ||
cfg->remotePortMax < cfg->remotePortMin) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("%s: remote_display_port_max: port must be between "
"the minimal port and %d"),
filename, QEMU_REMOTE_PORT_MAX);
return -1;
}
if (cfg->remotePortMin > cfg->remotePortMax) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("%s: remote_display_port_min: min port must not be "
"greater than max port"), filename);
return -1;
}
return 0;
}
static int
virQEMUDriverConfigLoadSaveEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
if (virConfGetValueString(conf, "save_image_format", &cfg->saveImageFormat) < 0)
return -1;
if (virConfGetValueString(conf, "dump_image_format", &cfg->dumpImageFormat) < 0)
return -1;
if (virConfGetValueString(conf, "snapshot_image_format", &cfg->snapshotImageFormat) < 0)
return -1;
if (virConfGetValueString(conf, "auto_dump_path", &cfg->autoDumpPath) < 0)
return -1;
if (virConfGetValueBool(conf, "auto_dump_bypass_cache", &cfg->autoDumpBypassCache) < 0)
return -1;
if (virConfGetValueBool(conf, "auto_start_bypass_cache", &cfg->autoStartBypassCache) < 0)
return -1;
return 0;
}
static int
virQEMUDriverConfigLoadProcessEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
g_auto(GStrv) hugetlbfs = NULL;
g_autofree char *stdioHandler = NULL;
g_autofree char *corestr = NULL;
size_t i;
if (virConfGetValueStringList(conf, "hugetlbfs_mount", true,
&hugetlbfs) < 0)
return -1;
if (hugetlbfs) {
/* There already might be something autodetected. Avoid leaking it. */
while (cfg->nhugetlbfs) {
cfg->nhugetlbfs--;
VIR_FREE(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir);
}
VIR_FREE(cfg->hugetlbfs);
cfg->nhugetlbfs = g_strv_length(hugetlbfs);
if (hugetlbfs[0])
cfg->hugetlbfs = g_new0(virHugeTLBFS, cfg->nhugetlbfs);
for (i = 0; hugetlbfs[i] != NULL; i++) {
if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[i],
hugetlbfs[i], i != 0) < 0)
return -1;
}
}
if (virConfGetValueString(conf, "bridge_helper", &cfg->bridgeHelperName) < 0)
return -1;
if (virConfGetValueString(conf, "pr_helper", &cfg->prHelperName) < 0)
return -1;
if (virConfGetValueString(conf, "slirp_helper", &cfg->slirpHelperName) < 0)
return -1;
if (virConfGetValueString(conf, "dbus_daemon", &cfg->dbusDaemonName) < 0)
return -1;
if (virConfGetValueBool(conf, "set_process_name", &cfg->setProcessName) < 0)
return -1;
if (virConfGetValueUInt(conf, "max_processes", &cfg->maxProcesses) < 0)
return -1;
if (virConfGetValueUInt(conf, "max_files", &cfg->maxFiles) < 0)
return -1;
if (virConfGetValueUInt(conf, "max_threads_per_process", &cfg->maxThreadsPerProc) < 0)
return -1;
if (virConfGetValueType(conf, "max_core") == VIR_CONF_STRING) {
if (virConfGetValueString(conf, "max_core", &corestr) < 0)
return -1;
if (STREQ(corestr, "unlimited")) {
cfg->maxCore = ULLONG_MAX;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unknown core size '%s'"),
corestr);
return -1;
}
} else if (virConfGetValueULLong(conf, "max_core", &cfg->maxCore) < 0) {
return -1;
}
if (virConfGetValueBool(conf, "dump_guest_core", &cfg->dumpGuestCore) < 0)
return -1;
if (virConfGetValueString(conf, "stdio_handler", &stdioHandler) < 0)
return -1;
if (stdioHandler) {
if (STREQ(stdioHandler, "logd")) {
cfg->stdioLogD = true;
} else if (STREQ(stdioHandler, "file")) {
cfg->stdioLogD = false;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unknown stdio handler %s"),
stdioHandler);
return -1;
}
}
return 0;
}
static int
virQEMUDriverConfigLoadDeviceEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
bool tmp;
int rv;
if (virConfGetValueBool(conf, "mac_filter", &cfg->macFilter) < 0)
return -1;
if (virConfGetValueBool(conf, "relaxed_acs_check", &cfg->relaxedACS) < 0)
return -1;
if (virConfGetValueString(conf, "lock_manager", &cfg->lockManagerName) < 0)
return -1;
if ((rv = virConfGetValueBool(conf, "allow_disk_format_probing", &tmp)) < 0)
return -1;
if (rv == 1 && tmp) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("allow_disk_format_probing is no longer supported"));
return -1;
}
return 0;
}
static int
virQEMUDriverConfigLoadRPCEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
if (virConfGetValueUInt(conf, "max_queued", &cfg->maxQueuedJobs) < 0)
return -1;
if (virConfGetValueInt(conf, "keepalive_interval", &cfg->keepAliveInterval) < 0)
return -1;
if (virConfGetValueUInt(conf, "keepalive_count", &cfg->keepAliveCount) < 0)
return -1;
return 0;
}
static int
virQEMUDriverConfigLoadNetworkEntry(virQEMUDriverConfig *cfg,
virConf *conf,
const char *filename)
{
if (virConfGetValueUInt(conf, "migration_port_min", &cfg->migrationPortMin) < 0)
return -1;
if (cfg->migrationPortMin <= 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("%s: migration_port_min: port must be greater than 0"),
filename);
return -1;
}
if (virConfGetValueUInt(conf, "migration_port_max", &cfg->migrationPortMax) < 0)
return -1;
if (cfg->migrationPortMax > 65535 ||
cfg->migrationPortMax < cfg->migrationPortMin) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("%s: migration_port_max: port must be between "
"the minimal port %d and 65535"),
filename, cfg->migrationPortMin);
return -1;
}
if (virConfGetValueString(conf, "migration_host", &cfg->migrateHost) < 0)
return -1;
virStringStripIPv6Brackets(cfg->migrateHost);
if (cfg->migrateHost &&
(STRPREFIX(cfg->migrateHost, "localhost") ||
virSocketAddrIsNumericLocalhost(cfg->migrateHost))) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("migration_host must not be the address of"
" the local machine: %s"),
cfg->migrateHost);
return -1;
}
if (virConfGetValueString(conf, "migration_address", &cfg->migrationAddress) < 0)
return -1;
virStringStripIPv6Brackets(cfg->migrationAddress);
if (cfg->migrationAddress &&
(STRPREFIX(cfg->migrationAddress, "localhost") ||
virSocketAddrIsNumericLocalhost(cfg->migrationAddress))) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("migration_address must not be the address of"
" the local machine: %s"),
cfg->migrationAddress);
return -1;
}
return 0;
}
static int
virQEMUDriverConfigLoadLogEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
return virConfGetValueBool(conf, "log_timestamp", &cfg->logTimestamp);
}
static int
virQEMUDriverConfigLoadNVRAMEntry(virQEMUDriverConfig *cfg,
virConf *conf,
bool privileged)
{
g_auto(GStrv) nvram = NULL;
size_t i;
if (virConfGetValueStringList(conf, "nvram", false, &nvram) < 0)
return -1;
if (nvram) {
g_auto(GStrv) fwList = NULL;
virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
cfg->firmwares = NULL;
cfg->nfirmwares = 0;
if (qemuFirmwareFetchConfigs(&fwList, privileged) < 0)
return -1;
if (fwList) {
VIR_WARN("Obsolete nvram variable is set while firmware metadata "
"files found. Note that the nvram config file variable is "
"going to be ignored.");
return 0;
}
cfg->nfirmwares = g_strv_length(nvram);
cfg->firmwares = g_new0(virFirmware *, cfg->nfirmwares);
for (i = 0; nvram[i] != NULL; i++) {
cfg->firmwares[i] = g_new0(virFirmware, 1);
if (virFirmwareParse(nvram[i], cfg->firmwares[i]) < 0)
return -1;
}
}
return 0;
}
static int
virQEMUDriverConfigLoadDebugEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
if (virConfGetValueUInt(conf, "gluster_debug_level", &cfg->glusterDebugLevel) < 0)
return -1;
if (virConfGetValueBool(conf, "virtiofsd_debug", &cfg->virtiofsdDebug) < 0)
return -1;
if (virConfGetValueString(conf, "deprecation_behavior", &cfg->deprecationBehavior) < 0)
return -1;
return 0;
}
static int
virQEMUDriverConfigLoadSecurityEntry(virQEMUDriverConfig *cfg,
virConf *conf,
bool privileged)
{
g_auto(GStrv) controllers = NULL;
g_auto(GStrv) namespaces = NULL;
g_autofree char *user = NULL;
g_autofree char *group = NULL;
size_t i, j;
if (virConfGetValueStringList(conf, "security_driver", true, &cfg->securityDriverNames) < 0)
return -1;
for (i = 0; cfg->securityDriverNames && cfg->securityDriverNames[i] != NULL; i++) {
for (j = i + 1; cfg->securityDriverNames[j] != NULL; j++) {
if (STREQ(cfg->securityDriverNames[i],
cfg->securityDriverNames[j])) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("Duplicate security driver %s"),
cfg->securityDriverNames[i]);
return -1;
}
}
}
if (virConfGetValueBool(conf, "security_default_confined", &cfg->securityDefaultConfined) < 0)
return -1;
if (virConfGetValueBool(conf, "security_require_confined", &cfg->securityRequireConfined) < 0)
return -1;
if (virConfGetValueString(conf, "user", &user) < 0)
return -1;
if (user && virGetUserID(user, &cfg->user) < 0)
return -1;
if (virConfGetValueString(conf, "group", &group) < 0)
return -1;
if (group && virGetGroupID(group, &cfg->group) < 0)
return -1;
if (virConfGetValueBool(conf, "dynamic_ownership", &cfg->dynamicOwnership) < 0)
return -1;
if (virConfGetValueBool(conf, "remember_owner", &cfg->rememberOwner) < 0)
return -1;
if (virConfGetValueStringList(conf, "cgroup_controllers", false,
&controllers) < 0)
return -1;
if (controllers) {
cfg->cgroupControllers = 0;
for (i = 0; controllers[i] != NULL; i++) {
int ctl;
if ((ctl = virCgroupControllerTypeFromString(controllers[i])) < 0) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("Unknown cgroup controller '%s'"),
controllers[i]);
return -1;
}
cfg->cgroupControllers |= (1 << ctl);
}
}
if (virConfGetValueStringList(conf, "cgroup_device_acl", false,
&cfg->cgroupDeviceACL) < 0)
return -1;
if (virConfGetValueInt(conf, "seccomp_sandbox", &cfg->seccompSandbox) < 0)
return -1;
if (virConfGetValueStringList(conf, "namespaces", false, &namespaces) < 0)
return -1;
if (namespaces) {
virBitmapClearAll(cfg->namespaces);
for (i = 0; namespaces[i]; i++) {
int ns = qemuDomainNamespaceTypeFromString(namespaces[i]);
if (ns < 0) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("Unknown namespace: %s"),
namespaces[i]);
return -1;
}
if (!privileged) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("cannot use namespaces in session mode"));
return -1;
}
if (!qemuDomainNamespaceAvailable(ns)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("%s namespace is not available"),
namespaces[i]);
return -1;
}
if (virBitmapSetBit(cfg->namespaces, ns) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to enable namespace: %s"),
namespaces[i]);
return -1;
}
}
}
return 0;
}
static int
virQEMUDriverConfigLoadMemoryEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
g_autofree char *dir = NULL;
int rc;
if ((rc = virConfGetValueString(conf, "memory_backing_dir", &dir)) < 0)
return -1;
if (rc > 0) {
VIR_FREE(cfg->memoryBackingDir);
cfg->memoryBackingDir = g_strdup_printf("%s/libvirt/qemu", dir);
}
return 0;
}
static int
virQEMUDriverConfigLoadSWTPMEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
g_autofree char *swtpm_user = NULL;
g_autofree char *swtpm_group = NULL;
if (virConfGetValueString(conf, "swtpm_user", &swtpm_user) < 0)
return -1;
if (swtpm_user && virGetUserID(swtpm_user, &cfg->swtpm_user) < 0)
return -1;
if (virConfGetValueString(conf, "swtpm_group", &swtpm_group) < 0)
return -1;
if (swtpm_group && virGetGroupID(swtpm_group, &cfg->swtpm_group) < 0)
return -1;
return 0;
}
static int
virQEMUDriverConfigLoadCapsFiltersEntry(virQEMUDriverConfig *cfg,
virConf *conf)
{
if (virConfGetValueStringList(conf, "capability_filters", false,
&cfg->capabilityfilters) < 0)
return -1;
return 0;
}
int virQEMUDriverConfigLoadFile(virQEMUDriverConfig *cfg,
const char *filename,
bool privileged)
{
g_autoptr(virConf) conf = NULL;
2007-10-12 16:05:44 +00:00
/* Just check the file is readable before opening it, otherwise
* libvirt emits an error.
*/
if (access(filename, R_OK) == -1) {
VIR_INFO("Could not read qemu config file %s", filename);
return 0;
}
2007-10-12 16:05:44 +00:00
if (!(conf = virConfReadFile(filename, 0)))
return -1;
2007-10-12 16:05:44 +00:00
if (virQEMUDriverConfigLoadDefaultTLSEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadVNCEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadNographicsEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadSPICEEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadSpecificTLSEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadRemoteDisplayEntry(cfg, conf, filename) < 0)
return -1;
if (virQEMUDriverConfigLoadSaveEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadProcessEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadDeviceEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadRPCEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadNetworkEntry(cfg, conf, filename) < 0)
return -1;
if (virQEMUDriverConfigLoadLogEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadNVRAMEntry(cfg, conf, privileged) < 0)
return -1;
if (virQEMUDriverConfigLoadDebugEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadSecurityEntry(cfg, conf, privileged) < 0)
return -1;
if (virQEMUDriverConfigLoadMemoryEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadSWTPMEntry(cfg, conf) < 0)
return -1;
if (virQEMUDriverConfigLoadCapsFiltersEntry(cfg, conf) < 0)
return -1;
return 0;
2007-10-12 16:05:44 +00:00
}
/**
* @cfg: Recently read config values
*
* Validate the recently read configuration values.
*
* Returns 0 on success, -1 on failure
*/
int
virQEMUDriverConfigValidate(virQEMUDriverConfig *cfg)
{
if (cfg->defaultTLSx509certdirPresent) {
if (!virFileExists(cfg->defaultTLSx509certdir)) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("default_tls_x509_cert_dir directory '%s' "
"does not exist"),
cfg->defaultTLSx509certdir);
return -1;
}
}
if (cfg->vncTLSx509certdir &&
!virFileExists(cfg->vncTLSx509certdir)) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("vnc_tls_x509_cert_dir directory '%s' does not exist"),
cfg->vncTLSx509certdir);
return -1;
}
if (cfg->spiceTLSx509certdir &&
!virFileExists(cfg->spiceTLSx509certdir)) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("spice_tls_x509_cert_dir directory '%s' does not exist"),
cfg->spiceTLSx509certdir);
return -1;
}
if (cfg->chardevTLSx509certdir &&
!virFileExists(cfg->chardevTLSx509certdir)) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("chardev_tls_x509_cert_dir directory '%s' does not exist"),
cfg->chardevTLSx509certdir);
return -1;
}
if (cfg->migrateTLSx509certdir &&
!virFileExists(cfg->migrateTLSx509certdir)) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("migrate_tls_x509_cert_dir directory '%s' does not exist"),
cfg->migrateTLSx509certdir);
return -1;
}
if (cfg->backupTLSx509certdir &&
!virFileExists(cfg->backupTLSx509certdir)) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("backup_tls_x509_cert_dir directory '%s' does not exist"),
cfg->backupTLSx509certdir);
return -1;
}
if (cfg->vxhsTLSx509certdir &&
!virFileExists(cfg->vxhsTLSx509certdir)) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("vxhs_tls_x509_cert_dir directory '%s' does not exist"),
cfg->vxhsTLSx509certdir);
return -1;
}
if (cfg->nbdTLSx509certdir &&
!virFileExists(cfg->nbdTLSx509certdir)) {
virReportError(VIR_ERR_CONF_SYNTAX,
_("nbd_tls_x509_cert_dir directory '%s' does not exist"),
cfg->nbdTLSx509certdir);
return -1;
}
return 0;
}
int
virQEMUDriverConfigSetDefaults(virQEMUDriverConfig *cfg)
{
#define SET_TLS_SECRET_UUID_DEFAULT(val) \
do { \
if (!cfg->val## TLSx509certdir && \
!cfg->val## TLSx509secretUUID && \
cfg->defaultTLSx509secretUUID) { \
cfg->val## TLSx509secretUUID = g_strdup(cfg->defaultTLSx509secretUUID); \
} \
} while (0)
SET_TLS_SECRET_UUID_DEFAULT(vnc);
SET_TLS_SECRET_UUID_DEFAULT(chardev);
SET_TLS_SECRET_UUID_DEFAULT(migrate);
SET_TLS_SECRET_UUID_DEFAULT(backup);
SET_TLS_SECRET_UUID_DEFAULT(vxhs);
SET_TLS_SECRET_UUID_DEFAULT(nbd);
#undef SET_TLS_SECRET_UUID_DEFAULT
/*
* If a "SYSCONFDIR" + "pki/libvirt-<val>" exists, then assume someone
* has created a val specific area to place service specific certificates.
*
* If the service specific directory doesn't exist, 'assume' that the
* user has created and populated the "SYSCONFDIR" + "pki/libvirt-default".
*/
#define SET_TLS_X509_CERT_DEFAULT(val) \
do { \
if (cfg->val ## TLSx509certdir) \
break; \
if (virFileExists(SYSCONFDIR "/pki/libvirt-"#val)) { \
cfg->val ## TLSx509certdir = g_strdup(SYSCONFDIR "/pki/libvirt-"#val); \
} else { \
cfg->val ## TLSx509certdir = g_strdup(cfg->defaultTLSx509certdir); \
} \
} while (0)
SET_TLS_X509_CERT_DEFAULT(vnc);
SET_TLS_X509_CERT_DEFAULT(spice);
SET_TLS_X509_CERT_DEFAULT(chardev);
SET_TLS_X509_CERT_DEFAULT(migrate);
SET_TLS_X509_CERT_DEFAULT(backup);
SET_TLS_X509_CERT_DEFAULT(vxhs);
SET_TLS_X509_CERT_DEFAULT(nbd);
#undef SET_TLS_X509_CERT_DEFAULT
#define SET_TLS_VERIFY_DEFAULT(val, defaultverify) \
do { \
if (!cfg->val## TLSx509verifyPresent) {\
if (cfg->defaultTLSx509verifyPresent) \
cfg->val## TLSx509verify = cfg->defaultTLSx509verify; \
else \
cfg->val## TLSx509verify = defaultverify;\
}\
} while (0)
SET_TLS_VERIFY_DEFAULT(vnc, false);
SET_TLS_VERIFY_DEFAULT(chardev, true);
SET_TLS_VERIFY_DEFAULT(migrate, true);
SET_TLS_VERIFY_DEFAULT(backup, true);
#undef SET_TLS_VERIFY_DEFAULT
return 0;
}
virQEMUDriverConfig *virQEMUDriverGetConfig(virQEMUDriver *driver)
{
VIR_LOCK_GUARD lock = virLockGuardLock(&driver->lock);
return virObjectRef(driver->config);
}
virDomainXMLOption *
virQEMUDriverCreateXMLConf(virQEMUDriver *driver,
const char *defsecmodel)
{
virQEMUDriverDomainDefParserConfig.priv = driver;
virQEMUDriverDomainDefParserConfig.defSecModel = defsecmodel;
return virDomainXMLOptionNew(&virQEMUDriverDomainDefParserConfig,
&virQEMUDriverPrivateDataCallbacks,
&virQEMUDriverDomainXMLNamespace,
&virQEMUDriverDomainABIStability,
&virQEMUDriverDomainSaveCookie);
}
virCPUDef *
virQEMUDriverGetHostCPU(virQEMUDriver *driver)
{
virCPUDef *hostcpu = NULL;
VIR_WITH_MUTEX_LOCK_GUARD(&driver->lock) {
if (!driver->hostcpu)
driver->hostcpu = virCPUProbeHost(virArchFromHost());
hostcpu = driver->hostcpu;
}
if (hostcpu)
virCPUDefRef(hostcpu);
return hostcpu;
}
virCaps *virQEMUDriverCreateCapabilities(virQEMUDriver *driver)
{
size_t i, j;
g_autoptr(virCaps) caps = NULL;
g_autofree virSecurityManager **sec_managers = NULL;
/* Security driver data */
const char *doi, *model, *lbl, *type;
const int virtTypes[] = {VIR_DOMAIN_VIRT_KVM,
VIR_DOMAIN_VIRT_QEMU,};
/* Basic host arch / guest machine capabilities */
if (!(caps = virQEMUCapsInit(driver->qemuCapsCache)))
return NULL;
if (virGetHostUUID(caps->host.host_uuid)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot get the host uuid"));
return NULL;
}
/* access sec drivers and create a sec model for each one */
if (!(sec_managers = qemuSecurityGetNested(driver->securityManager)))
return NULL;
/* calculate length */
for (i = 0; sec_managers[i]; i++)
;
caps->host.nsecModels = i;
caps->host.secModels = g_new0(virCapsHostSecModel, caps->host.nsecModels);
for (i = 0; sec_managers[i]; i++) {
virCapsHostSecModel *sm = &caps->host.secModels[i];
doi = qemuSecurityGetDOI(sec_managers[i]);
model = qemuSecurityGetModel(sec_managers[i]);
sm->model = g_strdup(model);
sm->doi = g_strdup(doi);
for (j = 0; j < G_N_ELEMENTS(virtTypes); j++) {
lbl = qemuSecurityGetBaseLabel(sec_managers[i], virtTypes[j]);
type = virDomainVirtTypeToString(virtTypes[j]);
if (lbl &&
virCapabilitiesHostSecModelAddBaseLabel(sm, type, lbl) < 0)
return NULL;
}
VIR_DEBUG("Initialized caps for security driver \"%s\" with "
"DOI \"%s\"", model, doi);
}
caps->host.numa = virCapabilitiesHostNUMANewHost();
caps->host.cpu = virQEMUDriverGetHostCPU(driver);
return g_steal_pointer(&caps);
}
/**
* virQEMUDriverGetCapabilities:
*
* Get a reference to the virCaps *instance for the
* driver. If @refresh is true, the capabilities will be
* rebuilt first
*
* The caller must release the reference with virObjectUnref
*
* Returns: a reference to a virCaps *instance or NULL
*/
virCaps *virQEMUDriverGetCapabilities(virQEMUDriver *driver,
bool refresh)
{
if (refresh) {
virCaps *caps = NULL;
if ((caps = virQEMUDriverCreateCapabilities(driver)) == NULL)
return NULL;
VIR_WITH_MUTEX_LOCK_GUARD(&driver->lock) {
virObjectUnref(driver->caps);
driver->caps = caps;
return virObjectRef(driver->caps);
}
}
VIR_WITH_MUTEX_LOCK_GUARD(&driver->lock) {
if (driver->caps && driver->caps->nguests > 0)
return virObjectRef(driver->caps);
}
VIR_DEBUG("Capabilities didn't detect any guests. Forcing a refresh.");
return virQEMUDriverGetCapabilities(driver, true);
}
/**
* virQEMUDriverGetDomainCapabilities:
*
* Get a reference to the virDomainCaps *instance. The caller
* must release the reference with virObjetUnref().
*
* Returns: a reference to a virDomainCaps *instance or NULL
*/
virDomainCaps *
virQEMUDriverGetDomainCapabilities(virQEMUDriver *driver,
virQEMUCaps *qemuCaps,
const char *machine,
virArch arch,
virDomainVirtType virttype)
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
g_autoptr(virDomainCaps) domCaps = NULL;
const char *path = virQEMUCapsGetBinary(qemuCaps);
if (!(domCaps = virDomainCapsNew(path, machine, arch, virttype)))
return NULL;
if (virQEMUCapsFillDomainCaps(qemuCaps, driver->hostarch,
domCaps, driver->privileged,
cfg->firmwares,
cfg->nfirmwares) < 0)
return NULL;
return g_steal_pointer(&domCaps);
}
int qemuDriverAllocateID(virQEMUDriver *driver)
{
return g_atomic_int_add(&driver->lastvmid, 1) + 1;
}
int
qemuTranslateSnapshotDiskSourcePool(virDomainSnapshotDiskDef *def)
{
if (def->src->type != VIR_STORAGE_TYPE_VOLUME)
return 0;
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Snapshots are not yet supported with 'pool' volumes"));
return -1;
}
char *
qemuGetBaseHugepagePath(virQEMUDriver *driver,
virHugeTLBFS *hugepage)
{
const char *root = driver->embeddedRoot;
if (root && !STRPREFIX(hugepage->mnt_dir, root)) {
g_autofree char * hash = virDomainDriverGenerateRootHash("qemu", root);
return g_strdup_printf("%s/libvirt/%s", hugepage->mnt_dir, hash);
}
return g_strdup_printf("%s/libvirt/qemu", hugepage->mnt_dir);
}
qemuBuildMemoryBackendStr: Don't crash if no hugetlbfs is mounted When trying to migrate a huge page enabled guest, I've noticed the following crash. Apparently, if no specific hugepages are requested: <memoryBacking> <hugepages/> </memoryBacking> and there are no hugepages configured on the destination, we try to dereference a NULL pointer. Program received signal SIGSEGV, Segmentation fault. 0x00007fcc907fb20e in qemuGetHugepagePath (hugepage=0x0) at qemu/qemu_conf.c:1447 1447 if (virAsprintf(&ret, "%s/libvirt/qemu", hugepage->mnt_dir) < 0) (gdb) bt #0 0x00007fcc907fb20e in qemuGetHugepagePath (hugepage=0x0) at qemu/qemu_conf.c:1447 #1 0x00007fcc907fb2f5 in qemuGetDefaultHugepath (hugetlbfs=0x0, nhugetlbfs=0) at qemu/qemu_conf.c:1466 #2 0x00007fcc907b4afa in qemuBuildMemoryBackendStr (size=4194304, pagesize=0, guestNode=0, userNodeset=0x0, autoNodeset=0x0, def=0x7fcc70019070, qemuCaps=0x7fcc70004000, cfg=0x7fcc5c011800, backendType=0x7fcc95087228, backendProps=0x7fcc95087218, force=false) at qemu/qemu_command.c:3297 #3 0x00007fcc907b4f91 in qemuBuildMemoryCellBackendStr (def=0x7fcc70019070, qemuCaps=0x7fcc70004000, cfg=0x7fcc5c011800, cell=0, auto_nodeset=0x0, backendStr=0x7fcc70020360) at qemu/qemu_command.c:3413 #4 0x00007fcc907c0406 in qemuBuildNumaArgStr (cfg=0x7fcc5c011800, def=0x7fcc70019070, cmd=0x7fcc700040c0, qemuCaps=0x7fcc70004000, auto_nodeset=0x0) at qemu/qemu_command.c:7470 #5 0x00007fcc907c5fdf in qemuBuildCommandLine (driver=0x7fcc5c07b8a0, logManager=0x7fcc70003c00, def=0x7fcc70019070, monitor_chr=0x7fcc70004bb0, monitor_json=true, qemuCaps=0x7fcc70004000, migrateURI=0x7fcc700199c0 "defer", snapshot=0x0, vmop=VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START, standalone=false, enableFips=false, nodeset=0x0, nnicindexes=0x7fcc95087498, nicindexes=0x7fcc950874a0, domainLibDir=0x7fcc700047c0 "/var/lib/libvirt/qemu/domain-1-fedora") at qemu/qemu_command.c:9547 Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2016-09-17 07:29:11 +00:00
char *
qemuGetDomainHugepagePath(virQEMUDriver *driver,
const virDomainDef *def,
virHugeTLBFS *hugepage)
{
g_autofree char *base = qemuGetBaseHugepagePath(driver, hugepage);
g_autofree char *domPath = virDomainDefGetShortName(def);
if (!base || !domPath)
return NULL;
return g_strdup_printf("%s/%s", base, domPath);
}
/**
* qemuGetDomainHupageMemPath: Construct HP enabled memory backend path
*
* The resulting path is stored at @memPath.
*
* Returns 0 on success,
* -1 otherwise.
*/
int
qemuGetDomainHupageMemPath(virQEMUDriver *driver,
const virDomainDef *def,
unsigned long long pagesize,
char **memPath)
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
size_t i = 0;
if (!cfg->nhugetlbfs) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("hugetlbfs filesystem is not mounted "
"or disabled by administrator config"));
return -1;
}
for (i = 0; i < cfg->nhugetlbfs; i++) {
if (cfg->hugetlbfs[i].size == pagesize)
break;
}
if (i == cfg->nhugetlbfs) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find any usable hugetlbfs "
"mount for %llu KiB"),
pagesize);
return -1;
}
if (!(*memPath = qemuGetDomainHugepagePath(driver, def, &cfg->hugetlbfs[i])))
return -1;
return 0;
}
int
qemuGetMemoryBackingDomainPath(virQEMUDriver *driver,
const virDomainDef *def,
char **path)
{
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
const char *root = driver->embeddedRoot;
g_autofree char *shortName = NULL;
if (!(shortName = virDomainDefGetShortName(def)))
return -1;
if (root && !STRPREFIX(cfg->memoryBackingDir, root)) {
g_autofree char * hash = virDomainDriverGenerateRootHash("qemu", root);
*path = g_strdup_printf("%s/%s-%s", cfg->memoryBackingDir, hash, shortName);
} else {
*path = g_strdup_printf("%s/%s", cfg->memoryBackingDir, shortName);
}
return 0;
}
/**
* qemuGetMemoryBackingPath:
* @driver: the qemu driver
* @def: domain definition
* @alias: memory object alias
* @memPath: constructed path
*
* Constructs path to memory backing dir and stores it at @memPath.
*
* Returns: 0 on success,
* -1 otherwise (with error reported).
*/
int
qemuGetMemoryBackingPath(virQEMUDriver *driver,
const virDomainDef *def,
const char *alias,
char **memPath)
{
g_autofree char *domainPath = NULL;
if (!alias) {
/* This should never happen (TM) */
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("memory device alias is not assigned"));
return -1;
}
if (qemuGetMemoryBackingDomainPath(driver, def, &domainPath) < 0)
return -1;
*memPath = g_strdup_printf("%s/%s", domainPath, alias);
return 0;
}