2007-02-14 01:40:09 +00:00
|
|
|
/*
|
2009-05-21 14:16:55 +00:00
|
|
|
* qemu_conf.c: QEMU configuration management
|
2007-02-14 01:40:09 +00:00
|
|
|
*
|
conf: use disk source accessors in qemu/
Part of a series of cleanups to use new accessor methods.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuAddSharedDevice, qemuRemoveSharedDevice, qemuSetUnprivSGIO):
Use accessors.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainObjCheckDiskTaint, qemuDomainSnapshotForEachQcow2Raw)
(qemuDomainCheckRemoveOptionalDisk, qemuDomainCheckDiskPresence)
(qemuDiskChainCheckBroken, qemuDomainDetermineDiskChain):
Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia)
(qemuDomainCheckEjectableMedia)
(qemuDomainAttachVirtioDiskDevice, qemuDomainAttachSCSIDisk)
(qemuDomainAttachUSBMassstorageDevice)
(qemuDomainAttachDeviceDiskLive, qemuDomainRemoveDiskDevice)
(qemuDomainDetachVirtioDiskDevice, qemuDomainDetachDiskDevice):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationStartNBDServer)
(qemuMigrationDriveMirror, qemuMigrationCancelDriveMirror)
(qemuMigrationIsSafe): Likewise.
* src/qemu/qemu_process.c (qemuProcessGetVolumeQcowPassphrase)
(qemuProcessHandleIOError, qemuProcessHandleBlockJob)
(qemuProcessInitPasswords): Likewise.
* src/qemu/qemu_driver.c (qemuDomainChangeDiskMediaLive)
(qemuDomainGetBlockInfo, qemuDiskPathToAlias): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-18 19:16:47 +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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2007-02-14 01:40:09 +00:00
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2007-11-26 11:50:16 +00:00
|
|
|
|
2007-02-14 01:40:09 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2007-06-27 00:12:29 +00:00
|
|
|
#include "qemu_conf.h"
|
2010-12-16 15:07:07 +00:00
|
|
|
#include "qemu_capabilities.h"
|
2016-02-10 14:43:57 +00:00
|
|
|
#include "qemu_domain.h"
|
2019-11-11 16:22:50 +00:00
|
|
|
#include "qemu_firmware.h"
|
2020-07-20 14:18:57 +00:00
|
|
|
#include "qemu_namespace.h"
|
2017-02-13 13:36:53 +00:00
|
|
|
#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"
|
2009-12-18 15:24:14 +00:00
|
|
|
#include "cpu/cpu.h"
|
2020-03-20 18:27:26 +00:00
|
|
|
#include "domain_driver.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2013-01-10 21:03:14 +00:00
|
|
|
#include "virstring.h"
|
2020-02-16 21:59:28 +00:00
|
|
|
#include "virutil.h"
|
2010-11-16 14:54:17 +00:00
|
|
|
#include "configmake.h"
|
2020-11-03 12:26:22 +00:00
|
|
|
#include "security/security_util.h"
|
2008-07-11 19:34:11 +00:00
|
|
|
|
2009-01-23 16:22:20 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_QEMU
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("qemu.qemu_conf");
|
|
|
|
|
2016-02-10 14:43:57 +00:00
|
|
|
/* 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
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static virClass *virQEMUDriverConfigClass;
|
2013-01-10 21:03:14 +00:00
|
|
|
static void virQEMUDriverConfigDispose(void *obj);
|
|
|
|
|
|
|
|
static int virQEMUConfigOnceInit(void)
|
|
|
|
{
|
2018-04-17 15:42:33 +00:00
|
|
|
if (!VIR_CLASS_NEW(virQEMUDriverConfig, virClassForObject()))
|
2013-02-15 12:05:12 +00:00
|
|
|
return -1;
|
2018-04-17 15:42:33 +00:00
|
|
|
|
|
|
|
return 0;
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:23:29 +00:00
|
|
|
VIR_ONCE_GLOBAL_INIT(virQEMUConfig);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
|
2017-07-21 10:09:58 +00:00
|
|
|
#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:" \
|
2017-07-20 19:56:55 +00:00
|
|
|
"/usr/share/AAVMF/AAVMF_CODE.fd:/usr/share/AAVMF/AAVMF_VARS.fd:" \
|
|
|
|
"/usr/share/AAVMF/AAVMF32_CODE.fd:/usr/share/AAVMF/AAVMF32_VARS.fd"
|
2017-07-21 10:09:58 +00:00
|
|
|
#endif
|
|
|
|
|
2014-08-07 14:59:21 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
|
2019-05-17 11:35:57 +00:00
|
|
|
const char *root)
|
2013-01-10 21:03:14 +00:00
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = NULL;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
if (virQEMUConfigInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(cfg = virObjectNew(virQEMUDriverConfigClass)))
|
|
|
|
return NULL;
|
|
|
|
|
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");
|
|
|
|
}
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
if (privileged) {
|
|
|
|
if (virGetUserID(QEMU_USER, &cfg->user) < 0)
|
2019-09-09 15:14:25 +00:00
|
|
|
return NULL;
|
2013-01-10 21:03:14 +00:00
|
|
|
if (virGetGroupID(QEMU_GROUP, &cfg->group) < 0)
|
2019-09-09 15:14:25 +00:00
|
|
|
return NULL;
|
2013-01-10 21:03:14 +00:00
|
|
|
} else {
|
2013-03-02 14:19:47 +00:00
|
|
|
cfg->user = (uid_t)-1;
|
|
|
|
cfg->group = (gid_t)-1;
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
cfg->dynamicOwnership = privileged;
|
2020-11-03 12:26:22 +00:00
|
|
|
|
|
|
|
if (privileged)
|
|
|
|
cfg->rememberOwner = virSecurityXATTRNamespaceDefined();
|
|
|
|
else
|
|
|
|
cfg->rememberOwner = false;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2013-03-21 13:27:13 +00:00
|
|
|
cfg->cgroupControllers = -1; /* -1 == auto-detect */
|
2013-01-10 21:03:14 +00:00
|
|
|
|
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) {
|
2019-10-22 13:26:14 +00:00
|
|
|
cfg->logDir = g_strdup_printf("%s/log/libvirt/qemu", LOCALSTATEDIR);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
cfg->swtpmLogDir = g_strdup_printf("%s/log/swtpm/libvirt/qemu",
|
|
|
|
LOCALSTATEDIR);
|
2017-04-04 16:22:31 +00:00
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
cfg->configBaseDir = g_strdup(SYSCONFDIR "/libvirt");
|
2007-10-12 16:05:44 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
cfg->stateDir = g_strdup_printf("%s/libvirt/qemu", RUNSTATEDIR);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
cfg->swtpmStateDir = g_strdup_printf("%s/libvirt/qemu/swtpm", RUNSTATEDIR);
|
2017-04-04 16:22:31 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
cfg->cacheDir = g_strdup_printf("%s/cache/libvirt/qemu", LOCALSTATEDIR);
|
2015-04-24 00:16:30 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
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);
|
2018-11-19 21:25:21 +00:00
|
|
|
if (!virDoesUserExist("tss") ||
|
2018-09-12 14:32:56 +00:00
|
|
|
virGetUserID("tss", &cfg->swtpm_user) < 0)
|
2017-04-04 16:22:31 +00:00
|
|
|
cfg->swtpm_user = 0; /* fall back to root */
|
2018-11-19 21:25:21 +00:00
|
|
|
if (!virDoesGroupExist("tss") ||
|
2018-09-12 14:32:56 +00:00
|
|
|
virGetGroupID("tss", &cfg->swtpm_group) < 0)
|
2017-04-04 16:22:31 +00:00
|
|
|
cfg->swtpm_group = 0; /* fall back to root */
|
2013-01-10 21:03:14 +00:00
|
|
|
} else {
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *rundir = NULL;
|
|
|
|
g_autofree char *cachedir = NULL;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
cachedir = virGetUserCacheDirectory();
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
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);
|
2010-01-13 17:41:36 +00:00
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
rundir = virGetUserRuntimeDirectory();
|
2019-10-22 13:26:14 +00:00
|
|
|
cfg->stateDir = g_strdup_printf("%s/qemu/run", rundir);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
cfg->swtpmStateDir = g_strdup_printf("%s/swtpm", cfg->stateDir);
|
2017-04-04 16:22:31 +00:00
|
|
|
|
2019-12-19 08:39:26 +00:00
|
|
|
cfg->configBaseDir = virGetUserConfigDirectory();
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
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);
|
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 {
|
2017-04-04 16:22:31 +00:00
|
|
|
cfg->swtpm_user = (uid_t)-1;
|
|
|
|
cfg->swtpm_group = (gid_t)-1;
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
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);
|
2020-02-25 09:55:07 +00:00
|
|
|
cfg->dbusStateDir = g_strdup_printf("%s/dbus", cfg->stateDir);
|
2012-06-18 08:22:07 +00:00
|
|
|
|
2016-06-14 18:14:31 +00:00
|
|
|
/* 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).
|
|
|
|
*/
|
2019-05-17 11:35:57 +00:00
|
|
|
if (root == NULL) {
|
2020-06-16 10:36:55 +00:00
|
|
|
cfg->defaultTLSx509certdir = g_strdup(SYSCONFDIR "/pki/qemu");
|
2019-05-17 11:35:57 +00:00
|
|
|
} else {
|
|
|
|
cfg->defaultTLSx509certdir = g_strdup_printf("%s/etc/pki/qemu", root);
|
|
|
|
}
|
2012-11-29 11:25:07 +00:00
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
cfg->vncListen = g_strdup(VIR_LOOPBACK_IPV4_ADDR);
|
|
|
|
cfg->spiceListen = g_strdup(VIR_LOOPBACK_IPV4_ADDR);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
cfg->remotePortMin = QEMU_REMOTE_PORT_MIN;
|
|
|
|
cfg->remotePortMax = QEMU_REMOTE_PORT_MAX;
|
|
|
|
|
2013-04-30 14:26:43 +00:00
|
|
|
cfg->webSocketPortMin = QEMU_WEBSOCKET_PORT_MIN;
|
|
|
|
cfg->webSocketPortMax = QEMU_WEBSOCKET_PORT_MAX;
|
|
|
|
|
2013-10-15 13:26:52 +00:00
|
|
|
cfg->migrationPortMin = QEMU_MIGRATION_PORT_MIN;
|
|
|
|
cfg->migrationPortMax = QEMU_MIGRATION_PORT_MAX;
|
|
|
|
|
2014-07-23 15:37:18 +00:00
|
|
|
/* For privileged driver, try and find hugetlbfs mounts automatically.
|
Support configuration of huge pages in guests
Add option to domain XML for
<memoryBacking>
<hugepages/>
</memoryBacking>
* configure.in: Add check for mntent.h
* qemud/libvirtd_qemu.aug, qemud/test_libvirtd_qemu.aug, src/qemu.conf
Add 'hugetlbfs_mount' config parameter
* src/qemu_conf.c, src/qemu_conf.h: Check for -mem-path flag in QEMU,
and pass it when hugepages are requested.
Load hugetlbfs_mount config parameter, search for mount if not given.
* src/qemu_driver.c: Free hugetlbfs_mount/path parameter in driver shutdown.
Create directory for QEMU hugepage usage, chowning if required.
* docs/formatdomain.html.in: Document memoryBacking/hugepages elements
* docs/schemas/domain.rng: Add memoryBacking/hugepages elements to schema
* src/util.c, src/util.h, src/libvirt_private.syms: Add virFileFindMountPoint
helper API
* tests/qemuhelptest.c: Add -mem-path constants
* tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c: Add tests for hugepage
handling
* tests/qemuxml2argvdata/qemuxml2argv-hugepages.xml,
tests/qemuxml2argvdata/qemuxml2argv-hugepages.args: Data files for
hugepage tests
2009-08-25 14:05:18 +00:00
|
|
|
* Non-privileged driver requires admin to create a dir for the
|
2014-07-23 15:37:18 +00:00
|
|
|
* user, chown it, and then let user configure it manually. */
|
2013-01-10 21:03:14 +00:00
|
|
|
if (privileged &&
|
2014-07-23 15:37:18 +00:00
|
|
|
virFileFindHugeTLBFS(&cfg->hugetlbfs, &cfg->nhugetlbfs) < 0) {
|
|
|
|
/* This however is not implemented on all platforms. */
|
2018-05-05 12:04:21 +00:00
|
|
|
if (virGetLastErrorCode() != VIR_ERR_NO_SUPPORT)
|
2019-09-09 15:14:25 +00:00
|
|
|
return NULL;
|
Support configuration of huge pages in guests
Add option to domain XML for
<memoryBacking>
<hugepages/>
</memoryBacking>
* configure.in: Add check for mntent.h
* qemud/libvirtd_qemu.aug, qemud/test_libvirtd_qemu.aug, src/qemu.conf
Add 'hugetlbfs_mount' config parameter
* src/qemu_conf.c, src/qemu_conf.h: Check for -mem-path flag in QEMU,
and pass it when hugepages are requested.
Load hugetlbfs_mount config parameter, search for mount if not given.
* src/qemu_driver.c: Free hugetlbfs_mount/path parameter in driver shutdown.
Create directory for QEMU hugepage usage, chowning if required.
* docs/formatdomain.html.in: Document memoryBacking/hugepages elements
* docs/schemas/domain.rng: Add memoryBacking/hugepages elements to schema
* src/util.c, src/util.h, src/libvirt_private.syms: Add virFileFindMountPoint
helper API
* tests/qemuhelptest.c: Add -mem-path constants
* tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c: Add tests for hugepage
handling
* tests/qemuxml2argvdata/qemuxml2argv-hugepages.xml,
tests/qemuxml2argvdata/qemuxml2argv-hugepages.args: Data files for
hugepage tests
2009-08-25 14:05:18 +00:00
|
|
|
}
|
2014-07-23 15:37:18 +00:00
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
cfg->bridgeHelperName = g_strdup(QEMU_BRIDGE_HELPER);
|
|
|
|
cfg->prHelperName = g_strdup(QEMU_PR_HELPER);
|
|
|
|
cfg->slirpHelperName = g_strdup(QEMU_SLIRP_HELPER);
|
2020-02-25 09:55:06 +00:00
|
|
|
cfg->dbusDaemonName = g_strdup(QEMU_DBUS_DAEMON);
|
Support configuration of huge pages in guests
Add option to domain XML for
<memoryBacking>
<hugepages/>
</memoryBacking>
* configure.in: Add check for mntent.h
* qemud/libvirtd_qemu.aug, qemud/test_libvirtd_qemu.aug, src/qemu.conf
Add 'hugetlbfs_mount' config parameter
* src/qemu_conf.c, src/qemu_conf.h: Check for -mem-path flag in QEMU,
and pass it when hugepages are requested.
Load hugetlbfs_mount config parameter, search for mount if not given.
* src/qemu_driver.c: Free hugetlbfs_mount/path parameter in driver shutdown.
Create directory for QEMU hugepage usage, chowning if required.
* docs/formatdomain.html.in: Document memoryBacking/hugepages elements
* docs/schemas/domain.rng: Add memoryBacking/hugepages elements to schema
* src/util.c, src/util.h, src/libvirt_private.syms: Add virFileFindMountPoint
helper API
* tests/qemuhelptest.c: Add -mem-path constants
* tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c: Add tests for hugepage
handling
* tests/qemuxml2argvdata/qemuxml2argv-hugepages.xml,
tests/qemuxml2argvdata/qemuxml2argv-hugepages.args: Data files for
hugepage tests
2009-08-25 14:05:18 +00:00
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
cfg->securityDefaultConfined = true;
|
|
|
|
cfg->securityRequireConfined = false;
|
|
|
|
|
|
|
|
cfg->keepAliveInterval = 5;
|
|
|
|
cfg->keepAliveCount = 5;
|
|
|
|
cfg->seccompSandbox = -1;
|
|
|
|
|
2014-04-09 13:23:45 +00:00
|
|
|
cfg->logTimestamp = true;
|
2016-09-21 19:34:18 +00:00
|
|
|
cfg->glusterDebugLevel = 4;
|
2016-04-27 10:58:13 +00:00
|
|
|
cfg->stdioLogD = true;
|
2014-04-09 13:23:45 +00:00
|
|
|
|
2020-10-01 15:42:11 +00:00
|
|
|
cfg->namespaces = virBitmapNew(QEMU_DOMAIN_NS_LAST);
|
2016-11-18 15:34:45 +00:00
|
|
|
|
2017-01-11 10:05:50 +00:00
|
|
|
if (privileged &&
|
2017-02-15 09:06:09 +00:00
|
|
|
qemuDomainNamespaceAvailable(QEMU_DOMAIN_NS_MOUNT) &&
|
2017-01-11 10:05:50 +00:00
|
|
|
virBitmapSetBit(cfg->namespaces, QEMU_DOMAIN_NS_MOUNT) < 0)
|
2019-09-09 15:14:25 +00:00
|
|
|
return NULL;
|
2016-11-18 15:34:45 +00:00
|
|
|
|
2016-05-17 22:45:27 +00:00
|
|
|
if (virFirmwareParseList(DEFAULT_LOADER_NVRAM,
|
|
|
|
&cfg->firmwares,
|
|
|
|
&cfg->nfirmwares) < 0)
|
2019-09-09 15:14:25 +00:00
|
|
|
return NULL;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2021-04-12 20:55:02 +00:00
|
|
|
cfg->deprecationBehavior = g_strdup("none");
|
|
|
|
|
2019-10-16 11:35:54 +00:00
|
|
|
return g_steal_pointer(&cfg);
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void virQEMUDriverConfigDispose(void *obj)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfig *cfg = obj;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2016-11-18 15:34:45 +00:00
|
|
|
virBitmapFree(cfg->namespaces);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2020-08-02 17:36:03 +00:00
|
|
|
g_strfreev(cfg->cgroupDeviceACL);
|
2021-02-03 20:13:53 +00:00
|
|
|
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);
|
2020-06-26 14:37:16 +00:00
|
|
|
|
2014-07-23 15:37:18 +00:00
|
|
|
while (cfg->nhugetlbfs) {
|
|
|
|
cfg->nhugetlbfs--;
|
2021-02-03 20:13:53 +00:00
|
|
|
g_free(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir);
|
2014-07-23 15:37:18 +00:00
|
|
|
}
|
2021-02-03 20:13:53 +00:00
|
|
|
g_free(cfg->hugetlbfs);
|
|
|
|
g_free(cfg->bridgeHelperName);
|
|
|
|
g_free(cfg->prHelperName);
|
|
|
|
g_free(cfg->slirpHelperName);
|
|
|
|
g_free(cfg->dbusDaemonName);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2021-02-03 20:13:53 +00:00
|
|
|
g_free(cfg->saveImageFormat);
|
|
|
|
g_free(cfg->dumpImageFormat);
|
|
|
|
g_free(cfg->snapshotImageFormat);
|
|
|
|
g_free(cfg->autoDumpPath);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2020-08-02 17:36:03 +00:00
|
|
|
g_strfreev(cfg->securityDriverNames);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2021-02-03 20:13:53 +00:00
|
|
|
g_free(cfg->lockManagerName);
|
2014-08-07 14:59:21 +00:00
|
|
|
|
2016-05-17 22:45:27 +00:00
|
|
|
virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
|
2017-02-02 13:27:31 +00:00
|
|
|
|
2021-02-03 20:13:53 +00:00
|
|
|
g_free(cfg->memoryBackingDir);
|
|
|
|
g_free(cfg->swtpmStorageDir);
|
2019-06-18 07:46:22 +00:00
|
|
|
|
2020-08-02 17:36:03 +00:00
|
|
|
g_strfreev(cfg->capabilityfilters);
|
2020-04-30 11:27:58 +00:00
|
|
|
|
|
|
|
g_free(cfg->deprecationBehavior);
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
|
Support configuration of huge pages in guests
Add option to domain XML for
<memoryBacking>
<hugepages/>
</memoryBacking>
* configure.in: Add check for mntent.h
* qemud/libvirtd_qemu.aug, qemud/test_libvirtd_qemu.aug, src/qemu.conf
Add 'hugetlbfs_mount' config parameter
* src/qemu_conf.c, src/qemu_conf.h: Check for -mem-path flag in QEMU,
and pass it when hugepages are requested.
Load hugetlbfs_mount config parameter, search for mount if not given.
* src/qemu_driver.c: Free hugetlbfs_mount/path parameter in driver shutdown.
Create directory for QEMU hugepage usage, chowning if required.
* docs/formatdomain.html.in: Document memoryBacking/hugepages elements
* docs/schemas/domain.rng: Add memoryBacking/hugepages elements to schema
* src/util.c, src/util.h, src/libvirt_private.syms: Add virFileFindMountPoint
helper API
* tests/qemuhelptest.c: Add -mem-path constants
* tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c: Add tests for hugepage
handling
* tests/qemuxml2argvdata/qemuxml2argv-hugepages.xml,
tests/qemuxml2argvdata/qemuxml2argv-hugepages.args: Data files for
hugepage tests
2009-08-25 14:05:18 +00:00
|
|
|
|
2014-07-23 15:37:18 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigHugeTLBFSInit(virHugeTLBFS *hugetlbfs,
|
2014-07-23 15:37:18 +00:00
|
|
|
const char *path,
|
|
|
|
bool deflt)
|
|
|
|
{
|
2019-10-20 11:49:46 +00:00
|
|
|
hugetlbfs->mnt_dir = g_strdup(path);
|
|
|
|
if (virFileGetHugepageSize(path, &hugetlbfs->size) < 0)
|
2019-09-09 15:24:22 +00:00
|
|
|
return -1;
|
2014-07-23 15:37:18 +00:00
|
|
|
|
|
|
|
hugetlbfs->deflt = deflt;
|
2019-09-09 15:24:22 +00:00
|
|
|
return 0;
|
2014-07-23 15:37:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 21:24:17 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadDefaultTLSEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-14 21:24:17 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
if ((rv = virConfGetValueString(conf, "default_tls_x509_cert_dir", &cfg->defaultTLSx509certdir)) < 0)
|
|
|
|
return -1;
|
2019-01-14 22:57:12 +00:00
|
|
|
cfg->defaultTLSx509certdirPresent = (rv == 1);
|
2020-11-13 14:13:29 +00:00
|
|
|
if ((rv = virConfGetValueBool(conf, "default_tls_x509_verify", &cfg->defaultTLSx509verify)) < 0)
|
2019-01-14 21:24:17 +00:00
|
|
|
return -1;
|
2020-11-13 14:13:29 +00:00
|
|
|
if (rv == 1)
|
|
|
|
cfg->defaultTLSx509verifyPresent = true;
|
2019-01-14 21:24:17 +00:00
|
|
|
if (virConfGetValueString(conf, "default_tls_x509_secret_uuid",
|
|
|
|
&cfg->defaultTLSx509secretUUID) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 21:15:40 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadVNCEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-14 21:15:40 +00:00
|
|
|
{
|
|
|
|
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;
|
2019-01-14 23:09:23 +00:00
|
|
|
if (virConfGetValueString(conf, "vnc_tls_x509_secret_uuid", &cfg->vncTLSx509secretUUID) < 0)
|
|
|
|
return -1;
|
2019-01-14 21:15:40 +00:00
|
|
|
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;
|
|
|
|
|
2021-12-16 10:20:37 +00:00
|
|
|
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';
|
|
|
|
}
|
2019-01-14 21:15:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:23:06 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadNographicsEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-15 09:23:06 +00:00
|
|
|
{
|
|
|
|
return virConfGetValueBool(conf, "nographics_allow_host_audio", &cfg->nogfxAllowHostAudio);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:51:51 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadSPICEEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-15 09:51:51 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 21:03:05 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadSpecificTLSEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-14 21:03:05 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "vxhs_tls", &cfg->vxhsTLS) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virConfGetValueBool(conf, "nbd_tls", &cfg->nbdTLS) < 0)
|
|
|
|
return -1;
|
2020-06-30 15:51:50 +00:00
|
|
|
if (virConfGetValueBool(conf, "chardev_tls", &cfg->chardevTLS) < 0)
|
|
|
|
return -1;
|
2020-11-24 13:08:04 +00:00
|
|
|
if (virConfGetValueBool(conf, "migrate_tls_force", &cfg->migrateTLSForce) < 0)
|
|
|
|
return -1;
|
2019-01-14 21:03:05 +00:00
|
|
|
|
2020-06-30 15:56:08 +00:00
|
|
|
#define GET_CONFIG_TLS_CERTINFO_COMMON(val) \
|
2019-01-14 21:03:05 +00:00
|
|
|
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)
|
|
|
|
|
2020-06-30 15:56:08 +00:00
|
|
|
#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);
|
2019-01-14 21:03:05 +00:00
|
|
|
|
2020-06-30 15:56:08 +00:00
|
|
|
GET_CONFIG_TLS_CERTINFO_COMMON(migrate);
|
|
|
|
GET_CONFIG_TLS_CERTINFO_SERVER(migrate);
|
2019-01-14 21:03:05 +00:00
|
|
|
|
2020-06-26 14:37:16 +00:00
|
|
|
GET_CONFIG_TLS_CERTINFO_COMMON(backup);
|
|
|
|
GET_CONFIG_TLS_CERTINFO_SERVER(backup);
|
|
|
|
|
2020-06-29 15:12:03 +00:00
|
|
|
GET_CONFIG_TLS_CERTINFO_COMMON(vxhs);
|
|
|
|
|
|
|
|
GET_CONFIG_TLS_CERTINFO_COMMON(nbd);
|
|
|
|
|
2020-06-30 15:56:08 +00:00
|
|
|
#undef GET_CONFIG_TLS_CERTINFO_COMMON
|
|
|
|
#undef GET_CONFIG_TLS_CERTINFO_SERVER
|
2019-01-14 21:03:05 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 20:53:01 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadRemoteDisplayEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf,
|
2019-01-14 20:53:01 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:24:02 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadSaveEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-15 11:24:02 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:35:59 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadProcessEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-15 11:35:59 +00:00
|
|
|
{
|
2020-12-01 08:21:32 +00:00
|
|
|
g_auto(GStrv) hugetlbfs = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *stdioHandler = NULL;
|
|
|
|
g_autofree char *corestr = NULL;
|
2019-01-15 11:35:59 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "hugetlbfs_mount", true,
|
|
|
|
&hugetlbfs) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
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);
|
|
|
|
|
2021-02-05 17:03:26 +00:00
|
|
|
cfg->nhugetlbfs = g_strv_length(hugetlbfs);
|
2020-10-05 10:28:26 +00:00
|
|
|
if (hugetlbfs[0])
|
|
|
|
cfg->hugetlbfs = g_new0(virHugeTLBFS, cfg->nhugetlbfs);
|
2019-01-15 11:35:59 +00:00
|
|
|
|
|
|
|
for (i = 0; hugetlbfs[i] != NULL; i++) {
|
|
|
|
if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[i],
|
|
|
|
hugetlbfs[i], i != 0) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "bridge_helper", &cfg->bridgeHelperName) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "pr_helper", &cfg->prHelperName) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
|
2019-08-08 14:55:03 +00:00
|
|
|
if (virConfGetValueString(conf, "slirp_helper", &cfg->slirpHelperName) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2020-02-25 09:55:06 +00:00
|
|
|
if (virConfGetValueString(conf, "dbus_daemon", &cfg->dbusDaemonName) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2019-01-15 11:35:59 +00:00
|
|
|
if (virConfGetValueBool(conf, "set_process_name", &cfg->setProcessName) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
if (virConfGetValueUInt(conf, "max_processes", &cfg->maxProcesses) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
if (virConfGetValueUInt(conf, "max_files", &cfg->maxFiles) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-05-22 23:12:14 +00:00
|
|
|
if (virConfGetValueUInt(conf, "max_threads_per_process", &cfg->maxThreadsPerProc) < 0)
|
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
|
|
|
|
if (virConfGetValueType(conf, "max_core") == VIR_CONF_STRING) {
|
|
|
|
if (virConfGetValueString(conf, "max_core", &corestr) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
if (STREQ(corestr, "unlimited")) {
|
|
|
|
cfg->maxCore = ULLONG_MAX;
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Unknown core size '%s'"),
|
|
|
|
corestr);
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
}
|
|
|
|
} else if (virConfGetValueULLong(conf, "max_core", &cfg->maxCore) < 0) {
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "dump_guest_core", &cfg->dumpGuestCore) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
if (virConfGetValueString(conf, "stdio_handler", &stdioHandler) < 0)
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
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);
|
2019-01-21 13:47:34 +00:00
|
|
|
return -1;
|
2019-01-15 11:35:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-21 13:47:34 +00:00
|
|
|
return 0;
|
2019-01-15 11:35:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:33:26 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadDeviceEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-15 11:33:26 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:33:07 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadRPCEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-15 11:33:07 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:32:40 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadNetworkEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf,
|
2019-01-15 11:32:40 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:18:04 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadLogEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-15 09:18:04 +00:00
|
|
|
{
|
|
|
|
return virConfGetValueBool(conf, "log_timestamp", &cfg->logTimestamp);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:17:00 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadNVRAMEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf,
|
2019-11-11 16:22:50 +00:00
|
|
|
bool privileged)
|
2019-01-15 09:17:00 +00:00
|
|
|
{
|
2020-12-01 08:21:32 +00:00
|
|
|
g_auto(GStrv) nvram = NULL;
|
2019-01-15 09:17:00 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "nvram", false, &nvram) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-15 09:17:00 +00:00
|
|
|
if (nvram) {
|
2020-12-01 08:21:32 +00:00
|
|
|
g_auto(GStrv) fwList = NULL;
|
2019-11-11 16:22:50 +00:00
|
|
|
|
2019-01-15 09:17:00 +00:00
|
|
|
virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
|
2020-11-24 03:12:00 +00:00
|
|
|
cfg->firmwares = NULL;
|
2020-12-02 12:43:21 +00:00
|
|
|
cfg->nfirmwares = 0;
|
2019-01-15 09:17:00 +00:00
|
|
|
|
2019-11-11 16:22:50 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-02-05 17:03:26 +00:00
|
|
|
cfg->nfirmwares = g_strv_length(nvram);
|
2021-03-11 07:16:13 +00:00
|
|
|
cfg->firmwares = g_new0(virFirmware *, cfg->nfirmwares);
|
2019-01-15 09:17:00 +00:00
|
|
|
|
|
|
|
for (i = 0; nvram[i] != NULL; i++) {
|
2020-10-05 10:28:26 +00:00
|
|
|
cfg->firmwares[i] = g_new0(virFirmware, 1);
|
2019-01-15 09:17:00 +00:00
|
|
|
if (virFirmwareParse(nvram[i], cfg->firmwares[i]) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-15 09:17:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-21 13:48:18 +00:00
|
|
|
return 0;
|
2019-01-15 09:17:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:14:44 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadDebugEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-15 09:14:44 +00:00
|
|
|
{
|
2019-12-11 21:22:31 +00:00
|
|
|
if (virConfGetValueUInt(conf, "gluster_debug_level", &cfg->glusterDebugLevel) < 0)
|
|
|
|
return -1;
|
2019-12-11 21:30:06 +00:00
|
|
|
if (virConfGetValueBool(conf, "virtiofsd_debug", &cfg->virtiofsdDebug) < 0)
|
|
|
|
return -1;
|
2020-04-30 11:27:58 +00:00
|
|
|
if (virConfGetValueString(conf, "deprecation_behavior", &cfg->deprecationBehavior) < 0)
|
|
|
|
return -1;
|
2019-12-11 21:22:31 +00:00
|
|
|
|
|
|
|
return 0;
|
2019-01-15 09:14:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 20:28:57 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadSecurityEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf,
|
2019-01-14 20:28:57 +00:00
|
|
|
bool privileged)
|
|
|
|
{
|
2020-12-01 08:21:32 +00:00
|
|
|
g_auto(GStrv) controllers = NULL;
|
|
|
|
g_auto(GStrv) namespaces = NULL;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *user = NULL;
|
|
|
|
g_autofree char *group = NULL;
|
2019-01-14 20:28:57 +00:00
|
|
|
size_t i, j;
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "security_driver", true, &cfg->securityDriverNames) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
|
|
|
|
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]);
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "security_default_confined", &cfg->securityDefaultConfined) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
if (virConfGetValueBool(conf, "security_require_confined", &cfg->securityRequireConfined) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "user", &user) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
if (user && virGetUserID(user, &cfg->user) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "group", &group) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
if (group && virGetGroupID(group, &cfg->group) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "dynamic_ownership", &cfg->dynamicOwnership) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
|
2019-01-15 08:50:58 +00:00
|
|
|
if (virConfGetValueBool(conf, "remember_owner", &cfg->rememberOwner) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2019-01-14 20:28:57 +00:00
|
|
|
if (virConfGetValueStringList(conf, "cgroup_controllers", false,
|
|
|
|
&controllers) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
|
|
|
|
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]);
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
}
|
|
|
|
cfg->cgroupControllers |= (1 << ctl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "cgroup_device_acl", false,
|
|
|
|
&cfg->cgroupDeviceACL) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
|
|
|
|
if (virConfGetValueInt(conf, "seccomp_sandbox", &cfg->seccompSandbox) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "namespaces", false, &namespaces) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
|
|
|
|
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]);
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!privileged) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("cannot use namespaces in session mode"));
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!qemuDomainNamespaceAvailable(ns)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("%s namespace is not available"),
|
|
|
|
namespaces[i]);
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virBitmapSetBit(cfg->namespaces, ns) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to enable namespace: %s"),
|
|
|
|
namespaces[i]);
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:28:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-21 13:48:18 +00:00
|
|
|
return 0;
|
2019-01-14 20:28:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:10:36 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadMemoryEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-15 09:10:36 +00:00
|
|
|
{
|
2020-05-18 13:23:09 +00:00
|
|
|
g_autofree char *dir = NULL;
|
2020-03-26 09:46:41 +00:00
|
|
|
int rc;
|
|
|
|
|
2021-11-23 17:20:10 +00:00
|
|
|
if ((rc = virConfGetValueString(conf, "memory_backing_dir", &dir)) < 0)
|
2020-03-26 09:46:41 +00:00
|
|
|
return -1;
|
2021-11-23 17:20:10 +00:00
|
|
|
|
|
|
|
if (rc > 0) {
|
2020-03-26 09:46:41 +00:00
|
|
|
VIR_FREE(cfg->memoryBackingDir);
|
|
|
|
cfg->memoryBackingDir = g_strdup_printf("%s/libvirt/qemu", dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2019-01-15 09:10:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 20:18:44 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadSWTPMEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-01-14 20:18:44 +00:00
|
|
|
{
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *swtpm_user = NULL;
|
|
|
|
g_autofree char *swtpm_group = NULL;
|
2019-01-14 20:18:44 +00:00
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "swtpm_user", &swtpm_user) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:18:44 +00:00
|
|
|
if (swtpm_user && virGetUserID(swtpm_user, &cfg->swtpm_user) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:18:44 +00:00
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "swtpm_group", &swtpm_group) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:18:44 +00:00
|
|
|
if (swtpm_group && virGetGroupID(swtpm_group, &cfg->swtpm_group) < 0)
|
2019-01-21 13:48:18 +00:00
|
|
|
return -1;
|
2019-01-14 20:18:44 +00:00
|
|
|
|
2019-01-21 13:48:18 +00:00
|
|
|
return 0;
|
2019-01-14 20:18:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-18 07:46:22 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigLoadCapsFiltersEntry(virQEMUDriverConfig *cfg,
|
|
|
|
virConf *conf)
|
2019-06-18 07:46:22 +00:00
|
|
|
{
|
|
|
|
if (virConfGetValueStringList(conf, "capability_filters", false,
|
|
|
|
&cfg->capabilityfilters) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
int virQEMUDriverConfigLoadFile(virQEMUDriverConfig *cfg,
|
2017-02-15 09:06:09 +00:00
|
|
|
const char *filename,
|
|
|
|
bool privileged)
|
2013-01-10 21:03:14 +00:00
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virConf) conf = NULL;
|
2011-09-16 11:50:56 +00:00
|
|
|
|
2007-10-12 16:05:44 +00:00
|
|
|
/* Just check the file is readable before opening it, otherwise
|
|
|
|
* libvirt emits an error.
|
|
|
|
*/
|
2012-10-17 09:23:12 +00:00
|
|
|
if (access(filename, R_OK) == -1) {
|
2010-06-30 18:14:37 +00:00
|
|
|
VIR_INFO("Could not read qemu config file %s", filename);
|
2013-01-10 21:03:14 +00:00
|
|
|
return 0;
|
2010-06-30 18:14:37 +00:00
|
|
|
}
|
2007-10-12 16:05:44 +00:00
|
|
|
|
2012-11-29 11:25:07 +00:00
|
|
|
if (!(conf = virConfReadFile(filename, 0)))
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2007-10-12 16:05:44 +00:00
|
|
|
|
2019-01-14 21:24:17 +00:00
|
|
|
if (virQEMUDriverConfigLoadDefaultTLSEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2016-09-08 14:04:59 +00:00
|
|
|
|
2019-01-14 21:15:40 +00:00
|
|
|
if (virQEMUDriverConfigLoadVNCEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2019-01-15 09:23:06 +00:00
|
|
|
|
|
|
|
if (virQEMUDriverConfigLoadNographicsEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2012-11-27 16:59:34 +00:00
|
|
|
|
2019-01-15 09:51:51 +00:00
|
|
|
if (virQEMUDriverConfigLoadSPICEEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2017-02-12 14:54:48 +00:00
|
|
|
|
2019-01-14 21:03:05 +00:00
|
|
|
if (virQEMUDriverConfigLoadSpecificTLSEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2010-03-05 20:31:50 +00:00
|
|
|
|
2019-01-14 20:53:01 +00:00
|
|
|
if (virQEMUDriverConfigLoadRemoteDisplayEntry(cfg, conf, filename) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2012-06-18 08:22:07 +00:00
|
|
|
|
2019-01-15 11:24:02 +00:00
|
|
|
if (virQEMUDriverConfigLoadSaveEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2009-11-03 22:41:23 +00:00
|
|
|
|
2019-01-15 11:35:59 +00:00
|
|
|
if (virQEMUDriverConfigLoadProcessEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2019-01-15 11:33:26 +00:00
|
|
|
if (virQEMUDriverConfigLoadDeviceEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2019-01-15 11:33:26 +00:00
|
|
|
|
2019-01-15 11:33:07 +00:00
|
|
|
if (virQEMUDriverConfigLoadRPCEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2019-01-15 11:32:40 +00:00
|
|
|
if (virQEMUDriverConfigLoadNetworkEntry(cfg, conf, filename) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2013-10-09 09:32:55 +00:00
|
|
|
|
2019-01-15 09:18:04 +00:00
|
|
|
if (virQEMUDriverConfigLoadLogEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2014-08-07 14:59:21 +00:00
|
|
|
|
2019-11-11 16:22:50 +00:00
|
|
|
if (virQEMUDriverConfigLoadNVRAMEntry(cfg, conf, privileged) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2019-01-15 09:14:44 +00:00
|
|
|
|
2019-12-11 21:22:31 +00:00
|
|
|
if (virQEMUDriverConfigLoadDebugEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2014-08-07 14:59:21 +00:00
|
|
|
|
2019-01-14 20:28:57 +00:00
|
|
|
if (virQEMUDriverConfigLoadSecurityEntry(cfg, conf, privileged) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2016-11-18 15:34:45 +00:00
|
|
|
|
2019-01-15 09:10:36 +00:00
|
|
|
if (virQEMUDriverConfigLoadMemoryEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2017-02-02 13:27:31 +00:00
|
|
|
|
2019-01-14 20:18:44 +00:00
|
|
|
if (virQEMUDriverConfigLoadSWTPMEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2017-04-04 16:22:31 +00:00
|
|
|
|
2019-06-18 07:46:22 +00:00
|
|
|
if (virQEMUDriverConfigLoadCapsFiltersEntry(cfg, conf) < 0)
|
2019-09-09 15:56:26 +00:00
|
|
|
return -1;
|
2012-11-29 11:25:07 +00:00
|
|
|
|
2019-09-09 15:56:26 +00:00
|
|
|
return 0;
|
2007-10-12 16:05:44 +00:00
|
|
|
}
|
2012-03-19 13:28:10 +00:00
|
|
|
|
2017-06-29 12:27:55 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @cfg: Recently read config values
|
|
|
|
*
|
|
|
|
* Validate the recently read configuration values.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure
|
|
|
|
*/
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigValidate(virQEMUDriverConfig *cfg)
|
2017-06-29 12:27:55 +00:00
|
|
|
{
|
2019-01-14 22:57:12 +00:00
|
|
|
if (cfg->defaultTLSx509certdirPresent) {
|
2017-06-29 12:27:55 +00:00
|
|
|
if (!virFileExists(cfg->defaultTLSx509certdir)) {
|
|
|
|
virReportError(VIR_ERR_CONF_SYNTAX,
|
|
|
|
_("default_tls_x509_cert_dir directory '%s' "
|
|
|
|
"does not exist"),
|
|
|
|
cfg->defaultTLSx509certdir);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-14 22:06:06 +00:00
|
|
|
if (cfg->vncTLSx509certdir &&
|
2017-06-29 12:27:55 +00:00
|
|
|
!virFileExists(cfg->vncTLSx509certdir)) {
|
|
|
|
virReportError(VIR_ERR_CONF_SYNTAX,
|
|
|
|
_("vnc_tls_x509_cert_dir directory '%s' does not exist"),
|
|
|
|
cfg->vncTLSx509certdir);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-01-14 22:06:06 +00:00
|
|
|
if (cfg->spiceTLSx509certdir &&
|
2017-06-29 12:27:55 +00:00
|
|
|
!virFileExists(cfg->spiceTLSx509certdir)) {
|
|
|
|
virReportError(VIR_ERR_CONF_SYNTAX,
|
|
|
|
_("spice_tls_x509_cert_dir directory '%s' does not exist"),
|
|
|
|
cfg->spiceTLSx509certdir);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-01-14 22:06:06 +00:00
|
|
|
if (cfg->chardevTLSx509certdir &&
|
2017-06-29 12:27:55 +00:00
|
|
|
!virFileExists(cfg->chardevTLSx509certdir)) {
|
|
|
|
virReportError(VIR_ERR_CONF_SYNTAX,
|
|
|
|
_("chardev_tls_x509_cert_dir directory '%s' does not exist"),
|
|
|
|
cfg->chardevTLSx509certdir);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-01-14 22:06:06 +00:00
|
|
|
if (cfg->migrateTLSx509certdir &&
|
2017-06-29 12:27:55 +00:00
|
|
|
!virFileExists(cfg->migrateTLSx509certdir)) {
|
|
|
|
virReportError(VIR_ERR_CONF_SYNTAX,
|
|
|
|
_("migrate_tls_x509_cert_dir directory '%s' does not exist"),
|
|
|
|
cfg->migrateTLSx509certdir);
|
|
|
|
return -1;
|
2017-08-30 15:32:33 +00:00
|
|
|
}
|
|
|
|
|
2020-06-26 14:37:16 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-01-14 22:06:06 +00:00
|
|
|
if (cfg->vxhsTLSx509certdir &&
|
2017-08-30 15:32:33 +00:00
|
|
|
!virFileExists(cfg->vxhsTLSx509certdir)) {
|
|
|
|
virReportError(VIR_ERR_CONF_SYNTAX,
|
|
|
|
_("vxhs_tls_x509_cert_dir directory '%s' does not exist"),
|
|
|
|
cfg->vxhsTLSx509certdir);
|
|
|
|
return -1;
|
2017-06-29 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2019-01-14 22:06:06 +00:00
|
|
|
if (cfg->nbdTLSx509certdir &&
|
2018-05-31 18:21:48 +00:00
|
|
|
!virFileExists(cfg->nbdTLSx509certdir)) {
|
|
|
|
virReportError(VIR_ERR_CONF_SYNTAX,
|
|
|
|
_("nbd_tls_x509_cert_dir directory '%s' does not exist"),
|
|
|
|
cfg->nbdTLSx509certdir);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-06-29 12:27:55 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 21:51:00 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfigSetDefaults(virQEMUDriverConfig *cfg)
|
2019-01-14 21:51:00 +00:00
|
|
|
{
|
2019-01-14 22:06:06 +00:00
|
|
|
#define SET_TLS_SECRET_UUID_DEFAULT(val) \
|
|
|
|
do { \
|
|
|
|
if (!cfg->val## TLSx509certdir && \
|
|
|
|
!cfg->val## TLSx509secretUUID && \
|
|
|
|
cfg->defaultTLSx509secretUUID) { \
|
2019-10-20 11:49:46 +00:00
|
|
|
cfg->val## TLSx509secretUUID = g_strdup(cfg->defaultTLSx509secretUUID); \
|
2019-01-14 22:06:06 +00:00
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2019-01-14 23:09:23 +00:00
|
|
|
SET_TLS_SECRET_UUID_DEFAULT(vnc);
|
2019-01-14 22:06:06 +00:00
|
|
|
SET_TLS_SECRET_UUID_DEFAULT(chardev);
|
|
|
|
SET_TLS_SECRET_UUID_DEFAULT(migrate);
|
2020-06-26 14:37:16 +00:00
|
|
|
SET_TLS_SECRET_UUID_DEFAULT(backup);
|
2020-06-29 15:12:03 +00:00
|
|
|
SET_TLS_SECRET_UUID_DEFAULT(vxhs);
|
|
|
|
SET_TLS_SECRET_UUID_DEFAULT(nbd);
|
2019-01-14 22:06:06 +00:00
|
|
|
|
|
|
|
#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)) { \
|
2019-10-20 11:49:46 +00:00
|
|
|
cfg->val ## TLSx509certdir = g_strdup(SYSCONFDIR "/pki/libvirt-"#val); \
|
2019-01-14 22:06:06 +00:00
|
|
|
} else { \
|
2019-10-20 11:49:46 +00:00
|
|
|
cfg->val ## TLSx509certdir = g_strdup(cfg->defaultTLSx509certdir); \
|
2019-01-14 22:06:06 +00:00
|
|
|
} \
|
|
|
|
} 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);
|
2020-06-26 14:37:16 +00:00
|
|
|
SET_TLS_X509_CERT_DEFAULT(backup);
|
2019-01-14 22:06:06 +00:00
|
|
|
SET_TLS_X509_CERT_DEFAULT(vxhs);
|
|
|
|
SET_TLS_X509_CERT_DEFAULT(nbd);
|
|
|
|
|
|
|
|
#undef SET_TLS_X509_CERT_DEFAULT
|
|
|
|
|
2020-11-13 14:13:29 +00:00
|
|
|
#define SET_TLS_VERIFY_DEFAULT(val, defaultverify) \
|
2019-01-14 21:51:00 +00:00
|
|
|
do { \
|
2020-11-13 14:13:29 +00:00
|
|
|
if (!cfg->val## TLSx509verifyPresent) {\
|
|
|
|
if (cfg->defaultTLSx509verifyPresent) \
|
|
|
|
cfg->val## TLSx509verify = cfg->defaultTLSx509verify; \
|
|
|
|
else \
|
|
|
|
cfg->val## TLSx509verify = defaultverify;\
|
|
|
|
}\
|
2019-01-14 21:51:00 +00:00
|
|
|
} while (0)
|
|
|
|
|
2020-11-13 14:13:29 +00:00
|
|
|
SET_TLS_VERIFY_DEFAULT(vnc, false);
|
2020-11-13 14:20:58 +00:00
|
|
|
SET_TLS_VERIFY_DEFAULT(chardev, true);
|
2020-11-13 14:20:58 +00:00
|
|
|
SET_TLS_VERIFY_DEFAULT(migrate, true);
|
2020-11-13 14:20:58 +00:00
|
|
|
SET_TLS_VERIFY_DEFAULT(backup, true);
|
2019-01-14 21:51:00 +00:00
|
|
|
|
|
|
|
#undef SET_TLS_VERIFY_DEFAULT
|
|
|
|
|
2019-09-09 15:24:22 +00:00
|
|
|
return 0;
|
2019-01-14 21:51:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virQEMUDriverConfig *virQEMUDriverGetConfig(virQEMUDriver *driver)
|
2013-01-10 21:03:14 +00:00
|
|
|
{
|
2022-03-08 14:59:06 +00:00
|
|
|
VIR_LOCK_GUARD lock = virLockGuardLock(&driver->lock);
|
|
|
|
|
|
|
|
return virObjectRef(driver->config);
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainXMLOption *
|
|
|
|
virQEMUDriverCreateXMLConf(virQEMUDriver *driver,
|
2019-11-26 18:57:30 +00:00
|
|
|
const char *defsecmodel)
|
2013-03-05 15:17:24 +00:00
|
|
|
{
|
2013-03-11 09:24:29 +00:00
|
|
|
virQEMUDriverDomainDefParserConfig.priv = driver;
|
2019-11-26 18:57:30 +00:00
|
|
|
virQEMUDriverDomainDefParserConfig.defSecModel = defsecmodel;
|
2013-02-19 16:33:52 +00:00
|
|
|
return virDomainXMLOptionNew(&virQEMUDriverDomainDefParserConfig,
|
2013-02-19 16:29:39 +00:00
|
|
|
&virQEMUDriverPrivateDataCallbacks,
|
2017-05-19 13:07:15 +00:00
|
|
|
&virQEMUDriverDomainXMLNamespace,
|
2017-06-01 22:44:46 +00:00
|
|
|
&virQEMUDriverDomainABIStability,
|
2017-06-02 20:50:18 +00:00
|
|
|
&virQEMUDriverDomainSaveCookie);
|
2013-03-05 15:17:24 +00:00
|
|
|
}
|
|
|
|
|
2013-02-01 17:04:15 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virCPUDef *
|
|
|
|
virQEMUDriverGetHostCPU(virQEMUDriver *driver)
|
2019-11-29 10:40:39 +00:00
|
|
|
{
|
2022-03-08 14:59:06 +00:00
|
|
|
virCPUDef *hostcpu = NULL;
|
2019-11-29 10:40:39 +00:00
|
|
|
|
2022-03-08 14:59:06 +00:00
|
|
|
VIR_WITH_MUTEX_LOCK_GUARD(&driver->lock) {
|
|
|
|
if (!driver->hostcpu)
|
|
|
|
driver->hostcpu = virCPUProbeHost(virArchFromHost());
|
|
|
|
hostcpu = driver->hostcpu;
|
|
|
|
}
|
2019-11-29 10:40:39 +00:00
|
|
|
|
2020-01-24 09:24:45 +00:00
|
|
|
if (hostcpu)
|
|
|
|
virCPUDefRef(hostcpu);
|
2019-11-29 10:40:39 +00:00
|
|
|
|
2020-01-24 09:24:45 +00:00
|
|
|
return hostcpu;
|
2019-11-29 10:40:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
virCaps *virQEMUDriverCreateCapabilities(virQEMUDriver *driver)
|
2013-02-01 17:04:15 +00:00
|
|
|
{
|
2013-10-18 12:13:21 +00:00
|
|
|
size_t i, j;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virCaps) caps = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
g_autofree virSecurityManager **sec_managers = NULL;
|
2013-02-01 17:04:15 +00:00
|
|
|
/* Security driver data */
|
2013-10-18 12:13:21 +00:00
|
|
|
const char *doi, *model, *lbl, *type;
|
|
|
|
const int virtTypes[] = {VIR_DOMAIN_VIRT_KVM,
|
|
|
|
VIR_DOMAIN_VIRT_QEMU,};
|
2013-02-01 17:04:15 +00:00
|
|
|
|
|
|
|
/* Basic host arch / guest machine capabilities */
|
2013-02-19 09:56:06 +00:00
|
|
|
if (!(caps = virQEMUCapsInit(driver->qemuCapsCache)))
|
2019-09-09 15:14:25 +00:00
|
|
|
return NULL;
|
2013-02-01 17:04:15 +00:00
|
|
|
|
|
|
|
if (virGetHostUUID(caps->host.host_uuid)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot get the host uuid"));
|
2019-09-09 15:14:25 +00:00
|
|
|
return NULL;
|
2013-02-01 17:04:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* access sec drivers and create a sec model for each one */
|
2017-02-13 13:36:53 +00:00
|
|
|
if (!(sec_managers = qemuSecurityGetNested(driver->securityManager)))
|
2019-09-09 15:14:25 +00:00
|
|
|
return NULL;
|
2013-02-01 17:04:15 +00:00
|
|
|
|
|
|
|
/* calculate length */
|
|
|
|
for (i = 0; sec_managers[i]; i++)
|
|
|
|
;
|
|
|
|
caps->host.nsecModels = i;
|
|
|
|
|
2020-10-05 10:28:26 +00:00
|
|
|
caps->host.secModels = g_new0(virCapsHostSecModel, caps->host.nsecModels);
|
2013-02-01 17:04:15 +00:00
|
|
|
|
|
|
|
for (i = 0; sec_managers[i]; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virCapsHostSecModel *sm = &caps->host.secModels[i];
|
2017-02-13 13:36:53 +00:00
|
|
|
doi = qemuSecurityGetDOI(sec_managers[i]);
|
|
|
|
model = qemuSecurityGetModel(sec_managers[i]);
|
2019-10-20 11:49:46 +00:00
|
|
|
sm->model = g_strdup(model);
|
|
|
|
sm->doi = g_strdup(doi);
|
2013-10-18 12:13:21 +00:00
|
|
|
|
2019-10-15 11:55:26 +00:00
|
|
|
for (j = 0; j < G_N_ELEMENTS(virtTypes); j++) {
|
2017-02-13 13:36:53 +00:00
|
|
|
lbl = qemuSecurityGetBaseLabel(sec_managers[i], virtTypes[j]);
|
2013-10-18 12:13:21 +00:00
|
|
|
type = virDomainVirtTypeToString(virtTypes[j]);
|
|
|
|
if (lbl &&
|
|
|
|
virCapabilitiesHostSecModelAddBaseLabel(sm, type, lbl) < 0)
|
2019-09-09 15:14:25 +00:00
|
|
|
return NULL;
|
2013-10-18 12:13:21 +00:00
|
|
|
}
|
|
|
|
|
2013-02-01 17:04:15 +00:00
|
|
|
VIR_DEBUG("Initialized caps for security driver \"%s\" with "
|
|
|
|
"DOI \"%s\"", model, doi);
|
|
|
|
}
|
|
|
|
|
2020-12-02 08:26:30 +00:00
|
|
|
caps->host.numa = virCapabilitiesHostNUMANewHost();
|
2019-11-29 10:40:39 +00:00
|
|
|
caps->host.cpu = virQEMUDriverGetHostCPU(driver);
|
2019-10-16 11:35:54 +00:00
|
|
|
return g_steal_pointer(&caps);
|
2013-02-01 17:04:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virQEMUDriverGetCapabilities:
|
|
|
|
*
|
2021-03-11 07:16:13 +00:00
|
|
|
* Get a reference to the virCaps *instance for the
|
2013-02-01 17:04:15 +00:00
|
|
|
* driver. If @refresh is true, the capabilities will be
|
|
|
|
* rebuilt first
|
|
|
|
*
|
2020-11-18 13:59:37 +00:00
|
|
|
* The caller must release the reference with virObjectUnref
|
2013-02-01 17:04:15 +00:00
|
|
|
*
|
2021-03-11 07:16:13 +00:00
|
|
|
* Returns: a reference to a virCaps *instance or NULL
|
2013-02-01 17:04:15 +00:00
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
virCaps *virQEMUDriverGetCapabilities(virQEMUDriver *driver,
|
2022-03-08 14:59:06 +00:00
|
|
|
bool refresh)
|
2013-02-01 17:04:15 +00:00
|
|
|
{
|
|
|
|
if (refresh) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virCaps *caps = NULL;
|
2013-02-01 17:04:15 +00:00
|
|
|
if ((caps = virQEMUDriverCreateCapabilities(driver)) == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2022-03-08 14:59:06 +00:00
|
|
|
VIR_WITH_MUTEX_LOCK_GUARD(&driver->lock) {
|
|
|
|
virObjectUnref(driver->caps);
|
|
|
|
driver->caps = caps;
|
|
|
|
return virObjectRef(driver->caps);
|
2019-12-02 13:04:26 +00:00
|
|
|
}
|
2015-04-16 18:51:26 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 14:59:06 +00:00
|
|
|
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);
|
2013-02-01 17:04:15 +00:00
|
|
|
}
|
|
|
|
|
2019-04-04 21:31:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virQEMUDriverGetDomainCapabilities:
|
|
|
|
*
|
2021-03-11 07:16:13 +00:00
|
|
|
* Get a reference to the virDomainCaps *instance. The caller
|
2020-11-13 20:09:33 +00:00
|
|
|
* must release the reference with virObjetUnref().
|
2019-04-04 21:31:00 +00:00
|
|
|
*
|
2021-03-11 07:16:13 +00:00
|
|
|
* Returns: a reference to a virDomainCaps *instance or NULL
|
2019-04-04 21:31:00 +00:00
|
|
|
*/
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainCaps *
|
|
|
|
virQEMUDriverGetDomainCapabilities(virQEMUDriver *driver,
|
|
|
|
virQEMUCaps *qemuCaps,
|
2019-04-04 21:31:00 +00:00
|
|
|
const char *machine,
|
|
|
|
virArch arch,
|
|
|
|
virDomainVirtType virttype)
|
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2020-11-13 20:09:33 +00:00
|
|
|
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;
|
2019-04-04 21:31:00 +00:00
|
|
|
|
2020-11-13 20:09:33 +00:00
|
|
|
return g_steal_pointer(&domCaps);
|
2019-04-04 21:31:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
int qemuDriverAllocateID(virQEMUDriver *driver)
|
2013-01-14 16:50:08 +00:00
|
|
|
{
|
2020-01-31 14:27:37 +00:00
|
|
|
return g_atomic_int_add(&driver->lastvmid, 1) + 1;
|
2013-01-14 16:50:08 +00:00
|
|
|
}
|
2013-04-04 19:38:00 +00:00
|
|
|
|
2013-11-25 16:26:02 +00:00
|
|
|
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuTranslateSnapshotDiskSourcePool(virDomainSnapshotDiskDef *def)
|
2013-11-25 16:26:02 +00:00
|
|
|
{
|
2014-05-21 21:21:02 +00:00
|
|
|
if (def->src->type != VIR_STORAGE_TYPE_VOLUME)
|
2013-11-25 16:26:02 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Snapshots are not yet supported with 'pool' volumes"));
|
|
|
|
return -1;
|
|
|
|
}
|
2014-07-23 15:37:18 +00:00
|
|
|
|
|
|
|
char *
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuGetBaseHugepagePath(virQEMUDriver *driver,
|
|
|
|
virHugeTLBFS *hugepage)
|
2014-07-23 15:37:18 +00:00
|
|
|
{
|
2020-03-20 18:27:26 +00:00
|
|
|
const char *root = driver->embeddedRoot;
|
2014-07-23 15:37:18 +00:00
|
|
|
|
2020-03-20 18:27:26 +00:00
|
|
|
if (root && !STRPREFIX(hugepage->mnt_dir, root)) {
|
|
|
|
g_autofree char * hash = virDomainDriverGenerateRootHash("qemu", root);
|
2021-11-23 16:34:36 +00:00
|
|
|
return g_strdup_printf("%s/libvirt/%s", hugepage->mnt_dir, hash);
|
2020-03-20 18:27:26 +00:00
|
|
|
}
|
2014-07-23 15:37:18 +00:00
|
|
|
|
2021-11-23 16:34:36 +00:00
|
|
|
return g_strdup_printf("%s/libvirt/qemu", hugepage->mnt_dir);
|
2014-07-23 15:37:18 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2016-11-22 12:21:51 +00:00
|
|
|
char *
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuGetDomainHugepagePath(virQEMUDriver *driver,
|
2020-03-20 18:27:26 +00:00
|
|
|
const virDomainDef *def,
|
2021-03-11 07:16:13 +00:00
|
|
|
virHugeTLBFS *hugepage)
|
2016-11-22 12:21:51 +00:00
|
|
|
{
|
2020-03-20 18:27:26 +00:00
|
|
|
g_autofree char *base = qemuGetBaseHugepagePath(driver, hugepage);
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *domPath = virDomainDefGetShortName(def);
|
2016-11-22 12:21:51 +00:00
|
|
|
|
2021-11-23 16:34:36 +00:00
|
|
|
if (!base || !domPath)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return g_strdup_printf("%s/%s", base, domPath);
|
2016-11-22 12:21:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-19 05:45:12 +00:00
|
|
|
/**
|
2016-11-22 12:21:51 +00:00
|
|
|
* qemuGetDomainHupageMemPath: Construct HP enabled memory backend path
|
2016-09-19 05:45:12 +00:00
|
|
|
*
|
|
|
|
* The resulting path is stored at @memPath.
|
|
|
|
*
|
|
|
|
* Returns 0 on success,
|
|
|
|
* -1 otherwise.
|
|
|
|
*/
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuGetDomainHupageMemPath(virQEMUDriver *driver,
|
2020-03-20 18:27:26 +00:00
|
|
|
const virDomainDef *def,
|
2016-11-22 12:21:51 +00:00
|
|
|
unsigned long long pagesize,
|
|
|
|
char **memPath)
|
2016-09-19 05:45:12 +00:00
|
|
|
{
|
2020-03-20 18:27:26 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
2016-09-19 05:45:12 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-04-04 11:53:17 +00:00
|
|
|
for (i = 0; i < cfg->nhugetlbfs; i++) {
|
|
|
|
if (cfg->hugetlbfs[i].size == pagesize)
|
|
|
|
break;
|
|
|
|
}
|
2016-09-19 05:45:12 +00:00
|
|
|
|
2019-04-04 11:53:17 +00:00
|
|
|
if (i == cfg->nhugetlbfs) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to find any usable hugetlbfs "
|
|
|
|
"mount for %llu KiB"),
|
|
|
|
pagesize);
|
|
|
|
return -1;
|
2016-09-19 05:45:12 +00:00
|
|
|
}
|
|
|
|
|
2020-03-20 18:27:26 +00:00
|
|
|
if (!(*memPath = qemuGetDomainHugepagePath(driver, def, &cfg->hugetlbfs[i])))
|
2019-04-04 11:53:17 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-09-19 05:45:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-10-23 09:33:06 +00:00
|
|
|
|
|
|
|
|
2017-11-07 14:20:12 +00:00
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuGetMemoryBackingDomainPath(virQEMUDriver *driver,
|
2020-03-23 12:33:32 +00:00
|
|
|
const virDomainDef *def,
|
2017-11-07 14:20:12 +00:00
|
|
|
char **path)
|
|
|
|
{
|
2020-03-23 12:33:32 +00:00
|
|
|
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
|
|
|
|
const char *root = driver->embeddedRoot;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *shortName = NULL;
|
2017-11-07 14:20:12 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
if (!(shortName = virDomainDefGetShortName(def)))
|
2019-09-09 15:07:28 +00:00
|
|
|
return -1;
|
2017-11-07 14:20:12 +00:00
|
|
|
|
2020-03-23 12:33:32 +00:00
|
|
|
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);
|
|
|
|
}
|
2019-10-22 13:26:14 +00:00
|
|
|
|
2019-09-09 15:07:28 +00:00
|
|
|
return 0;
|
2017-11-07 14:20:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-23 09:33:06 +00:00
|
|
|
/**
|
|
|
|
* qemuGetMemoryBackingPath:
|
2020-03-23 12:33:32 +00:00
|
|
|
* @driver: the qemu driver
|
2017-11-07 14:20:12 +00:00
|
|
|
* @def: domain definition
|
|
|
|
* @alias: memory object alias
|
2017-10-23 09:33:06 +00:00
|
|
|
* @memPath: constructed path
|
|
|
|
*
|
|
|
|
* Constructs path to memory backing dir and stores it at @memPath.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success,
|
|
|
|
* -1 otherwise (with error reported).
|
|
|
|
*/
|
|
|
|
int
|
2021-03-11 07:16:13 +00:00
|
|
|
qemuGetMemoryBackingPath(virQEMUDriver *driver,
|
2020-03-23 12:33:32 +00:00
|
|
|
const virDomainDef *def,
|
2017-11-07 14:20:12 +00:00
|
|
|
const char *alias,
|
2017-10-23 09:33:06 +00:00
|
|
|
char **memPath)
|
|
|
|
{
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *domainPath = NULL;
|
2017-11-07 14:20:12 +00:00
|
|
|
|
|
|
|
if (!alias) {
|
|
|
|
/* This should never happen (TM) */
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("memory device alias is not assigned"));
|
2019-09-09 15:07:28 +00:00
|
|
|
return -1;
|
2017-11-07 14:20:12 +00:00
|
|
|
}
|
|
|
|
|
2020-03-23 12:33:32 +00:00
|
|
|
if (qemuGetMemoryBackingDomainPath(driver, def, &domainPath) < 0)
|
2019-09-09 15:07:28 +00:00
|
|
|
return -1;
|
2017-11-07 14:20:12 +00:00
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
*memPath = g_strdup_printf("%s/%s", domainPath, alias);
|
2019-09-09 15:07:28 +00:00
|
|
|
return 0;
|
2017-10-23 09:33:06 +00:00
|
|
|
}
|