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>
|
2007-02-23 17:15:18 +00:00
|
|
|
#include <sys/wait.h>
|
2007-04-10 23:17:46 +00:00
|
|
|
#include <arpa/inet.h>
|
2007-02-14 01:40:09 +00:00
|
|
|
|
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"
|
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-04 12:04:07 +00:00
|
|
|
#include "virbuffer.h"
|
2012-12-12 16:35:35 +00:00
|
|
|
#include "virconf.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2008-12-20 13:09:45 +00:00
|
|
|
#include "datatypes.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"
|
2010-06-21 18:18:31 +00:00
|
|
|
#include "domain_nwfilter.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2017-07-05 10:19:43 +00:00
|
|
|
#include "virsocketaddr.h"
|
2013-01-10 21:03:14 +00:00
|
|
|
#include "virstring.h"
|
2013-01-14 16:50:08 +00:00
|
|
|
#include "viratomic.h"
|
2013-07-18 10:39:55 +00:00
|
|
|
#include "storage_conf.h"
|
2010-11-16 14:54:17 +00:00
|
|
|
#include "configmake.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
|
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
static virClassPtr virQEMUDriverConfigClass;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
VIR_ONCE_GLOBAL_INIT(virQEMUConfig)
|
|
|
|
|
|
|
|
|
2013-02-06 18:17:20 +00:00
|
|
|
static void
|
|
|
|
qemuDriverLock(virQEMUDriverPtr driver)
|
2010-12-16 16:11:48 +00:00
|
|
|
{
|
|
|
|
virMutexLock(&driver->lock);
|
|
|
|
}
|
2013-02-06 18:17:20 +00:00
|
|
|
static void
|
|
|
|
qemuDriverUnlock(virQEMUDriverPtr driver)
|
2010-12-16 16:11:48 +00:00
|
|
|
{
|
|
|
|
virMutexUnlock(&driver->lock);
|
|
|
|
}
|
|
|
|
|
2013-09-24 15:38:26 +00:00
|
|
|
void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < def->num_args; i++)
|
|
|
|
VIR_FREE(def->args[i]);
|
|
|
|
for (i = 0; i < def->num_env; i++) {
|
|
|
|
VIR_FREE(def->env_name[i]);
|
|
|
|
VIR_FREE(def->env_value[i]);
|
|
|
|
}
|
|
|
|
VIR_FREE(def->args);
|
|
|
|
VIR_FREE(def->env_name);
|
|
|
|
VIR_FREE(def->env_value);
|
|
|
|
VIR_FREE(def);
|
|
|
|
}
|
2010-12-16 16:11:48 +00:00
|
|
|
|
2015-01-21 18:38:57 +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
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
|
|
|
|
{
|
|
|
|
virQEMUDriverConfigPtr cfg;
|
|
|
|
|
|
|
|
if (virQEMUConfigInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(cfg = virObjectNew(virQEMUDriverConfigClass)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
cfg->uri = privileged ? "qemu:///system" : "qemu:///session";
|
|
|
|
|
|
|
|
if (privileged) {
|
|
|
|
if (virGetUserID(QEMU_USER, &cfg->user) < 0)
|
|
|
|
goto error;
|
|
|
|
if (virGetGroupID(QEMU_GROUP, &cfg->group) < 0)
|
|
|
|
goto error;
|
|
|
|
} 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;
|
|
|
|
|
2013-03-21 13:27:13 +00:00
|
|
|
cfg->cgroupControllers = -1; /* -1 == auto-detect */
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
if (privileged) {
|
|
|
|
if (virAsprintf(&cfg->logDir,
|
|
|
|
"%s/log/libvirt/qemu", LOCALSTATEDIR) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2017-04-04 16:22:31 +00:00
|
|
|
if (virAsprintf(&cfg->swtpmLogDir,
|
|
|
|
"%s/log/swtpm/libvirt/qemu", LOCALSTATEDIR) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2013-05-20 09:23:13 +00:00
|
|
|
if (VIR_STRDUP(cfg->configBaseDir, SYSCONFDIR "/libvirt") < 0)
|
|
|
|
goto error;
|
2007-10-12 16:05:44 +00:00
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
if (virAsprintf(&cfg->stateDir,
|
|
|
|
"%s/run/libvirt/qemu", LOCALSTATEDIR) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2017-04-04 16:22:31 +00:00
|
|
|
if (virAsprintf(&cfg->swtpmStateDir,
|
|
|
|
"%s/run/libvirt/qemu/swtpm", LOCALSTATEDIR) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
if (virAsprintf(&cfg->cacheDir,
|
|
|
|
"%s/cache/libvirt/qemu", LOCALSTATEDIR) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2015-04-24 00:16:30 +00:00
|
|
|
|
|
|
|
if (virAsprintf(&cfg->libDir,
|
|
|
|
"%s/lib/libvirt/qemu", LOCALSTATEDIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (virAsprintf(&cfg->saveDir, "%s/save", cfg->libDir) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2015-04-24 00:16:30 +00:00
|
|
|
if (virAsprintf(&cfg->snapshotDir, "%s/snapshot", cfg->libDir) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2015-04-24 00:16:30 +00:00
|
|
|
if (virAsprintf(&cfg->autoDumpPath, "%s/dump", cfg->libDir) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2015-04-23 23:24:50 +00:00
|
|
|
if (virAsprintf(&cfg->channelTargetDir,
|
|
|
|
"%s/channel/target", cfg->libDir) < 0)
|
|
|
|
goto error;
|
2015-04-24 00:01:05 +00:00
|
|
|
if (virAsprintf(&cfg->nvramDir, "%s/nvram", cfg->libDir) < 0)
|
|
|
|
goto error;
|
2017-02-02 13:27:31 +00:00
|
|
|
if (virAsprintf(&cfg->memoryBackingDir, "%s/ram", cfg->libDir) < 0)
|
|
|
|
goto error;
|
2017-04-04 16:22:31 +00:00
|
|
|
if (virAsprintf(&cfg->swtpmStorageDir, "%s/lib/libvirt/swtpm",
|
|
|
|
LOCALSTATEDIR) < 0)
|
|
|
|
goto error;
|
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 {
|
|
|
|
char *rundir;
|
|
|
|
char *cachedir;
|
|
|
|
|
|
|
|
cachedir = virGetUserCacheDirectory();
|
|
|
|
if (!cachedir)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virAsprintf(&cfg->logDir,
|
|
|
|
"%s/qemu/log", cachedir) < 0) {
|
|
|
|
VIR_FREE(cachedir);
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
2017-04-04 16:22:31 +00:00
|
|
|
if (virAsprintf(&cfg->swtpmLogDir,
|
|
|
|
"%s/qemu/log", cachedir) < 0) {
|
|
|
|
VIR_FREE(cachedir);
|
|
|
|
goto error;
|
|
|
|
}
|
2013-01-10 21:03:14 +00:00
|
|
|
if (virAsprintf(&cfg->cacheDir, "%s/qemu/cache", cachedir) < 0) {
|
|
|
|
VIR_FREE(cachedir);
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(cachedir);
|
2010-01-13 17:41:36 +00:00
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
rundir = virGetUserRuntimeDirectory();
|
|
|
|
if (!rundir)
|
|
|
|
goto error;
|
|
|
|
if (virAsprintf(&cfg->stateDir, "%s/qemu/run", rundir) < 0) {
|
|
|
|
VIR_FREE(rundir);
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(rundir);
|
|
|
|
|
2017-04-04 16:22:31 +00:00
|
|
|
if (virAsprintf(&cfg->swtpmStateDir, "%s/swtpm", cfg->stateDir) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
if (!(cfg->configBaseDir = virGetUserConfigDirectory()))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virAsprintf(&cfg->libDir, "%s/qemu/lib", cfg->configBaseDir) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-01-10 21:03:14 +00:00
|
|
|
if (virAsprintf(&cfg->saveDir, "%s/qemu/save", cfg->configBaseDir) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-01-10 21:03:14 +00:00
|
|
|
if (virAsprintf(&cfg->snapshotDir, "%s/qemu/snapshot", cfg->configBaseDir) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-01-10 21:03:14 +00:00
|
|
|
if (virAsprintf(&cfg->autoDumpPath, "%s/qemu/dump", cfg->configBaseDir) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2015-04-23 23:24:50 +00:00
|
|
|
if (virAsprintf(&cfg->channelTargetDir,
|
|
|
|
"%s/qemu/channel/target", cfg->configBaseDir) < 0)
|
|
|
|
goto error;
|
2015-04-24 00:01:05 +00:00
|
|
|
if (virAsprintf(&cfg->nvramDir,
|
|
|
|
"%s/qemu/nvram", cfg->configBaseDir) < 0)
|
|
|
|
goto error;
|
2017-02-02 13:27:31 +00:00
|
|
|
if (virAsprintf(&cfg->memoryBackingDir, "%s/qemu/ram", cfg->configBaseDir) < 0)
|
|
|
|
goto error;
|
2017-04-04 16:22:31 +00:00
|
|
|
if (virAsprintf(&cfg->swtpmStorageDir, "%s/qemu/swtpm", cfg->configBaseDir) < 0)
|
|
|
|
goto error;
|
|
|
|
cfg->swtpm_user = (uid_t)-1;
|
|
|
|
cfg->swtpm_group = (gid_t)-1;
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (virAsprintf(&cfg->configDir, "%s/qemu", cfg->configBaseDir) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-01-10 21:03:14 +00:00
|
|
|
if (virAsprintf(&cfg->autostartDir, "%s/qemu/autostart", cfg->configBaseDir) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
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).
|
|
|
|
*/
|
|
|
|
if (VIR_STRDUP(cfg->defaultTLSx509certdir,
|
|
|
|
SYSCONFDIR "/pki/qemu") < 0)
|
2013-05-20 09:23:13 +00:00
|
|
|
goto error;
|
2012-11-29 11:25:07 +00:00
|
|
|
|
2017-05-19 21:31:48 +00:00
|
|
|
if (VIR_STRDUP(cfg->vncListen, VIR_LOOPBACK_IPV4_ADDR) < 0)
|
2013-05-20 09:23:13 +00:00
|
|
|
goto error;
|
2007-10-12 16:05:44 +00:00
|
|
|
|
2017-05-19 21:31:48 +00:00
|
|
|
if (VIR_STRDUP(cfg->spiceListen, VIR_LOOPBACK_IPV4_ADDR) < 0)
|
2013-05-20 09:23:13 +00:00
|
|
|
goto error;
|
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)
|
2013-01-10 21:03:14 +00:00
|
|
|
goto error;
|
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
|
|
|
|
2017-12-15 09:42:40 +00:00
|
|
|
if (VIR_STRDUP(cfg->bridgeHelperName, QEMU_BRIDGE_HELPER) < 0 ||
|
|
|
|
VIR_STRDUP(cfg->prHelperName, QEMU_PR_HELPER) < 0)
|
2013-05-20 09:23:13 +00:00
|
|
|
goto error;
|
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->clearEmulatorCapabilities = true;
|
|
|
|
|
|
|
|
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
|
|
|
|
2016-11-18 15:34:45 +00:00
|
|
|
if (!(cfg->namespaces = virBitmapNew(QEMU_DOMAIN_NS_LAST)))
|
|
|
|
goto error;
|
|
|
|
|
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)
|
2016-11-18 15:34:45 +00:00
|
|
|
goto error;
|
|
|
|
|
2016-05-17 22:45:27 +00:00
|
|
|
if (virFirmwareParseList(DEFAULT_LOADER_NVRAM,
|
|
|
|
&cfg->firmwares,
|
|
|
|
&cfg->nfirmwares) < 0)
|
2015-01-21 18:38:57 +00:00
|
|
|
goto error;
|
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
return cfg;
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
error:
|
2013-01-10 21:03:14 +00:00
|
|
|
virObjectUnref(cfg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void virQEMUDriverConfigDispose(void *obj)
|
|
|
|
{
|
|
|
|
virQEMUDriverConfigPtr cfg = obj;
|
|
|
|
|
2016-11-18 15:34:45 +00:00
|
|
|
virBitmapFree(cfg->namespaces);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(cfg->cgroupDeviceACL);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
VIR_FREE(cfg->configBaseDir);
|
|
|
|
VIR_FREE(cfg->configDir);
|
|
|
|
VIR_FREE(cfg->autostartDir);
|
|
|
|
VIR_FREE(cfg->logDir);
|
2017-04-04 16:22:31 +00:00
|
|
|
VIR_FREE(cfg->swtpmLogDir);
|
2013-01-10 21:03:14 +00:00
|
|
|
VIR_FREE(cfg->stateDir);
|
2017-04-04 16:22:31 +00:00
|
|
|
VIR_FREE(cfg->swtpmStateDir);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
VIR_FREE(cfg->libDir);
|
|
|
|
VIR_FREE(cfg->cacheDir);
|
|
|
|
VIR_FREE(cfg->saveDir);
|
|
|
|
VIR_FREE(cfg->snapshotDir);
|
2015-04-23 23:24:50 +00:00
|
|
|
VIR_FREE(cfg->channelTargetDir);
|
2015-04-24 00:01:05 +00:00
|
|
|
VIR_FREE(cfg->nvramDir);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2016-06-14 18:14:31 +00:00
|
|
|
VIR_FREE(cfg->defaultTLSx509certdir);
|
2016-09-08 14:04:59 +00:00
|
|
|
VIR_FREE(cfg->defaultTLSx509secretUUID);
|
2016-06-14 18:14:31 +00:00
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
VIR_FREE(cfg->vncTLSx509certdir);
|
|
|
|
VIR_FREE(cfg->vncListen);
|
|
|
|
VIR_FREE(cfg->vncPassword);
|
|
|
|
VIR_FREE(cfg->vncSASLdir);
|
|
|
|
|
|
|
|
VIR_FREE(cfg->spiceTLSx509certdir);
|
|
|
|
VIR_FREE(cfg->spiceListen);
|
|
|
|
VIR_FREE(cfg->spicePassword);
|
2012-02-24 14:13:06 +00:00
|
|
|
VIR_FREE(cfg->spiceSASLdir);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2016-06-14 19:52:37 +00:00
|
|
|
VIR_FREE(cfg->chardevTLSx509certdir);
|
2016-09-08 14:04:59 +00:00
|
|
|
VIR_FREE(cfg->chardevTLSx509secretUUID);
|
2016-06-14 19:52:37 +00:00
|
|
|
|
2017-08-30 15:32:33 +00:00
|
|
|
VIR_FREE(cfg->vxhsTLSx509certdir);
|
2018-05-31 18:21:48 +00:00
|
|
|
VIR_FREE(cfg->nbdTLSx509certdir);
|
2017-08-30 15:32:33 +00:00
|
|
|
|
2017-02-24 21:44:32 +00:00
|
|
|
VIR_FREE(cfg->migrateTLSx509certdir);
|
|
|
|
VIR_FREE(cfg->migrateTLSx509secretUUID);
|
|
|
|
|
2014-07-23 15:37:18 +00:00
|
|
|
while (cfg->nhugetlbfs) {
|
|
|
|
cfg->nhugetlbfs--;
|
|
|
|
VIR_FREE(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir);
|
|
|
|
}
|
|
|
|
VIR_FREE(cfg->hugetlbfs);
|
2013-03-25 14:25:30 +00:00
|
|
|
VIR_FREE(cfg->bridgeHelperName);
|
2017-12-15 09:42:40 +00:00
|
|
|
VIR_FREE(cfg->prHelperName);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
VIR_FREE(cfg->saveImageFormat);
|
|
|
|
VIR_FREE(cfg->dumpImageFormat);
|
2017-04-12 12:54:04 +00:00
|
|
|
VIR_FREE(cfg->snapshotImageFormat);
|
2013-01-10 21:03:14 +00:00
|
|
|
VIR_FREE(cfg->autoDumpPath);
|
|
|
|
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(cfg->securityDriverNames);
|
2013-01-10 21:03:14 +00:00
|
|
|
|
|
|
|
VIR_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
|
|
|
|
|
|
|
VIR_FREE(cfg->memoryBackingDir);
|
2017-04-04 16:22:31 +00:00
|
|
|
VIR_FREE(cfg->swtpmStorageDir);
|
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
|
|
|
|
virQEMUDriverConfigHugeTLBFSInit(virHugeTLBFSPtr hugetlbfs,
|
|
|
|
const char *path,
|
|
|
|
bool deflt)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(hugetlbfs->mnt_dir, path) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virFileGetHugepageSize(path, &hugetlbfs->size) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
hugetlbfs->deflt = deflt;
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 21:03:05 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadSpecificTLSEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "vxhs_tls", &cfg->vxhsTLS) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virConfGetValueString(conf, "vxhs_tls_x509_cert_dir", &cfg->vxhsTLSx509certdir) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virConfGetValueBool(conf, "nbd_tls", &cfg->nbdTLS) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virConfGetValueString(conf, "nbd_tls_x509_cert_dir", &cfg->nbdTLSx509certdir) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#define GET_CONFIG_TLS_CERTINFO(val) \
|
|
|
|
do { \
|
|
|
|
if ((rv = virConfGetValueBool(conf, #val "_tls_x509_verify", \
|
|
|
|
&cfg->val## TLSx509verify)) < 0) \
|
|
|
|
return -1; \
|
|
|
|
if (rv == 1) \
|
|
|
|
cfg->val## TLSx509verifyPresent = true; \
|
|
|
|
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)
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "chardev_tls", &cfg->chardevTLS) < 0)
|
|
|
|
return -1;
|
|
|
|
GET_CONFIG_TLS_CERTINFO(chardev);
|
|
|
|
|
|
|
|
GET_CONFIG_TLS_CERTINFO(migrate);
|
|
|
|
|
|
|
|
#undef GET_CONFIG_TLS_CERTINFO
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 20:53:01 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadRemoteDisplayEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:24:02 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadSaveEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:35:59 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadProcessEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf)
|
|
|
|
{
|
|
|
|
char *stdioHandler = NULL;
|
|
|
|
char **hugetlbfs = NULL;
|
|
|
|
char *corestr = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "hugetlbfs_mount", true,
|
|
|
|
&hugetlbfs) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
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 = virStringListLength((const char *const *)hugetlbfs);
|
|
|
|
if (hugetlbfs[0] &&
|
|
|
|
VIR_ALLOC_N(cfg->hugetlbfs, cfg->nhugetlbfs) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; hugetlbfs[i] != NULL; i++) {
|
|
|
|
if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[i],
|
|
|
|
hugetlbfs[i], i != 0) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "clear_emulator_capabilities", &cfg->clearEmulatorCapabilities) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueString(conf, "bridge_helper", &cfg->bridgeHelperName) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "pr_helper", &cfg->prHelperName) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "set_process_name", &cfg->setProcessName) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueUInt(conf, "max_processes", &cfg->maxProcesses) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueUInt(conf, "max_files", &cfg->maxFiles) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueType(conf, "max_core") == VIR_CONF_STRING) {
|
|
|
|
if (virConfGetValueString(conf, "max_core", &corestr) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (STREQ(corestr, "unlimited")) {
|
|
|
|
cfg->maxCore = ULLONG_MAX;
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("Unknown core size '%s'"),
|
|
|
|
corestr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else if (virConfGetValueULLong(conf, "max_core", &cfg->maxCore) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "dump_guest_core", &cfg->dumpGuestCore) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueString(conf, "stdio_handler", &stdioHandler) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
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);
|
|
|
|
VIR_FREE(stdioHandler);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
VIR_FREE(stdioHandler);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virStringListFree(hugetlbfs);
|
|
|
|
VIR_FREE(corestr);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:33:26 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadDeviceEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:33:07 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadRPCEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 11:32:40 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadNetworkEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:18:04 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadLogEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf)
|
|
|
|
{
|
|
|
|
return virConfGetValueBool(conf, "log_timestamp", &cfg->logTimestamp);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:17:00 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadNVRAMEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf)
|
|
|
|
{
|
|
|
|
char **nvram = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "nvram", false, &nvram) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (nvram) {
|
|
|
|
virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
|
|
|
|
|
|
|
|
cfg->nfirmwares = virStringListLength((const char *const *)nvram);
|
|
|
|
if (nvram[0] && VIR_ALLOC_N(cfg->firmwares, cfg->nfirmwares) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; nvram[i] != NULL; i++) {
|
|
|
|
if (VIR_ALLOC(cfg->firmwares[i]) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virFirmwareParse(nvram[i], cfg->firmwares[i]) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virStringListFree(nvram);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:14:44 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadGlusterDebugEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf)
|
|
|
|
{
|
|
|
|
return virConfGetValueUInt(conf, "gluster_debug_level", &cfg->glusterDebugLevel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 20:28:57 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadSecurityEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf,
|
|
|
|
bool privileged)
|
|
|
|
{
|
|
|
|
char *user = NULL, *group = NULL;
|
|
|
|
char **controllers = NULL;
|
|
|
|
char **namespaces = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
size_t i, j;
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "security_driver", true, &cfg->securityDriverNames) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
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]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "security_default_confined", &cfg->securityDefaultConfined) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueBool(conf, "security_require_confined", &cfg->securityRequireConfined) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "user", &user) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (user && virGetUserID(user, &cfg->user) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "group", &group) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (group && virGetGroupID(group, &cfg->group) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueBool(conf, "dynamic_ownership", &cfg->dynamicOwnership) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "cgroup_controllers", false,
|
|
|
|
&controllers) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
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]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
cfg->cgroupControllers |= (1 << ctl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "cgroup_device_acl", false,
|
|
|
|
&cfg->cgroupDeviceACL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueInt(conf, "seccomp_sandbox", &cfg->seccompSandbox) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueStringList(conf, "namespaces", false, &namespaces) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
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]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!privileged) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("cannot use namespaces in session mode"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!qemuDomainNamespaceAvailable(ns)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("%s namespace is not available"),
|
|
|
|
namespaces[i]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virBitmapSetBit(cfg->namespaces, ns) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to enable namespace: %s"),
|
|
|
|
namespaces[i]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virStringListFree(controllers);
|
|
|
|
virStringListFree(namespaces);
|
|
|
|
VIR_FREE(user);
|
|
|
|
VIR_FREE(group);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-15 09:10:36 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadMemoryEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf)
|
|
|
|
{
|
|
|
|
return virConfGetValueString(conf, "memory_backing_dir", &cfg->memoryBackingDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-14 20:18:44 +00:00
|
|
|
static int
|
|
|
|
virQEMUDriverConfigLoadSWTPMEntry(virQEMUDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf)
|
|
|
|
{
|
|
|
|
char *swtpm_user = NULL, *swtpm_group = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "swtpm_user", &swtpm_user) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (swtpm_user && virGetUserID(swtpm_user, &cfg->swtpm_user) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virConfGetValueString(conf, "swtpm_group", &swtpm_group) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (swtpm_group && virGetGroupID(swtpm_group, &cfg->swtpm_group) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(swtpm_user);
|
|
|
|
VIR_FREE(swtpm_group);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
|
2017-02-15 09:06:09 +00:00
|
|
|
const char *filename,
|
|
|
|
bool privileged)
|
2013-01-10 21:03:14 +00:00
|
|
|
{
|
|
|
|
virConfPtr conf = NULL;
|
|
|
|
int ret = -1;
|
2016-06-14 18:14:31 +00:00
|
|
|
int rv;
|
2015-03-18 11:14:55 +00:00
|
|
|
char *corestr = 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)))
|
|
|
|
goto cleanup;
|
2007-10-12 16:05:44 +00:00
|
|
|
|
2017-06-29 12:27:55 +00:00
|
|
|
if ((rv = virConfGetValueString(conf, "default_tls_x509_cert_dir", &cfg->defaultTLSx509certdir)) < 0)
|
2016-06-14 18:14:31 +00:00
|
|
|
goto cleanup;
|
2017-06-29 12:27:55 +00:00
|
|
|
cfg->checkdefaultTLSx509certdir = (rv == 1);
|
2016-06-14 18:14:31 +00:00
|
|
|
if (virConfGetValueBool(conf, "default_tls_x509_verify", &cfg->defaultTLSx509verify) < 0)
|
|
|
|
goto cleanup;
|
2016-09-08 14:04:59 +00:00
|
|
|
if (virConfGetValueString(conf, "default_tls_x509_secret_uuid",
|
|
|
|
&cfg->defaultTLSx509secretUUID) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-07-08 10:37:54 +00:00
|
|
|
if (virConfGetValueBool(conf, "vnc_auto_unix_socket", &cfg->vncAutoUnixSocket) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueBool(conf, "vnc_tls", &cfg->vncTLS) < 0)
|
|
|
|
goto cleanup;
|
2016-06-14 18:14:31 +00:00
|
|
|
if ((rv = virConfGetValueBool(conf, "vnc_tls_x509_verify", &cfg->vncTLSx509verify)) < 0)
|
2016-07-08 10:37:54 +00:00
|
|
|
goto cleanup;
|
2019-01-14 21:51:00 +00:00
|
|
|
if (rv == 1)
|
|
|
|
cfg->vncTLSx509verifyPresent = true;
|
2016-07-08 10:37:54 +00:00
|
|
|
if (virConfGetValueString(conf, "vnc_tls_x509_cert_dir", &cfg->vncTLSx509certdir) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueString(conf, "vnc_listen", &cfg->vncListen) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueString(conf, "vnc_password", &cfg->vncPassword) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueBool(conf, "vnc_sasl", &cfg->vncSASL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueString(conf, "vnc_sasl_dir", &cfg->vncSASLdir) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueBool(conf, "vnc_allow_host_audio", &cfg->vncAllowHostAudio) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueBool(conf, "nographics_allow_host_audio", &cfg->nogfxAllowHostAudio) < 0)
|
|
|
|
goto cleanup;
|
2012-11-27 16:59:34 +00:00
|
|
|
|
2014-12-09 15:22:09 +00:00
|
|
|
|
2016-07-08 10:37:54 +00:00
|
|
|
if (virConfGetValueBool(conf, "spice_tls", &cfg->spiceTLS) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueString(conf, "spice_tls_x509_cert_dir", &cfg->spiceTLSx509certdir) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueBool(conf, "spice_sasl", &cfg->spiceSASL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueString(conf, "spice_sasl_dir", &cfg->spiceSASLdir) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueString(conf, "spice_listen", &cfg->spiceListen) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueString(conf, "spice_password", &cfg->spicePassword) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
if (virConfGetValueBool(conf, "spice_auto_unix_socket", &cfg->spiceAutoUnixSocket) < 0)
|
|
|
|
goto cleanup;
|
2017-02-12 14:54:48 +00:00
|
|
|
|
2019-01-14 21:03:05 +00:00
|
|
|
if (virQEMUDriverConfigLoadSpecificTLSEntry(cfg, conf) < 0)
|
2016-06-14 19:52:37 +00:00
|
|
|
goto cleanup;
|
2010-03-05 20:31:50 +00:00
|
|
|
|
2019-01-14 20:53:01 +00:00
|
|
|
if (virQEMUDriverConfigLoadRemoteDisplayEntry(cfg, conf, filename) < 0)
|
2012-11-29 11:25:07 +00:00
|
|
|
goto cleanup;
|
2012-06-18 08:22:07 +00:00
|
|
|
|
2019-01-15 11:24:02 +00:00
|
|
|
if (virQEMUDriverConfigLoadSaveEntry(cfg, conf) < 0)
|
2016-07-08 10:37:54 +00:00
|
|
|
goto cleanup;
|
2009-11-03 22:41:23 +00:00
|
|
|
|
2019-01-15 11:35:59 +00:00
|
|
|
if (virQEMUDriverConfigLoadProcessEntry(cfg, conf) < 0)
|
2016-07-08 10:37:54 +00:00
|
|
|
goto cleanup;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2019-01-15 11:33:26 +00:00
|
|
|
if (virQEMUDriverConfigLoadDeviceEntry(cfg, conf) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-01-15 11:33:07 +00:00
|
|
|
if (virQEMUDriverConfigLoadRPCEntry(cfg, conf) < 0)
|
2016-07-08 10:37:54 +00:00
|
|
|
goto cleanup;
|
2013-01-10 21:03:14 +00:00
|
|
|
|
2019-01-15 11:32:40 +00:00
|
|
|
if (virQEMUDriverConfigLoadNetworkEntry(cfg, conf, filename) < 0)
|
2014-10-07 04:07:32 +00:00
|
|
|
goto cleanup;
|
2013-10-09 09:32:55 +00:00
|
|
|
|
2019-01-15 09:18:04 +00:00
|
|
|
if (virQEMUDriverConfigLoadLogEntry(cfg, conf) < 0)
|
2016-07-08 10:37:54 +00:00
|
|
|
goto cleanup;
|
2014-08-07 14:59:21 +00:00
|
|
|
|
2019-01-15 09:17:00 +00:00
|
|
|
if (virQEMUDriverConfigLoadNVRAMEntry(cfg, conf) < 0)
|
2016-07-08 10:37:54 +00:00
|
|
|
goto cleanup;
|
2019-01-15 09:14:44 +00:00
|
|
|
|
|
|
|
if (virQEMUDriverConfigLoadGlusterDebugEntry(cfg, conf) < 0)
|
2016-09-21 19:34:18 +00:00
|
|
|
goto cleanup;
|
2014-08-07 14:59:21 +00:00
|
|
|
|
2019-01-14 20:28:57 +00:00
|
|
|
if (virQEMUDriverConfigLoadSecurityEntry(cfg, conf, privileged) < 0)
|
2016-11-18 15:34:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-01-15 09:10:36 +00:00
|
|
|
if (virQEMUDriverConfigLoadMemoryEntry(cfg, conf) < 0)
|
2017-02-02 13:27:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-01-14 20:18:44 +00:00
|
|
|
if (virQEMUDriverConfigLoadSWTPMEntry(cfg, conf) < 0)
|
2017-04-04 16:22:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-11-29 11:25:07 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2015-03-18 11:14:55 +00:00
|
|
|
VIR_FREE(corestr);
|
2012-10-17 09:23:12 +00:00
|
|
|
virConfFree(conf);
|
2012-11-29 11:25:07 +00:00
|
|
|
return ret;
|
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
|
|
|
|
virQEMUDriverConfigValidate(virQEMUDriverConfigPtr cfg)
|
|
|
|
{
|
|
|
|
if (cfg->checkdefaultTLSx509certdir) {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
|
virQEMUDriverConfigSetDefaults(virQEMUDriverConfigPtr cfg)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
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) { \
|
|
|
|
if (VIR_STRDUP(cfg->val## TLSx509secretUUID, \
|
|
|
|
cfg->defaultTLSx509secretUUID) < 0) \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
SET_TLS_SECRET_UUID_DEFAULT(chardev);
|
|
|
|
SET_TLS_SECRET_UUID_DEFAULT(migrate);
|
|
|
|
|
|
|
|
#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)) { \
|
|
|
|
if (VIR_STRDUP(cfg->val ## TLSx509certdir, \
|
|
|
|
SYSCONFDIR "/pki/libvirt-"#val) < 0) \
|
|
|
|
goto cleanup; \
|
|
|
|
} else { \
|
|
|
|
if (VIR_STRDUP(cfg->val ## TLSx509certdir, \
|
|
|
|
cfg->defaultTLSx509certdir) < 0) \
|
|
|
|
goto cleanup; \
|
|
|
|
} \
|
|
|
|
} 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(vxhs);
|
|
|
|
SET_TLS_X509_CERT_DEFAULT(nbd);
|
|
|
|
|
|
|
|
#undef SET_TLS_X509_CERT_DEFAULT
|
|
|
|
|
2019-01-14 21:51:00 +00:00
|
|
|
#define SET_TLS_VERIFY_DEFAULT(val) \
|
|
|
|
do { \
|
|
|
|
if (!cfg->val## TLSx509verifyPresent) \
|
|
|
|
cfg->val## TLSx509verify = cfg->defaultTLSx509verify; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
SET_TLS_VERIFY_DEFAULT(vnc);
|
|
|
|
SET_TLS_VERIFY_DEFAULT(chardev);
|
|
|
|
SET_TLS_VERIFY_DEFAULT(migrate);
|
|
|
|
|
|
|
|
#undef SET_TLS_VERIFY_DEFAULT
|
|
|
|
|
|
|
|
ret = 0;
|
2019-01-14 22:06:06 +00:00
|
|
|
cleanup:
|
2019-01-14 21:51:00 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-10 21:03:14 +00:00
|
|
|
virQEMUDriverConfigPtr virQEMUDriverGetConfig(virQEMUDriverPtr driver)
|
|
|
|
{
|
2013-02-06 18:17:20 +00:00
|
|
|
virQEMUDriverConfigPtr conf;
|
|
|
|
qemuDriverLock(driver);
|
|
|
|
conf = virObjectRef(driver->config);
|
|
|
|
qemuDriverUnlock(driver);
|
|
|
|
return conf;
|
2013-01-10 21:03:14 +00:00
|
|
|
}
|
|
|
|
|
2015-06-15 18:59:58 +00:00
|
|
|
bool
|
|
|
|
virQEMUDriverIsPrivileged(virQEMUDriverPtr driver)
|
|
|
|
{
|
|
|
|
return driver->privileged;
|
|
|
|
}
|
|
|
|
|
2013-03-31 18:03:42 +00:00
|
|
|
virDomainXMLOptionPtr
|
2013-03-11 09:24:29 +00:00
|
|
|
virQEMUDriverCreateXMLConf(virQEMUDriverPtr driver)
|
2013-03-05 15:17:24 +00:00
|
|
|
{
|
2013-03-11 09:24:29 +00:00
|
|
|
virQEMUDriverDomainDefParserConfig.priv = driver;
|
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
|
|
|
|
|
|
|
virCapsPtr virQEMUDriverCreateCapabilities(virQEMUDriverPtr driver)
|
|
|
|
{
|
2013-10-18 12:13:21 +00:00
|
|
|
size_t i, j;
|
2013-02-01 17:04:15 +00:00
|
|
|
virCapsPtr caps;
|
|
|
|
virSecurityManagerPtr *sec_managers = NULL;
|
|
|
|
/* Security driver data */
|
2013-10-18 12:13:21 +00:00
|
|
|
const char *doi, *model, *lbl, *type;
|
2013-02-01 17:04:15 +00:00
|
|
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
2013-10-18 12:13:21 +00:00
|
|
|
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)))
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
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"));
|
2013-02-19 09:56:06 +00:00
|
|
|
goto error;
|
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)))
|
2013-02-19 09:56:06 +00:00
|
|
|
goto error;
|
2013-02-01 17:04:15 +00:00
|
|
|
|
|
|
|
/* calculate length */
|
|
|
|
for (i = 0; sec_managers[i]; i++)
|
|
|
|
;
|
|
|
|
caps->host.nsecModels = i;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0)
|
2013-07-04 10:14:12 +00:00
|
|
|
goto error;
|
2013-02-01 17:04:15 +00:00
|
|
|
|
|
|
|
for (i = 0; sec_managers[i]; i++) {
|
2013-10-18 12:13:21 +00:00
|
|
|
virCapsHostSecModelPtr sm = &caps->host.secModels[i];
|
2017-02-13 13:36:53 +00:00
|
|
|
doi = qemuSecurityGetDOI(sec_managers[i]);
|
|
|
|
model = qemuSecurityGetModel(sec_managers[i]);
|
2013-10-18 12:13:21 +00:00
|
|
|
if (VIR_STRDUP(sm->model, model) < 0 ||
|
|
|
|
VIR_STRDUP(sm->doi, doi) < 0)
|
2013-05-20 09:23:13 +00:00
|
|
|
goto error;
|
2013-10-18 12:13:21 +00:00
|
|
|
|
|
|
|
for (j = 0; j < ARRAY_CARDINALITY(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)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-02-01 17:04:15 +00:00
|
|
|
VIR_DEBUG("Initialized caps for security driver \"%s\" with "
|
|
|
|
"DOI \"%s\"", model, doi);
|
|
|
|
}
|
|
|
|
VIR_FREE(sec_managers);
|
|
|
|
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
return caps;
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
error:
|
2013-02-01 17:04:15 +00:00
|
|
|
VIR_FREE(sec_managers);
|
|
|
|
virObjectUnref(caps);
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virQEMUDriverGetCapabilities:
|
|
|
|
*
|
|
|
|
* Get a reference to the virCapsPtr instance for the
|
|
|
|
* driver. If @refresh is true, the capabilities will be
|
|
|
|
* rebuilt first
|
|
|
|
*
|
|
|
|
* The caller must release the reference with virObjetUnref
|
|
|
|
*
|
|
|
|
* Returns: a reference to a virCapsPtr instance or NULL
|
|
|
|
*/
|
|
|
|
virCapsPtr virQEMUDriverGetCapabilities(virQEMUDriverPtr driver,
|
|
|
|
bool refresh)
|
|
|
|
{
|
2013-02-06 18:17:20 +00:00
|
|
|
virCapsPtr ret = NULL;
|
2013-02-01 17:04:15 +00:00
|
|
|
if (refresh) {
|
|
|
|
virCapsPtr caps = NULL;
|
|
|
|
if ((caps = virQEMUDriverCreateCapabilities(driver)) == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2013-02-06 18:17:20 +00:00
|
|
|
qemuDriverLock(driver);
|
2013-02-01 17:04:15 +00:00
|
|
|
virObjectUnref(driver->caps);
|
|
|
|
driver->caps = caps;
|
2013-02-06 18:17:20 +00:00
|
|
|
} else {
|
|
|
|
qemuDriverLock(driver);
|
2013-02-01 17:04:15 +00:00
|
|
|
}
|
|
|
|
|
2015-04-16 18:51:26 +00:00
|
|
|
if (driver->caps->nguests == 0 && !refresh) {
|
|
|
|
VIR_DEBUG("Capabilities didn't detect any guests. Forcing a "
|
|
|
|
"refresh.");
|
|
|
|
qemuDriverUnlock(driver);
|
|
|
|
return virQEMUDriverGetCapabilities(driver, true);
|
|
|
|
}
|
|
|
|
|
2013-02-06 18:17:20 +00:00
|
|
|
ret = virObjectRef(driver->caps);
|
|
|
|
qemuDriverUnlock(driver);
|
|
|
|
return ret;
|
2013-02-01 17:04:15 +00:00
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:35 +00:00
|
|
|
struct _qemuSharedDeviceEntry {
|
2013-02-20 07:43:55 +00:00
|
|
|
size_t ref;
|
|
|
|
char **domains; /* array of domain names */
|
|
|
|
};
|
|
|
|
|
2013-05-03 18:07:35 +00:00
|
|
|
/* Construct the hash key for sharedDevices as "major:minor" */
|
2013-01-02 14:37:07 +00:00
|
|
|
char *
|
2013-05-03 18:07:35 +00:00
|
|
|
qemuGetSharedDeviceKey(const char *device_path)
|
2013-01-02 14:37:07 +00:00
|
|
|
{
|
|
|
|
int maj, min;
|
|
|
|
char *key = NULL;
|
|
|
|
int rc;
|
|
|
|
|
2013-05-03 18:07:35 +00:00
|
|
|
if ((rc = virGetDeviceID(device_path, &maj, &min)) < 0) {
|
2013-01-02 14:37:07 +00:00
|
|
|
virReportSystemError(-rc,
|
|
|
|
_("Unable to get minor number of device '%s'"),
|
2013-05-03 18:07:35 +00:00
|
|
|
device_path);
|
2013-01-02 14:37:07 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-04 10:14:12 +00:00
|
|
|
if (virAsprintf(&key, "%d:%d", maj, min) < 0)
|
2013-01-02 14:37:07 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
2015-07-06 17:08:32 +00:00
|
|
|
/*
|
|
|
|
* Make necessary checks for the need to check and for the current setting
|
|
|
|
* of the 'unpriv_sgio' value for the device_path passed.
|
2013-02-19 12:27:41 +00:00
|
|
|
*
|
2015-07-06 17:08:32 +00:00
|
|
|
* Returns:
|
|
|
|
* 0 - Success
|
|
|
|
* -1 - Some failure which would already have been messaged
|
|
|
|
* -2 - Mismatch with the "shared" sgio setting - needs to be messaged
|
|
|
|
* by caller since it has context of which type of disk resource is
|
|
|
|
* being used and in the future the hostdev information.
|
2013-02-19 12:27:41 +00:00
|
|
|
*/
|
|
|
|
static int
|
2015-07-06 17:08:32 +00:00
|
|
|
qemuCheckUnprivSGIO(virHashTablePtr sharedDevices,
|
|
|
|
const char *device_path,
|
|
|
|
int sgio)
|
2013-02-19 12:27:41 +00:00
|
|
|
{
|
|
|
|
char *sysfs_path = NULL;
|
|
|
|
char *key = NULL;
|
2013-02-20 07:43:55 +00:00
|
|
|
int val;
|
2014-08-07 12:56:30 +00:00
|
|
|
int ret = -1;
|
2013-05-03 18:07:44 +00:00
|
|
|
|
2015-07-06 17:08:32 +00:00
|
|
|
if (!(sysfs_path = virGetUnprivSGIOSysfsPath(device_path, NULL)))
|
2013-02-19 12:27:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-08-07 12:56:30 +00:00
|
|
|
/* It can't be conflict if unpriv_sgio is not supported by kernel. */
|
|
|
|
if (!virFileExists(sysfs_path)) {
|
|
|
|
ret = 0;
|
2013-02-19 12:27:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-07-06 17:08:32 +00:00
|
|
|
if (!(key = qemuGetSharedDeviceKey(device_path)))
|
2013-02-19 12:27:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-08-07 12:56:30 +00:00
|
|
|
/* It can't be conflict if no other domain is sharing it. */
|
|
|
|
if (!(virHashLookup(sharedDevices, key))) {
|
|
|
|
ret = 0;
|
2013-02-19 12:27:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2015-07-06 17:08:32 +00:00
|
|
|
if (virGetDeviceUnprivSGIO(device_path, NULL, &val) < 0)
|
2013-02-19 12:27:41 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2015-07-06 17:08:32 +00:00
|
|
|
/* Error message on failure needs to be handled in caller
|
|
|
|
* since there is more specific knowledge of device
|
|
|
|
*/
|
2014-08-07 12:56:30 +00:00
|
|
|
if (!((val == 0 &&
|
2015-07-06 17:08:32 +00:00
|
|
|
(sgio == VIR_DOMAIN_DEVICE_SGIO_FILTERED ||
|
|
|
|
sgio == VIR_DOMAIN_DEVICE_SGIO_DEFAULT)) ||
|
2014-08-07 12:56:30 +00:00
|
|
|
(val == 1 &&
|
2015-07-06 17:08:32 +00:00
|
|
|
sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED))) {
|
|
|
|
ret = -2;
|
2014-08-07 12:56:30 +00:00
|
|
|
goto cleanup;
|
2013-04-04 19:38:02 +00:00
|
|
|
}
|
|
|
|
|
2014-08-07 12:56:30 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2013-02-19 12:27:41 +00:00
|
|
|
VIR_FREE(sysfs_path);
|
|
|
|
VIR_FREE(key);
|
|
|
|
return ret;
|
|
|
|
}
|
qemu: Forbid "sgio" support for SCSI generic host device
The kernel didn't support the unprivileged SGIO for SCSI generic
device finally, and since it's unknow whether the way to support
unprivileged SGIO for SCSI generic device will be similar as for
SCSI block device or not, even it's simliar (I.e. via sysfs, for
SCSI block device, it's /sys/dev/block/8\:0/queue/unpriv_sgio,
for example), the file name might be different, So it's better not
guess what it should be like currently.
This patch removes the related code (mainly about the "shareable"
checking on the "sgio" setting, it's not supported at all, why
we leave checking code there? :-), and error out if "sgio" is
specified in the domain config.
2014-03-07 14:23:26 +00:00
|
|
|
|
2014-08-07 12:56:30 +00:00
|
|
|
|
2015-07-06 17:08:32 +00:00
|
|
|
/* Check if a shared device's setting conflicts with the conf
|
|
|
|
* used by other domain(s). Currently only checks the sgio
|
|
|
|
* setting. Note that this should only be called for disk with
|
|
|
|
* block source if the device type is disk.
|
|
|
|
*
|
|
|
|
* Returns 0 if no conflicts, otherwise returns -1.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
qemuCheckSharedDisk(virHashTablePtr sharedDevices,
|
|
|
|
virDomainDiskDefPtr disk)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if ((ret = qemuCheckUnprivSGIO(sharedDevices, disk->src->path,
|
|
|
|
disk->sgio)) < 0) {
|
|
|
|
if (ret == -2) {
|
|
|
|
if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_VOLUME) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("sgio of shared disk 'pool=%s' 'volume=%s' "
|
|
|
|
"conflicts with other active domains"),
|
|
|
|
disk->src->srcpool->pool,
|
|
|
|
disk->src->srcpool->volume);
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("sgio of shared disk '%s' conflicts with "
|
|
|
|
"other active domains"),
|
|
|
|
disk->src->path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-20 07:43:55 +00:00
|
|
|
bool
|
2013-05-03 18:07:35 +00:00
|
|
|
qemuSharedDeviceEntryDomainExists(qemuSharedDeviceEntryPtr entry,
|
|
|
|
const char *name,
|
|
|
|
int *idx)
|
2013-02-20 07:43:55 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < entry->ref; i++) {
|
|
|
|
if (STREQ(entry->domains[i], name)) {
|
|
|
|
if (idx)
|
|
|
|
*idx = i;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-05-03 18:07:35 +00:00
|
|
|
qemuSharedDeviceEntryFree(void *payload, const void *name ATTRIBUTE_UNUSED)
|
2013-02-20 07:43:55 +00:00
|
|
|
{
|
2013-05-03 18:07:35 +00:00
|
|
|
qemuSharedDeviceEntryPtr entry = payload;
|
2013-02-20 07:43:55 +00:00
|
|
|
size_t i;
|
|
|
|
|
2013-03-12 08:10:41 +00:00
|
|
|
if (!entry)
|
|
|
|
return;
|
|
|
|
|
2014-11-13 14:25:30 +00:00
|
|
|
for (i = 0; i < entry->ref; i++)
|
2013-02-20 07:43:55 +00:00
|
|
|
VIR_FREE(entry->domains[i]);
|
|
|
|
VIR_FREE(entry->domains);
|
|
|
|
VIR_FREE(entry);
|
|
|
|
}
|
|
|
|
|
2014-08-06 11:57:42 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
qemuSharedDeviceEntryInsert(virQEMUDriverPtr driver,
|
|
|
|
const char *key,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
qemuSharedDeviceEntry *entry = NULL;
|
|
|
|
|
|
|
|
if ((entry = virHashLookup(driver->sharedDevices, key))) {
|
|
|
|
/* Nothing to do if the shared scsi host device is already
|
|
|
|
* recorded in the table.
|
|
|
|
*/
|
2014-09-17 10:36:21 +00:00
|
|
|
if (!qemuSharedDeviceEntryDomainExists(entry, name, NULL)) {
|
|
|
|
if (VIR_EXPAND_N(entry->domains, entry->ref, 1) < 0 ||
|
|
|
|
VIR_STRDUP(entry->domains[entry->ref - 1], name) < 0) {
|
|
|
|
/* entry is owned by the hash table here */
|
|
|
|
entry = NULL;
|
|
|
|
goto error;
|
|
|
|
}
|
2014-08-06 11:57:42 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (VIR_ALLOC(entry) < 0 ||
|
|
|
|
VIR_ALLOC_N(entry->domains, 1) < 0 ||
|
|
|
|
VIR_STRDUP(entry->domains[0], name) < 0)
|
2014-09-17 10:36:21 +00:00
|
|
|
goto error;
|
2014-08-06 11:57:42 +00:00
|
|
|
|
|
|
|
entry->ref = 1;
|
|
|
|
|
2017-09-15 11:36:55 +00:00
|
|
|
if (virHashAddEntry(driver->sharedDevices, key, entry) < 0)
|
2014-09-17 10:36:21 +00:00
|
|
|
goto error;
|
2014-08-06 11:57:42 +00:00
|
|
|
}
|
|
|
|
|
2014-09-17 10:36:21 +00:00
|
|
|
return 0;
|
2014-08-06 11:57:42 +00:00
|
|
|
|
2014-09-17 10:36:21 +00:00
|
|
|
error:
|
2014-08-06 11:57:42 +00:00
|
|
|
qemuSharedDeviceEntryFree(entry, NULL);
|
2014-09-17 10:36:21 +00:00
|
|
|
return -1;
|
2014-08-06 11:57:42 +00:00
|
|
|
}
|
|
|
|
|
2014-08-07 13:20:40 +00:00
|
|
|
|
|
|
|
/* qemuAddSharedDisk:
|
2013-02-20 07:43:55 +00:00
|
|
|
* @driver: Pointer to qemu driver struct
|
2014-08-07 13:20:40 +00:00
|
|
|
* @src: disk source
|
2013-02-20 07:43:55 +00:00
|
|
|
* @name: The domain name
|
|
|
|
*
|
|
|
|
* Increase ref count and add the domain name into the list which
|
2013-05-03 18:07:37 +00:00
|
|
|
* records all the domains that use the shared device if the entry
|
2013-02-20 07:43:55 +00:00
|
|
|
* already exists, otherwise add a new entry.
|
2013-01-02 14:37:07 +00:00
|
|
|
*/
|
2018-09-25 13:02:25 +00:00
|
|
|
int
|
2014-08-07 13:20:40 +00:00
|
|
|
qemuAddSharedDisk(virQEMUDriverPtr driver,
|
|
|
|
virDomainDiskDefPtr disk,
|
|
|
|
const char *name)
|
2013-01-02 14:37:07 +00:00
|
|
|
{
|
|
|
|
char *key = NULL;
|
2013-02-06 14:18:34 +00:00
|
|
|
int ret = -1;
|
2013-01-02 14:37:07 +00:00
|
|
|
|
2016-05-02 11:42:32 +00:00
|
|
|
if (virStorageSourceIsEmpty(disk->src) ||
|
|
|
|
!disk->src->shared ||
|
|
|
|
!virStorageSourceIsBlockLocal(disk->src))
|
2014-08-07 13:20:40 +00:00
|
|
|
return 0;
|
2013-05-03 18:07:37 +00:00
|
|
|
|
2014-08-07 13:20:40 +00:00
|
|
|
qemuDriverLock(driver);
|
2013-05-03 18:07:37 +00:00
|
|
|
|
2014-08-07 13:20:40 +00:00
|
|
|
if (qemuCheckSharedDisk(driver->sharedDevices, disk) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(key = qemuGetSharedDeviceKey(virDomainDiskGetSource(disk))))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuSharedDeviceEntryInsert(driver, key, name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
qemuDriverUnlock(driver);
|
|
|
|
VIR_FREE(key);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-16 17:33:37 +00:00
|
|
|
static bool
|
|
|
|
qemuIsSharedHostdev(virDomainHostdevDefPtr hostdev)
|
|
|
|
{
|
|
|
|
return (hostdev->shareable &&
|
2016-11-15 18:25:41 +00:00
|
|
|
(virHostdevIsSCSIDevice(hostdev) &&
|
|
|
|
hostdev->source.subsys.u.scsi.protocol !=
|
|
|
|
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI));
|
2015-06-16 17:33:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-07 16:16:38 +00:00
|
|
|
static char *
|
2015-06-16 17:58:44 +00:00
|
|
|
qemuGetHostdevPath(virDomainHostdevDefPtr hostdev)
|
2014-08-07 13:20:40 +00:00
|
|
|
{
|
|
|
|
virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
|
|
|
|
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
|
|
|
|
char *dev_name = NULL;
|
|
|
|
char *dev_path = NULL;
|
2013-02-19 12:27:41 +00:00
|
|
|
|
2014-08-07 13:20:40 +00:00
|
|
|
if (!(dev_name = virSCSIDeviceGetDevName(NULL,
|
|
|
|
scsihostsrc->adapter,
|
|
|
|
scsihostsrc->bus,
|
|
|
|
scsihostsrc->target,
|
|
|
|
scsihostsrc->unit)))
|
|
|
|
goto cleanup;
|
2013-05-03 18:07:37 +00:00
|
|
|
|
2015-06-16 17:58:44 +00:00
|
|
|
ignore_value(virAsprintf(&dev_path, "/dev/%s", dev_name));
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(dev_name);
|
|
|
|
return dev_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-07 16:16:38 +00:00
|
|
|
static int
|
|
|
|
qemuAddSharedHostdev(virQEMUDriverPtr driver,
|
|
|
|
virDomainHostdevDefPtr hostdev,
|
|
|
|
const char *name)
|
|
|
|
{
|
2015-06-16 15:34:06 +00:00
|
|
|
char *dev_path = NULL;
|
2014-08-07 16:16:38 +00:00
|
|
|
char *key = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2015-06-16 17:33:37 +00:00
|
|
|
if (!qemuIsSharedHostdev(hostdev))
|
2014-08-07 16:16:38 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-06-16 15:34:06 +00:00
|
|
|
if (!(dev_path = qemuGetHostdevPath(hostdev)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(key = qemuGetSharedDeviceKey(dev_path)))
|
|
|
|
goto cleanup;
|
2014-08-07 16:16:38 +00:00
|
|
|
|
|
|
|
qemuDriverLock(driver);
|
|
|
|
ret = qemuSharedDeviceEntryInsert(driver, key, name);
|
|
|
|
qemuDriverUnlock(driver);
|
|
|
|
|
2015-06-16 15:34:06 +00:00
|
|
|
cleanup:
|
|
|
|
VIR_FREE(dev_path);
|
2013-01-02 14:37:07 +00:00
|
|
|
VIR_FREE(key);
|
2013-02-06 14:18:34 +00:00
|
|
|
return ret;
|
2013-01-02 14:37:07 +00:00
|
|
|
}
|
|
|
|
|
2014-08-07 15:55:12 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
qemuSharedDeviceEntryRemove(virQEMUDriverPtr driver,
|
|
|
|
const char *key,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
qemuSharedDeviceEntryPtr entry = NULL;
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
if (!(entry = virHashLookup(driver->sharedDevices, key)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Nothing to do if the shared disk is not recored in the table. */
|
|
|
|
if (!qemuSharedDeviceEntryDomainExists(entry, name, &idx))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (entry->ref != 1)
|
|
|
|
VIR_DELETE_ELEMENT(entry->domains, idx, entry->ref);
|
|
|
|
else
|
|
|
|
ignore_value(virHashRemoveEntry(driver->sharedDevices, key));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-07 13:20:40 +00:00
|
|
|
/* qemuAddSharedDevice:
|
|
|
|
* @driver: Pointer to qemu driver struct
|
|
|
|
* @dev: The device def
|
|
|
|
* @name: The domain name
|
|
|
|
*
|
|
|
|
* Increase ref count and add the domain name into the list which
|
|
|
|
* records all the domains that use the shared device if the entry
|
|
|
|
* already exists, otherwise add a new entry.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuAddSharedDevice(virQEMUDriverPtr driver,
|
|
|
|
virDomainDeviceDefPtr dev,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
/* Currently the only conflicts we have to care about for
|
|
|
|
* the shared disk and shared host device is "sgio" setting,
|
|
|
|
* which is only valid for block disk and scsi host device.
|
|
|
|
*/
|
|
|
|
if (dev->type == VIR_DOMAIN_DEVICE_DISK)
|
|
|
|
return qemuAddSharedDisk(driver, dev->data.disk, name);
|
|
|
|
else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV)
|
|
|
|
return qemuAddSharedHostdev(driver, dev->data.hostdev, name);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-07 13:20:40 +00:00
|
|
|
|
2014-08-08 08:55:30 +00:00
|
|
|
int
|
2014-08-07 13:20:40 +00:00
|
|
|
qemuRemoveSharedDisk(virQEMUDriverPtr driver,
|
|
|
|
virDomainDiskDefPtr disk,
|
|
|
|
const char *name)
|
2013-01-02 14:37:07 +00:00
|
|
|
{
|
|
|
|
char *key = NULL;
|
2013-02-06 14:18:34 +00:00
|
|
|
int ret = -1;
|
2013-01-02 14:37:07 +00:00
|
|
|
|
2016-05-02 11:42:32 +00:00
|
|
|
if (virStorageSourceIsEmpty(disk->src) ||
|
|
|
|
!disk->src->shared ||
|
|
|
|
!virStorageSourceIsBlockLocal(disk->src))
|
2014-08-07 13:20:40 +00:00
|
|
|
return 0;
|
2013-05-03 18:07:37 +00:00
|
|
|
|
2014-08-07 13:20:40 +00:00
|
|
|
qemuDriverLock(driver);
|
2013-05-03 18:07:37 +00:00
|
|
|
|
2014-08-07 13:20:40 +00:00
|
|
|
if (!(key = qemuGetSharedDeviceKey(virDomainDiskGetSource(disk))))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuSharedDeviceEntryRemove(driver, key, name) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
qemuDriverUnlock(driver);
|
|
|
|
VIR_FREE(key);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
qemuRemoveSharedHostdev(virQEMUDriverPtr driver,
|
|
|
|
virDomainHostdevDefPtr hostdev,
|
|
|
|
const char *name)
|
|
|
|
{
|
2015-06-16 15:34:06 +00:00
|
|
|
char *dev_path = NULL;
|
2014-08-07 13:20:40 +00:00
|
|
|
char *key = NULL;
|
2015-07-09 17:08:49 +00:00
|
|
|
int ret = -1;
|
2014-08-07 13:20:40 +00:00
|
|
|
|
2015-06-16 17:33:37 +00:00
|
|
|
if (!qemuIsSharedHostdev(hostdev))
|
2013-02-19 12:27:40 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-06-16 15:34:06 +00:00
|
|
|
if (!(dev_path = qemuGetHostdevPath(hostdev)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(key = qemuGetSharedDeviceKey(dev_path)))
|
|
|
|
goto cleanup;
|
2013-01-02 14:37:07 +00:00
|
|
|
|
2014-08-07 16:16:38 +00:00
|
|
|
qemuDriverLock(driver);
|
|
|
|
ret = qemuSharedDeviceEntryRemove(driver, key, name);
|
2013-02-06 18:17:20 +00:00
|
|
|
qemuDriverUnlock(driver);
|
2014-08-07 16:16:38 +00:00
|
|
|
|
2015-06-16 15:34:06 +00:00
|
|
|
cleanup:
|
|
|
|
VIR_FREE(dev_path);
|
2013-01-02 14:37:07 +00:00
|
|
|
VIR_FREE(key);
|
2013-02-06 14:18:34 +00:00
|
|
|
return ret;
|
2013-01-02 14:37:07 +00:00
|
|
|
}
|
2013-01-14 16:50:08 +00:00
|
|
|
|
2014-08-07 13:20:40 +00:00
|
|
|
|
|
|
|
/* qemuRemoveSharedDevice:
|
|
|
|
* @driver: Pointer to qemu driver struct
|
|
|
|
* @device: The device def
|
|
|
|
* @name: The domain name
|
|
|
|
*
|
|
|
|
* Decrease ref count and remove the domain name from the list which
|
|
|
|
* records all the domains that use the shared device if ref is not
|
|
|
|
* 1, otherwise remove the entry.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuRemoveSharedDevice(virQEMUDriverPtr driver,
|
|
|
|
virDomainDeviceDefPtr dev,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
if (dev->type == VIR_DOMAIN_DEVICE_DISK)
|
|
|
|
return qemuRemoveSharedDisk(driver, dev->data.disk, name);
|
|
|
|
else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV)
|
|
|
|
return qemuRemoveSharedHostdev(driver, dev->data.hostdev, name);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-05-03 18:07:41 +00:00
|
|
|
int
|
2013-05-03 18:07:42 +00:00
|
|
|
qemuSetUnprivSGIO(virDomainDeviceDefPtr dev)
|
2013-05-03 18:07:41 +00:00
|
|
|
{
|
2013-05-03 18:07:42 +00:00
|
|
|
virDomainDiskDefPtr disk = NULL;
|
|
|
|
virDomainHostdevDefPtr hostdev = NULL;
|
2013-05-03 18:07:41 +00:00
|
|
|
char *sysfs_path = NULL;
|
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
|
|
|
const char *path = NULL;
|
2015-09-18 12:18:38 +00:00
|
|
|
int val = -1;
|
2015-07-06 14:33:04 +00:00
|
|
|
int ret = -1;
|
2013-05-03 18:07:41 +00:00
|
|
|
|
|
|
|
/* "sgio" is only valid for block disk; cdrom
|
|
|
|
* and floopy disk can have empty source.
|
|
|
|
*/
|
2013-05-03 18:07:42 +00:00
|
|
|
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
|
|
|
|
disk = dev->data.disk;
|
|
|
|
|
2013-07-18 10:39:55 +00:00
|
|
|
if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN ||
|
2016-05-02 11:42:32 +00:00
|
|
|
!virStorageSourceIsBlockLocal(disk->src))
|
2013-05-03 18:07:42 +00:00
|
|
|
return 0;
|
|
|
|
|
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
|
|
|
path = virDomainDiskGetSource(disk);
|
2013-05-03 18:07:42 +00:00
|
|
|
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
|
|
|
|
hostdev = dev->data.hostdev;
|
|
|
|
|
2015-06-16 17:33:37 +00:00
|
|
|
if (!qemuIsSharedHostdev(hostdev))
|
|
|
|
return 0;
|
2013-05-03 18:07:42 +00:00
|
|
|
|
2015-06-16 17:33:37 +00:00
|
|
|
if (hostdev->source.subsys.u.scsi.sgio) {
|
qemu: Forbid "sgio" support for SCSI generic host device
The kernel didn't support the unprivileged SGIO for SCSI generic
device finally, and since it's unknow whether the way to support
unprivileged SGIO for SCSI generic device will be similar as for
SCSI block device or not, even it's simliar (I.e. via sysfs, for
SCSI block device, it's /sys/dev/block/8\:0/queue/unpriv_sgio,
for example), the file name might be different, So it's better not
guess what it should be like currently.
This patch removes the related code (mainly about the "shareable"
checking on the "sgio" setting, it's not supported at all, why
we leave checking code there? :-), and error out if "sgio" is
specified in the domain config.
2014-03-07 14:23:26 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("'sgio' is not supported for SCSI "
|
|
|
|
"generic device yet "));
|
2013-05-03 18:07:42 +00:00
|
|
|
goto cleanup;
|
qemu: Forbid "sgio" support for SCSI generic host device
The kernel didn't support the unprivileged SGIO for SCSI generic
device finally, and since it's unknow whether the way to support
unprivileged SGIO for SCSI generic device will be similar as for
SCSI block device or not, even it's simliar (I.e. via sysfs, for
SCSI block device, it's /sys/dev/block/8\:0/queue/unpriv_sgio,
for example), the file name might be different, So it's better not
guess what it should be like currently.
This patch removes the related code (mainly about the "shareable"
checking on the "sgio" setting, it's not supported at all, why
we leave checking code there? :-), and error out if "sgio" is
specified in the domain config.
2014-03-07 14:23:26 +00:00
|
|
|
}
|
2013-05-03 18:07:42 +00:00
|
|
|
|
qemu: Forbid "sgio" support for SCSI generic host device
The kernel didn't support the unprivileged SGIO for SCSI generic
device finally, and since it's unknow whether the way to support
unprivileged SGIO for SCSI generic device will be similar as for
SCSI block device or not, even it's simliar (I.e. via sysfs, for
SCSI block device, it's /sys/dev/block/8\:0/queue/unpriv_sgio,
for example), the file name might be different, So it's better not
guess what it should be like currently.
This patch removes the related code (mainly about the "shareable"
checking on the "sgio" setting, it's not supported at all, why
we leave checking code there? :-), and error out if "sgio" is
specified in the domain config.
2014-03-07 14:23:26 +00:00
|
|
|
return 0;
|
2013-05-03 18:07:42 +00:00
|
|
|
} else {
|
2013-05-03 18:07:41 +00:00
|
|
|
return 0;
|
2013-05-03 18:07:42 +00:00
|
|
|
}
|
2013-05-03 18:07:41 +00:00
|
|
|
|
2015-07-06 14:33:04 +00:00
|
|
|
if (!(sysfs_path = virGetUnprivSGIOSysfsPath(path, NULL)))
|
2013-05-03 18:07:42 +00:00
|
|
|
goto cleanup;
|
2013-05-03 18:07:41 +00:00
|
|
|
|
|
|
|
/* By default, filter the SG_IO commands, i.e. set unpriv_sgio to 0. */
|
qemu: Forbid "sgio" support for SCSI generic host device
The kernel didn't support the unprivileged SGIO for SCSI generic
device finally, and since it's unknow whether the way to support
unprivileged SGIO for SCSI generic device will be similar as for
SCSI block device or not, even it's simliar (I.e. via sysfs, for
SCSI block device, it's /sys/dev/block/8\:0/queue/unpriv_sgio,
for example), the file name might be different, So it's better not
guess what it should be like currently.
This patch removes the related code (mainly about the "shareable"
checking on the "sgio" setting, it's not supported at all, why
we leave checking code there? :-), and error out if "sgio" is
specified in the domain config.
2014-03-07 14:23:26 +00:00
|
|
|
val = (disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED);
|
2013-05-03 18:07:41 +00:00
|
|
|
|
|
|
|
/* Do not do anything if unpriv_sgio is not supported by the kernel and the
|
|
|
|
* whitelist is enabled. But if requesting unfiltered access, always call
|
|
|
|
* virSetDeviceUnprivSGIO, to report an error for unsupported unpriv_sgio.
|
|
|
|
*/
|
2015-09-18 12:18:38 +00:00
|
|
|
if ((virFileExists(sysfs_path) || val == 1) &&
|
|
|
|
virSetDeviceUnprivSGIO(path, NULL, val) < 0)
|
2015-07-06 14:33:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2013-05-03 18:07:41 +00:00
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2013-05-03 18:07:41 +00:00
|
|
|
VIR_FREE(sysfs_path);
|
|
|
|
return ret;
|
|
|
|
}
|
2013-02-06 14:18:34 +00:00
|
|
|
|
2013-01-14 16:50:08 +00:00
|
|
|
int qemuDriverAllocateID(virQEMUDriverPtr driver)
|
|
|
|
{
|
2015-07-28 15:33:53 +00:00
|
|
|
return virAtomicIntInc(&driver->lastvmid);
|
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
|
2018-02-09 16:06:43 +00:00
|
|
|
qemuTranslateSnapshotDiskSourcePool(virDomainSnapshotDiskDefPtr 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 *
|
2016-11-22 12:21:51 +00:00
|
|
|
qemuGetBaseHugepagePath(virHugeTLBFSPtr hugepage)
|
2014-07-23 15:37:18 +00:00
|
|
|
{
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
if (virAsprintf(&ret, "%s/libvirt/qemu", hugepage->mnt_dir) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
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 *
|
|
|
|
qemuGetDomainHugepagePath(const virDomainDef *def,
|
|
|
|
virHugeTLBFSPtr hugepage)
|
|
|
|
{
|
|
|
|
char *base = qemuGetBaseHugepagePath(hugepage);
|
2017-10-23 13:13:09 +00:00
|
|
|
char *domPath = virDomainDefGetShortName(def);
|
2016-12-09 09:51:37 +00:00
|
|
|
char *ret = NULL;
|
2016-11-22 12:21:51 +00:00
|
|
|
|
|
|
|
if (base && domPath)
|
|
|
|
ignore_value(virAsprintf(&ret, "%s/%s", base, domPath));
|
|
|
|
VIR_FREE(domPath);
|
|
|
|
VIR_FREE(base);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
* qemuGetDomainDefaultHugepath:
|
|
|
|
* @def: domain definition
|
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
|
|
|
* @hugetlbfs: array of configured hugepages
|
|
|
|
* @nhugetlbfs: number of item in the array
|
|
|
|
*
|
|
|
|
* Callers must ensure that @hugetlbfs contains at least one entry.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 otherwise.
|
|
|
|
* */
|
2014-07-23 15:37:18 +00:00
|
|
|
char *
|
2016-11-22 12:21:51 +00:00
|
|
|
qemuGetDomainDefaultHugepath(const virDomainDef *def,
|
|
|
|
virHugeTLBFSPtr hugetlbfs,
|
|
|
|
size_t nhugetlbfs)
|
2014-07-23 15:37:18 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < nhugetlbfs; i++)
|
|
|
|
if (hugetlbfs[i].deflt)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (i == nhugetlbfs)
|
|
|
|
i = 0;
|
|
|
|
|
2016-11-22 12:21:51 +00:00
|
|
|
return qemuGetDomainHugepagePath(def, &hugetlbfs[i]);
|
2014-07-23 15:37:18 +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
|
|
|
*
|
|
|
|
* If no specific hugepage size is requested (@pagesize is zero)
|
|
|
|
* the default hugepage size is used).
|
|
|
|
* The resulting path is stored at @memPath.
|
|
|
|
*
|
|
|
|
* Returns 0 on success,
|
|
|
|
* -1 otherwise.
|
|
|
|
*/
|
|
|
|
int
|
2016-11-22 12:21:51 +00:00
|
|
|
qemuGetDomainHupageMemPath(const virDomainDef *def,
|
|
|
|
virQEMUDriverConfigPtr cfg,
|
|
|
|
unsigned long long pagesize,
|
|
|
|
char **memPath)
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pagesize) {
|
2016-11-22 12:21:51 +00:00
|
|
|
if (!(*memPath = qemuGetDomainDefaultHugepath(def,
|
|
|
|
cfg->hugetlbfs,
|
|
|
|
cfg->nhugetlbfs)))
|
2016-09-19 05:45:12 +00:00
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-11-22 12:21:51 +00:00
|
|
|
if (!(*memPath = qemuGetDomainHugepagePath(def, &cfg->hugetlbfs[i])))
|
2016-09-19 05:45:12 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2017-10-23 09:33:06 +00:00
|
|
|
|
|
|
|
|
2017-11-07 14:20:12 +00:00
|
|
|
int
|
|
|
|
qemuGetMemoryBackingBasePath(virQEMUDriverConfigPtr cfg,
|
|
|
|
char **path)
|
|
|
|
{
|
|
|
|
return virAsprintf(path, "%s/libvirt/qemu", cfg->memoryBackingDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuGetMemoryBackingDomainPath(const virDomainDef *def,
|
|
|
|
virQEMUDriverConfigPtr cfg,
|
|
|
|
char **path)
|
|
|
|
{
|
|
|
|
char *shortName = NULL;
|
|
|
|
char *base = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(shortName = virDomainDefGetShortName(def)) ||
|
|
|
|
qemuGetMemoryBackingBasePath(cfg, &base) < 0 ||
|
|
|
|
virAsprintf(path, "%s/%s", base, shortName) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(base);
|
|
|
|
VIR_FREE(shortName);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-23 09:33:06 +00:00
|
|
|
/**
|
|
|
|
* qemuGetMemoryBackingPath:
|
2017-11-07 14:20:12 +00:00
|
|
|
* @def: domain definition
|
2017-10-23 09:33:06 +00:00
|
|
|
* @cfg: the driver config
|
2017-11-07 14:20:12 +00:00
|
|
|
* @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
|
2017-11-07 14:20:12 +00:00
|
|
|
qemuGetMemoryBackingPath(const virDomainDef *def,
|
|
|
|
virQEMUDriverConfigPtr cfg,
|
|
|
|
const char *alias,
|
2017-10-23 09:33:06 +00:00
|
|
|
char **memPath)
|
|
|
|
{
|
2017-11-07 14:20:12 +00:00
|
|
|
char *domainPath = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!alias) {
|
|
|
|
/* This should never happen (TM) */
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("memory device alias is not assigned"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemuGetMemoryBackingDomainPath(def, cfg, &domainPath) < 0 ||
|
|
|
|
virAsprintf(memPath, "%s/%s", domainPath, alias) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(domainPath);
|
|
|
|
return ret;
|
2017-10-23 09:33:06 +00:00
|
|
|
}
|