From a6936523412162ca8c45a75d44cf64b9c13acabb Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Fri, 17 Apr 2015 12:38:55 -0400 Subject: [PATCH] caps: Add virCapabilitiesDomainDataLookup This is a helper function to look up all capabilities data for all the OS bits that are relevant to . 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 9f84766a28..234924b1c4 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) +{ + const 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 (STRNEQ_NULLABLE(check_emulator, emulator)) + return false; + } + + if (machinetype) { + if (!machine) + return false; + if (STRNEQ(machine->name, machinetype) && + (STRNEQ_NULLABLE(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 7ee834f981..61cd84a0d6 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; + const char *emulator; + const 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 a587597fbb..58430613f1 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 5f88b18d52..c6d60cd9e6 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 deabc7a991..3e5038bd62 100644 --- a/tests/vircapstest.c +++ b/tests/vircapstest.c @@ -21,6 +21,9 @@ #include #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; } -- GitLab