This is a helper function to look up all capabilities data for all
the OS bits that are relevant to <domain>. This is
- os type
- arch
- domain type
- emulator
- machine type
This will be used to replace several functions in later commits.
---
src/conf/capabilities.c | 163 +++++++++++++++++++++++++++++++++++-
src/conf/capabilities.h | 18 ++++
src/libvirt_private.syms | 1 +
tests/Makefile.am | 8 +-
tests/vircapstest.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 393 insertions(+), 6 deletions(-)
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index 9f84766..8d3d2a3 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -225,7 +225,6 @@ virCapabilitiesDispose(void *object)
virCPUDefFree(caps->host.cpu);
}
-
/**
* virCapabilitiesAddHostFeature:
* @caps: capabilities to extend
@@ -568,6 +567,168 @@ virCapabilitiesHostSecModelAddBaseLabel(virCapsHostSecModelPtr
secmodel,
return -1;
}
+static bool
+virCapsDomainDataCompare(virCapsGuestPtr guest,
+ virCapsGuestDomainPtr domain,
+ virCapsGuestMachinePtr machine,
+ int ostype,
+ virArch arch,
+ int domaintype,
+ const char *emulator,
+ const char *machinetype)
+{
+ char *check_emulator = NULL;
+
+ if (ostype != -1 && guest->ostype != ostype)
+ return false;
+ if ((arch != VIR_ARCH_NONE) && (guest->arch.id != arch))
+ return false;
+
+ if (domaintype != -1 && (!domain || domain->type != domaintype))
+ return false;
+
+ if (emulator) {
+ if (domain)
+ check_emulator = domain->info.emulator;
+ if (!check_emulator)
+ check_emulator = guest->arch.defaultInfo.emulator;
+ if (!check_emulator || STRNEQ(check_emulator, emulator))
+ return false;
+ }
+
+ if (machinetype) {
+ if (!machine)
+ return false;
+ if (STRNEQ(machine->name, machinetype) &&
+ (!machine->canonical || STRNEQ(machine->canonical, machinetype)))
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * virCapabilitiesDomainDataLookup:
+ * @caps: capabilities to query
+ * @ostype: guest operating system type, of enum VIR_DOMAIN_OSTYPE
+ * @arch: Architecture to search for
+ * @domaintype: domain type to search for, of enum VIR_DOMAIN_VIRT
+ * @emulator: Emulator path to search for
+ * @machinetype: Machine type to search for
+ *
+ * Search capabilities for the passed values, and if found return
+ * virCapabilitiesDomainDataLookup filled in with the default values
+ */
+virCapsDomainDataPtr
+virCapabilitiesDomainDataLookup(virCapsPtr caps,
+ int ostype,
+ virArch arch,
+ int domaintype,
+ const char *emulator,
+ const char *machinetype)
+{
+ virCapsGuestPtr foundguest = NULL;
+ virCapsGuestDomainPtr founddomain = NULL;
+ virCapsGuestMachinePtr foundmachine = NULL;
+ virCapsDomainDataPtr ret = NULL;
+ size_t i, j, k;
+
+ for (i = 0; i < caps->nguests; i++) {
+ virCapsGuestPtr guest = caps->guests[i];
+
+ for (j = 0; j < guest->arch.ndomains; j++) {
+ virCapsGuestDomainPtr domain = guest->arch.domains[j];
+ virCapsGuestMachinePtr *machinelist;
+ int nmachines;
+
+ if (domain->info.nmachines) {
+ nmachines = domain->info.nmachines;
+ machinelist = domain->info.machines;
+ } else {
+ nmachines = guest->arch.defaultInfo.nmachines;
+ machinelist = guest->arch.defaultInfo.machines;
+ }
+
+ for (k = 0; k < nmachines; k++) {
+ virCapsGuestMachinePtr machine = machinelist[k];
+ if (!virCapsDomainDataCompare(guest, domain, machine,
+ ostype, arch, domaintype,
+ emulator, machinetype))
+ continue;
+
+ foundmachine = machine;
+ break;
+ }
+
+ if (!foundmachine) {
+ if (!virCapsDomainDataCompare(guest, domain, NULL,
+ ostype, arch, domaintype,
+ emulator, machinetype))
+ continue;
+ }
+
+ founddomain = domain;
+ break;
+ }
+
+ if (!founddomain) {
+ if (!virCapsDomainDataCompare(guest, NULL, NULL,
+ ostype, arch, domaintype,
+ emulator, machinetype))
+ continue;
+ }
+
+ foundguest = guest;
+ break;
+ }
+
+ /* XXX check default_emulator, see how it uses this */
+ if (!foundguest) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ if (ostype)
+ virBufferAsprintf(&buf, "ostype=%s ",
+ virDomainOSTypeToString(ostype));
+ if (arch)
+ virBufferAsprintf(&buf, "arch=%s ", virArchToString(arch));
+ if (domaintype)
+ virBufferAsprintf(&buf, "domaintype=%s ",
+ virDomainVirtTypeToString(domaintype));
+ if (emulator)
+ virBufferAsprintf(&buf, "emulator=%s ", emulator);
+ if (machinetype)
+ virBufferAsprintf(&buf, "machine=%s ", machinetype);
+ if (virBufferCurrentContent(&buf) &&
+ !virBufferCurrentContent(&buf)[0])
+ virBufferAsprintf(&buf, "%s", _("any
configuration"));
+ if (virBufferCheckError(&buf) < 0) {
+ virBufferContentAndReset(&buf);
+ goto error;
+ }
+
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("could not find capabilities for %s"),
+ virBufferContentAndReset(&buf));
+ goto error;
+ }
+
+ if (VIR_ALLOC(ret) < 0)
+ goto error;
+
+ ret->ostype = foundguest->ostype;
+ ret->arch = foundguest->arch.id;
+ if (founddomain) {
+ ret->domaintype = founddomain->type;
+ ret->emulator = founddomain->info.emulator;
+ }
+ if (!ret->emulator)
+ ret->emulator = foundguest->arch.defaultInfo.emulator;
+ if (foundmachine)
+ ret->machinetype = foundmachine->name;
+
+ error:
+ return ret;
+}
+
/**
* virCapabilitiesSupportsGuestArch:
* @caps: capabilities to query
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
index 7ee834f..87acf39 100644
--- a/src/conf/capabilities.h
+++ b/src/conf/capabilities.h
@@ -192,6 +192,16 @@ struct _virCaps {
virCapsGuestPtr *guests;
};
+typedef struct _virCapsDomainData virCapsDomainData;
+typedef virCapsDomainData *virCapsDomainDataPtr;
+struct _virCapsDomainData {
+ int ostype;
+ int arch;
+ int domaintype;
+ char *emulator;
+ char *machinetype;
+};
+
extern virCapsPtr
virCapabilitiesNew(virArch hostarch,
@@ -262,6 +272,14 @@ virCapabilitiesHostSecModelAddBaseLabel(virCapsHostSecModelPtr
secmodel,
const char *type,
const char *label);
+virCapsDomainDataPtr
+virCapabilitiesDomainDataLookup(virCapsPtr caps,
+ int ostype,
+ virArch arch,
+ int domaintype,
+ const char *emulator,
+ const char *machinetype);
+
extern int
virCapabilitiesSupportsGuestArch(virCapsPtr caps,
virArch arch);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a587597..5843061 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -54,6 +54,7 @@ virCapabilitiesClearHostNUMACellCPUTopology;
virCapabilitiesDefaultGuestArch;
virCapabilitiesDefaultGuestEmulator;
virCapabilitiesDefaultGuestMachine;
+virCapabilitiesDomainDataLookup;
virCapabilitiesFormatXML;
virCapabilitiesFreeMachines;
virCapabilitiesFreeNUMAInfo;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5f88b18..c6d60cd 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -877,8 +877,12 @@ virkmodtest_SOURCES = \
virkmodtest_LDADD = $(LDADDS)
vircapstest_SOURCES = \
- vircapstest.c testutils.h testutils.c
-vircapstest_LDADD = $(LDADDS)
+ vircapstest.c testutils.h testutils.c \
+ testutilsqemu.c testutilsqemu.h \
+ testutilslxc.c testutilslxc.h \
+ testutilsxen.c testutilsxen.h \
+ $(NULL)
+vircapstest_LDADD = $(qemu_LDADDS) $(LDADDS)
vircaps2xmltest_SOURCES = \
vircaps2xmltest.c testutils.h testutils.c
diff --git a/tests/vircapstest.c b/tests/vircapstest.c
index deabc7a..3e5038b 100644
--- a/tests/vircapstest.c
+++ b/tests/vircapstest.c
@@ -21,6 +21,9 @@
#include <stdlib.h>
#include "testutils.h"
+#include "testutilslxc.h"
+#include "testutilsxen.h"
+#include "testutilsqemu.h"
#include "capabilities.h"
#include "virbitmap.h"
@@ -66,8 +69,8 @@ buildNUMATopology(int seq)
if (virCapabilitiesAddHostNUMACell(caps, cell_id + seq,
MAX_MEM_IN_CELL,
MAX_CPUS_IN_CELL, cell_cpus,
- 0, NULL,
- 0, NULL) < 0)
+ VIR_ARCH_NONE, NULL,
+ VIR_ARCH_NONE, NULL) < 0)
goto error;
cell_cpus = NULL;
@@ -101,7 +104,7 @@ test_virCapabilitiesGetCpusForNodemask(const void *data
ATTRIBUTE_UNUSED)
if (!(caps = buildNUMATopology(3)))
goto error;
- if (virBitmapParse(nodestr, 0, &nodemask, mask_size) < 0)
+ if (virBitmapParse(nodestr, VIR_ARCH_NONE, &nodemask, mask_size) < 0)
goto error;
if (!(cpumap = virCapabilitiesGetCpusForNodemask(caps, nodemask)))
@@ -118,6 +121,197 @@ test_virCapabilitiesGetCpusForNodemask(const void *data
ATTRIBUTE_UNUSED)
}
+static bool
+doCapsExpectFailure(virCapsPtr caps,
+ int ostype,
+ virArch arch,
+ int domaintype,
+ const char *emulator,
+ const char *machinetype)
+{
+ virCapsDomainDataPtr data = virCapabilitiesDomainDataLookup(caps, ostype,
+ arch, domaintype, emulator, machinetype);
+
+ if (data) {
+ VIR_FREE(data);
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+doCapsCompare(virCapsPtr caps,
+ int ostype,
+ virArch arch,
+ int domaintype,
+ const char *emulator,
+ const char *machinetype,
+ int expect_ostype,
+ virArch expect_arch,
+ int expect_domaintype,
+ const char *expect_emulator,
+ const char *expect_machinetype)
+{
+ bool ret = false;
+ virCapsDomainDataPtr data = virCapabilitiesDomainDataLookup(caps, ostype,
+ arch, domaintype, emulator, machinetype);
+
+ if (!data)
+ goto error;
+
+ if (data->ostype != expect_ostype) {
+ fprintf(stderr, "data->ostype=%s doesn't match
expect_ostype=%s\n",
+ virDomainOSTypeToString(data->ostype),
+ virDomainOSTypeToString(expect_ostype));
+ goto error;
+ }
+
+ if (data->arch != expect_arch) {
+ fprintf(stderr, "data->arch=%s doesn't match expect_arch=%s\n",
+ virArchToString(data->arch),
+ virArchToString(expect_arch));
+ goto error;
+ }
+
+ if (data->domaintype != expect_domaintype) {
+ fprintf(stderr, "data->domaintype=%s doesn't match "
+ "expect_domaintype=%s\n",
+ virDomainVirtTypeToString(data->domaintype),
+ virDomainVirtTypeToString(expect_domaintype));
+ goto error;
+ }
+
+ if (STRNEQ(data->emulator, expect_emulator)) {
+ fprintf(stderr, "data->emulator=%s doesn't match
expect_emulator=%s\n",
+ data->emulator, expect_emulator);
+ goto error;
+ }
+
+ if (data->machinetype != expect_machinetype &&
+ STRNEQ(data->machinetype, expect_machinetype)) {
+ fprintf(stderr, "data->machinetype=%s doesn't match "
+ "expect_machinetype=%s\n",
+ data->machinetype, expect_machinetype);
+ goto error;
+ }
+
+ ret = true;
+ error:
+ VIR_FREE(data);
+ return ret;
+}
+
+#define CAPSCOMP(o, a, d, e, m, fo, fa, fd, fe, fm) \
+ if (!doCapsCompare(caps, o, a, d, e, m, fo, fa, fd, fe, fm)) \
+ ret = 1;
+
+#define CAPS_EXPECT_ERR(o, a, d, e, m) \
+ if (!doCapsExpectFailure(caps, o, a, d, e, m)) \
+ ret = 1;
+
+static int
+test_virCapsDomainDataLookupQEMU(const void *data ATTRIBUTE_UNUSED)
+{
+ int ret = 0;
+ virCapsPtr caps = NULL;
+
+ if (!(caps = testQemuCapsInit())) {
+ ret = -1;
+ goto out;
+ }
+
+ /* Checking each parameter individually */
+ CAPSCOMP(-1, VIR_ARCH_NONE, -1, NULL, NULL,
+ VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_I686,
+ VIR_DOMAIN_VIRT_QEMU, "/usr/bin/qemu", "pc");
+ CAPSCOMP(VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_NONE, -1, NULL, NULL,
+ VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_I686,
+ VIR_DOMAIN_VIRT_QEMU, "/usr/bin/qemu", "pc");
+ CAPSCOMP(-1, VIR_ARCH_AARCH64, -1, NULL, NULL,
+ VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_AARCH64,
+ VIR_DOMAIN_VIRT_QEMU, "/usr/bin/qemu-system-aarch64",
"virt");
+ CAPSCOMP(-1, VIR_ARCH_NONE, VIR_DOMAIN_VIRT_KVM, NULL, NULL,
+ VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_X86_64,
+ VIR_DOMAIN_VIRT_KVM, "/usr/bin/kvm", "pc");
+ CAPSCOMP(-1, VIR_ARCH_NONE, -1, "/usr/bin/qemu-system-ppc64", NULL,
+ VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_PPC64,
+ VIR_DOMAIN_VIRT_QEMU, "/usr/bin/qemu-system-ppc64",
"pseries");
+ CAPSCOMP(-1, VIR_ARCH_NONE, -1, NULL, "s390-virtio",
+ VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_S390X,
+ VIR_DOMAIN_VIRT_QEMU, "/usr/bin/qemu-system-s390x",
+ "s390-virtio");
+
+ CAPSCOMP(-1, VIR_ARCH_NONE, -1, NULL, "pseries",
+ VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_PPC64,
+ VIR_DOMAIN_VIRT_QEMU, "/usr/bin/qemu-system-ppc64",
"pseries");
+ CAPSCOMP(-1, VIR_ARCH_PPC64LE, -1, NULL, "pseries",
+ VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_PPC64LE,
+ VIR_DOMAIN_VIRT_QEMU, "/usr/bin/qemu-system-ppc64",
"pseries");
+
+ CAPS_EXPECT_ERR(VIR_DOMAIN_OSTYPE_AIX, VIR_ARCH_NONE, -1, NULL, NULL);
+ CAPS_EXPECT_ERR(-1, VIR_ARCH_PPC64LE, -1, NULL, "pc");
+ CAPS_EXPECT_ERR(-1, VIR_ARCH_MIPS, -1, NULL, NULL);
+ CAPS_EXPECT_ERR(-1, VIR_ARCH_AARCH64, VIR_DOMAIN_VIRT_KVM,
+ "/usr/bin/qemu-system-aarch64", NULL);
+ CAPS_EXPECT_ERR(-1, VIR_ARCH_NONE, -1,
+ "/usr/bin/qemu-system-aarch64", "pc");
+ CAPS_EXPECT_ERR(-1, VIR_ARCH_NONE, VIR_DOMAIN_VIRT_VMWARE, NULL, "pc");
+
+ out:
+ virObjectUnref(caps);
+ return ret;
+}
+
+static int
+test_virCapsDomainDataLookupXen(const void *data ATTRIBUTE_UNUSED)
+{
+ int ret = -1;
+ virCapsPtr caps = NULL;
+
+ if (!(caps = testXenCapsInit())) {
+ ret = -1;
+ goto out;
+ }
+
+ CAPSCOMP(-1, VIR_ARCH_NONE, -1, NULL, NULL,
+ VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_I686, VIR_DOMAIN_VIRT_XEN,
+ "/usr/lib/xen/bin/qemu-dm", "xenfv");
+ CAPSCOMP(VIR_DOMAIN_OSTYPE_XEN, VIR_ARCH_NONE, -1, NULL, NULL,
+ VIR_DOMAIN_OSTYPE_XEN, VIR_ARCH_I686, VIR_DOMAIN_VIRT_XEN,
+ "/usr/lib/xen/bin/qemu-dm", "xenpv");
+
+ CAPS_EXPECT_ERR(VIR_DOMAIN_OSTYPE_XEN, VIR_ARCH_NONE, -1, NULL, "xenfv");
+
+ ret = 0;
+ out:
+ virObjectUnref(caps);
+ return ret;
+}
+
+static int
+test_virCapsDomainDataLookupLXC(const void *data ATTRIBUTE_UNUSED)
+{
+ int ret = 0;
+ virCapsPtr caps = NULL;
+
+ if (!(caps = testLXCCapsInit())) {
+ ret = -1;
+ goto out;
+ }
+
+ CAPSCOMP(-1, VIR_ARCH_NONE, -1, NULL, NULL,
+ VIR_DOMAIN_OSTYPE_EXE, VIR_ARCH_I686,
+ VIR_DOMAIN_VIRT_LXC, "/usr/libexec/libvirt_lxc", NULL);
+ CAPSCOMP(-1, VIR_ARCH_X86_64, -1, NULL, NULL,
+ VIR_DOMAIN_OSTYPE_EXE, VIR_ARCH_X86_64,
+ VIR_DOMAIN_VIRT_LXC, "/usr/libexec/libvirt_lxc", NULL);
+
+ out:
+ virObjectUnref(caps);
+ return ret;
+}
+
static int
mymain(void)
{
@@ -126,6 +320,15 @@ mymain(void)
if (virtTestRun("virCapabilitiesGetCpusForNodemask",
test_virCapabilitiesGetCpusForNodemask, NULL) < 0)
ret = -1;
+ if (virtTestRun("virCapsDomainDataLookupQEMU",
+ test_virCapsDomainDataLookupQEMU, NULL) < 0)
+ ret = -1;
+ if (virtTestRun("virCapsDomainDataLookupXen",
+ test_virCapsDomainDataLookupXen, NULL) < 0)
+ ret = -1;
+ if (virtTestRun("virCapsDomainDataLookupLXC",
+ test_virCapsDomainDataLookupLXC, NULL) < 0)
+ ret = -1;
return ret;
}
--
2.3.5