Move capabilities code out of libxl_conf.{ch} and into new
libxl_capabilities.{ch} files.
Signed-off-by: Jim Fehlig <jfehlig(a)suse.com>
---
po/POTFILES.in | 1 +
src/Makefile.am | 9 +-
src/libxl/libxl_capabilities.c | 458 +++++++++++++++++++++++++++++++++++++++++
src/libxl/libxl_capabilities.h | 50 +++++
src/libxl/libxl_conf.c | 419 -------------------------------------
src/libxl/libxl_conf.h | 18 +-
src/libxl/libxl_domain.c | 1 +
src/libxl/libxl_driver.c | 1 +
8 files changed, 517 insertions(+), 440 deletions(-)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index d6e79a8..822cfbc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -75,6 +75,7 @@ src/libvirt-secret.c
src/libvirt-storage.c
src/libvirt-stream.c
src/libvirt.c
+src/libxl/libxl_capabilities.c
src/libxl/libxl_conf.c
src/libxl/libxl_domain.c
src/libxl/libxl_driver.c
diff --git a/src/Makefile.am b/src/Makefile.am
index d0782f2..7004d14 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -828,10 +828,11 @@ XENAPI_DRIVER_SOURCES = \
xenapi/xenapi_driver_private.h \
xenapi/xenapi_utils.c xenapi/xenapi_utils.h
-LIBXL_DRIVER_SOURCES = \
- libxl/libxl_conf.c libxl/libxl_conf.h \
- libxl/libxl_domain.c libxl/libxl_domain.h \
- libxl/libxl_driver.c libxl/libxl_driver.h \
+LIBXL_DRIVER_SOURCES = \
+ libxl/libxl_conf.c libxl/libxl_conf.h \
+ libxl/libxl_capabilities.c libxl/libxl_capabilities.h \
+ libxl/libxl_domain.c libxl/libxl_domain.h \
+ libxl/libxl_driver.c libxl/libxl_driver.h \
libxl/libxl_migration.c libxl/libxl_migration.h
UML_DRIVER_SOURCES = \
diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c
new file mode 100644
index 0000000..aef2c2d
--- /dev/null
+++ b/src/libxl/libxl_capabilities.c
@@ -0,0 +1,458 @@
+/*
+ * libxl_capabilities.c: libxl capabilities generation
+ *
+ * Copyright (C) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Author: Jim Fehlig <jfehlig(a)suse.com>
+ */
+
+#include <config.h>
+
+#include <libxl.h>
+#include <regex.h>
+
+#include "internal.h"
+#include "virlog.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "viralloc.h"
+#include "domain_conf.h"
+#include "capabilities.h"
+#include "vircommand.h"
+#include "libxl_capabilities.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_LIBXL
+
+VIR_LOG_INIT("libxl.libxl_capabilities");
+
+/* see xen-unstable.hg/xen/include/asm-x86/cpufeature.h */
+#define LIBXL_X86_FEATURE_PAE_MASK 0x40
+
+
+struct guest_arch {
+ virArch arch;
+ int bits;
+ int hvm;
+ int pae;
+ int nonpae;
+ int ia64_be;
+};
+
+#define XEN_CAP_REGEX
"(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(aarch64|armv7l|x86_32|x86_64|ia64|powerpc64)(p|be)?"
+
+
+static int
+libxlCapsInitHost(libxl_ctx *ctx, virCapsPtr caps)
+{
+ libxl_physinfo phy_info;
+ int host_pae;
+
+ if (libxl_get_physinfo(ctx, &phy_info) != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to get node physical info from
libxenlight"));
+ return -1;
+ }
+
+ /* 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;
+
+ if (virCapabilitiesSetNetPrefix(caps, LIBXL_GENERATED_PREFIX_XEN) < 0)
+ return -1;
+
+ return 0;
+}
+
+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;
+
+ if (virCapabilitiesAddHostNUMACell(caps, i,
+ numa_info[i].size / 1024,
+ nr_cpus_node[i], cpus[i],
+ 0, NULL,
+ 0, NULL) < 0) {
+ 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) {
+ for (i = 0; cpus && i < nr_nodes; i++)
+ 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;
+}
+
+static int
+libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps)
+{
+ const libxl_version_info *ver_info;
+ int err;
+ regex_t regex;
+ char *str, *token;
+ regmatch_t subs[4];
+ char *saveptr = NULL;
+ size_t i;
+
+ struct guest_arch guest_archs[32];
+ int nr_guest_archs = 0;
+
+ memset(guest_archs, 0, sizeof(guest_archs));
+
+ if ((ver_info = libxl_get_version_info(ctx)) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to get version info from libxenlight"));
+ return -1;
+ }
+
+ if (!ver_info->capabilities) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to get capabilities from libxenlight"));
+ return -1;
+ }
+
+ 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;
+ }
+
+ /* 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.
+ */
+ for (str = ver_info->capabilities, nr_guest_archs = 0;
+ nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0])
+ && (token = strtok_r(str, " ", &saveptr)) !=
NULL;
+ str = NULL) {
+ if (regexec(®ex, token, sizeof(subs) / sizeof(subs[0]),
+ subs, 0) == 0) {
+ int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
+ virArch arch;
+ int pae = 0, nonpae = 0, ia64_be = 0;
+
+ if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
+ arch = VIR_ARCH_I686;
+ if (subs[3].rm_so != -1 &&
+ STRPREFIX(&token[subs[3].rm_so], "p"))
+ pae = 1;
+ else
+ nonpae = 1;
+ } else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
+ arch = VIR_ARCH_X86_64;
+ } else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
+ arch = VIR_ARCH_ITANIUM;
+ if (subs[3].rm_so != -1 &&
+ STRPREFIX(&token[subs[3].rm_so], "be"))
+ ia64_be = 1;
+ } else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
+ arch = VIR_ARCH_PPC64;
+ } 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;
+ } else {
+ continue;
+ }
+
+ /* Search for existing matching (model,hvm) tuple */
+ for (i = 0; i < nr_guest_archs; i++) {
+ if ((guest_archs[i].arch == arch) &&
+ guest_archs[i].hvm == hvm)
+ 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++;
+
+ guest_archs[i].arch = arch;
+ 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;
+ }
+ }
+ regfree(®ex);
+
+ for (i = 0; i < nr_guest_archs; ++i) {
+ virCapsGuestPtr guest;
+ char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" :
"xenpv"};
+ virCapsGuestMachinePtr *machines;
+
+ if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
+ return -1;
+
+ if ((guest = virCapabilitiesAddGuest(caps,
+ guest_archs[i].hvm ? VIR_DOMAIN_OSTYPE_HVM :
VIR_DOMAIN_OSTYPE_XEN,
+ guest_archs[i].arch,
+ LIBXL_EXECBIN_DIR
"/qemu-system-i386",
+ (guest_archs[i].hvm ?
+ LIBXL_FIRMWARE_DIR "/hvmloader"
:
+ NULL),
+ 1,
+ machines)) == NULL) {
+ virCapabilitiesFreeMachines(machines, 1);
+ return -1;
+ }
+ machines = NULL;
+
+ if (virCapabilitiesAddGuestDomain(guest,
+ VIR_DOMAIN_VIRT_XEN,
+ 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",
+ 1,
+ 1) == NULL)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+virCapsPtr
+libxlMakeCapabilities(libxl_ctx *ctx)
+{
+ virCapsPtr caps;
+
+#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
+ if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL)
+#else
+ if ((caps = virCapabilitiesNew(virArchFromHost(), true, true)) == NULL)
+#endif
+ return NULL;
+
+ if (libxlCapsInitHost(ctx, caps) < 0)
+ goto error;
+
+ if (libxlCapsInitNuma(ctx, caps) < 0)
+ goto error;
+
+ if (libxlCapsInitGuests(ctx, caps) < 0)
+ goto error;
+
+ return caps;
+
+ error:
+ virObjectUnref(caps);
+ return NULL;
+}
+
+#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;
+
+ if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
+ if (def->emulator) {
+ if (!virFileExists(def->emulator))
+ goto cleanup;
+
+ 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;
+}
diff --git a/src/libxl/libxl_capabilities.h b/src/libxl/libxl_capabilities.h
new file mode 100644
index 0000000..df1c327
--- /dev/null
+++ b/src/libxl/libxl_capabilities.h
@@ -0,0 +1,50 @@
+/*
+ * libxl_capabilities.h: libxl capabilities generation
+ *
+ * Copyright (C) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Author: Jim Fehlig <jfehlig(a)suse.com>
+ */
+
+#ifndef LIBXL_CAPABILITIES_H
+# define LIBXL_CAPABILITIES_H
+
+# include <libxl.h>
+
+# include "virobject.h"
+# include "capabilities.h"
+
+
+# ifndef LIBXL_FIRMWARE_DIR
+# define LIBXL_FIRMWARE_DIR "/usr/lib/xen/boot"
+# endif
+# ifndef LIBXL_EXECBIN_DIR
+# define LIBXL_EXECBIN_DIR "/usr/lib/xen/bin"
+# endif
+
+/* Used for prefix of ifname of any network name generated dynamically
+ * by libvirt for Xen, and cannot be used for a persistent network name. */
+# define LIBXL_GENERATED_PREFIX_XEN "vif"
+
+
+virCapsPtr
+libxlMakeCapabilities(libxl_ctx *ctx);
+
+int
+libxlDomainGetEmulatorType(const virDomainDef *def);
+
+#endif /* LIBXL_CAPABILITIES_H */
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index c6a23c2..96f9635 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -40,7 +40,6 @@
#include "virstring.h"
#include "viralloc.h"
#include "viruuid.h"
-#include "capabilities.h"
#include "vircommand.h"
#include "libxl_domain.h"
#include "libxl_conf.h"
@@ -53,21 +52,6 @@
VIR_LOG_INIT("libxl.libxl_conf");
-/* see xen-unstable.hg/xen/include/asm-x86/cpufeature.h */
-#define LIBXL_X86_FEATURE_PAE_MASK 0x40
-
-
-struct guest_arch {
- virArch arch;
- int bits;
- int hvm;
- int pae;
- int nonpae;
- int ia64_be;
-};
-
-#define XEN_CAP_REGEX
"(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(aarch64|armv7l|x86_32|x86_64|ia64|powerpc64)(p|be)?"
-
static virClassPtr libxlDriverConfigClass;
static void libxlDriverConfigDispose(void *obj);
@@ -164,346 +148,6 @@ libxlActionFromVirLifecycleCrash(virDomainLifecycleCrashAction
action)
static int
-libxlCapsInitHost(libxl_ctx *ctx, virCapsPtr caps)
-{
- libxl_physinfo phy_info;
- int host_pae;
-
- if (libxl_get_physinfo(ctx, &phy_info) != 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Failed to get node physical info from
libxenlight"));
- return -1;
- }
-
- /* 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;
-
- if (virCapabilitiesSetNetPrefix(caps, LIBXL_GENERATED_PREFIX_XEN) < 0)
- return -1;
-
- return 0;
-}
-
-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;
-
- if (virCapabilitiesAddHostNUMACell(caps, i,
- numa_info[i].size / 1024,
- nr_cpus_node[i], cpus[i],
- 0, NULL,
- 0, NULL) < 0) {
- 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) {
- for (i = 0; cpus && i < nr_nodes; i++)
- 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;
-}
-
-static int
-libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps)
-{
- const libxl_version_info *ver_info;
- int err;
- regex_t regex;
- char *str, *token;
- regmatch_t subs[4];
- char *saveptr = NULL;
- size_t i;
-
- struct guest_arch guest_archs[32];
- int nr_guest_archs = 0;
-
- memset(guest_archs, 0, sizeof(guest_archs));
-
- if ((ver_info = libxl_get_version_info(ctx)) == NULL) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Failed to get version info from libxenlight"));
- return -1;
- }
-
- if (!ver_info->capabilities) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Failed to get capabilities from libxenlight"));
- return -1;
- }
-
- 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;
- }
-
- /* 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.
- */
- for (str = ver_info->capabilities, nr_guest_archs = 0;
- nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0])
- && (token = strtok_r(str, " ", &saveptr)) !=
NULL;
- str = NULL) {
- if (regexec(®ex, token, sizeof(subs) / sizeof(subs[0]),
- subs, 0) == 0) {
- int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
- virArch arch;
- int pae = 0, nonpae = 0, ia64_be = 0;
-
- if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
- arch = VIR_ARCH_I686;
- if (subs[3].rm_so != -1 &&
- STRPREFIX(&token[subs[3].rm_so], "p"))
- pae = 1;
- else
- nonpae = 1;
- } else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
- arch = VIR_ARCH_X86_64;
- } else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
- arch = VIR_ARCH_ITANIUM;
- if (subs[3].rm_so != -1 &&
- STRPREFIX(&token[subs[3].rm_so], "be"))
- ia64_be = 1;
- } else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
- arch = VIR_ARCH_PPC64;
- } 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;
- } else {
- continue;
- }
-
- /* Search for existing matching (model,hvm) tuple */
- for (i = 0; i < nr_guest_archs; i++) {
- if ((guest_archs[i].arch == arch) &&
- guest_archs[i].hvm == hvm)
- 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++;
-
- guest_archs[i].arch = arch;
- 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;
- }
- }
- regfree(®ex);
-
- for (i = 0; i < nr_guest_archs; ++i) {
- virCapsGuestPtr guest;
- char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" :
"xenpv"};
- virCapsGuestMachinePtr *machines;
-
- if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
- return -1;
-
- if ((guest = virCapabilitiesAddGuest(caps,
- guest_archs[i].hvm ? VIR_DOMAIN_OSTYPE_HVM :
VIR_DOMAIN_OSTYPE_XEN,
- guest_archs[i].arch,
- LIBXL_EXECBIN_DIR
"/qemu-system-i386",
- (guest_archs[i].hvm ?
- LIBXL_FIRMWARE_DIR "/hvmloader"
:
- NULL),
- 1,
- machines)) == NULL) {
- virCapabilitiesFreeMachines(machines, 1);
- return -1;
- }
- machines = NULL;
-
- if (virCapabilitiesAddGuestDomain(guest,
- VIR_DOMAIN_VIRT_XEN,
- 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",
- 1,
- 1) == NULL)
- return -1;
- }
- }
-
- return 0;
-}
-
-static int
libxlMakeDomCreateInfo(libxl_ctx *ctx,
virDomainDefPtr def,
libxl_domain_create_info *c_info)
@@ -905,41 +549,6 @@ libxlDiskSetDiscard(libxl_device_disk *x_disk, int discard)
#endif
}
-
-#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;
-
- if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
- if (def->emulator) {
- if (!virFileExists(def->emulator))
- goto cleanup;
-
- 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;
-}
-
-
static char *
libxlMakeNetworkDiskSrcStr(virStorageSourcePtr src,
const char *username,
@@ -2066,34 +1675,6 @@ libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr
info)
return ret;
}
-virCapsPtr
-libxlMakeCapabilities(libxl_ctx *ctx)
-{
- virCapsPtr caps;
-
-#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
- if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL)
-#else
- if ((caps = virCapabilitiesNew(virArchFromHost(), true, true)) == NULL)
-#endif
- return NULL;
-
- if (libxlCapsInitHost(ctx, caps) < 0)
- goto error;
-
- if (libxlCapsInitNuma(ctx, caps) < 0)
- goto error;
-
- if (libxlCapsInitGuests(ctx, caps) < 0)
- goto error;
-
- return caps;
-
- error:
- virObjectUnref(caps);
- return NULL;
-}
-
int
libxlBuildDomainConfig(virPortAllocatorPtr graphicsports,
virDomainDefPtr def,
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index e55717a..6547056 100644
--- a/src/libxl/libxl_conf.h
+++ b/src/libxl/libxl_conf.h
@@ -40,6 +40,7 @@
# include "virhostdev.h"
# include "locking/lock_manager.h"
# include "virfirmware.h"
+# include "libxl_capabilities.h"
# define LIBXL_DRIVER_NAME "xenlight"
# define LIBXL_VNC_PORT_MIN 5900
@@ -48,10 +49,6 @@
# define LIBXL_MIGRATION_PORT_MIN 49152
# define LIBXL_MIGRATION_PORT_MAX 49216
-/* Used for prefix of ifname of any network name generated dynamically
- * by libvirt for Xen, and cannot be used for a persistent network name. */
-# define LIBXL_GENERATED_PREFIX_XEN "vif"
-
# define LIBXL_CONFIG_BASE_DIR SYSCONFDIR "/libvirt"
# define LIBXL_CONFIG_DIR SYSCONFDIR "/libvirt/libxl"
# define LIBXL_AUTOSTART_DIR LIBXL_CONFIG_DIR "/autostart"
@@ -62,13 +59,6 @@
# define LIBXL_DUMP_DIR LIBXL_LIB_DIR "/dump"
# define LIBXL_BOOTLOADER_PATH "pygrub"
-# ifndef LIBXL_FIRMWARE_DIR
-# define LIBXL_FIRMWARE_DIR "/usr/lib/xen/boot"
-# endif
-# ifndef LIBXL_EXECBIN_DIR
-# define LIBXL_EXECBIN_DIR "/usr/lib/xen/bin"
-# endif
-
typedef struct _libxlDriverPrivate libxlDriverPrivate;
typedef libxlDriverPrivate *libxlDriverPrivatePtr;
@@ -181,12 +171,6 @@ libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver,
int libxlDriverConfigLoadFile(libxlDriverConfigPtr cfg,
const char *filename);
-virCapsPtr
-libxlMakeCapabilities(libxl_ctx *ctx);
-
-int
-libxlDomainGetEmulatorType(const virDomainDef *def);
-
int
libxlMakeDisk(virDomainDiskDefPtr l_dev, libxl_device_disk *x_dev);
int
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 4a21f68..223862a 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -26,6 +26,7 @@
#include <fcntl.h>
#include "libxl_domain.h"
+#include "libxl_capabilities.h"
#include "viralloc.h"
#include "viratomic.h"
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 2ab08ac..afc5ac3 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -45,6 +45,7 @@
#include "libxl_domain.h"
#include "libxl_driver.h"
#include "libxl_conf.h"
+#include "libxl_capabilities.h"
#include "libxl_migration.h"
#include "xen_xm.h"
#include "xen_sxpr.h"
--
2.1.4