[libvirt] [PATCH 07/11] caps: Add virCapabilitiesDomainDataLookup

Cole Robinson crobinso at redhat.com
Sat Apr 18 01:45:17 UTC 2015


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




More information about the libvir-list mailing list