2013-09-04 05:43:00 +00:00
|
|
|
/*
|
|
|
|
* libxl_conf.c: libxl configuration management
|
|
|
|
*
|
2014-03-17 20:14:11 +00:00
|
|
|
* Copyright (C) 2012-2014 Red Hat, Inc.
|
2013-09-04 05:43:00 +00:00
|
|
|
* Copyright (c) 2011-2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
2012-02-02 22:47:04 +00:00
|
|
|
* Copyright (C) 2011 Univention GmbH.
|
2011-02-10 22:42:34 +00:00
|
|
|
*
|
|
|
|
* 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/>.
|
2011-03-29 12:24:05 +00:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Jim Fehlig <jfehlig@novell.com>
|
2011-05-26 15:09:01 +00:00
|
|
|
* Markus Groß <gross@univention.de>
|
2011-02-10 22:42:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <regex.h>
|
|
|
|
#include <libxl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
#include "datatypes.h"
|
2013-09-09 15:15:15 +00:00
|
|
|
#include "virconf.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2012-11-26 16:28:56 +00:00
|
|
|
#include "virstring.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:01:25 +00:00
|
|
|
#include "viruuid.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
#include "capabilities.h"
|
2014-09-19 16:32:43 +00:00
|
|
|
#include "vircommand.h"
|
2013-08-30 17:18:31 +00:00
|
|
|
#include "libxl_domain.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
#include "libxl_conf.h"
|
2012-11-26 16:28:56 +00:00
|
|
|
#include "libxl_utils.h"
|
2012-12-13 15:25:48 +00:00
|
|
|
#include "virstoragefile.h"
|
2016-04-04 17:31:29 +00:00
|
|
|
#include "secret_util.h"
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_LIBXL
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("libxl.libxl_conf");
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
/* see xen-unstable.hg/xen/include/asm-x86/cpufeature.h */
|
|
|
|
#define LIBXL_X86_FEATURE_PAE_MASK 0x40
|
|
|
|
|
|
|
|
|
|
|
|
struct guest_arch {
|
2012-12-10 22:28:09 +00:00
|
|
|
virArch arch;
|
2011-02-10 22:42:34 +00:00
|
|
|
int bits;
|
|
|
|
int hvm;
|
|
|
|
int pae;
|
|
|
|
int nonpae;
|
|
|
|
int ia64_be;
|
|
|
|
};
|
|
|
|
|
2014-02-26 12:34:17 +00:00
|
|
|
#define XEN_CAP_REGEX "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(aarch64|armv7l|x86_32|x86_64|ia64|powerpc64)(p|be)?"
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
|
2013-08-30 20:52:14 +00:00
|
|
|
static virClassPtr libxlDriverConfigClass;
|
|
|
|
static void libxlDriverConfigDispose(void *obj);
|
|
|
|
|
|
|
|
static int libxlConfigOnceInit(void)
|
|
|
|
{
|
|
|
|
if (!(libxlDriverConfigClass = virClassNew(virClassForObject(),
|
|
|
|
"libxlDriverConfig",
|
|
|
|
sizeof(libxlDriverConfig),
|
|
|
|
libxlDriverConfigDispose)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_ONCE_GLOBAL_INIT(libxlConfig)
|
|
|
|
|
|
|
|
static void
|
|
|
|
libxlDriverConfigDispose(void *obj)
|
|
|
|
{
|
|
|
|
libxlDriverConfigPtr cfg = obj;
|
|
|
|
|
|
|
|
virObjectUnref(cfg->caps);
|
|
|
|
libxl_ctx_free(cfg->ctx);
|
|
|
|
xtl_logger_destroy(cfg->logger);
|
|
|
|
if (cfg->logger_file)
|
|
|
|
VIR_FORCE_FCLOSE(cfg->logger_file);
|
|
|
|
|
|
|
|
VIR_FREE(cfg->configDir);
|
|
|
|
VIR_FREE(cfg->autostartDir);
|
|
|
|
VIR_FREE(cfg->logDir);
|
|
|
|
VIR_FREE(cfg->stateDir);
|
|
|
|
VIR_FREE(cfg->libDir);
|
|
|
|
VIR_FREE(cfg->saveDir);
|
2014-02-19 23:09:36 +00:00
|
|
|
VIR_FREE(cfg->autoDumpDir);
|
2015-04-14 20:38:46 +00:00
|
|
|
VIR_FREE(cfg->lockManagerName);
|
2013-08-30 20:52:14 +00:00
|
|
|
}
|
|
|
|
|
2014-09-03 20:14:50 +00:00
|
|
|
|
|
|
|
static libxl_action_on_shutdown
|
|
|
|
libxlActionFromVirLifecycle(virDomainLifecycleAction action)
|
|
|
|
{
|
|
|
|
switch (action) {
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_DESTROY:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_RESTART:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_RESTART;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_RESTART_RENAME:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_PRESERVE:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_PRESERVE;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static libxl_action_on_shutdown
|
|
|
|
libxlActionFromVirLifecycleCrash(virDomainLifecycleCrashAction action)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (action) {
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_CRASH_DESTROY:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_DESTROY;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_CRASH_RESTART:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_RESTART;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_CRASH_RESTART_RENAME:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_RESTART_RENAME;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_CRASH_PRESERVE:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_PRESERVE;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_DESTROY:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_DESTROY;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_CRASH_COREDUMP_RESTART:
|
|
|
|
return LIBXL_ACTION_ON_SHUTDOWN_COREDUMP_RESTART;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_LIFECYCLE_CRASH_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
static int
|
|
|
|
libxlCapsInitHost(libxl_ctx *ctx, virCapsPtr caps)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
2013-08-12 20:15:25 +00:00
|
|
|
libxl_physinfo phy_info;
|
|
|
|
int host_pae;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
if (libxl_get_physinfo(ctx, &phy_info) != 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Failed to get node physical info from libxenlight"));
|
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
/* hw_caps is an array of 32-bit words whose meaning is listed in
|
|
|
|
* xen-unstable.hg/xen/include/asm-x86/cpufeature.h. Each feature
|
|
|
|
* is defined in the form X*32+Y, corresponding to the Y'th bit in
|
|
|
|
* the X'th 32-bit word of hw_cap.
|
|
|
|
*/
|
|
|
|
host_pae = phy_info.hw_cap[0] & LIBXL_X86_FEATURE_PAE_MASK;
|
|
|
|
if (host_pae &&
|
|
|
|
virCapabilitiesAddHostFeature(caps, "pae") < 0)
|
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2016-02-03 21:40:37 +00:00
|
|
|
if (virCapabilitiesSetNetPrefix(caps, LIBXL_GENERATED_PREFIX_XEN) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
return 0;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
2013-08-16 21:37:46 +00:00
|
|
|
static int
|
|
|
|
libxlCapsInitNuma(libxl_ctx *ctx, virCapsPtr caps)
|
|
|
|
{
|
|
|
|
libxl_numainfo *numa_info = NULL;
|
|
|
|
libxl_cputopology *cpu_topo = NULL;
|
|
|
|
int nr_nodes = 0, nr_cpus = 0;
|
|
|
|
virCapsHostNUMACellCPUPtr *cpus = NULL;
|
|
|
|
int *nr_cpus_node = NULL;
|
|
|
|
size_t i;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
/* Let's try to fetch all the topology information */
|
|
|
|
numa_info = libxl_get_numainfo(ctx, &nr_nodes);
|
|
|
|
if (numa_info == NULL || nr_nodes == 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_numainfo failed"));
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
cpu_topo = libxl_get_cpu_topology(ctx, &nr_cpus);
|
|
|
|
if (cpu_topo == NULL || nr_cpus == 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_cpu_topology failed"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(cpus, nr_nodes) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(nr_cpus_node, nr_nodes) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* For each node, prepare a list of CPUs belonging to that node */
|
|
|
|
for (i = 0; i < nr_cpus; i++) {
|
|
|
|
int node = cpu_topo[i].node;
|
|
|
|
|
|
|
|
if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
nr_cpus_node[node]++;
|
|
|
|
|
|
|
|
if (nr_cpus_node[node] == 1) {
|
|
|
|
if (VIR_ALLOC(cpus[node]) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
if (VIR_REALLOC_N(cpus[node], nr_cpus_node[node]) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Mapping between what libxl tells and what libvirt wants */
|
|
|
|
cpus[node][nr_cpus_node[node]-1].id = i;
|
|
|
|
cpus[node][nr_cpus_node[node]-1].socket_id = cpu_topo[i].socket;
|
|
|
|
cpus[node][nr_cpus_node[node]-1].core_id = cpu_topo[i].core;
|
|
|
|
/* Allocate the siblings maps. We will be filling them later */
|
|
|
|
cpus[node][nr_cpus_node[node]-1].siblings = virBitmapNew(nr_cpus);
|
|
|
|
if (!cpus[node][nr_cpus_node[node]-1].siblings) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Let's now populate the siblings bitmaps */
|
|
|
|
for (i = 0; i < nr_cpus; i++) {
|
|
|
|
int node = cpu_topo[i].node;
|
|
|
|
size_t j;
|
|
|
|
|
|
|
|
if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (j = 0; j < nr_cpus_node[node]; j++) {
|
|
|
|
if (cpus[node][j].socket_id == cpu_topo[i].socket &&
|
|
|
|
cpus[node][j].core_id == cpu_topo[i].core)
|
|
|
|
ignore_value(virBitmapSetBit(cpus[node][j].siblings, i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nr_nodes; i++) {
|
|
|
|
if (numa_info[i].size == LIBXL_NUMAINFO_INVALID_ENTRY)
|
|
|
|
continue;
|
|
|
|
|
2014-06-03 13:18:27 +00:00
|
|
|
if (virCapabilitiesAddHostNUMACell(caps, i,
|
2013-08-16 21:37:46 +00:00
|
|
|
numa_info[i].size / 1024,
|
2014-06-03 13:18:27 +00:00
|
|
|
nr_cpus_node[i], cpus[i],
|
2014-06-06 16:12:51 +00:00
|
|
|
0, NULL,
|
2014-06-03 13:18:27 +00:00
|
|
|
0, NULL) < 0) {
|
2013-08-16 21:37:46 +00:00
|
|
|
virCapabilitiesClearHostNUMACellCPUTopology(cpus[i],
|
|
|
|
nr_cpus_node[i]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is safe, as the CPU list is now stored in the NUMA cell */
|
|
|
|
cpus[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (ret != 0) {
|
2013-08-20 17:20:56 +00:00
|
|
|
for (i = 0; cpus && i < nr_nodes; i++)
|
2013-08-16 21:37:46 +00:00
|
|
|
VIR_FREE(cpus[i]);
|
|
|
|
virCapabilitiesFreeNUMAInfo(caps);
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(cpus);
|
|
|
|
VIR_FREE(nr_cpus_node);
|
|
|
|
libxl_cputopology_list_free(cpu_topo, nr_cpus);
|
|
|
|
libxl_numainfo_list_free(numa_info, nr_nodes);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
static int
|
|
|
|
libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
2013-08-12 20:15:25 +00:00
|
|
|
const libxl_version_info *ver_info;
|
2013-09-04 22:14:30 +00:00
|
|
|
int err;
|
|
|
|
regex_t regex;
|
2011-02-10 22:42:34 +00:00
|
|
|
char *str, *token;
|
|
|
|
regmatch_t subs[4];
|
|
|
|
char *saveptr = NULL;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
struct guest_arch guest_archs[32];
|
|
|
|
int nr_guest_archs = 0;
|
|
|
|
|
|
|
|
memset(guest_archs, 0, sizeof(guest_archs));
|
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
if ((ver_info = libxl_get_version_info(ctx)) == NULL) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Failed to get version info from libxenlight"));
|
|
|
|
return -1;
|
|
|
|
}
|
2013-09-04 22:14:30 +00:00
|
|
|
|
2015-09-24 18:57:14 +00:00
|
|
|
if (!ver_info->capabilities) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Failed to get capabilities from libxenlight"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-09-04 22:14:30 +00:00
|
|
|
err = regcomp(®ex, XEN_CAP_REGEX, REG_EXTENDED);
|
|
|
|
if (err != 0) {
|
|
|
|
char error[100];
|
|
|
|
regerror(err, ®ex, error, sizeof(error));
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to compile regex %s"), error);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
/* Format of capabilities string is documented in the code in
|
|
|
|
* xen-unstable.hg/xen/arch/.../setup.c.
|
|
|
|
*
|
|
|
|
* It is a space-separated list of supported guest architectures.
|
|
|
|
*
|
|
|
|
* For x86:
|
|
|
|
* TYP-VER-ARCH[p]
|
|
|
|
* ^ ^ ^ ^
|
|
|
|
* | | | +-- PAE supported
|
|
|
|
* | | +------- x86_32 or x86_64
|
|
|
|
* | +----------- the version of Xen, eg. "3.0"
|
|
|
|
* +--------------- "xen" or "hvm" for para or full virt respectively
|
|
|
|
*
|
|
|
|
* For IA64:
|
|
|
|
* TYP-VER-ARCH[be]
|
|
|
|
* ^ ^ ^ ^
|
|
|
|
* | | | +-- Big-endian supported
|
|
|
|
* | | +------- always "ia64"
|
|
|
|
* | +----------- the version of Xen, eg. "3.0"
|
|
|
|
* +--------------- "xen" or "hvm" for para or full virt respectively
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Split capabilities string into tokens. strtok_r is OK here because
|
|
|
|
* we "own" the buffer. Parse out the features from each token.
|
|
|
|
*/
|
2013-08-12 20:15:25 +00:00
|
|
|
for (str = ver_info->capabilities, nr_guest_archs = 0;
|
2011-02-10 22:42:34 +00:00
|
|
|
nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0])
|
|
|
|
&& (token = strtok_r(str, " ", &saveptr)) != NULL;
|
|
|
|
str = NULL) {
|
2013-09-04 22:14:30 +00:00
|
|
|
if (regexec(®ex, token, sizeof(subs) / sizeof(subs[0]),
|
2011-02-10 22:42:34 +00:00
|
|
|
subs, 0) == 0) {
|
|
|
|
int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
|
2012-12-10 22:28:09 +00:00
|
|
|
virArch arch;
|
|
|
|
int pae = 0, nonpae = 0, ia64_be = 0;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
|
2012-12-10 22:28:09 +00:00
|
|
|
arch = VIR_ARCH_I686;
|
2011-02-10 22:42:34 +00:00
|
|
|
if (subs[3].rm_so != -1 &&
|
|
|
|
STRPREFIX(&token[subs[3].rm_so], "p"))
|
|
|
|
pae = 1;
|
|
|
|
else
|
|
|
|
nonpae = 1;
|
2014-09-03 19:04:59 +00:00
|
|
|
} else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
|
2012-12-10 22:28:09 +00:00
|
|
|
arch = VIR_ARCH_X86_64;
|
2014-09-03 19:04:59 +00:00
|
|
|
} else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
|
2012-12-10 22:28:09 +00:00
|
|
|
arch = VIR_ARCH_ITANIUM;
|
2011-02-10 22:42:34 +00:00
|
|
|
if (subs[3].rm_so != -1 &&
|
|
|
|
STRPREFIX(&token[subs[3].rm_so], "be"))
|
|
|
|
ia64_be = 1;
|
2014-09-03 19:04:59 +00:00
|
|
|
} else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
|
2012-12-10 22:28:09 +00:00
|
|
|
arch = VIR_ARCH_PPC64;
|
2014-02-26 12:34:17 +00:00
|
|
|
} else if (STRPREFIX(&token[subs[2].rm_so], "armv7l")) {
|
|
|
|
arch = VIR_ARCH_ARMV7L;
|
|
|
|
} else if (STRPREFIX(&token[subs[2].rm_so], "aarch64")) {
|
|
|
|
arch = VIR_ARCH_AARCH64;
|
2011-02-10 22:42:34 +00:00
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search for existing matching (model,hvm) tuple */
|
2013-05-21 07:21:16 +00:00
|
|
|
for (i = 0; i < nr_guest_archs; i++) {
|
2012-12-10 22:28:09 +00:00
|
|
|
if ((guest_archs[i].arch == arch) &&
|
2013-08-14 21:33:48 +00:00
|
|
|
guest_archs[i].hvm == hvm)
|
2011-02-10 22:42:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Too many arch flavours - highly unlikely ! */
|
|
|
|
if (i >= ARRAY_CARDINALITY(guest_archs))
|
|
|
|
continue;
|
|
|
|
/* Didn't find a match, so create a new one */
|
|
|
|
if (i == nr_guest_archs)
|
|
|
|
nr_guest_archs++;
|
|
|
|
|
2012-12-10 22:28:09 +00:00
|
|
|
guest_archs[i].arch = arch;
|
2011-02-10 22:42:34 +00:00
|
|
|
guest_archs[i].hvm = hvm;
|
|
|
|
|
|
|
|
/* Careful not to overwrite a previous positive
|
|
|
|
setting with a negative one here - some archs
|
|
|
|
can do both pae & non-pae, but Xen reports
|
|
|
|
separately capabilities so we're merging archs */
|
|
|
|
if (pae)
|
|
|
|
guest_archs[i].pae = pae;
|
|
|
|
if (nonpae)
|
|
|
|
guest_archs[i].nonpae = nonpae;
|
|
|
|
if (ia64_be)
|
|
|
|
guest_archs[i].ia64_be = ia64_be;
|
|
|
|
}
|
|
|
|
}
|
2013-09-04 22:14:30 +00:00
|
|
|
regfree(®ex);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
for (i = 0; i < nr_guest_archs; ++i) {
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"};
|
|
|
|
virCapsGuestMachinePtr *machines;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
|
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
if ((guest = virCapabilitiesAddGuest(caps,
|
2015-04-17 22:09:16 +00:00
|
|
|
guest_archs[i].hvm ? VIR_DOMAIN_OSTYPE_HVM : VIR_DOMAIN_OSTYPE_XEN,
|
2013-08-12 20:15:25 +00:00
|
|
|
guest_archs[i].arch,
|
2015-03-17 20:10:28 +00:00
|
|
|
LIBXL_EXECBIN_DIR "/qemu-system-i386",
|
2013-08-12 20:15:25 +00:00
|
|
|
(guest_archs[i].hvm ?
|
2015-03-17 20:10:28 +00:00
|
|
|
LIBXL_FIRMWARE_DIR "/hvmloader" :
|
2013-08-12 20:15:25 +00:00
|
|
|
NULL),
|
|
|
|
1,
|
|
|
|
machines)) == NULL) {
|
|
|
|
virCapabilitiesFreeMachines(machines, 1);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
machines = NULL;
|
|
|
|
|
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
2015-04-17 22:38:10 +00:00
|
|
|
VIR_DOMAIN_VIRT_XEN,
|
2013-08-12 20:15:25 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (guest_archs[i].pae &&
|
|
|
|
virCapabilitiesAddGuestFeature(guest,
|
|
|
|
"pae",
|
|
|
|
1,
|
|
|
|
0) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (guest_archs[i].nonpae &&
|
|
|
|
virCapabilitiesAddGuestFeature(guest,
|
|
|
|
"nonpae",
|
|
|
|
1,
|
|
|
|
0) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (guest_archs[i].ia64_be &&
|
|
|
|
virCapabilitiesAddGuestFeature(guest,
|
|
|
|
"ia64_be",
|
|
|
|
1,
|
|
|
|
0) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (guest_archs[i].hvm) {
|
|
|
|
if (virCapabilitiesAddGuestFeature(guest,
|
|
|
|
"acpi",
|
|
|
|
1,
|
|
|
|
1) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virCapabilitiesAddGuestFeature(guest, "apic",
|
|
|
|
1,
|
|
|
|
0) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virCapabilitiesAddGuestFeature(guest,
|
|
|
|
"hap",
|
2016-02-23 02:20:41 +00:00
|
|
|
1,
|
2013-08-12 20:15:25 +00:00
|
|
|
1) == NULL)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-08-30 20:34:10 +00:00
|
|
|
libxlMakeDomCreateInfo(libxl_ctx *ctx,
|
2012-11-26 16:28:56 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
libxl_domain_create_info *c_info)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_domain_create_info_init(c_info);
|
|
|
|
|
2016-02-23 03:06:57 +00:00
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
|
2012-11-26 16:28:56 +00:00
|
|
|
c_info->type = LIBXL_DOMAIN_TYPE_HVM;
|
2016-02-23 03:06:57 +00:00
|
|
|
switch ((virTristateSwitch) def->features[VIR_DOMAIN_FEATURE_HAP]) {
|
|
|
|
case VIR_TRISTATE_SWITCH_OFF:
|
|
|
|
libxl_defbool_set(&c_info->hap, false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_TRISTATE_SWITCH_ON:
|
|
|
|
libxl_defbool_set(&c_info->hap, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_TRISTATE_SWITCH_ABSENT:
|
|
|
|
case VIR_TRISTATE_SWITCH_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2012-11-26 16:28:56 +00:00
|
|
|
c_info->type = LIBXL_DOMAIN_TYPE_PV;
|
2016-02-23 03:06:57 +00:00
|
|
|
}
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(c_info->name, def->name) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
if (def->nseclabels &&
|
|
|
|
def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_STATIC) {
|
2013-08-30 20:34:10 +00:00
|
|
|
if (libxl_flask_context_to_sid(ctx,
|
2012-11-26 16:28:56 +00:00
|
|
|
def->seclabels[0]->label,
|
|
|
|
strlen(def->seclabels[0]->label),
|
|
|
|
&c_info->ssidref)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to resolve security label '%s'"),
|
|
|
|
def->seclabels[0]->label);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
virUUIDFormat(def->uuid, uuidstr);
|
2012-10-17 09:23:12 +00:00
|
|
|
if (libxl_uuid_from_string(&c_info->uuid, uuidstr)) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight failed to parse UUID '%s'"), uuidstr);
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_domain_create_info_dispose(c_info);
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-07-26 03:30:50 +00:00
|
|
|
static int
|
|
|
|
libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf)
|
|
|
|
{
|
|
|
|
virDomainChrSourceDef srcdef = def->source;
|
|
|
|
const char *type = virDomainChrTypeToString(srcdef.type);
|
|
|
|
|
|
|
|
if (!type) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s", _("unknown chrdev type"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (srcdef.type) {
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_NULL:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_STDIO:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_VC:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PTY:
|
|
|
|
if (VIR_STRDUP(*buf, type) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_FILE:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PIPE:
|
|
|
|
if (virAsprintf(buf, "%s:%s", type, srcdef.data.file.path) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_DEV:
|
|
|
|
if (VIR_STRDUP(*buf, srcdef.data.file.path) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UDP: {
|
|
|
|
const char *connectHost = srcdef.data.udp.connectHost;
|
|
|
|
const char *bindHost = srcdef.data.udp.bindHost;
|
|
|
|
const char *bindService = srcdef.data.udp.bindService;
|
|
|
|
|
|
|
|
if (connectHost == NULL)
|
|
|
|
connectHost = "";
|
|
|
|
if (bindHost == NULL)
|
|
|
|
bindHost = "";
|
|
|
|
if (bindService == NULL)
|
|
|
|
bindService = "0";
|
|
|
|
|
|
|
|
if (virAsprintf(buf, "udp:%s:%s@%s:%s",
|
|
|
|
connectHost,
|
|
|
|
srcdef.data.udp.connectService,
|
|
|
|
bindHost,
|
|
|
|
bindService) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_TCP: {
|
|
|
|
const char *prefix;
|
|
|
|
|
|
|
|
if (srcdef.data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET)
|
|
|
|
prefix = "telnet";
|
|
|
|
else
|
|
|
|
prefix = "tcp";
|
|
|
|
|
|
|
|
if (virAsprintf(buf, "%s:%s:%s%s",
|
|
|
|
prefix,
|
|
|
|
srcdef.data.tcp.host,
|
|
|
|
srcdef.data.tcp.service,
|
|
|
|
srcdef.data.tcp.listen ? ",server,nowait" : "") < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
|
|
|
if (virAsprintf(buf, "unix:%s%s",
|
|
|
|
srcdef.data.nix.path,
|
|
|
|
srcdef.data.nix.listen ? ",server,nowait" : "") < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported chardev '%s'"), type);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
2014-05-30 13:46:35 +00:00
|
|
|
libxlMakeDomBuildInfo(virDomainDefPtr def,
|
|
|
|
libxl_ctx *ctx,
|
|
|
|
libxl_domain_config *d_config)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
libxl_domain_build_info *b_info = &d_config->b_info;
|
2015-04-17 00:11:06 +00:00
|
|
|
int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_domain_build_info_init(b_info);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
if (hvm)
|
|
|
|
libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_HVM);
|
2011-05-23 22:06:00 +00:00
|
|
|
else
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_PV);
|
2013-07-24 11:43:43 +00:00
|
|
|
|
2015-10-19 17:21:24 +00:00
|
|
|
b_info->max_vcpus = virDomainDefGetVcpusMax(def);
|
|
|
|
if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, b_info->max_vcpus))
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-07-24 11:43:43 +00:00
|
|
|
libxl_bitmap_set_none(&b_info->avail_vcpus);
|
2015-10-22 12:59:03 +00:00
|
|
|
for (i = 0; i < virDomainDefGetVcpus(def); i++)
|
2013-07-24 11:43:43 +00:00
|
|
|
libxl_bitmap_set((&b_info->avail_vcpus), i);
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
if (def->clock.ntimers > 0 &&
|
|
|
|
def->clock.timers[0]->name == VIR_DOMAIN_TIMER_NAME_TSC) {
|
|
|
|
switch (def->clock.timers[0]->mode) {
|
|
|
|
case VIR_DOMAIN_TIMER_MODE_NATIVE:
|
|
|
|
b_info->tsc_mode = 2;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_TIMER_MODE_PARAVIRT:
|
|
|
|
b_info->tsc_mode = 3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
b_info->tsc_mode = 1;
|
|
|
|
}
|
|
|
|
}
|
2012-11-26 16:28:56 +00:00
|
|
|
b_info->sched_params.weight = 1000;
|
2015-02-17 17:01:09 +00:00
|
|
|
b_info->max_memkb = virDomainDefGetMemoryInitial(def);
|
2011-02-10 22:42:34 +00:00
|
|
|
b_info->target_memkb = def->mem.cur_balloon;
|
|
|
|
if (hvm) {
|
2012-12-12 21:28:24 +00:00
|
|
|
char bootorder[VIR_DOMAIN_BOOT_LAST + 1];
|
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&b_info->u.hvm.pae,
|
2013-09-23 13:02:38 +00:00
|
|
|
def->features[VIR_DOMAIN_FEATURE_PAE] ==
|
2014-06-27 15:18:53 +00:00
|
|
|
VIR_TRISTATE_SWITCH_ON);
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&b_info->u.hvm.apic,
|
2013-09-23 13:02:38 +00:00
|
|
|
def->features[VIR_DOMAIN_FEATURE_APIC] ==
|
2014-06-27 15:18:53 +00:00
|
|
|
VIR_TRISTATE_SWITCH_ON);
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&b_info->u.hvm.acpi,
|
2013-09-23 13:02:38 +00:00
|
|
|
def->features[VIR_DOMAIN_FEATURE_ACPI] ==
|
2014-06-27 15:18:53 +00:00
|
|
|
VIR_TRISTATE_SWITCH_ON);
|
2011-05-10 11:24:15 +00:00
|
|
|
for (i = 0; i < def->clock.ntimers; i++) {
|
|
|
|
if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET &&
|
|
|
|
def->clock.timers[i]->present == 1) {
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&b_info->u.hvm.hpet, 1);
|
2011-05-10 11:24:15 +00:00
|
|
|
}
|
|
|
|
}
|
2015-05-04 19:50:10 +00:00
|
|
|
|
|
|
|
if (def->nsounds > 0) {
|
|
|
|
/*
|
|
|
|
* Use first sound device. man xl.cfg(5) describes soundhw as
|
|
|
|
* a single device. From the man page: soundhw=DEVICE
|
|
|
|
*/
|
|
|
|
virDomainSoundDefPtr snd = def->sounds[0];
|
|
|
|
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.soundhw,
|
|
|
|
virDomainSoundModelTypeToString(snd->model)) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-05-21 07:21:16 +00:00
|
|
|
for (i = 0; i < def->os.nBootDevs; i++) {
|
2012-12-12 21:28:24 +00:00
|
|
|
switch (def->os.bootDevs[i]) {
|
|
|
|
case VIR_DOMAIN_BOOT_FLOPPY:
|
|
|
|
bootorder[i] = 'a';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case VIR_DOMAIN_BOOT_DISK:
|
|
|
|
bootorder[i] = 'c';
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_CDROM:
|
|
|
|
bootorder[i] = 'd';
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_BOOT_NET:
|
|
|
|
bootorder[i] = 'n';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (def->os.nBootDevs == 0) {
|
|
|
|
bootorder[0] = 'c';
|
|
|
|
bootorder[1] = '\0';
|
2014-09-03 19:04:59 +00:00
|
|
|
} else {
|
2012-12-12 21:28:24 +00:00
|
|
|
bootorder[def->os.nBootDevs] = '\0';
|
|
|
|
}
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(b_info->u.hvm.boot, bootorder) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-05-10 11:24:15 +00:00
|
|
|
|
2015-03-20 04:16:11 +00:00
|
|
|
#ifdef LIBXL_HAVE_BUILDINFO_KERNEL
|
|
|
|
if (VIR_STRDUP(b_info->cmdline, def->os.cmdline) < 0)
|
|
|
|
return -1;
|
|
|
|
if (VIR_STRDUP(b_info->kernel, def->os.kernel) < 0)
|
|
|
|
return -1;
|
|
|
|
if (VIR_STRDUP(b_info->ramdisk, def->os.initrd) < 0)
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
2014-09-19 19:03:18 +00:00
|
|
|
if (def->emulator) {
|
|
|
|
if (!virFileExists(def->emulator)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("emulator '%s' not found"),
|
|
|
|
def->emulator);
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2014-09-19 19:03:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!virFileIsExecutable(def->emulator)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("emulator '%s' is not executable"),
|
|
|
|
def->emulator);
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2014-09-19 19:03:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(b_info->device_model);
|
|
|
|
if (VIR_STRDUP(b_info->device_model, def->emulator) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2014-09-19 19:03:18 +00:00
|
|
|
|
|
|
|
b_info->device_model_version = libxlDomainGetEmulatorType(def);
|
|
|
|
}
|
|
|
|
|
2013-07-26 03:30:50 +00:00
|
|
|
if (def->nserials) {
|
|
|
|
if (def->nserials > 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s",
|
|
|
|
_("Only one serial device is supported by libxl"));
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-07-26 03:30:50 +00:00
|
|
|
}
|
|
|
|
if (libxlMakeChrdevStr(def->serials[0], &b_info->u.hvm.serial) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-07-26 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (def->nparallels) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s",
|
|
|
|
_("Parallel devices are not supported by libxl"));
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-07-26 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2015-02-10 02:36:47 +00:00
|
|
|
/* Disable VNC and SDL until explicitly enabled */
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.vnc.enable, 0);
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.sdl.enable, 0);
|
|
|
|
|
2015-03-06 14:36:12 +00:00
|
|
|
if (def->ninputs) {
|
|
|
|
#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
|
|
|
|
if (VIR_ALLOC_N(b_info->u.hvm.usbdevice_list, def->ninputs+1) < 0)
|
|
|
|
return -1;
|
|
|
|
#else
|
|
|
|
if (def->ninputs > 1) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("libxenlight supports only one input device"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (i = 0; i < def->ninputs; i++) {
|
|
|
|
char **usbdevice;
|
2015-03-14 00:36:04 +00:00
|
|
|
|
|
|
|
if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_USB)
|
|
|
|
continue;
|
|
|
|
|
2015-03-06 14:36:12 +00:00
|
|
|
#ifdef LIBXL_HAVE_BUILDINFO_USBDEVICE_LIST
|
|
|
|
usbdevice = &b_info->u.hvm.usbdevice_list[i];
|
|
|
|
#else
|
|
|
|
usbdevice = &b_info->u.hvm.usbdevice;
|
|
|
|
#endif
|
|
|
|
switch (def->inputs[i]->type) {
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_MOUSE:
|
|
|
|
VIR_FREE(*usbdevice);
|
|
|
|
if (VIR_STRDUP(*usbdevice, "mouse") < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_TABLET:
|
|
|
|
VIR_FREE(*usbdevice);
|
|
|
|
if (VIR_STRDUP(*usbdevice, "tablet") < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Unknown input device type"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
/*
|
|
|
|
* The following comment and calculation were taken directly from
|
|
|
|
* libxenlight's internal function libxl_get_required_shadow_memory():
|
|
|
|
*
|
|
|
|
* 256 pages (1MB) per vcpu, plus 1 page per MiB of RAM for the P2M map,
|
|
|
|
* plus 1 page per MiB of RAM to shadow the resident processes.
|
|
|
|
*/
|
2012-11-26 16:28:56 +00:00
|
|
|
b_info->shadow_memkb = 4 * (256 * libxl_bitmap_count_set(&b_info->avail_vcpus) +
|
2011-02-10 22:42:34 +00:00
|
|
|
2 * (b_info->max_memkb / 1024));
|
|
|
|
} else {
|
2013-05-17 15:30:08 +00:00
|
|
|
/*
|
|
|
|
* For compatibility with the legacy xen toolstack, default to pygrub
|
|
|
|
* if bootloader is not specified AND direct kernel boot is not specified.
|
|
|
|
*/
|
|
|
|
if (def->os.bootloader) {
|
|
|
|
if (VIR_STRDUP(b_info->u.pv.bootloader, def->os.bootloader) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-05-17 15:30:08 +00:00
|
|
|
} else if (def->os.kernel == NULL) {
|
|
|
|
if (VIR_STRDUP(b_info->u.pv.bootloader, LIBXL_BOOTLOADER_PATH) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2013-05-17 15:30:08 +00:00
|
|
|
}
|
2011-02-10 22:42:34 +00:00
|
|
|
if (def->os.bootloaderArgs) {
|
2012-11-26 16:28:56 +00:00
|
|
|
if (!(b_info->u.pv.bootloader_args =
|
|
|
|
virStringSplit(def->os.bootloaderArgs, " \t\n", 0)))
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(b_info->u.pv.cmdline, def->os.cmdline) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
if (def->os.kernel) {
|
2013-05-03 12:42:47 +00:00
|
|
|
/* libxl_init_build_info() sets VIR_STRDUP(kernel.path, "hvmloader") */
|
2012-11-26 16:28:56 +00:00
|
|
|
VIR_FREE(b_info->u.pv.kernel);
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(b_info->u.pv.kernel, def->os.kernel) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(b_info->u.pv.ramdisk, def->os.initrd) < 0)
|
2014-10-10 21:39:46 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-07-07 15:05:17 +00:00
|
|
|
static int
|
|
|
|
libxlDiskSetDiscard(libxl_device_disk *x_disk, int discard)
|
|
|
|
{
|
|
|
|
if (!x_disk->readwrite)
|
|
|
|
return 0;
|
|
|
|
#if defined(LIBXL_HAVE_LIBXL_DEVICE_DISK_DISCARD_ENABLE)
|
2014-07-11 13:43:47 +00:00
|
|
|
switch ((virDomainDiskDiscard)discard) {
|
2014-07-07 15:05:17 +00:00
|
|
|
case VIR_DOMAIN_DISK_DISCARD_DEFAULT:
|
|
|
|
case VIR_DOMAIN_DISK_DISCARD_LAST:
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DISK_DISCARD_UNMAP:
|
|
|
|
libxl_defbool_set(&x_disk->discard_enable, true);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DISK_DISCARD_IGNORE:
|
|
|
|
libxl_defbool_set(&x_disk->discard_enable, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
if (discard == VIR_DOMAIN_DISK_DISCARD_DEFAULT)
|
|
|
|
return 0;
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("This version of libxenlight does not support "
|
|
|
|
"disk 'discard' option passing"));
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-19 16:32:43 +00:00
|
|
|
#define LIBXL_QEMU_DM_STR "Options specific to the Xen version:"
|
|
|
|
|
|
|
|
int
|
|
|
|
libxlDomainGetEmulatorType(const virDomainDef *def)
|
|
|
|
{
|
|
|
|
int ret = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
|
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
char *output = NULL;
|
|
|
|
|
2015-04-17 00:11:06 +00:00
|
|
|
if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
|
2014-09-19 16:32:43 +00:00
|
|
|
if (def->emulator) {
|
2016-05-12 20:40:28 +00:00
|
|
|
if (!virFileExists(def->emulator))
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-09-19 16:32:43 +00:00
|
|
|
cmd = virCommandNew(def->emulator);
|
|
|
|
|
|
|
|
virCommandAddArgList(cmd, "-help", NULL);
|
|
|
|
virCommandSetOutputBuffer(cmd, &output);
|
|
|
|
|
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (strstr(output, LIBXL_QEMU_DM_STR))
|
|
|
|
ret = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(output);
|
|
|
|
virCommandFree(cmd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-02-11 03:53:36 +00:00
|
|
|
|
|
|
|
static char *
|
|
|
|
libxlMakeNetworkDiskSrcStr(virStorageSourcePtr src,
|
|
|
|
const char *username,
|
|
|
|
const char *secret)
|
|
|
|
{
|
|
|
|
char *ret = NULL;
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
switch ((virStorageNetProtocol) src->protocol) {
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_HTTP:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_HTTPS:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_FTP:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_FTPS:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_TFTP:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
_("Unsupported network block protocol '%s'"),
|
|
|
|
virStorageNetProtocolTypeToString(src->protocol));
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
|
|
|
if (strchr(src->path, ':')) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("':' not allowed in RBD source volume name '%s'"),
|
|
|
|
src->path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferStrcat(&buf, "rbd:", src->path, NULL);
|
|
|
|
|
|
|
|
if (username) {
|
|
|
|
virBufferEscape(&buf, '\\', ":", ":id=%s", username);
|
|
|
|
virBufferEscape(&buf, '\\', ":",
|
|
|
|
":key=%s:auth_supported=cephx\\;none",
|
|
|
|
secret);
|
|
|
|
} else {
|
|
|
|
virBufferAddLit(&buf, ":auth_supported=none");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src->nhosts > 0) {
|
|
|
|
virBufferAddLit(&buf, ":mon_host=");
|
|
|
|
for (i = 0; i < src->nhosts; i++) {
|
|
|
|
if (i)
|
|
|
|
virBufferAddLit(&buf, "\\;");
|
|
|
|
|
|
|
|
/* assume host containing : is ipv6 */
|
|
|
|
if (strchr(src->hosts[i].name, ':'))
|
|
|
|
virBufferEscape(&buf, '\\', ":", "[%s]",
|
|
|
|
src->hosts[i].name);
|
|
|
|
else
|
|
|
|
virBufferAsprintf(&buf, "%s", src->hosts[i].name);
|
|
|
|
|
|
|
|
if (src->hosts[i].port)
|
|
|
|
virBufferAsprintf(&buf, "\\:%s", src->hosts[i].port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src->configFile)
|
|
|
|
virBufferEscape(&buf, '\\', ":", ":conf=%s", src->configFile);
|
|
|
|
|
|
|
|
if (virBufferCheckError(&buf) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = virBufferContentAndReset(&buf);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virBufferFreeAndReset(&buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
libxlMakeNetworkDiskSrc(virStorageSourcePtr src, char **srcstr)
|
|
|
|
{
|
|
|
|
virConnectPtr conn = NULL;
|
2016-05-12 15:43:39 +00:00
|
|
|
uint8_t *secret = NULL;
|
|
|
|
char *base64secret = NULL;
|
|
|
|
size_t secretlen = 0;
|
2016-02-11 03:53:36 +00:00
|
|
|
char *username = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
*srcstr = NULL;
|
|
|
|
if (src->auth && src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD) {
|
|
|
|
username = src->auth->username;
|
|
|
|
if (!(conn = virConnectOpen("xen:///system")))
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-05-12 15:43:39 +00:00
|
|
|
if (virSecretGetSecretString(conn, src->auth,
|
|
|
|
VIR_SECRET_USAGE_TYPE_CEPH,
|
|
|
|
&secret, &secretlen) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* RBD expects an encoded secret */
|
|
|
|
if (!(base64secret = virStringEncodeBase64(secret, secretlen)))
|
2016-02-11 03:53:36 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-05-12 15:43:39 +00:00
|
|
|
if (!(*srcstr = libxlMakeNetworkDiskSrcStr(src, username, base64secret)))
|
2016-02-23 22:28:04 +00:00
|
|
|
goto cleanup;
|
2016-02-11 03:53:36 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2016-05-12 15:43:39 +00:00
|
|
|
VIR_DISPOSE_N(secret, secretlen);
|
|
|
|
VIR_DISPOSE_STRING(base64secret);
|
2016-02-11 03:53:36 +00:00
|
|
|
virObjectUnref(conn);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-09-19 16:32:43 +00:00
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
int
|
2012-11-26 16:28:56 +00:00
|
|
|
libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk)
|
2011-05-26 15:09:01 +00:00
|
|
|
{
|
2014-03-17 20:14:11 +00:00
|
|
|
const char *driver;
|
|
|
|
int format;
|
2016-02-11 03:53:36 +00:00
|
|
|
int actual_type = virStorageSourceGetActualType(l_disk->src);
|
2014-03-17 20:14:11 +00:00
|
|
|
|
2013-06-13 01:54:10 +00:00
|
|
|
libxl_device_disk_init(x_disk);
|
|
|
|
|
2016-02-11 03:53:36 +00:00
|
|
|
if (actual_type == VIR_STORAGE_TYPE_NETWORK) {
|
|
|
|
if (libxlMakeNetworkDiskSrc(l_disk->src, &x_disk->pdev_path) < 0)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
if (VIR_STRDUP(x_disk->pdev_path, virDomainDiskGetSource(l_disk)) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
2016-02-11 03:53:36 +00:00
|
|
|
}
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_disk->vdev, l_disk->dst) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-03-17 20:14:11 +00:00
|
|
|
driver = virDomainDiskGetDriver(l_disk);
|
|
|
|
format = virDomainDiskGetFormat(l_disk);
|
|
|
|
if (driver) {
|
|
|
|
if (STREQ(driver, "tap") || STREQ(driver, "tap2")) {
|
|
|
|
switch (format) {
|
2012-10-15 21:47:42 +00:00
|
|
|
case VIR_STORAGE_FILE_QCOW:
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QCOW;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
|
2012-10-15 21:47:42 +00:00
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_QCOW2:
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QCOW2;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
|
2012-10-15 21:47:42 +00:00
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_VHD:
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_VHD;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_TAP;
|
2012-10-15 21:47:42 +00:00
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_NONE:
|
2011-05-26 15:09:01 +00:00
|
|
|
/* No subtype specified, default to raw/tap */
|
2012-10-15 21:47:42 +00:00
|
|
|
case VIR_STORAGE_FILE_RAW:
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_TAP;
|
2012-10-15 21:47:42 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2013-05-13 18:14:20 +00:00
|
|
|
_("libxenlight does not support disk format %s "
|
|
|
|
"with disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
virStorageFileFormatTypeToString(format),
|
|
|
|
driver);
|
2012-10-15 21:47:42 +00:00
|
|
|
return -1;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
2014-03-17 20:14:11 +00:00
|
|
|
} else if (STREQ(driver, "qemu")) {
|
2013-05-13 18:14:21 +00:00
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
|
2014-03-17 20:14:11 +00:00
|
|
|
switch (format) {
|
2013-05-13 18:14:21 +00:00
|
|
|
case VIR_STORAGE_FILE_QCOW:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QCOW;
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_QCOW2:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_QCOW2;
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_VHD:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_VHD;
|
|
|
|
break;
|
|
|
|
case VIR_STORAGE_FILE_NONE:
|
|
|
|
/* No subtype specified, default to raw */
|
|
|
|
case VIR_STORAGE_FILE_RAW:
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight does not support disk format %s "
|
|
|
|
"with disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
virStorageFileFormatTypeToString(format),
|
|
|
|
driver);
|
2013-05-13 18:14:21 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2014-03-17 20:14:11 +00:00
|
|
|
} else if (STREQ(driver, "file")) {
|
|
|
|
if (format != VIR_STORAGE_FILE_NONE &&
|
|
|
|
format != VIR_STORAGE_FILE_RAW) {
|
2013-05-13 18:14:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight does not support disk format %s "
|
|
|
|
"with disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
virStorageFileFormatTypeToString(format),
|
|
|
|
driver);
|
2013-05-13 18:14:20 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
2014-06-20 05:36:25 +00:00
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
|
2014-03-17 20:14:11 +00:00
|
|
|
} else if (STREQ(driver, "phy")) {
|
|
|
|
if (format != VIR_STORAGE_FILE_NONE &&
|
|
|
|
format != VIR_STORAGE_FILE_RAW) {
|
2013-05-13 18:14:20 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight does not support disk format %s "
|
|
|
|
"with disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
virStorageFileFormatTypeToString(format),
|
|
|
|
driver);
|
2013-05-13 18:14:20 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_PHY;
|
2011-05-26 15:09:01 +00:00
|
|
|
} else {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("libxenlight does not support disk driver %s"),
|
2014-03-17 20:14:11 +00:00
|
|
|
driver);
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
2013-02-20 20:02:28 +00:00
|
|
|
/*
|
|
|
|
* If driverName is not specified, default to raw as per
|
|
|
|
* xl-disk-configuration.txt in the xen documentation and let
|
|
|
|
* libxl pick a suitable backend.
|
|
|
|
*/
|
2012-11-26 16:28:56 +00:00
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_RAW;
|
2013-02-20 20:02:28 +00:00
|
|
|
x_disk->backend = LIBXL_DISK_BACKEND_UNKNOWN;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
/* XXX is this right? */
|
|
|
|
x_disk->removable = 1;
|
2014-06-24 13:15:55 +00:00
|
|
|
x_disk->readwrite = !l_disk->src->readonly;
|
2011-05-26 15:09:01 +00:00
|
|
|
x_disk->is_cdrom = l_disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? 1 : 0;
|
2014-07-07 15:05:17 +00:00
|
|
|
if (libxlDiskSetDiscard(x_disk, l_disk->discard) < 0)
|
|
|
|
return -1;
|
2014-03-27 16:55:03 +00:00
|
|
|
/* An empty CDROM must have the empty format, otherwise libxl fails. */
|
|
|
|
if (x_disk->is_cdrom && !x_disk->pdev_path)
|
|
|
|
x_disk->format = LIBXL_DISK_FORMAT_EMPTY;
|
2011-08-13 21:42:48 +00:00
|
|
|
if (l_disk->transient) {
|
2012-07-18 13:32:10 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxenlight does not support transient disks"));
|
2011-08-13 21:42:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2015-02-20 03:22:06 +00:00
|
|
|
if (l_disk->domain_name) {
|
|
|
|
#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME
|
|
|
|
if (VIR_STRDUP(x_disk->backend_domname, l_disk->domain_name) < 0)
|
|
|
|
return -1;
|
|
|
|
#else
|
|
|
|
virReportError(VIR_ERR_XML_DETAIL, "%s",
|
|
|
|
_("this version of libxenlight does not "
|
|
|
|
"support backend domain name"));
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
|
|
|
libxlMakeDiskList(virDomainDefPtr def, libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
virDomainDiskDefPtr *l_disks = def->disks;
|
|
|
|
int ndisks = def->ndisks;
|
|
|
|
libxl_device_disk *x_disks;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-07-04 10:10:38 +00:00
|
|
|
if (VIR_ALLOC_N(x_disks, ndisks) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < ndisks; i++) {
|
2012-11-26 16:28:56 +00:00
|
|
|
if (libxlMakeDisk(l_disks[i], &x_disks[i]) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
d_config->disks = x_disks;
|
|
|
|
d_config->num_disks = ndisks;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2011-02-10 22:42:34 +00:00
|
|
|
for (i = 0; i < ndisks; i++)
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_device_disk_dispose(&x_disks[i]);
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_FREE(x_disks);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
int
|
2014-01-06 18:37:20 +00:00
|
|
|
libxlMakeNic(virDomainDefPtr def,
|
|
|
|
virDomainNetDefPtr l_nic,
|
|
|
|
libxl_device_nic *x_nic)
|
2011-05-26 15:09:01 +00:00
|
|
|
{
|
2015-04-17 00:11:06 +00:00
|
|
|
bool ioemu_nic = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
|
2014-06-10 20:28:07 +00:00
|
|
|
virDomainNetType actual_type = virDomainNetGetActualType(l_nic);
|
2016-02-24 22:40:00 +00:00
|
|
|
virNetworkPtr network = NULL;
|
|
|
|
virConnectPtr conn = NULL;
|
2015-12-29 00:26:58 +00:00
|
|
|
virNetDevBandwidthPtr actual_bw;
|
2016-02-24 22:40:00 +00:00
|
|
|
int ret = -1;
|
2014-01-06 18:37:20 +00:00
|
|
|
|
2012-11-26 16:28:56 +00:00
|
|
|
/* TODO: Where is mtu stored?
|
|
|
|
*
|
|
|
|
* x_nics[i].mtu = 1492;
|
|
|
|
*/
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2014-06-10 20:53:55 +00:00
|
|
|
if (l_nic->script && !(actual_type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
|
|
|
|
actual_type == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("specifying a script is only supported with "
|
|
|
|
"interface types bridge and ethernet"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-06-13 01:54:10 +00:00
|
|
|
libxl_device_nic_init(x_nic);
|
|
|
|
|
2012-07-17 12:07:59 +00:00
|
|
|
virMacAddrGetRaw(&l_nic->mac, x_nic->mac);
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2014-01-06 18:37:20 +00:00
|
|
|
if (ioemu_nic)
|
2012-11-26 16:28:56 +00:00
|
|
|
x_nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
|
2014-01-06 18:37:20 +00:00
|
|
|
else
|
2012-11-26 16:28:56 +00:00
|
|
|
x_nic->nictype = LIBXL_NIC_TYPE_VIF;
|
2014-01-06 18:37:20 +00:00
|
|
|
|
|
|
|
if (l_nic->model) {
|
|
|
|
if (VIR_STRDUP(x_nic->model, l_nic->model) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2014-01-06 18:37:20 +00:00
|
|
|
if (STREQ(l_nic->model, "netfront"))
|
|
|
|
x_nic->nictype = LIBXL_NIC_TYPE_VIF;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
|
|
|
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_nic->ifname, l_nic->ifname) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2014-06-10 20:28:07 +00:00
|
|
|
switch (actual_type) {
|
2013-06-13 01:54:03 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
2014-06-10 20:28:07 +00:00
|
|
|
if (VIR_STRDUP(x_nic->bridge,
|
|
|
|
virDomainNetGetActualBridgeName(l_nic)) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2013-06-13 01:54:03 +00:00
|
|
|
/* fallthrough */
|
|
|
|
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
|
|
|
if (VIR_STRDUP(x_nic->script, l_nic->script) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2015-02-10 02:17:23 +00:00
|
|
|
if (l_nic->nips > 0) {
|
|
|
|
x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address);
|
|
|
|
if (!x_nic->ip)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2015-02-10 02:17:23 +00:00
|
|
|
}
|
2013-06-13 01:54:03 +00:00
|
|
|
break;
|
2014-06-10 20:28:07 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
|
|
|
{
|
|
|
|
if (!(conn = virConnectOpen("xen:///system")))
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2014-06-10 20:28:07 +00:00
|
|
|
|
|
|
|
if (!(network =
|
|
|
|
virNetworkLookupByName(conn, l_nic->data.network.name))) {
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2014-06-10 20:28:07 +00:00
|
|
|
}
|
|
|
|
|
2015-02-10 02:17:23 +00:00
|
|
|
if (l_nic->nips > 0) {
|
|
|
|
x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address);
|
|
|
|
if (!x_nic->ip)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2014-06-10 20:28:07 +00:00
|
|
|
}
|
|
|
|
|
2016-02-24 22:40:00 +00:00
|
|
|
if (!(x_nic->bridge = virNetworkGetBridgeName(network)))
|
|
|
|
goto cleanup;
|
2014-06-10 20:28:07 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-07-11 17:47:31 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
2014-06-10 20:28:07 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_USER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_SERVER:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_CLIENT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_MCAST:
|
2015-08-29 20:19:10 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_UDP:
|
2014-06-10 20:28:07 +00:00
|
|
|
case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
|
|
|
case VIR_DOMAIN_NET_TYPE_LAST:
|
2014-06-10 20:53:55 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unsupported interface type %s"),
|
2013-06-13 01:54:03 +00:00
|
|
|
virDomainNetTypeToString(l_nic->type));
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
|
|
|
|
2015-02-20 03:22:06 +00:00
|
|
|
if (l_nic->domain_name) {
|
|
|
|
#ifdef LIBXL_HAVE_DEVICE_BACKEND_DOMNAME
|
|
|
|
if (VIR_STRDUP(x_nic->backend_domname, l_nic->domain_name) < 0)
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2015-02-20 03:22:06 +00:00
|
|
|
#else
|
|
|
|
virReportError(VIR_ERR_XML_DETAIL, "%s",
|
|
|
|
_("this version of libxenlight does not "
|
|
|
|
"support backend domain name"));
|
2016-02-24 22:40:00 +00:00
|
|
|
goto cleanup;
|
2015-02-20 03:22:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-12-29 00:26:58 +00:00
|
|
|
/*
|
|
|
|
* Set bandwidth.
|
|
|
|
* From $xen-sources/docs/misc/xl-network-configuration.markdown:
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Specifies the rate at which the outgoing traffic will be limited to.
|
|
|
|
* The default if this keyword is not specified is unlimited.
|
|
|
|
*
|
|
|
|
* The rate may be specified as "<RATE>/s" or optionally "<RATE>/s@<INTERVAL>".
|
|
|
|
*
|
|
|
|
* `RATE` is in bytes and can accept suffixes:
|
|
|
|
* GB, MB, KB, B for bytes.
|
|
|
|
* Gb, Mb, Kb, b for bits.
|
|
|
|
* `INTERVAL` is in microseconds and can accept suffixes: ms, us, s.
|
|
|
|
* It determines the frequency at which the vif transmission credit
|
|
|
|
* is replenished. The default is 50ms.
|
|
|
|
|
|
|
|
* Vif rate limiting is credit-based. It means that for "1MB/s@20ms",
|
|
|
|
* the available credit will be equivalent of the traffic you would have
|
|
|
|
* done at "1MB/s" during 20ms. This will results in a credit of 20,000
|
|
|
|
* bytes replenished every 20,000 us.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* libvirt doesn't support the notion of rate limiting over an interval.
|
|
|
|
* Similar to xl's behavior when interval is not specified, set a default
|
|
|
|
* interval of 50ms and calculate the number of bytes per interval based
|
|
|
|
* on the specified average bandwidth.
|
|
|
|
*/
|
|
|
|
actual_bw = virDomainNetGetActualBandwidth(l_nic);
|
|
|
|
if (actual_bw && actual_bw->out && actual_bw->out->average) {
|
|
|
|
uint64_t bytes_per_sec = actual_bw->out->average * 1024;
|
|
|
|
uint64_t bytes_per_interval =
|
|
|
|
(((uint64_t) bytes_per_sec * 50000UL) / 1000000UL);
|
|
|
|
|
|
|
|
x_nic->rate_bytes_per_interval = bytes_per_interval;
|
|
|
|
x_nic->rate_interval_usecs = 50000UL;
|
|
|
|
}
|
|
|
|
|
2016-02-24 22:40:00 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virObjectUnref(network);
|
|
|
|
virObjectUnref(conn);
|
|
|
|
|
|
|
|
return ret;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
|
|
|
libxlMakeNicList(virDomainDefPtr def, libxl_domain_config *d_config)
|
|
|
|
{
|
|
|
|
virDomainNetDefPtr *l_nics = def->nets;
|
2014-05-08 06:44:04 +00:00
|
|
|
size_t nnics = def->nnets;
|
2011-02-10 22:42:34 +00:00
|
|
|
libxl_device_nic *x_nics;
|
2014-05-08 06:44:04 +00:00
|
|
|
size_t i, nvnics = 0;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-07-04 10:10:38 +00:00
|
|
|
if (VIR_ALLOC_N(x_nics, nnics) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < nnics; i++) {
|
2016-03-10 02:50:41 +00:00
|
|
|
if (virDomainNetGetActualType(l_nics[i]) == VIR_DOMAIN_NET_TYPE_HOSTDEV)
|
2014-05-08 06:44:04 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (libxlMakeNic(def, l_nics[i], &x_nics[nvnics]))
|
2011-02-10 22:42:34 +00:00
|
|
|
goto error;
|
2014-01-08 10:39:19 +00:00
|
|
|
/*
|
|
|
|
* The devid (at least right now) will not get initialized by
|
|
|
|
* libxl in the setup case but is required for starting the
|
|
|
|
* device-model.
|
|
|
|
*/
|
2014-05-08 06:44:04 +00:00
|
|
|
if (x_nics[nvnics].devid < 0)
|
|
|
|
x_nics[nvnics].devid = nvnics;
|
|
|
|
|
|
|
|
nvnics++;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
2014-05-08 06:44:04 +00:00
|
|
|
VIR_SHRINK_N(x_nics, nnics, nnics - nvnics);
|
2012-11-26 16:28:56 +00:00
|
|
|
d_config->nics = x_nics;
|
2016-02-23 08:07:58 +00:00
|
|
|
d_config->num_nics = nvnics;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2011-02-10 22:42:34 +00:00
|
|
|
for (i = 0; i < nnics; i++)
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_device_nic_dispose(&x_nics[i]);
|
2011-02-10 22:42:34 +00:00
|
|
|
VIR_FREE(x_nics);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
int
|
2014-05-30 13:48:56 +00:00
|
|
|
libxlMakeVfb(virPortAllocatorPtr graphicsports,
|
2012-11-26 16:28:56 +00:00
|
|
|
virDomainGraphicsDefPtr l_vfb,
|
|
|
|
libxl_device_vfb *x_vfb)
|
2011-05-26 15:09:01 +00:00
|
|
|
{
|
2013-01-11 12:09:53 +00:00
|
|
|
unsigned short port;
|
2016-05-17 12:55:55 +00:00
|
|
|
virDomainGraphicsListenDefPtr glisten = NULL;
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2013-06-13 01:54:10 +00:00
|
|
|
libxl_device_vfb_init(x_vfb);
|
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
switch (l_vfb->type) {
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&x_vfb->sdl.enable, 1);
|
2015-04-17 17:19:31 +00:00
|
|
|
libxl_defbool_set(&x_vfb->vnc.enable, 0);
|
2015-04-24 20:11:26 +00:00
|
|
|
libxl_defbool_set(&x_vfb->sdl.opengl, 0);
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_vfb->sdl.display, l_vfb->data.sdl.display) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_vfb->sdl.xauthority, l_vfb->data.sdl.xauth) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&x_vfb->vnc.enable, 1);
|
2015-04-17 17:19:31 +00:00
|
|
|
libxl_defbool_set(&x_vfb->sdl.enable, 0);
|
2011-05-26 15:09:01 +00:00
|
|
|
/* driver handles selection of free port */
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_defbool_set(&x_vfb->vnc.findunused, 0);
|
2011-05-26 15:09:01 +00:00
|
|
|
if (l_vfb->data.vnc.autoport) {
|
2013-01-11 12:09:53 +00:00
|
|
|
|
2014-05-30 13:48:56 +00:00
|
|
|
if (virPortAllocatorAcquire(graphicsports, &port) < 0)
|
2013-01-11 12:09:53 +00:00
|
|
|
return -1;
|
2011-05-26 15:09:01 +00:00
|
|
|
l_vfb->data.vnc.port = port;
|
|
|
|
}
|
2012-11-26 16:28:56 +00:00
|
|
|
x_vfb->vnc.display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN;
|
2011-05-26 15:09:01 +00:00
|
|
|
|
2016-05-17 12:55:55 +00:00
|
|
|
if ((glisten = virDomainGraphicsGetListen(l_vfb, 0)) &&
|
|
|
|
glisten->address) {
|
2013-05-03 12:42:47 +00:00
|
|
|
/* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */
|
2012-11-26 16:28:56 +00:00
|
|
|
VIR_FREE(x_vfb->vnc.listen);
|
2016-05-17 12:55:55 +00:00
|
|
|
if (VIR_STRDUP(x_vfb->vnc.listen, glisten->address) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-04-28 00:20:30 +00:00
|
|
|
if (VIR_STRDUP(x_vfb->vnc.passwd, l_vfb->data.vnc.auth.passwd) < 0)
|
|
|
|
return -1;
|
2013-05-03 12:42:47 +00:00
|
|
|
if (VIR_STRDUP(x_vfb->keymap, l_vfb->data.vnc.keymap) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
return -1;
|
|
|
|
break;
|
2016-05-02 15:45:23 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
|
|
|
|
break;
|
2011-05-26 15:09:01 +00:00
|
|
|
}
|
2012-11-26 16:28:56 +00:00
|
|
|
|
2011-05-26 15:09:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
static int
|
2014-05-30 13:48:56 +00:00
|
|
|
libxlMakeVfbList(virPortAllocatorPtr graphicsports,
|
2012-11-26 16:28:56 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
libxl_domain_config *d_config)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
|
|
|
virDomainGraphicsDefPtr *l_vfbs = def->graphics;
|
|
|
|
int nvfbs = def->ngraphics;
|
|
|
|
libxl_device_vfb *x_vfbs;
|
|
|
|
libxl_device_vkb *x_vkbs;
|
Convert 'int i' to 'size_t i' in src/libxl/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
if (nvfbs == 0)
|
|
|
|
return 0;
|
|
|
|
|
2013-07-04 10:10:38 +00:00
|
|
|
if (VIR_ALLOC_N(x_vfbs, nvfbs) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
if (VIR_ALLOC_N(x_vkbs, nvfbs) < 0) {
|
|
|
|
VIR_FREE(x_vfbs);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nvfbs; i++) {
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_device_vkb_init(&x_vkbs[i]);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2014-05-30 13:48:56 +00:00
|
|
|
if (libxlMakeVfb(graphicsports, l_vfbs[i], &x_vfbs[i]) < 0)
|
2011-05-26 15:09:01 +00:00
|
|
|
goto error;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
d_config->vfbs = x_vfbs;
|
|
|
|
d_config->vkbs = x_vkbs;
|
|
|
|
d_config->num_vfbs = d_config->num_vkbs = nvfbs;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2011-02-10 22:42:34 +00:00
|
|
|
for (i = 0; i < nvfbs; i++) {
|
2012-11-26 16:28:56 +00:00
|
|
|
libxl_device_vfb_dispose(&x_vfbs[i]);
|
|
|
|
libxl_device_vkb_dispose(&x_vkbs[i]);
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(x_vfbs);
|
|
|
|
VIR_FREE(x_vkbs);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-04-27 18:32:55 +00:00
|
|
|
/*
|
|
|
|
* Populate vfb info in libxl_domain_build_info struct for HVM domains.
|
|
|
|
* Prior to calling this function, libxlMakeVfbList must be called to
|
|
|
|
* populate libxl_domain_config->vfbs.
|
|
|
|
*/
|
|
|
|
static int
|
2015-04-27 22:27:52 +00:00
|
|
|
libxlMakeBuildInfoVfb(virPortAllocatorPtr graphicsports,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
libxl_domain_config *d_config)
|
2015-04-27 18:32:55 +00:00
|
|
|
{
|
|
|
|
libxl_domain_build_info *b_info = &d_config->b_info;
|
|
|
|
libxl_device_vfb x_vfb;
|
2015-04-27 22:27:52 +00:00
|
|
|
size_t i;
|
2015-04-27 18:32:55 +00:00
|
|
|
|
|
|
|
if (def->os.type != VIR_DOMAIN_OSTYPE_HVM)
|
|
|
|
return 0;
|
|
|
|
|
2015-04-27 22:27:52 +00:00
|
|
|
if (def->ngraphics == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prefer SPICE, otherwise use first libxl_device_vfb device in
|
|
|
|
* libxl_domain_config->vfbs. Prior to calling this function,
|
|
|
|
*/
|
|
|
|
for (i = 0; i < def->ngraphics; i++) {
|
|
|
|
virDomainGraphicsDefPtr l_vfb = def->graphics[i];
|
|
|
|
unsigned short port;
|
2016-05-17 12:55:55 +00:00
|
|
|
virDomainGraphicsListenDefPtr glisten = NULL;
|
2015-04-27 22:27:52 +00:00
|
|
|
|
|
|
|
if (l_vfb->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.enable, true);
|
|
|
|
|
|
|
|
if (l_vfb->data.spice.autoport) {
|
|
|
|
if (virPortAllocatorAcquire(graphicsports, &port) < 0)
|
|
|
|
return -1;
|
|
|
|
l_vfb->data.spice.port = port;
|
|
|
|
}
|
|
|
|
b_info->u.hvm.spice.port = l_vfb->data.spice.port;
|
|
|
|
|
2016-05-17 12:55:55 +00:00
|
|
|
if ((glisten = virDomainGraphicsGetListen(l_vfb, 0)) &&
|
|
|
|
glisten->address &&
|
|
|
|
VIR_STRDUP(b_info->u.hvm.spice.host, glisten->address) < 0)
|
2015-04-27 22:27:52 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.keymap, l_vfb->data.spice.keymap) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (l_vfb->data.spice.auth.passwd) {
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.spice.passwd,
|
|
|
|
l_vfb->data.spice.auth.passwd) < 0)
|
|
|
|
return -1;
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.disable_ticketing, false);
|
|
|
|
} else {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.disable_ticketing, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (l_vfb->data.spice.mousemode) {
|
|
|
|
/* client mouse mode is default in xl.cfg */
|
|
|
|
case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_DEFAULT:
|
|
|
|
case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT:
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.agent_mouse, true);
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER:
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.agent_mouse, false);
|
|
|
|
break;
|
2016-05-02 15:45:23 +00:00
|
|
|
case VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST:
|
|
|
|
break;
|
2015-04-27 22:27:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef LIBXL_HAVE_SPICE_VDAGENT
|
|
|
|
if (l_vfb->data.spice.copypaste == VIR_TRISTATE_BOOL_YES) {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.vdagent, true);
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.clipboard_sharing, true);
|
|
|
|
} else {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.vdagent, false);
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.spice.clipboard_sharing, false);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-04-27 18:32:55 +00:00
|
|
|
return 0;
|
2015-04-27 22:27:52 +00:00
|
|
|
}
|
2015-04-27 18:32:55 +00:00
|
|
|
|
|
|
|
x_vfb = d_config->vfbs[0];
|
|
|
|
|
|
|
|
if (libxl_defbool_val(x_vfb.vnc.enable)) {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.vnc.enable, true);
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.vnc.listen, x_vfb.vnc.listen) < 0)
|
|
|
|
return -1;
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.vnc.passwd, x_vfb.vnc.passwd) < 0)
|
|
|
|
return -1;
|
|
|
|
b_info->u.hvm.vnc.display = x_vfb.vnc.display;
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.vnc.findunused,
|
|
|
|
libxl_defbool_val(x_vfb.vnc.findunused));
|
|
|
|
} else if (libxl_defbool_val(x_vfb.sdl.enable)) {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.sdl.enable, true);
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.sdl.opengl,
|
|
|
|
libxl_defbool_val(x_vfb.sdl.opengl));
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.sdl.display, x_vfb.sdl.display) < 0)
|
|
|
|
return -1;
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.sdl.xauthority, x_vfb.sdl.xauthority) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_STRDUP(b_info->u.hvm.keymap, x_vfb.keymap) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
/*
|
|
|
|
* Get domain0 autoballoon configuration. Honor user-specified
|
|
|
|
* setting in libxl.conf first. If not specified, autoballooning
|
|
|
|
* is disabled when domain0's memory is set with 'dom0_mem'.
|
|
|
|
* Otherwise autoballooning is enabled.
|
|
|
|
*/
|
2013-09-04 06:21:42 +00:00
|
|
|
static int
|
2013-09-09 15:15:15 +00:00
|
|
|
libxlGetAutoballoonConf(libxlDriverConfigPtr cfg,
|
|
|
|
virConfPtr conf)
|
2013-08-30 17:11:08 +00:00
|
|
|
{
|
2013-09-09 15:15:15 +00:00
|
|
|
virConfValuePtr p;
|
2013-08-30 17:11:08 +00:00
|
|
|
regex_t regex;
|
2013-09-04 06:21:42 +00:00
|
|
|
int res;
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
p = virConfGetValue(conf, "autoballoon");
|
|
|
|
if (p) {
|
|
|
|
if (p->type != VIR_CONF_ULONG) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s",
|
|
|
|
_("Unexpected type for 'autoballoon' setting"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
cfg->autoballoon = p->l != 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-09-04 06:21:42 +00:00
|
|
|
if ((res = regcomp(®ex,
|
|
|
|
"(^| )dom0_mem=((|min:|max:)[0-9]+[bBkKmMgG]?,?)+($| )",
|
|
|
|
REG_NOSUB | REG_EXTENDED)) != 0) {
|
|
|
|
char error[100];
|
|
|
|
regerror(res, ®ex, error, sizeof(error));
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to compile regex %s"),
|
|
|
|
error);
|
2013-08-30 17:11:08 +00:00
|
|
|
|
2013-09-04 06:21:42 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2013-08-30 17:11:08 +00:00
|
|
|
|
2013-09-04 06:21:42 +00:00
|
|
|
res = regexec(®ex, cfg->verInfo->commandline, 0, NULL, 0);
|
2013-08-30 17:11:08 +00:00
|
|
|
regfree(®ex);
|
2013-09-09 15:15:15 +00:00
|
|
|
cfg->autoballoon = res == REG_NOMATCH;
|
2013-09-04 06:21:42 +00:00
|
|
|
return 0;
|
2013-08-30 17:11:08 +00:00
|
|
|
}
|
|
|
|
|
2013-08-30 20:52:14 +00:00
|
|
|
libxlDriverConfigPtr
|
|
|
|
libxlDriverConfigNew(void)
|
|
|
|
{
|
|
|
|
libxlDriverConfigPtr cfg;
|
|
|
|
char *log_file = NULL;
|
2015-09-16 03:10:59 +00:00
|
|
|
xentoollog_level log_level = XTL_DEBUG;
|
2013-08-30 20:52:14 +00:00
|
|
|
char ebuf[1024];
|
|
|
|
unsigned int free_mem;
|
|
|
|
|
|
|
|
if (libxlConfigInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(cfg = virObjectNew(libxlDriverConfigClass)))
|
|
|
|
return NULL;
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
if (VIR_STRDUP(cfg->configBaseDir, LIBXL_CONFIG_BASE_DIR) < 0)
|
|
|
|
goto error;
|
2013-08-30 20:52:14 +00:00
|
|
|
if (VIR_STRDUP(cfg->configDir, LIBXL_CONFIG_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->autostartDir, LIBXL_AUTOSTART_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->logDir, LIBXL_LOG_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->stateDir, LIBXL_STATE_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->libDir, LIBXL_LIB_DIR) < 0)
|
|
|
|
goto error;
|
|
|
|
if (VIR_STRDUP(cfg->saveDir, LIBXL_SAVE_DIR) < 0)
|
|
|
|
goto error;
|
2014-02-19 23:09:36 +00:00
|
|
|
if (VIR_STRDUP(cfg->autoDumpDir, LIBXL_DUMP_DIR) < 0)
|
|
|
|
goto error;
|
2013-08-30 20:52:14 +00:00
|
|
|
|
|
|
|
if (virAsprintf(&log_file, "%s/libxl-driver.log", cfg->logDir) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-03-25 15:28:36 +00:00
|
|
|
if (virFileMakePath(cfg->logDir) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to create log dir '%s': %s"),
|
|
|
|
cfg->logDir,
|
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-08-30 20:52:14 +00:00
|
|
|
if ((cfg->logger_file = fopen(log_file, "a")) == NULL) {
|
|
|
|
VIR_ERROR(_("Failed to create log file '%s': %s"),
|
|
|
|
log_file, virStrerror(errno, ebuf, sizeof(ebuf)));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(log_file);
|
|
|
|
|
2015-09-15 14:17:44 +00:00
|
|
|
switch (virLogGetDefaultPriority()) {
|
|
|
|
case VIR_LOG_DEBUG:
|
|
|
|
log_level = XTL_DEBUG;
|
|
|
|
break;
|
|
|
|
case VIR_LOG_INFO:
|
|
|
|
log_level = XTL_INFO;
|
|
|
|
break;
|
|
|
|
case VIR_LOG_WARN:
|
|
|
|
log_level = XTL_WARN;
|
|
|
|
break;
|
|
|
|
case VIR_LOG_ERROR:
|
|
|
|
log_level = XTL_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-08-30 20:52:14 +00:00
|
|
|
cfg->logger =
|
|
|
|
(xentoollog_logger *)xtl_createlogger_stdiostream(cfg->logger_file,
|
2015-09-15 14:17:44 +00:00
|
|
|
log_level, XTL_STDIOSTREAM_SHOW_DATE);
|
2013-08-30 20:52:14 +00:00
|
|
|
if (!cfg->logger) {
|
|
|
|
VIR_ERROR(_("cannot create logger for libxenlight, disabling driver"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (libxl_ctx_alloc(&cfg->ctx, LIBXL_VERSION, 0, cfg->logger)) {
|
|
|
|
VIR_ERROR(_("cannot initialize libxenlight context, probably not "
|
|
|
|
"running in a Xen Dom0, disabling driver"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((cfg->verInfo = libxl_get_version_info(cfg->ctx)) == NULL) {
|
|
|
|
VIR_ERROR(_("cannot version information from libxenlight, "
|
|
|
|
"disabling driver"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
cfg->version = (cfg->verInfo->xen_version_major * 1000000) +
|
|
|
|
(cfg->verInfo->xen_version_minor * 1000);
|
|
|
|
|
|
|
|
/* This will fill xenstore info about free and dom0 memory if missing,
|
|
|
|
* should be called before starting first domain */
|
|
|
|
if (libxl_get_free_memory(cfg->ctx, &free_mem)) {
|
|
|
|
VIR_ERROR(_("Unable to configure libxl's memory management parameters"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cfg;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2013-08-30 20:52:14 +00:00
|
|
|
VIR_FREE(log_file);
|
|
|
|
virObjectUnref(cfg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
libxlDriverConfigPtr
|
|
|
|
libxlDriverConfigGet(libxlDriverPrivatePtr driver)
|
|
|
|
{
|
2013-08-30 20:57:42 +00:00
|
|
|
libxlDriverConfigPtr cfg;
|
|
|
|
|
|
|
|
libxlDriverLock(driver);
|
|
|
|
cfg = virObjectRef(driver->config);
|
|
|
|
libxlDriverUnlock(driver);
|
|
|
|
return cfg;
|
2013-08-30 20:52:14 +00:00
|
|
|
}
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
int libxlDriverConfigLoadFile(libxlDriverConfigPtr cfg,
|
|
|
|
const char *filename)
|
|
|
|
{
|
|
|
|
virConfPtr conf = NULL;
|
2015-04-14 20:38:46 +00:00
|
|
|
virConfValuePtr p;
|
2013-09-09 15:15:15 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2016-02-05 20:45:03 +00:00
|
|
|
/* defaults for keepalive messages */
|
|
|
|
cfg->keepAliveInterval = 5;
|
|
|
|
cfg->keepAliveCount = 5;
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
/* Check the file is readable before opening it, otherwise
|
|
|
|
* libvirt emits an error.
|
|
|
|
*/
|
|
|
|
if (access(filename, R_OK) == -1) {
|
|
|
|
VIR_INFO("Could not read libxl config file %s", filename);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(conf = virConfReadFile(filename, 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* setup autoballoon */
|
|
|
|
if (libxlGetAutoballoonConf(cfg, conf) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2015-04-14 20:38:46 +00:00
|
|
|
if ((p = virConfGetValue(conf, "lock_manager"))) {
|
|
|
|
if (p->type != VIR_CONF_STRING) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s",
|
|
|
|
_("Unexpected type for 'lock_manager' setting"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_STRDUP(cfg->lockManagerName, p->str) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-02-05 20:45:03 +00:00
|
|
|
if ((p = virConfGetValue(conf, "keepalive_interval"))) {
|
|
|
|
if (p->type != VIR_CONF_LONG && p->type != VIR_CONF_ULONG) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s",
|
|
|
|
_("Unexpected type for 'keepalive_interval' setting"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg->keepAliveInterval = p->l;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((p = virConfGetValue(conf, "keepalive_count"))) {
|
|
|
|
if (p->type != VIR_CONF_ULONG) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s",
|
|
|
|
_("Unexpected type for 'keepalive_count' setting"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg->keepAliveCount = p->l;
|
|
|
|
}
|
|
|
|
|
2013-09-09 15:15:15 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virConfFree(conf);
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-03-06 09:46:11 +00:00
|
|
|
int
|
2014-03-13 11:59:32 +00:00
|
|
|
libxlMakePCI(virDomainHostdevDefPtr hostdev, libxl_device_pci *pcidev)
|
2014-03-06 09:46:11 +00:00
|
|
|
{
|
2014-07-03 20:31:39 +00:00
|
|
|
virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
|
2014-03-06 09:46:11 +00:00
|
|
|
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
|
|
return -1;
|
|
|
|
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
|
|
|
return -1;
|
|
|
|
|
2014-07-03 20:31:39 +00:00
|
|
|
pcidev->domain = pcisrc->addr.domain;
|
|
|
|
pcidev->bus = pcisrc->addr.bus;
|
|
|
|
pcidev->dev = pcisrc->addr.slot;
|
|
|
|
pcidev->func = pcisrc->addr.function;
|
2014-03-06 09:46:11 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-03-13 11:59:32 +00:00
|
|
|
libxlMakePCIList(virDomainDefPtr def, libxl_domain_config *d_config)
|
2014-03-06 09:46:11 +00:00
|
|
|
{
|
|
|
|
virDomainHostdevDefPtr *l_hostdevs = def->hostdevs;
|
|
|
|
size_t nhostdevs = def->nhostdevs;
|
|
|
|
size_t npcidevs = 0;
|
|
|
|
libxl_device_pci *x_pcidevs;
|
|
|
|
size_t i, j;
|
|
|
|
|
|
|
|
if (nhostdevs == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(x_pcidevs, nhostdevs) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0, j = 0; i < nhostdevs; i++) {
|
|
|
|
if (l_hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
|
|
continue;
|
|
|
|
if (l_hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
libxl_device_pci_init(&x_pcidevs[j]);
|
|
|
|
|
2014-03-13 11:59:32 +00:00
|
|
|
if (libxlMakePCI(l_hostdevs[i], &x_pcidevs[j]) < 0)
|
2014-03-06 09:46:11 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
npcidevs++;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_SHRINK_N(x_pcidevs, nhostdevs, nhostdevs - npcidevs);
|
|
|
|
d_config->pcidevs = x_pcidevs;
|
|
|
|
d_config->num_pcidevs = npcidevs;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2014-03-06 09:46:11 +00:00
|
|
|
for (i = 0; i < npcidevs; i++)
|
|
|
|
libxl_device_pci_dispose(&x_pcidevs[i]);
|
|
|
|
|
|
|
|
VIR_FREE(x_pcidevs);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-07-01 07:58:18 +00:00
|
|
|
static int
|
|
|
|
libxlMakeVideo(virDomainDefPtr def, libxl_domain_config *d_config)
|
|
|
|
|
|
|
|
{
|
|
|
|
libxl_domain_build_info *b_info = &d_config->b_info;
|
|
|
|
int dm_type = libxlDomainGetEmulatorType(def);
|
|
|
|
|
|
|
|
if (d_config->c_info.type != LIBXL_DOMAIN_TYPE_HVM)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Take the first defined video device (graphics card) to display
|
|
|
|
* on the first graphics device (display).
|
|
|
|
*/
|
|
|
|
if (def->nvideos) {
|
|
|
|
switch (def->videos[0]->type) {
|
|
|
|
case VIR_DOMAIN_VIDEO_TYPE_VGA:
|
|
|
|
case VIR_DOMAIN_VIDEO_TYPE_XEN:
|
|
|
|
b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_STD;
|
|
|
|
if (dm_type == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
|
|
|
|
if (def->videos[0]->vram < 16 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 16MB for VGA"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (def->videos[0]->vram < 8 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 8MB for VGA"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
|
|
|
|
b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_CIRRUS;
|
|
|
|
if (dm_type == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
|
|
|
|
if (def->videos[0]->vram < 8 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 8MB for CIRRUS"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (def->videos[0]->vram < 4 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 4MB for CIRRUS"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2015-04-29 16:50:33 +00:00
|
|
|
#ifdef LIBXL_HAVE_QXL
|
|
|
|
case VIR_DOMAIN_VIDEO_TYPE_QXL:
|
|
|
|
b_info->u.hvm.vga.kind = LIBXL_VGA_INTERFACE_TYPE_QXL;
|
|
|
|
if (def->videos[0]->vram < 128 * 1024) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("videoram must be at least 128MB for QXL"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2014-07-01 07:58:18 +00:00
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("video type %s is not supported by libxl"),
|
|
|
|
virDomainVideoTypeToString(def->videos[0]->type));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* vram validated for each video type, now set it */
|
|
|
|
b_info->video_memkb = def->videos[0]->vram;
|
|
|
|
} else {
|
|
|
|
libxl_defbool_set(&b_info->u.hvm.nographic, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-02-26 20:44:09 +00:00
|
|
|
int
|
|
|
|
libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
|
|
|
|
{
|
|
|
|
libxl_physinfo phy_info;
|
|
|
|
virArch hostarch = virArchFromHost();
|
|
|
|
libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("libxl_get_physinfo_info failed"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStrcpyStatic(info->model, virArchToString(hostarch)) == NULL) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("machine type %s too big for destination"),
|
|
|
|
virArchToString(hostarch));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
info->memory = phy_info.total_pages * (cfg->verInfo->pagesize / 1024);
|
|
|
|
info->cpus = phy_info.nr_cpus;
|
|
|
|
info->nodes = phy_info.nr_nodes;
|
|
|
|
info->cores = phy_info.cores_per_socket;
|
|
|
|
info->threads = phy_info.threads_per_core;
|
|
|
|
info->sockets = 1;
|
|
|
|
info->mhz = phy_info.cpu_khz / 1000;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
cleanup:
|
2014-02-26 20:44:09 +00:00
|
|
|
virObjectUnref(cfg);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-10 22:42:34 +00:00
|
|
|
virCapsPtr
|
|
|
|
libxlMakeCapabilities(libxl_ctx *ctx)
|
|
|
|
{
|
2013-08-12 20:15:25 +00:00
|
|
|
virCapsPtr caps;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2014-06-24 17:10:49 +00:00
|
|
|
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
|
2014-07-14 12:56:13 +00:00
|
|
|
if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL)
|
2014-06-24 17:10:49 +00:00
|
|
|
#else
|
2014-07-14 12:56:13 +00:00
|
|
|
if ((caps = virCapabilitiesNew(virArchFromHost(), true, true)) == NULL)
|
2014-06-24 17:10:49 +00:00
|
|
|
#endif
|
2013-02-28 14:46:34 +00:00
|
|
|
return NULL;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
if (libxlCapsInitHost(ctx, caps) < 0)
|
|
|
|
goto error;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-16 21:37:46 +00:00
|
|
|
if (libxlCapsInitNuma(ctx, caps) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2013-08-12 20:15:25 +00:00
|
|
|
if (libxlCapsInitGuests(ctx, caps) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return caps;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2014-03-25 06:51:17 +00:00
|
|
|
error:
|
2013-08-12 20:15:25 +00:00
|
|
|
virObjectUnref(caps);
|
|
|
|
return NULL;
|
2011-02-10 22:42:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-05-30 13:48:56 +00:00
|
|
|
libxlBuildDomainConfig(virPortAllocatorPtr graphicsports,
|
2014-05-30 13:46:35 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
libxl_ctx *ctx,
|
|
|
|
libxl_domain_config *d_config)
|
2011-02-10 22:42:34 +00:00
|
|
|
{
|
2013-06-13 01:54:10 +00:00
|
|
|
libxl_domain_config_init(d_config);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2014-05-30 13:46:35 +00:00
|
|
|
if (libxlMakeDomCreateInfo(ctx, def, &d_config->c_info) < 0)
|
2011-02-10 22:42:34 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-05-30 13:46:35 +00:00
|
|
|
if (libxlMakeDomBuildInfo(def, ctx, d_config) < 0)
|
2013-04-29 23:04:55 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-14 21:33:48 +00:00
|
|
|
if (libxlMakeDiskList(def, d_config) < 0)
|
2013-04-29 23:04:55 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2013-08-14 21:33:48 +00:00
|
|
|
if (libxlMakeNicList(def, d_config) < 0)
|
2013-04-29 23:04:55 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2014-05-30 13:48:56 +00:00
|
|
|
if (libxlMakeVfbList(graphicsports, def, d_config) < 0)
|
2013-04-29 23:04:55 +00:00
|
|
|
return -1;
|
2011-02-10 22:42:34 +00:00
|
|
|
|
2015-04-27 22:27:52 +00:00
|
|
|
if (libxlMakeBuildInfoVfb(graphicsports, def, d_config) < 0)
|
2015-04-27 18:32:55 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-03-13 11:59:32 +00:00
|
|
|
if (libxlMakePCIList(def, d_config) < 0)
|
2014-03-06 09:46:11 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-07-01 07:58:18 +00:00
|
|
|
/*
|
|
|
|
* Now that any potential VFBs are defined, update the build info with
|
|
|
|
* the data of the primary display. Some day libxl might implicitely do
|
|
|
|
* so but as it does not right now, better be explicit.
|
|
|
|
*/
|
|
|
|
if (libxlMakeVideo(def, d_config) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2014-09-03 20:14:50 +00:00
|
|
|
d_config->on_reboot = libxlActionFromVirLifecycle(def->onReboot);
|
|
|
|
d_config->on_poweroff = libxlActionFromVirLifecycle(def->onPoweroff);
|
|
|
|
d_config->on_crash = libxlActionFromVirLifecycleCrash(def->onCrash);
|
2011-02-10 22:42:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-05-30 14:53:12 +00:00
|
|
|
|
|
|
|
virDomainXMLOptionPtr
|
|
|
|
libxlCreateXMLConf(void)
|
|
|
|
{
|
|
|
|
return virDomainXMLOptionNew(&libxlDomainDefParserConfig,
|
|
|
|
&libxlDomainXMLPrivateDataCallbacks,
|
|
|
|
NULL);
|
|
|
|
}
|