]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add formal internal capabilities API and update drivers to use it
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 27 Feb 2008 04:35:08 +0000 (04:35 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Wed, 27 Feb 2008 04:35:08 +0000 (04:35 +0000)
29 files changed:
ChangeLog
proxy/Makefile.am
src/Makefile.am
src/capabilities.c [new file with mode: 0644]
src/capabilities.h [new file with mode: 0644]
src/qemu_conf.c
src/qemu_conf.h
src/qemu_driver.c
src/test.c
src/util.c
src/util.h
src/xen_internal.c
src/xend_internal.c
src/xend_internal.h
src/xml.c
src/xml.h
tests/qemuxml2argvtest.c
tests/qemuxml2xmltest.c
tests/xencapsdata/xen-i686-pae-hvm.xml
tests/xencapsdata/xen-i686-pae.xml
tests/xencapsdata/xen-i686.xml
tests/xencapsdata/xen-ia64-be-hvm.xml
tests/xencapsdata/xen-ia64-be.xml
tests/xencapsdata/xen-ia64-hvm.xml
tests/xencapsdata/xen-ia64.xml
tests/xencapsdata/xen-ppc64.xml
tests/xencapsdata/xen-x86_64-hvm.xml
tests/xencapsdata/xen-x86_64.xml
tests/xencapstest.c

index da1c3c1dfd5b863009792a6726bb59767d7aad52..3d82e43443d6daedc17d7529eff512ef22b6efde 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Tue Feb 26 23:16:00 EST 2006 Daniel P. Berrange <berrange@redhat.com>
+
+       * src/capabilities.h, src/capabilities.c, src/Makefile.am:
+       Add generic API for dealing with hypervisor capabilities
+       * src/qemu_conf.c, src/qemu_conf.h, src/qemu_driver.c: Switch
+       to using capabilities API. Add support for Xenner guests
+       * src/xen_internalc, src/xend_internal.c, src/xend_internal.h,
+       src/xml.h, src/xml.c, src/util.c, src/util.h, src/test.c:
+       Switch to using capabilities API
+       * tests/xencapstest.c, tests/xencapsdata/*.xml: Update for
+       changes to capabilities API
+       * proxy/Makefile.am: Link to capabilities.c and util.c
+
 Tue Feb 26 18:38:00 UTC 2008 Richard W.M. Jones <rjones@redhat.com>
 
        Implement virDomainBlockStats for QEMU/KVM.
index 68e331744f48aab6e6b1df19e7fbff2a2bac879e..789a6429fab33e4c82e36e0620622f29ec87d696 100644 (file)
@@ -13,7 +13,8 @@ libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xend_internal.c \
            @top_srcdir@/src/xen_internal.c @top_srcdir@/src/virterror.c \
            @top_srcdir@/src/sexpr.c @top_srcdir@/src/xml.c \
             @top_srcdir@/src/xs_internal.c @top_srcdir@/src/buf.c \
-            @top_srcdir@/src/util-lib.c \
+            @top_srcdir@/src/capabilities.c \
+            @top_srcdir@/src/util.c \
            @top_srcdir@/src/uuid.c
 libvirt_proxy_LDFLAGS = $(WARN_CFLAGS)
 libvirt_proxy_DEPENDENCIES =
index b2bc900e6e1eed4881b5ea60b5ce343246d13e7f..02be9dbc0cbda49914413dcb99cab3b9a6c8b3e0 100644 (file)
@@ -37,6 +37,7 @@ CLIENT_SOURCES =                                              \
                test.c test.h                                   \
                 buf.c buf.h                                    \
                qparams.c qparams.h                             \
+                capabilities.c capabilities.h                  \
                xml.c xml.h                                     \
                event.c event.h                                 \
                xen_unified.c xen_unified.h                     \
diff --git a/src/capabilities.c b/src/capabilities.c
new file mode 100644 (file)
index 0000000..94f7d17
--- /dev/null
@@ -0,0 +1,696 @@
+/*
+ * capabilities.c: hypervisor capabilities
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ * Copyright (C) 2006-2008 Daniel P. Berrange
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#include "capabilities.h"
+#include "buf.h"
+
+
+/**
+ * virCapabilitiesNew:
+ * @arch: host machine architecture
+ * @offlineMigrate: non-zero if offline migration is available
+ * @liveMigrate: non-zero if live migration is available
+ * 
+ * Allocate a new capabilities object
+ */
+virCapsPtr
+virCapabilitiesNew(const char *arch,
+                   int offlineMigrate,
+                   int liveMigrate)
+{
+    virCapsPtr caps;
+
+    if ((caps = calloc(1, sizeof(*caps))) == NULL)
+        goto no_memory;
+
+    if ((caps->host.arch = strdup(arch)) == NULL)
+        goto no_memory;
+    caps->host.offlineMigrate = offlineMigrate;
+    caps->host.liveMigrate = liveMigrate;
+
+    return caps;
+
+ no_memory:
+    virCapabilitiesFree(caps);
+    return NULL;
+}
+
+static void
+virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell)
+{
+    free(cell->cpus);
+    free(cell);
+}
+
+static void
+virCapabilitiesFreeGuestDomain(virCapsGuestDomainPtr dom)
+{
+    int i;
+    free(dom->info.emulator);
+    free(dom->info.loader);
+    for (i = 0 ; i < dom->info.nmachines ; i++)
+        free(dom->info.machines[i]);
+    free(dom->info.machines);
+
+    free(dom);
+}
+
+static void
+virCapabilitiesFreeGuestFeature(virCapsGuestFeaturePtr feature)
+{
+    free(feature->name);
+    free(feature);
+}
+
+static void
+virCapabilitiesFreeGuest(virCapsGuestPtr guest)
+{
+    int i;
+    free(guest->ostype);
+
+    free(guest->arch.defaultInfo.emulator);
+    free(guest->arch.defaultInfo.loader);
+    for (i = 0 ; i < guest->arch.defaultInfo.nmachines ; i++)
+        free(guest->arch.defaultInfo.machines[i]);
+    free(guest->arch.defaultInfo.machines);
+
+    for (i = 0 ; i < guest->arch.ndomains ; i++)
+        virCapabilitiesFreeGuestDomain(guest->arch.domains[i]);
+    free(guest->arch.domains);
+
+    for (i = 0 ; i < guest->nfeatures ; i++)
+        virCapabilitiesFreeGuestFeature(guest->features[i]);
+    free(guest->features);
+
+    free(guest);
+}
+
+
+/**
+ * virCapabilitiesFree:
+ * @caps: object to free
+ *
+ * Free all memory associated with capabilities
+ */
+void
+virCapabilitiesFree(virCapsPtr caps) {
+    int i;
+
+    for (i = 0 ; i < caps->nguests ; i++)
+        virCapabilitiesFreeGuest(caps->guests[i]);
+    free(caps->guests);
+
+    for (i = 0 ; i < caps->host.nfeatures ; i++)
+        free(caps->host.features[i]);
+    free(caps->host.features);
+    for (i = 0 ; i < caps->host.nnumaCell ; i++)
+        virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]);
+    free(caps->host.numaCell);
+
+    free(caps->host.arch);
+    free(caps);
+}
+
+
+/**
+ * virCapabilitiesAddHostFeature:
+ * @caps: capabilities to extend
+ * @name: name of new feature
+ *
+ * Registers a new host CPU feature, eg 'pae', or 'vmx'
+ */
+int
+virCapabilitiesAddHostFeature(virCapsPtr caps,
+                              const char *name)
+{
+    char **features;
+
+    if ((features = realloc(caps->host.features,
+                            sizeof(*features) * (caps->host.nfeatures+1))) == NULL)
+        return -1;
+    caps->host.features = features;
+
+    if ((caps->host.features[caps->host.nfeatures] = strdup(name)) == NULL)
+        return -1;
+    caps->host.nfeatures++;
+
+    return 0;
+}
+
+
+/**
+ * virCapabilitiesAddHostMigrateTransport:
+ * @caps: capabilities to extend
+ * @name: name of migration transport
+ *
+ * Registers a new domain migration transport URI
+ */
+int
+virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
+                                       const char *name)
+{
+    char **migrateTrans;
+
+    if ((migrateTrans = realloc(caps->host.migrateTrans,
+                                sizeof(*migrateTrans) * (caps->host.nmigrateTrans+1))) == NULL)
+        return -1;
+    caps->host.migrateTrans = migrateTrans;
+
+    if ((caps->host.migrateTrans[caps->host.nmigrateTrans] = strdup(name)) == NULL)
+        return -1;
+    caps->host.nmigrateTrans++;
+
+    return 0;
+}
+
+
+/**
+ * virCapabilitiesAddHostNUMACell:
+ * @caps: capabilities to extend
+ * @num: ID number of NUMA cell
+ * @ncpus: number of CPUs in cell
+ * @cpus: array of CPU ID numbers for cell
+ *
+ * Registers a new NUMA cell for a host, passing in a
+ * array of CPU IDs belonging to the cell
+ */
+int
+virCapabilitiesAddHostNUMACell(virCapsPtr caps,
+                               int num,
+                               int ncpus,
+                               const int *cpus)
+{
+    virCapsHostNUMACellPtr cell, *cells;
+
+    if ((cells = realloc(caps->host.numaCell,
+                         sizeof(*cells) * (caps->host.nnumaCell+1))) == NULL)
+        return -1;
+    caps->host.numaCell = cells;
+
+    if ((cell = calloc(1, sizeof(cell))) == NULL)
+        return -1;
+    caps->host.numaCell[caps->host.nnumaCell] = cell;
+
+    if ((caps->host.numaCell[caps->host.nnumaCell]->cpus =
+         malloc(ncpus * sizeof(*cpus))) == NULL)
+        return -1;
+    memcpy(caps->host.numaCell[caps->host.nnumaCell]->cpus,
+           cpus,
+           ncpus * sizeof(*cpus));
+
+    caps->host.numaCell[caps->host.nnumaCell]->ncpus = ncpus;
+    caps->host.numaCell[caps->host.nnumaCell]->num = num;
+    caps->host.nnumaCell++;
+
+    return 0;
+}
+
+
+/**
+ * virCapabilitiesAddGuest:
+ * @caps: capabilities to extend
+ * @ostype: guest operating system type ('hvm' or 'xen')
+ * @arch: guest CPU architecture ('i686', or 'x86_64', etc)
+ * @wordsize: number of bits in CPU word
+ * @emulator: path to default device emulator for arch/ostype
+ * @loader: path to default BIOS loader for arch/ostype
+ * @nmachines: number of machine variants for emulator
+ * @machines: machine variants for emulator ('pc', or 'isapc', etc)
+ *
+ * Registers a new guest operating system. This should be
+ * followed by registration of at least one domain for
+ * running the guest
+ */
+virCapsGuestPtr
+virCapabilitiesAddGuest(virCapsPtr caps,
+                        const char *ostype,
+                        const char *arch,
+                        int wordsize,
+                        const char *emulator,
+                        const char *loader,
+                        int nmachines,
+                        const char *const *machines)
+{
+    virCapsGuestPtr guest, *guests;
+    int i;
+
+    if ((guest = calloc(1, sizeof(*guest))) == NULL)
+        goto no_memory;
+
+    if ((guest->ostype = strdup(ostype)) == NULL)
+        goto no_memory;
+
+    if ((guest->arch.name = strdup(arch)) == NULL)
+        goto no_memory;
+    guest->arch.wordsize = wordsize;
+
+    if (emulator &&
+        (guest->arch.defaultInfo.emulator = strdup(emulator)) == NULL)
+        goto no_memory;
+    if (loader &&
+        (guest->arch.defaultInfo.loader = strdup(loader)) == NULL)
+        goto no_memory;
+    if (nmachines) {
+        if ((guest->arch.defaultInfo.machines =
+             calloc(nmachines, sizeof(*guest->arch.defaultInfo.machines))) == NULL)
+            goto no_memory;
+        for (i = 0 ; i < nmachines ; i++) {
+            if ((guest->arch.defaultInfo.machines[i] = strdup(machines[i])) == NULL)
+                goto no_memory;
+            guest->arch.defaultInfo.nmachines++;
+        }
+    }
+
+    if ((guests = realloc(caps->guests,
+                          sizeof(*guests) *
+                          (caps->nguests + 1))) == NULL)
+        goto no_memory;
+    caps->guests = guests;
+    caps->guests[caps->nguests] = guest;
+    caps->nguests++;
+
+    return guest;
+
+ no_memory:
+    virCapabilitiesFreeGuest(guest);
+    return NULL;
+}
+
+
+/**
+ * virCapabilitiesAddGuestDomain:
+ * @guest: guest to support
+ * @hvtype: hypervisor type ('xen', 'qemu', 'kvm')
+ * @emulator: specialized device emulator for domain
+ * @loader: specialized BIOS loader for domain
+ * @nmachines: number of machine variants for emulator
+ * @machines: specialized machine variants for emulator
+ *
+ * Registers a virtual domain capable of running a
+ * guest operating system
+ */
+virCapsGuestDomainPtr
+virCapabilitiesAddGuestDomain(virCapsGuestPtr guest,
+                              const char *hvtype,
+                              const char *emulator,
+                              const char *loader,
+                              int nmachines,
+                              const char *const *machines)
+{
+    virCapsGuestDomainPtr dom, *doms;
+    int i;
+
+    if ((dom = calloc(1, sizeof(*dom))) == NULL)
+        goto no_memory;
+
+    if ((dom->type = strdup(hvtype)) == NULL)
+        goto no_memory;
+
+    if ((dom->type = strdup(hvtype)) == NULL)
+        goto no_memory;
+
+    if (emulator &&
+        (dom->info.emulator = strdup(emulator)) == NULL)
+        goto no_memory;
+    if (loader &&
+        (dom->info.loader = strdup(loader)) == NULL)
+        goto no_memory;
+    if (nmachines) {
+        if ((dom->info.machines =
+             calloc(nmachines, sizeof(*dom->info.machines))) == NULL)
+            goto no_memory;
+        for (i = 0 ; i < nmachines ; i++) {
+            if ((dom->info.machines[i] = strdup(machines[i])) == NULL)
+                goto no_memory;
+            dom->info.nmachines++;
+        }
+    }
+
+    if ((doms = realloc(guest->arch.domains,
+                        sizeof(*doms) *
+                        (guest->arch.ndomains + 1))) == NULL)
+        goto no_memory;
+    guest->arch.domains = doms;
+    guest->arch.domains[guest->arch.ndomains] = dom;
+    guest->arch.ndomains++;
+
+
+    return dom;
+
+ no_memory:
+    virCapabilitiesFreeGuestDomain(dom);
+    return NULL;
+}
+
+
+/**
+ * virCapabilitiesAddGuestFeature:
+ * @guest: guest to associate feature with
+ * @name: name of feature ('pae', 'acpi', 'apic')
+ * @defaultOn: non-zero if it defaults to on
+ * @toggle: non-zero if its state can be toggled
+ *
+ * Registers a feature for a guest domain
+ */
+virCapsGuestFeaturePtr
+virCapabilitiesAddGuestFeature(virCapsGuestPtr guest,
+                               const char *name,
+                               int defaultOn,
+                               int toggle)
+{
+    virCapsGuestFeaturePtr feature, *features;
+
+    if ((feature = calloc(1, sizeof(*feature))) == NULL)
+        goto no_memory;
+
+    if ((feature->name = strdup(name)) == NULL)
+        goto no_memory;
+    feature->defaultOn = defaultOn;
+    feature->toggle = toggle;
+
+    if ((features = realloc(guest->features,
+                            sizeof(*features) *
+                            (guest->nfeatures + 1))) == NULL)
+        goto no_memory;
+    guest->features = features;
+    guest->features[guest->nfeatures] = feature;
+    guest->nfeatures++;
+
+    return feature;
+
+ no_memory:
+    virCapabilitiesFreeGuestFeature(feature);
+    return NULL;
+}
+
+
+/**
+ * virCapabilitiesSupportsGuestOSType:
+ * @caps: capabilities to query
+ * @ostype: OS type to search for (eg 'hvm', 'xen')
+ *
+ * Returns non-zero if the capabilities support the
+ * requested operating system type
+ */
+extern int
+virCapabilitiesSupportsGuestOSType(virCapsPtr caps,
+                                   const char *ostype)
+{
+    int i;
+    for (i = 0 ; i < caps->nguests ; i++) {
+        if (STREQ(caps->guests[i]->ostype, ostype))
+            return 1;
+    }
+    return 0;
+}
+
+
+/**
+ * virCapabilitiesDefaultGuestArch:
+ * @caps: capabilities to query
+ * @ostype: OS type to search for
+ *
+ * Returns the first architecture able to run the
+ * requested operating system type
+ */
+extern const char *
+virCapabilitiesDefaultGuestArch(virCapsPtr caps,
+                                const char *ostype)
+{
+    int i;
+    for (i = 0 ; i < caps->nguests ; i++) {
+        if (STREQ(caps->guests[i]->ostype, ostype))
+            return caps->guests[i]->arch.name;
+    }
+    return NULL;
+}
+
+/**
+ * virCapabilitiesDefaultGuestMachine:
+ * @caps: capabilities to query
+ * @ostype: OS type to search for
+ * @arch: architecture to search for
+ *
+ * Returns the first machine variant associated with
+ * the requested operating system type and architecture
+ */
+extern const char *
+virCapabilitiesDefaultGuestMachine(virCapsPtr caps,
+                                   const char *ostype,
+                                   const char *arch)
+{
+    int i;
+    for (i = 0 ; i < caps->nguests ; i++) {
+        if (STREQ(caps->guests[i]->ostype, ostype) &&
+            STREQ(caps->guests[i]->arch.name, arch) &&
+            caps->guests[i]->arch.defaultInfo.nmachines)
+            return caps->guests[i]->arch.defaultInfo.machines[0];
+    }
+    return NULL;
+}
+
+/**
+ * virCapabilitiesDefaultGuestMachine:
+ * @caps: capabilities to query
+ * @ostype: OS type to search for ('xen', 'hvm')
+ * @arch: architecture to search for
+ * @domain: domain type ('xen', 'qemu', 'kvm')
+ *
+ * Returns the first emulator path associated with
+ * the requested operating system type, architecture
+ * and domain type
+ */
+extern const char *
+virCapabilitiesDefaultGuestEmulator(virCapsPtr caps,
+                                    const char *ostype,
+                                    const char *arch,
+                                    const char *domain)
+{
+    int i, j;
+    for (i = 0 ; i < caps->nguests ; i++) {
+        char *emulator;
+        if (STREQ(caps->guests[i]->ostype, ostype) &&
+            STREQ(caps->guests[i]->arch.name, arch)) {
+            emulator = caps->guests[i]->arch.defaultInfo.emulator;
+            for (j = 0 ; j < caps->guests[i]->arch.ndomains ; j++) {
+                if (STREQ(caps->guests[i]->arch.domains[j]->type, domain)) {
+                    if (caps->guests[i]->arch.domains[j]->info.emulator)
+                        emulator = caps->guests[i]->arch.domains[j]->info.emulator;
+                }
+            }
+            return emulator;
+        }
+    }
+    return NULL;
+}
+
+
+/**
+ * virCapabilitiesFormatXML:
+ * @caps: capabilities to format
+ *
+ * Convert the capabilities object into an XML representation
+ *
+ * Returns the XML document as a string
+ */
+char *
+virCapabilitiesFormatXML(virCapsPtr caps)
+{
+    virBuffer xml = { NULL, 0, 0 };
+    int i, j, k;
+
+    if (virBufferAddLit(&xml, "<capabilities>\n\n") < 0)
+      goto no_memory;
+    if (virBufferAddLit(&xml, "  <host>\n") < 0)
+        goto no_memory;
+    if (virBufferAddLit(&xml, "    <cpu>\n") < 0)
+        goto no_memory;
+    if (virBufferVSprintf(&xml, "      <arch>%s</arch>\n",
+                          caps->host.arch) < 0)
+        goto no_memory;
+
+    if (caps->host.nfeatures) {
+        if (virBufferAddLit(&xml, "      <features>\n") < 0)
+            goto no_memory;
+        for (i = 0 ; i < caps->host.nfeatures ; i++) {
+            if (virBufferVSprintf(&xml, "        <%s/>\n",
+                                  caps->host.features[i]) <0)
+                goto no_memory;
+        }
+        if (virBufferAddLit(&xml, "      </features>\n") < 0)
+            goto no_memory;
+    }
+    if (virBufferAddLit(&xml, "    </cpu>\n") < 0)
+        goto no_memory;
+
+    if (caps->host.offlineMigrate) {
+        if (virBufferAddLit(&xml, "    <migration_features>\n") < 0)
+            goto no_memory;
+        if (caps->host.liveMigrate &&
+            virBufferAddLit(&xml, "      <live/>\n") < 0)
+            goto no_memory;
+        if (caps->host.nmigrateTrans) {
+            if (virBufferAddLit(&xml, "      <uri_transports>\n") < 0)
+                goto no_memory;
+            for (i = 0 ; i < caps->host.nmigrateTrans ; i++) {
+                if (virBufferVSprintf(&xml, "        <uri_transport>%s</uri_transport>\n",
+                                      caps->host.migrateTrans[i]) < 0)
+                    goto no_memory;
+            }
+            if (virBufferAddLit(&xml, "      </uri_transports>\n") < 0)
+                goto no_memory;
+        }
+        if (virBufferAddLit(&xml, "    </migration_features>\n") < 0)
+            goto no_memory;
+    }
+
+    if (caps->host.nnumaCell) {
+        if (virBufferAddLit(&xml, "    <topology>\n") < 0)
+            goto no_memory;
+        if (virBufferVSprintf(&xml, "      <cells num='%d'>\n",
+                              caps->host.nnumaCell) < 0)
+            goto no_memory;
+        for (i = 0 ; i < caps->host.nnumaCell ; i++) {
+            if (virBufferVSprintf(&xml, "        <cell id='%d'>\n",
+                                  caps->host.numaCell[i]->num) < 0)
+                goto no_memory;
+            if (virBufferVSprintf(&xml, "          <cpus num='%d'>\n",
+                                  caps->host.numaCell[i]->ncpus) < 0)
+                goto no_memory;
+            for (j = 0 ; j < caps->host.numaCell[i]->ncpus ; j++)
+                if (virBufferVSprintf(&xml, "            <cpu id='%d'>\n",
+                                      caps->host.numaCell[i]->cpus[j]) < 0)
+                    goto no_memory;
+            if (virBufferAddLit(&xml, "          </cpus>\n") < 0)
+                goto no_memory;
+            if (virBufferAddLit(&xml, "        </cell>\n") < 0)
+                goto no_memory;
+        }
+        if (virBufferAddLit(&xml, "      </cells>\n") < 0)
+            goto no_memory;
+        if (virBufferAddLit(&xml, "    </topology>\n") < 0)
+            goto no_memory;
+    }
+    if (virBufferAddLit(&xml, "  </host>\n\n") < 0)
+        goto no_memory;
+
+
+    for (i = 0 ; i < caps->nguests ; i++) {
+        if (virBufferAddLit(&xml, "  <guest>\n") < 0)
+            goto no_memory;
+        if (virBufferVSprintf(&xml, "    <os_type>%s</os_type>\n",
+                              caps->guests[i]->ostype) < 0)
+            goto no_memory;
+        if (virBufferVSprintf(&xml, "    <arch name='%s'>\n",
+                              caps->guests[i]->arch.name) < 0)
+            goto no_memory;
+        if (virBufferVSprintf(&xml, "      <wordsize>%d</wordsize>\n",
+                              caps->guests[i]->arch.wordsize) < 0)
+            goto no_memory;
+        if (caps->guests[i]->arch.defaultInfo.emulator &&
+            virBufferVSprintf(&xml, "      <emulator>%s</emulator>\n",
+                              caps->guests[i]->arch.defaultInfo.emulator) < 0)
+            goto no_memory;
+        if (caps->guests[i]->arch.defaultInfo.loader &&
+            virBufferVSprintf(&xml, "      <loader>%s</loader>\n",
+                              caps->guests[i]->arch.defaultInfo.loader) < 0)
+            goto no_memory;
+
+        for (j = 0 ; j < caps->guests[i]->arch.defaultInfo.nmachines ; j++) {
+            if (virBufferVSprintf(&xml, "      <machine>%s</machine>\n",
+                                  caps->guests[i]->arch.defaultInfo.machines[j]) < 0)
+                goto no_memory;
+        }
+
+        for (j = 0 ; j < caps->guests[i]->arch.ndomains ; j++) {
+            if (virBufferVSprintf(&xml, "      <domain type='%s'>\n",
+                                  caps->guests[i]->arch.domains[j]->type) < 0)
+            goto no_memory;
+            if (caps->guests[i]->arch.domains[j]->info.emulator &&
+                virBufferVSprintf(&xml, "        <emulator>%s</emulator>\n",
+                                  caps->guests[i]->arch.domains[j]->info.emulator) < 0)
+                goto no_memory;
+            if (caps->guests[i]->arch.domains[j]->info.loader &&
+                virBufferVSprintf(&xml, "        <loader>%s</loader>\n",
+                                  caps->guests[i]->arch.domains[j]->info.loader) < 0)
+                goto no_memory;
+
+            for (k = 0 ; k < caps->guests[i]->arch.domains[j]->info.nmachines ; k++) {
+                if (virBufferVSprintf(&xml, "        <machine>%s</machine>\n",
+                                      caps->guests[i]->arch.domains[j]->info.machines[k]) < 0)
+                    goto no_memory;
+            }
+            if (virBufferAddLit(&xml, "      </domain>\n") < 0)
+                goto no_memory;
+        }
+
+        if (virBufferAddLit(&xml, "    </arch>\n") < 0)
+            goto no_memory;
+
+        if (caps->guests[i]->nfeatures) {
+            if (virBufferAddLit(&xml, "    <features>\n") < 0)
+                goto no_memory;
+
+            for (j = 0 ; j < caps->guests[i]->nfeatures ; j++) {
+                if (STREQ(caps->guests[i]->features[j]->name, "pae") ||
+                    STREQ(caps->guests[i]->features[j]->name, "nonpae") ||
+                    STREQ(caps->guests[i]->features[j]->name, "ia64_be")) {
+                    if (virBufferVSprintf(&xml, "      <%s/>\n",
+                                          caps->guests[i]->features[j]->name) < 0)
+                        goto no_memory;
+                } else {
+                    if (virBufferVSprintf(&xml, "      <%s default='%s' toggle='%s'/>\n",
+                                          caps->guests[i]->features[j]->name,
+                                          caps->guests[i]->features[j]->defaultOn ? "on" : "off",
+                                          caps->guests[i]->features[j]->toggle ? "yes" : "no") < 0)
+                        goto no_memory;
+                }
+            }
+
+            if (virBufferAddLit(&xml, "    </features>\n") < 0)
+                goto no_memory;
+        }
+
+
+        if (virBufferAddLit(&xml, "  </guest>\n\n") < 0)
+            goto no_memory;
+    }
+
+    if (virBufferAddLit(&xml, "</capabilities>\n") < 0)
+      goto no_memory;
+
+    return xml.content;
+
+ no_memory:
+    free(xml.content);
+    return NULL;
+}
+
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff --git a/src/capabilities.h b/src/capabilities.h
new file mode 100644 (file)
index 0000000..97bd06f
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * capabilities.h: hypervisor capabilities
+ *
+ * Copyright (C) 2006-2008 Red Hat, Inc.
+ * Copyright (C) 2006-2008 Daniel P. Berrange
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#ifndef __VIR_CAPABILITIES_H
+#define __VIR_CAPABILITIES_H
+
+#include <config.h>
+
+
+typedef struct _virCapsGuestFeature virCapsGuestFeature;
+typedef virCapsGuestFeature *virCapsGuestFeaturePtr;
+struct _virCapsGuestFeature {
+    char *name;
+    int defaultOn;
+    int toggle;
+};
+
+typedef struct _virCapsGuestDomainInfo virCapsGuestDomainInfo;
+typedef virCapsGuestDomainInfo *virCapsGuestDomainInfoPtr;
+struct _virCapsGuestDomainInfo {
+    char *emulator;
+    char *loader;
+    int nmachines;
+    char **machines;
+};
+
+typedef struct _virCapsGuestDomain virCapsGuestDomain;
+typedef virCapsGuestDomain *virCapsGuestDomainPtr;
+struct _virCapsGuestDomain {
+    char *type;
+    virCapsGuestDomainInfo info;
+};
+
+typedef struct _virCapsGuestArch virCapsGuestArch;
+typedef virCapsGuestArch *virCapsGuestArchptr;
+struct _virCapsGuestArch {
+    char *name;
+    int wordsize;
+    virCapsGuestDomainInfo defaultInfo;
+    int ndomains;
+    virCapsGuestDomainPtr *domains;
+};
+
+typedef struct _virCapsGuest virCapsGuest;
+typedef virCapsGuest *virCapsGuestPtr;
+struct _virCapsGuest {
+    char *ostype;
+    virCapsGuestArch arch;
+    int nfeatures;
+    virCapsGuestFeaturePtr *features;
+};
+
+typedef struct _virCapsHostNUMACell virCapsHostNUMACell;
+typedef virCapsHostNUMACell *virCapsHostNUMACellPtr;
+struct _virCapsHostNUMACell {
+    int num;
+    int ncpus;
+    int *cpus;
+};
+
+typedef struct _virCapsHost virCapsHost;
+typedef virCapsHost *virCapsHostPtr;
+struct _virCapsHost {
+    char *arch;
+    int nfeatures;
+    char **features;
+    int offlineMigrate;
+    int liveMigrate;
+    int nmigrateTrans;
+    char **migrateTrans;
+    int nnumaCell;
+    virCapsHostNUMACellPtr *numaCell;
+};
+
+typedef struct _virCaps virCaps;
+typedef virCaps* virCapsPtr;
+struct _virCaps {
+    virCapsHost host;
+    int nguests;
+    virCapsGuestPtr *guests;
+};
+
+
+extern virCapsPtr
+virCapabilitiesNew(const char *arch,
+                   int offlineMigrate,
+                   int liveMigrate);
+
+extern void
+virCapabilitiesFree(virCapsPtr caps);
+
+
+extern int
+virCapabilitiesAddHostFeature(virCapsPtr caps,
+                              const char *name);
+
+extern int
+virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
+                                       const char *name);
+
+
+extern int
+virCapabilitiesAddHostNUMACell(virCapsPtr caps,
+                               int num,
+                               int ncpus,
+                               const int *cpus);
+
+
+
+extern virCapsGuestPtr
+virCapabilitiesAddGuest(virCapsPtr caps,
+                        const char *ostype,
+                        const char *arch,
+                        int wordsize,
+                        const char *emulator,
+                        const char *loader,
+                        int nmachines,
+                        const char *const *machines);
+
+extern virCapsGuestDomainPtr
+virCapabilitiesAddGuestDomain(virCapsGuestPtr guest,
+                              const char *hvtype,
+                              const char *emulator,
+                              const char *loader,
+                              int nmachines,
+                              const char *const *machines);
+
+extern virCapsGuestFeaturePtr
+virCapabilitiesAddGuestFeature(virCapsGuestPtr guest,
+                               const char *name,
+                               int defaultOn,
+                               int toggle);
+
+extern int
+virCapabilitiesSupportsGuestOSType(virCapsPtr caps,
+                                   const char *ostype);
+extern const char *
+virCapabilitiesDefaultGuestArch(virCapsPtr caps,
+                                const char *ostype);
+extern const char *
+virCapabilitiesDefaultGuestMachine(virCapsPtr caps,
+                                   const char *ostype,
+                                   const char *arch);
+extern const char *
+virCapabilitiesDefaultGuestEmulator(virCapsPtr caps,
+                                    const char *ostype,
+                                    const char *arch,
+                                    const char *domain);
+
+extern char *
+virCapabilitiesFormatXML(virCapsPtr caps);
+
+
+#endif /* __VIR_CAPABILITIES_H */
+
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
index fc82a6d47c31ba73df6e61a6767610d57e390139..8c10ba45c79101ec32685ad75466b2a21f07ded4 100644 (file)
@@ -232,102 +232,184 @@ void qemudFreeVM(struct qemud_vm *vm) {
 
 /* The list of possible machine types for various architectures,
    as supported by QEMU - taken from 'qemu -M ?' for each arch */
-static const char *const arch_info_x86_machines[] = {
-    "pc", "isapc", NULL
+static const char *const arch_info_hvm_x86_machines[] = {
+    "pc", "isapc"
 };
-static const char *const arch_info_mips_machines[] = {
-    "mips", NULL
+static const char *const arch_info_hvm_mips_machines[] = {
+    "mips"
 };
-static const char *const arch_info_sparc_machines[] = {
-    "sun4m", NULL
+static const char *const arch_info_hvm_sparc_machines[] = {
+    "sun4m"
 };
-static const char *const arch_info_ppc_machines[] = {
-    "g3bw", "mac99", "prep", NULL
+static const char *const arch_info_hvm_ppc_machines[] = {
+    "g3bw", "mac99", "prep"
+};
+
+static const char *const arch_info_xen_x86_machines[] = {
+    "xenner"
+};
+
+struct qemu_feature_flags {
+    const char *name;
+    const int default_on;
+    const int toggle;
+};
+
+struct qemu_arch_info {
+    const char *arch;
+    int wordsize;
+    const char *const *machines;
+    int nmachines;
+    const char *binary;
+    const struct qemu_feature_flags *flags;
+    int nflags;
 };
 
 /* Feature flags for the architecture info */
 static const struct qemu_feature_flags const arch_info_i686_flags [] = {
-    { "pae",  1, 1 },
+    { "pae",  1, 0 },
+    { "nonpae",  1, 0 },
     { "acpi", 1, 1 },
     { "apic", 1, 0 },
-    { NULL, -1, -1 }
 };
 
 static const struct qemu_feature_flags const arch_info_x86_64_flags [] = {
     { "acpi", 1, 1 },
     { "apic", 1, 0 },
-    { NULL, -1, -1 }
 };
 
 /* The archicture tables for supported QEMU archs */
-const struct qemu_arch_info const qemudArchs[] = {
-    /* i686 must be in position 0 */
-    {  "i686", 32, arch_info_x86_machines, "qemu", arch_info_i686_flags },
-    /* x86_64 must be in position 1 */
-    {  "x86_64", 64, arch_info_x86_machines, "qemu-system-x86_64", arch_info_x86_64_flags },
-    {  "mips", 32, arch_info_mips_machines, "qemu-system-mips", NULL },
-    {  "mipsel", 32, arch_info_mips_machines, "qemu-system-mipsel", NULL },
-    {  "sparc", 32, arch_info_sparc_machines, "qemu-system-sparc", NULL },
-    {  "ppc", 32, arch_info_ppc_machines, "qemu-system-ppc", NULL },
-    { NULL, -1, NULL, NULL, NULL }
+static const struct qemu_arch_info const arch_info_hvm[] = {
+    {  "i686", 32, arch_info_hvm_x86_machines, 2,
+       "/usr/bin/qemu", arch_info_i686_flags, 4 },
+    {  "x86_64", 64, arch_info_hvm_x86_machines, 2,
+       "/usr/bin/qemu-system-x86_64", arch_info_x86_64_flags, 2 },
+    {  "mips", 32, arch_info_hvm_mips_machines, 1,
+       "/usr/bin/qemu-system-mips", NULL, 0 },
+    {  "mipsel", 32, arch_info_hvm_mips_machines, 1,
+       "/usr/bin/qemu-system-mipsel", NULL, 0 },
+    {  "sparc", 32, arch_info_hvm_sparc_machines, 1,
+       "/usr/bin/qemu-system-sparc", NULL, 0 },
+    {  "ppc", 32, arch_info_hvm_ppc_machines, 3,
+       "/usr/bin/qemu-system-ppc", NULL, 0 },
 };
 
-/* Return the default architecture if none is explicitly requested*/
-static const char *qemudDefaultArch(void) {
-    return qemudArchs[0].arch;
-}
+static const struct qemu_arch_info const arch_info_xen[] = {
+    {  "i686", 32, arch_info_xen_x86_machines, 1,
+       "/usr/bin/xenner", arch_info_i686_flags, 4 },
+    {  "x86_64", 64, arch_info_xen_x86_machines, 1,
+       "/usr/bin/xenner", arch_info_x86_64_flags, 2 },
+};
 
-/* Return the default machine type for a given architecture */
-static const char *qemudDefaultMachineForArch(const char *arch) {
+static int
+qemudCapsInitGuest(virCapsPtr caps,
+                   const char *hostmachine,
+                   const struct qemu_arch_info *info,
+                   int hvm) {
+    virCapsGuestPtr guest;
     int i;
 
-    for (i = 0; qemudArchs[i].arch; i++) {
-        if (!strcmp(qemudArchs[i].arch, arch)) {
-            return qemudArchs[i].machines[0];
-        }
-    }
+    if ((guest = virCapabilitiesAddGuest(caps,
+                                         hvm ? "hvm" : "xen",
+                                         info->arch,
+                                         info->wordsize,
+                                         info->binary,
+                                         NULL,
+                                         info->nmachines,
+                                         info->machines)) == NULL)
+        return -1;
 
-    return NULL;
-}
+    if (hvm) {
+        /* Check for existance of base emulator */
+        if (access(info->binary, X_OK) == 0 &&
+            virCapabilitiesAddGuestDomain(guest,
+                                          "qemu",
+                                          NULL,
+                                          NULL,
+                                          0,
+                                          NULL) == NULL)
+            return -1;
 
-/* Return the default binary name for a particular architecture */
-static const char *qemudDefaultBinaryForArch(const char *arch) {
-    int i;
+        /* If guest & host match, then we can accelerate */
+        if (STREQ(info->arch, hostmachine)) {
+            if (access("/dev/kqemu", F_OK) == 0 &&
+                virCapabilitiesAddGuestDomain(guest,
+                                              "kqemu",
+                                              NULL,
+                                              NULL,
+                                              0,
+                                              NULL) == NULL)
+                return -1;
+
+            if (access("/dev/kvm", F_OK) == 0 &&
+                virCapabilitiesAddGuestDomain(guest,
+                                              "kvm",
+                                              "/usr/bin/qemu-kvm",
+                                              NULL,
+                                              0,
+                                              NULL) == NULL)
+                return -1;
+        }
+    } else {
+        if (virCapabilitiesAddGuestDomain(guest,
+                                          "kvm",
+                                          NULL,
+                                          NULL,
+                                          0,
+                                          NULL) == NULL)
+            return -1;
+    }
 
-    for (i = 0 ; qemudArchs[i].arch; i++) {
-        if (!strcmp(qemudArchs[i].arch, arch)) {
-            return qemudArchs[i].binary;
+    if (info->nflags) {
+        for (i = 0 ; i < info->nflags ; i++) {
+            if (virCapabilitiesAddGuestFeature(guest,
+                                               info->flags[i].name,
+                                               info->flags[i].default_on,
+                                               info->flags[i].toggle) == NULL)
+                return -1;
         }
     }
 
-    return NULL;
+    return 0;
 }
 
-/* Find the fully qualified path to the binary for an architecture */
-static char *qemudLocateBinaryForArch(virConnectPtr conn,
-                                      int virtType, const char *arch) {
-    const char *name;
-    char *path;
+virCapsPtr qemudCapsInit(void) {
+    struct utsname utsname;
+    virCapsPtr caps;
+    int i;
 
-    if (virtType == QEMUD_VIRT_KVM)
-        name = "qemu-kvm";
-    else
-        name = qemudDefaultBinaryForArch(arch);
+    /* Really, this never fails - look at the man-page. */
+    uname (&utsname);
 
-    if (!name) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot determin binary for architecture %s", arch);
-        return NULL;
-    }
+    if ((caps = virCapabilitiesNew(utsname.machine,
+                                   0, 0)) == NULL)
+        goto no_memory;
 
-    /* XXX lame. should actually use $PATH ... */
-    path = malloc(strlen(name) + strlen("/usr/bin/") + 1);
-    if (!path) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "path");
-        return NULL;
+    for (i = 0 ; i < (sizeof(arch_info_hvm)/sizeof(arch_info_hvm[0])) ; i++)
+        if (qemudCapsInitGuest(caps,
+                               utsname.machine,
+                               &arch_info_hvm[i], 1) < 0)
+            goto no_memory;
+
+    if (access("/usr/bin/xenner", X_OK) == 0 &&
+        access("/dev/kvm", F_OK) == 0) {
+        for (i = 0 ; i < (sizeof(arch_info_xen)/sizeof(arch_info_xen[0])) ; i++)
+            /* Allow Xen 32-on-32, 32-on-64 and 64-on-64 */
+            if (STREQ(arch_info_xen[i].arch, utsname.machine) ||
+                (STREQ(utsname.machine, "x86_64") &&
+                 STREQ(arch_info_xen[i].arch, "i686"))) {
+                if (qemudCapsInitGuest(caps,
+                                       utsname.machine,
+                                       &arch_info_xen[i], 0) < 0)
+                    goto no_memory;
+            }
     }
-    strcpy(path, "/usr/bin/");
-    strcat(path, name);
-    return path;
+
+    return caps;
+
+ no_memory:
+    virCapabilitiesFree(caps);
+    return NULL;
 }
 
 
@@ -429,31 +511,31 @@ static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
 }
 
 int qemudExtractVersion(virConnectPtr conn,
-                        struct qemud_driver *driver ATTRIBUTE_UNUSED) {
-    char *binary = NULL;
+                        struct qemud_driver *driver) {
+    const char *binary;
     struct stat sb;
     int ignored;
 
     if (driver->qemuVersion > 0)
         return 0;
 
-    if (!(binary = qemudLocateBinaryForArch(conn, QEMUD_VIRT_QEMU, "i686")))
+    if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps,
+                                                      "hvm",
+                                                      "i686",
+                                                      "qemu")) == NULL)
         return -1;
 
     if (stat(binary, &sb) < 0) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
                          "Cannot find QEMU binary %s: %s", binary,
                          strerror(errno));
-        free(binary);
         return -1;
     }
 
     if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) {
-        free(binary);
         return -1;
     }
 
-    free(binary);
     return 0;
 }
 
@@ -1086,7 +1168,7 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
         qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE, NULL);
         goto error;
     }
-    if (strcmp((const char *)obj->stringval, "hvm")) {
+    if (!virCapabilitiesSupportsGuestOSType(driver->caps, (const char*)obj->stringval)) {
         qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE, "%s", obj->stringval);
         goto error;
     }
@@ -1097,7 +1179,11 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
     obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@arch)", ctxt);
     if ((obj == NULL) || (obj->type != XPATH_STRING) ||
         (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        const char *defaultArch = qemudDefaultArch();
+        const char *defaultArch = virCapabilitiesDefaultGuestArch(driver->caps, def->os.type);
+        if (defaultArch == NULL) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported architecture");
+            goto error;
+        }
         if (strlen(defaultArch) >= (QEMUD_OS_TYPE_MAX_LEN-1)) {
             qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "architecture type too long");
             goto error;
@@ -1115,9 +1201,11 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
     obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@machine)", ctxt);
     if ((obj == NULL) || (obj->type != XPATH_STRING) ||
         (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        const char *defaultMachine = qemudDefaultMachineForArch(def->os.arch);
-        if (!defaultMachine) {
-            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "unsupported arch %s", def->os.arch);
+        const char *defaultMachine = virCapabilitiesDefaultGuestMachine(driver->caps,
+                                                                        def->os.type,
+                                                                        def->os.arch);
+        if (defaultMachine == NULL) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported architecture");
             goto error;
         }
         if (strlen(defaultMachine) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) {
@@ -1205,12 +1293,18 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
     obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
     if ((obj == NULL) || (obj->type != XPATH_STRING) ||
         (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
-        char *tmp = qemudLocateBinaryForArch(conn, def->virtType, def->os.arch);
-        if (!tmp) {
+        const char *type = (def->virtType == QEMUD_VIRT_QEMU ? "qemu" :
+                            def->virtType == QEMUD_VIRT_KQEMU ? "kqemu":
+                            "kvm");
+        const char *emulator = virCapabilitiesDefaultGuestEmulator(driver->caps,
+                                                                   def->os.type,
+                                                                   def->os.arch,
+                                                                   type);
+        if (!emulator) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported guest type");
             goto error;
         }
-        strcpy(def->os.binary, tmp);
-        free(tmp);
+        strcpy(def->os.binary, emulator);
     } else {
         if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
             qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "emulator path too long");
index 735da4885fb6b4a2a03c0422b954e29948d82fd4..12aa6aeb33af2d5adb09a3bcbc7ef5f095779fa1 100644 (file)
@@ -31,6 +31,7 @@
 #include "internal.h"
 #include "bridge.h"
 #include "iptables.h"
+#include "capabilities.h"
 #include <netinet/in.h>
 
 #define qemudDebug(fmt, ...) do {} while(0)
@@ -314,6 +315,8 @@ struct qemud_driver {
     unsigned int vncTLSx509verify : 1;
     char *vncTLSx509certdir;
     char vncListen[BR_INET_ADDR_MAXLEN];
+
+    virCapsPtr caps;
 };
 
 
@@ -351,6 +354,8 @@ struct qemud_network *qemudFindNetworkByUUID(const struct qemud_driver *driver,
 struct qemud_network *qemudFindNetworkByName(const struct qemud_driver *driver,
                                              const char *name);
 
+virCapsPtr  qemudCapsInit               (void);
+
 int         qemudExtractVersion         (virConnectPtr conn,
                                          struct qemud_driver *driver);
 int         qemudBuildCommandLine       (virConnectPtr conn,
@@ -418,20 +423,6 @@ char *      qemudGenerateNetworkXML     (virConnectPtr conn,
                                          struct qemud_network *network,
                                          struct qemud_network_def *def);
 
-struct qemu_feature_flags {
-    const char *name;
-    const int default_on;
-    const int toggle;
-};
-
-struct qemu_arch_info {
-    const char *arch;
-    int wordsize;
-    const char *const *machines;
-    const char *binary;
-    const struct qemu_feature_flags *fflags;
-};
-extern const struct qemu_arch_info const qemudArchs[];
 
 #endif /* WITH_QEMU */
 
index bfa5e397d66b9c3258c1963f7c05bc3a4f9bc608..21f0fed85dea47b99d18581f4d191a480b804000 100644 (file)
@@ -56,6 +56,7 @@
 #include "qemu_conf.h"
 #include "nodeinfo.h"
 #include "stats_linux.h"
+#include "capabilities.h"
 
 static int qemudShutdown(void);
 
@@ -214,6 +215,10 @@ qemudStartup(void) {
         goto out_of_memory;
 
     free(base);
+    base = NULL;
+
+    if ((qemu_driver->caps = qemudCapsInit()) == NULL)
+        goto out_of_memory;
 
     if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
         qemudShutdown();
@@ -297,6 +302,8 @@ qemudShutdown(void) {
     if (!qemu_driver)
         return -1;
 
+    virCapabilitiesFree(qemu_driver->caps);
+
     /* shutdown active VMs */
     vm = qemu_driver->vms;
     while (vm) {
@@ -1479,191 +1486,17 @@ static int qemudGetNodeInfo(virConnectPtr conn,
     return virNodeInfoPopulate(conn, nodeinfo);
 }
 
-static int qemudGetFeatures(virBufferPtr xml,
-                            const struct qemu_feature_flags *flags) {
-    int i, r;
-
-    if (flags == NULL)
-        return 0;
-
-    r = virBufferAddLit(xml, "\
-    <features>\n");
-    if (r == -1) return r;
-    for (i = 0; flags[i].name; ++i) {
-        if (STREQ(flags[i].name, "pae")) {
-            int pae = flags[i].default_on || flags[i].toggle;
-            int nonpae = flags[i].toggle;
-            if (pae) {
-                r = virBufferAddLit(xml, "      <pae/>\n");
-                if (r == -1) return r;
-            }
-            if (nonpae) {
-                r = virBufferAddLit(xml, "      <nonpae/>\n");
-                if (r == -1) return r;
-            }
-        } else {
-            r = virBufferVSprintf(xml, "      <%s default='%s' toggle='%s'/>\n",
-                                  flags[i].name,
-                                  flags[i].default_on ? "on" : "off",
-                                  flags[i].toggle ? "yes" : "no");
-            if (r == -1) return r;
-        }
-    }
-    r = virBufferAddLit(xml, "    </features>\n");
-    return r;
-}
-
-static char *qemudGetCapabilities(virConnectPtr conn ATTRIBUTE_UNUSED) {
-    struct utsname utsname;
-    int i, j, r;
-    int have_kqemu = 0;
-    int have_kvm = 0;
-    virBufferPtr xml;
-
-    /* Really, this never fails - look at the man-page. */
-    uname (&utsname);
 
-    have_kqemu = access ("/dev/kqemu", F_OK) == 0;
-    have_kvm = access ("/dev/kvm", F_OK) == 0;
-
-    /* Construct the XML. */
-    xml = virBufferNew (1024);
-    if (!xml) {
-        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
-        return NULL;
-    }
+static char *qemudGetCapabilities(virConnectPtr conn) {
+    struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
+    char *xml;
 
-    r = virBufferVSprintf (xml,
-                        "\
-<capabilities>\n\
-  <host>\n\
-    <cpu>\n\
-      <arch>%s</arch>\n\
-    </cpu>\n\
-  </host>\n",
-                        utsname.machine);
-    if (r == -1) {
-    vir_buffer_failed:
-        virBufferFree (xml);
-        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
+    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "capabilities");
         return NULL;
     }
 
-    i = -1;
-    if (strcmp (utsname.machine, "i686") == 0) i = 0;
-    else if (strcmp (utsname.machine, "x86_64") == 0) i = 1;
-    if (i >= 0) {
-        /* For the default (PC-like) guest, qemudArchs[0] or [1]. */
-        r = virBufferVSprintf (xml,
-                            "\
-\n\
-  <guest>\n\
-    <os_type>hvm</os_type>\n\
-    <arch name=\"%s\">\n\
-      <wordsize>%d</wordsize>\n\
-      <emulator>/usr/bin/%s</emulator>\n\
-      <domain type=\"qemu\"/>\n",
-                            qemudArchs[i].arch,
-                            qemudArchs[i].wordsize,
-                            qemudArchs[i].binary);
-        if (r == -1) goto vir_buffer_failed;
-
-        for (j = 0; qemudArchs[i].machines[j]; ++j) {
-            r = virBufferVSprintf (xml,
-                                "\
-      <machine>%s</machine>\n",
-                                qemudArchs[i].machines[j]);
-            if (r == -1) goto vir_buffer_failed;
-        }
-
-        if (have_kqemu) {
-            r = virBufferAddLit (xml,
-                           "\
-      <domain type=\"kqemu\"/>\n");
-            if (r == -1) goto vir_buffer_failed;
-        }
-        if (have_kvm) {
-            r = virBufferAddLit (xml,
-                           "\
-      <domain type=\"kvm\">\n\
-        <emulator>/usr/bin/qemu-kvm</emulator>\n\
-      </domain>\n");
-            if (r == -1) goto vir_buffer_failed;
-        }
-        r = virBufferAddLit (xml, "    </arch>\n");
-        if (r == -1) goto vir_buffer_failed;
-
-        r = qemudGetFeatures(xml, qemudArchs[i].fflags);
-        if (r == -1) goto vir_buffer_failed;
-
-        r = virBufferAddLit (xml, "  </guest>\n");
-        if (r == -1) goto vir_buffer_failed;
-
-        /* The "other" PC architecture needs emulation. */
-        i = i ^ 1;
-        r = virBufferVSprintf (xml,
-                            "\
-\n\
-  <guest>\n\
-    <os_type>hvm</os_type>\n\
-    <arch name=\"%s\">\n\
-      <wordsize>%d</wordsize>\n\
-      <emulator>/usr/bin/%s</emulator>\n\
-      <domain type=\"qemu\"/>\n",
-                            qemudArchs[i].arch,
-                            qemudArchs[i].wordsize,
-                            qemudArchs[i].binary);
-        if (r == -1) goto vir_buffer_failed;
-        for (j = 0; qemudArchs[i].machines[j]; ++j) {
-            r = virBufferVSprintf (xml,
-                                "\
-      <machine>%s</machine>\n",
-                                qemudArchs[i].machines[j]);
-            if (r == -1) goto vir_buffer_failed;
-        }
-        r = virBufferAddLit (xml, "    </arch>\n  </guest>\n");
-        if (r == -1) goto vir_buffer_failed;
-    }
-
-    /* The non-PC architectures, qemudArchs[>=2]. */
-    for (i = 2; qemudArchs[i].arch; ++i) {
-        r = virBufferVSprintf (xml,
-                            "\
-\n\
-  <guest>\n\
-    <os_type>hvm</os_type>\n\
-    <arch name=\"%s\">\n\
-      <wordsize>%d</wordsize>\n\
-      <emulator>/usr/bin/%s</emulator>\n\
-      <domain type=\"qemu\"/>\n",
-                            qemudArchs[i].arch,
-                            qemudArchs[i].wordsize,
-                            qemudArchs[i].binary);
-        if (r == -1) goto vir_buffer_failed;
-        for (j = 0; qemudArchs[i].machines[j]; ++j) {
-            r = virBufferVSprintf (xml,
-                                "\
-      <machine>%s</machine>\n",
-                                qemudArchs[i].machines[j]);
-            if (r == -1) goto vir_buffer_failed;
-        }
-        r = virBufferAddLit (xml, "    </arch>\n");
-        if (r == -1) goto vir_buffer_failed;
-
-        r = qemudGetFeatures(xml, qemudArchs[i].fflags);
-        if (r == -1) goto vir_buffer_failed;
-
-        r = virBufferAddLit (xml, "  </guest>\n");
-        if (r == -1) goto vir_buffer_failed;
-    }
-
-    /* Finish off. */
-    r = virBufferAddLit (xml,
-                      "\
-</capabilities>\n");
-    if (r == -1) goto vir_buffer_failed;
-
-    return virBufferContentAndFree(xml);
+    return xml;
 }
 
 
index ce8cea8f8f4700465f4534f0dbdd68fbcac48377..f401d7de2106c22158de8d3ac3f2e554099ca84e 100644 (file)
@@ -44,6 +44,7 @@
 #include "buf.h"
 #include "util.h"
 #include "uuid.h"
+#include "capabilities.h"
 
 /* Flags that determine the action to take on a shutdown or crash of a domain
  */
@@ -119,7 +120,7 @@ typedef struct _testConn testConn;
 typedef struct _testConn *testConnPtr;
 
 #define TEST_MODEL "i686"
-#define TEST_MODEL_WORDSIZE "32"
+#define TEST_MODEL_WORDSIZE 32
 
 static const virNodeInfo defaultNodeInfo = {
     TEST_MODEL,
@@ -978,38 +979,60 @@ static int testNodeGetInfo(virConnectPtr conn,
 
 static char *testGetCapabilities (virConnectPtr conn)
 {
-    static char caps[] = "\
-<capabilities>\n\
-  <host>\n\
-    <cpu>\n\
-      <arch>" TEST_MODEL "</arch>\n\
-      <features>\n\
-        <pae/>\n\
-        <nonpae/>\n\
-      </features>\n\
-    </cpu>\n\
-  </host>\n\
-\n\
-  <guest>\n\
-    <os_type>linux</os_type>\n\
-    <arch name=\"" TEST_MODEL "\">\n\
-      <wordsize>" TEST_MODEL_WORDSIZE "</wordsize>\n\
-      <domain type=\"test\"/>\n\
-    </arch>\n\
-    <features>\n\
-      <pae/>\n\
-      <nonpae/>\n\
-    </features>\n\
-  </guest>\n\
-</capabilities>\n\
-";
-
-    char *caps_copy = strdup (caps);
-    if (!caps_copy) {
-        testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
-        return NULL;
-    }
-    return caps_copy;
+    virCapsPtr caps;
+    virCapsGuestPtr guest;
+    char *xml;
+    int cell1[] = { 0, 2, 4, 6, 8, 10, 12, 14 };
+    int cell2[] = { 1, 3, 5, 7, 9, 11, 13, 15 };
+
+    if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL)
+        goto no_memory;
+
+    if (virCapabilitiesAddHostFeature(caps, "pae") < 0)
+        goto no_memory;
+    if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0)
+        goto no_memory;
+
+    if (virCapabilitiesAddHostNUMACell(caps, 0, 8, cell1) < 0)
+        goto no_memory;
+    if (virCapabilitiesAddHostNUMACell(caps, 1, 8, cell2) < 0)
+        goto no_memory;
+
+    if ((guest = virCapabilitiesAddGuest(caps,
+                                         "linux",
+                                         TEST_MODEL,
+                                         TEST_MODEL_WORDSIZE,
+                                         NULL,
+                                         NULL,
+                                         0,
+                                         NULL)) == NULL)
+        goto no_memory;
+
+    if (virCapabilitiesAddGuestDomain(guest,
+                                      "test",
+                                      NULL,
+                                      NULL,
+                                      0,
+                                      NULL) == NULL)
+        goto no_memory;
+
+
+    if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL)
+        goto no_memory;
+    if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL)
+        goto no_memory;
+
+    if ((xml = virCapabilitiesFormatXML(caps)) == NULL)
+        goto no_memory;
+
+    virCapabilitiesFree(caps);
+
+    return xml;
+
+ no_memory:
+    virCapabilitiesFree(caps);
+    testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
+    return NULL;
 }
 
 static int testNumOfDomains(virConnectPtr conn)
index da1610a0363f6219d09b0810575134d218152f0b..91a5f813a2ec8f54028d3578fb11ed7d58893fcd 100644 (file)
@@ -52,6 +52,7 @@
 
 #define virLog(msg...) fprintf(stderr, msg)
 
+#ifndef PROXY
 static void
 ReportError(virConnectPtr conn,
                       virDomainPtr dom,
@@ -601,6 +602,57 @@ __virStrToLong_ull(char const *s, char **end_ptr, int base, unsigned long long *
     *result = val;
     return 0;
 }
+#endif /* PROXY */
+
+/**
+ * virSkipSpaces:
+ * @str: pointer to the char pointer used
+ *
+ * Skip potential blanks, this includes space tabs, line feed,
+ * carriage returns and also '\\' which can be erronously emitted
+ * by xend
+ */
+void
+virSkipSpaces(const char **str)
+{
+    const char *cur = *str;
+
+    while ((*cur == ' ') || (*cur == '\t') || (*cur == '\n') ||
+           (*cur == '\r') || (*cur == '\\'))
+        cur++;
+    *str = cur;
+}
+
+/**
+ * virParseNumber:
+ * @str: pointer to the char pointer used
+ *
+ * Parse an unsigned number
+ *
+ * Returns the unsigned number or -1 in case of error. @str will be
+ *         updated to skip the number.
+ */
+int
+virParseNumber(const char **str)
+{
+    int ret = 0;
+    const char *cur = *str;
+
+    if ((*cur < '0') || (*cur > '9'))
+        return (-1);
+
+    while ((*cur >= '0') && (*cur <= '9')) {
+        unsigned int c = *cur - '0';
+
+        if ((ret > INT_MAX / 10) ||
+            ((ret == INT_MAX / 10) && (c > INT_MAX % 10)))
+            return (-1);
+        ret = ret * 10 + c;
+        cur++;
+    }
+    *str = cur;
+    return (ret);
+}
 
 /*
  * Local variables:
index 4ababaecf39f465f4e5bbc7036725fcd8c735d0d..4c12200c9f73fac7ceefb26a8e7042682c67db84 100644 (file)
@@ -79,4 +79,8 @@ int __virStrToLong_ull(char const *s,
                       unsigned long long *result);
 #define virStrToLong_ull(s,e,b,r) __virStrToLong_ull((s),(e),(b),(r))
 
+void virSkipSpaces(const char **str);
+int virParseNumber(const char **str);
+
+
 #endif /* __VIR_UTIL_H__ */
index adee7e2ce70e333c37069aab6cbe88adf3df272e..9b1258fb11ed4ec1dd4467f20c42d4c55f54ad96 100644 (file)
@@ -47,6 +47,7 @@
 #include <xen/sched.h>
 
 #include "buf.h"
+#include "capabilities.h"
 
 /* #define DEBUG */
 /*
@@ -2154,6 +2155,121 @@ xenHypervisorGetVersion(virConnectPtr conn, unsigned long *hvVer)
     return(0);
 }
 
+struct guest_arch {
+    const char *model;
+    int bits;
+    int hvm;
+    int pae;
+    int nonpae;
+    int ia64_be;
+};
+
+
+static virCapsPtr
+xenHypervisorBuildCapabilities(virConnectPtr conn,
+                               const char *hostmachine,
+                               int host_pae,
+                               char *hvm_type,
+                               struct guest_arch *guest_archs,
+                               int nr_guest_archs) {
+    virCapsPtr caps;
+    int i;
+    int hv_major = hv_version >> 16;
+    int hv_minor = hv_version & 0xFFFF;
+
+    if ((caps = virCapabilitiesNew(hostmachine, 1, 1)) == NULL)
+        goto no_memory;
+    if (hvm_type && STRNEQ(hvm_type, "") &&
+        virCapabilitiesAddHostFeature(caps, hvm_type) < 0)
+        goto no_memory;
+    if (host_pae &&
+        virCapabilitiesAddHostFeature(caps, "pae") < 0)
+        goto no_memory;
+
+
+    if (virCapabilitiesAddHostMigrateTransport(caps,
+                                               "xenmigr") < 0)
+        goto no_memory;
+
+
+    if (sys_interface_version >= 4) {
+        if (xenDaemonNodeGetTopology(conn, caps) != 0) {
+            virCapabilitiesFree(caps);
+            return NULL;
+        }
+    }
+
+    for (i = 0; i < nr_guest_archs; ++i) {
+        virCapsGuestPtr guest;
+        const char const *machines[] = { guest_archs[i].hvm ? "xenfv" : "xenpv" };
+
+        if ((guest = virCapabilitiesAddGuest(caps,
+                                             guest_archs[i].hvm ? "hvm" : "xen",
+                                             guest_archs[i].model,
+                                             guest_archs[i].bits,
+                                             (STREQ(hostmachine, "x86_64") ?
+                                              "/usr/lib64/xen/bin/qemu-dm" :
+                                              "/usr/lib/xen/bin/qemu-dm"),
+                                             (guest_archs[i].hvm ?
+                                              "/usr/lib/xen/boot/hvmloader" :
+                                              NULL),
+                                             1,
+                                             machines)) == NULL)
+            goto no_memory;
+
+        if (virCapabilitiesAddGuestDomain(guest,
+                                          "xen",
+                                          NULL,
+                                          NULL,
+                                          0,
+                                          NULL) == NULL)
+            goto no_memory;
+
+        if (guest_archs[i].pae &&
+            virCapabilitiesAddGuestFeature(guest,
+                                           "pae",
+                                           1,
+                                           0) == NULL)
+            goto no_memory;
+
+        if (guest_archs[i].nonpae &&
+            virCapabilitiesAddGuestFeature(guest,
+                                           "nonpae",
+                                           1,
+                                           0) == NULL)
+            goto no_memory;
+
+        if (guest_archs[i].ia64_be &&
+            virCapabilitiesAddGuestFeature(guest,
+                                           "ia64_be",
+                                           1,
+                                           0) == NULL)
+            goto no_memory;
+
+        if (guest_archs[i].hvm) {
+            if (virCapabilitiesAddGuestFeature(guest,
+                                               "acpi",
+                                               1, 1) == NULL)
+                goto no_memory;
+
+            // In Xen 3.1.0, APIC is always on and can't be toggled
+            if (virCapabilitiesAddGuestFeature(guest,
+                                               "apic",
+                                               1,
+                                               (hv_major > 3 &&
+                                                hv_minor > 0 ?
+                                                0 : 1)) == NULL)
+                goto no_memory;
+        }
+    }
+
+    return caps;
+
+ no_memory:
+    virCapabilitiesFree(caps);
+    return NULL;
+}
+
 /**
  * xenHypervisorGetCapabilities:
  * @conn: pointer to the connection block
@@ -2170,25 +2286,17 @@ xenHypervisorMakeCapabilitiesXML(virConnectPtr conn,
     char line[1024], *str, *token;
     regmatch_t subs[4];
     char *saveptr = NULL;
-    int i, r, topology;
+    int i;
 
     char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */
     int host_pae = 0;
-    struct guest_arch {
-        const char *model;
-        int bits;
-        int hvm;
-        int pae;
-        int nonpae;
-        int ia64_be;
-    } guest_archs[32];
+    struct guest_arch guest_archs[32];
     int nr_guest_archs = 0;
 
-    virBufferPtr xml;
-    char *xml_str;
+    char *xml;
 
-    int hv_major = hv_version >> 16;
-    int hv_minor = hv_version & 0xFFFF;
+
+    virCapsPtr caps = NULL;
 
     memset(guest_archs, 0, sizeof(guest_archs));
 
@@ -2306,129 +2414,22 @@ xenHypervisorMakeCapabilitiesXML(virConnectPtr conn,
         }
     }
 
-    /* Construct the final XML. */
-    xml = virBufferNew (1024);
-    if (!xml) {
-        virXenError(conn, VIR_ERR_NO_MEMORY, __FUNCTION__, 0);
-        return NULL;
-    }
-    r = virBufferVSprintf (xml,
-                           "\
-<capabilities>\n\
-  <host>\n\
-    <cpu>\n\
-      <arch>%s</arch>\n\
-      <features>\n",
-                           hostmachine);
-    if (r == -1) goto vir_buffer_failed;
-
-    if (strcmp (hvm_type, "") != 0) {
-        r = virBufferVSprintf (xml,
-                               "\
-        <%s/>\n",
-                               hvm_type);
-        if (r == -1) goto vir_buffer_failed;
-    }
-    if (host_pae) {
-        r = virBufferAddLit (xml, "\
-        <pae/>\n");
-        if (r == -1) goto vir_buffer_failed;
-    }
-    r = virBufferAddLit (xml,
-                      "\
-      </features>\n\
-    </cpu>\n\
-    <migration_features>\n\
-      <live/>\n\
-      <uri_transports>\n\
-        <uri_transport>xenmigr</uri_transport>\n\
-      </uri_transports>\n\
-    </migration_features>\n\
-  </host>\n");
-    if (r == -1) goto vir_buffer_failed;
-
-    if (sys_interface_version >= 4) {
-        topology = xenDaemonNodeGetTopology(conn, xml);
-        if (topology != 0)
-            goto topology_failed;
-    }
-
-    for (i = 0; i < nr_guest_archs; ++i) {
-        r = virBufferVSprintf (xml,
-                               "\
-\n\
-  <guest>\n\
-    <os_type>%s</os_type>\n\
-    <arch name=\"%s\">\n\
-      <wordsize>%d</wordsize>\n\
-      <domain type=\"xen\"></domain>\n",
-                               guest_archs[i].hvm ? "hvm" : "xen",
-                               guest_archs[i].model,
-                               guest_archs[i].bits);
-        if (r == -1) goto vir_buffer_failed;
-        if (guest_archs[i].hvm) {
-            r = virBufferVSprintf (xml,
-                              "\
-      <emulator>/usr/lib%s/xen/bin/qemu-dm</emulator>\n\
-      <machine>pc</machine>\n\
-      <machine>isapc</machine>\n\
-      <loader>/usr/lib/xen/boot/hvmloader</loader>\n",
-                                   guest_archs[i].bits == 64 ? "64" : "");
-            if (r == -1) goto vir_buffer_failed;
-        }
-        r = virBufferAddLit (xml,
-                          "\
-    </arch>\n\
-    <features>\n");
-        if (r == -1) goto vir_buffer_failed;
-        if (guest_archs[i].pae) {
-            r = virBufferAddLit (xml,
-                              "\
-      <pae/>\n");
-            if (r == -1) goto vir_buffer_failed;
-        }
-        if (guest_archs[i].nonpae) {
-            r = virBufferAddLit (xml, "      <nonpae/>\n");
-            if (r == -1) goto vir_buffer_failed;
-        }
-        if (guest_archs[i].ia64_be) {
-            r = virBufferAddLit (xml, "      <ia64_be/>\n");
-            if (r == -1) goto vir_buffer_failed;
-        }
-        if (guest_archs[i].hvm) {
-            r = virBufferAddLit (xml,
-                                 "      <acpi default='on' toggle='yes'/>\n");
-            if (r == -1) goto vir_buffer_failed;
-            // In Xen 3.1.0, APIC is always on and can't be toggled
-            if (hv_major >= 3 && hv_minor > 0) {
-                r = virBufferAddLit (xml,
-                             "      <apic default='off' toggle='no'/>\n");
-            } else {
-                r = virBufferAddLit (xml,
-                             "      <apic default='on' toggle='yes'/>\n");
-            }
-            if (r == -1) goto vir_buffer_failed;
-        }
-        r = virBufferAddLit (xml, "\
-    </features>\n\
-  </guest>\n");
-        if (r == -1) goto vir_buffer_failed;
-    }
-
-    r = virBufferAddLit (xml,
-                      "\
-</capabilities>\n");
-    if (r == -1) goto vir_buffer_failed;
-    xml_str = strdup (xml->content);
-    if (!xml_str) goto vir_buffer_failed;
-    virBufferFree (xml);
+    if ((caps = xenHypervisorBuildCapabilities(conn,
+                                               hostmachine,
+                                               host_pae,
+                                               hvm_type,
+                                               guest_archs,
+                                               nr_guest_archs)) == NULL)
+        goto no_memory;
+    if ((xml = virCapabilitiesFormatXML(caps)) == NULL)
+        goto no_memory;
 
-    return xml_str;
+    virCapabilitiesFree(caps);
+    return xml;
 
vir_buffer_failed:
no_memory:
     virXenError(conn, VIR_ERR_NO_MEMORY, __FUNCTION__, 0);
- topology_failed:
-    virBufferFree (xml);
+    virCapabilitiesFree(caps);
     return NULL;
 }
 
index bfd793557e115f061d46f93e5ba764b0615fe59c..8bbc28f07c91b3a79583e4d5e2a175ab12671bb4 100644 (file)
@@ -39,6 +39,7 @@
 #include "sexpr.h"
 #include "xml.h"
 #include "buf.h"
+#include "capabilities.h"
 #include "uuid.h"
 #include "xen_unified.h"
 #include "xend_internal.h"
@@ -1952,59 +1953,104 @@ sexpr_to_xend_node_info(const struct sexpr *root, virNodeInfoPtr info)
     return (0);
 }
 
+
 /**
- * sexpr_to_xend_topology_xml:
+ * sexpr_to_xend_topology
  * @root: an S-Expression describing a node
+ * @caps: capability info
  *
- * Internal routine creating an XML string with the values from
- * the node root provided.
+ * Internal routine populating capability info with
+ * NUMA node mapping details
  *
  * Returns 0 in case of success, -1 in case of error
  */
 static int
-sexpr_to_xend_topology_xml(virConnectPtr conn, const struct sexpr *root,
-                           virBufferPtr xml)
+sexpr_to_xend_topology(virConnectPtr conn,
+                       const struct sexpr *root,
+                       virCapsPtr caps)
 {
     const char *nodeToCpu;
-    int numCells = 0;
+    const char *cur;
+    char *cpuset = NULL;
+    int *cpuNums = NULL;
+    int cell, cpu, nb_cpus;
+    int n = 0;
     int numCpus;
-    int r;
 
     nodeToCpu = sexpr_node(root, "node/node_to_cpu");
     if (nodeToCpu == NULL) {
         virXendError(conn, VIR_ERR_INTERNAL_ERROR,
                      _("failed to parse topology information"));
-        goto error;
+        return -1;
     }
 
-    numCells = sexpr_int(root, "node/nr_nodes");
     numCpus = sexpr_int(root, "node/nr_cpus");
 
-    /* start filling in xml */
-    r = virBufferVSprintf (xml,
-                               "\
-  <topology>\n\
-    <cells num='%d'>\n",
-                           numCells);
-    if (r < 0) goto vir_buffer_failed;
-
-    r = virParseXenCpuTopology(conn, xml, nodeToCpu, numCpus);
-    if (r < 0) goto error;
-
-    r = virBufferAddLit (xml, "\
-    </cells>\n\
-  </topology>\n");
-    if (r < 0) goto vir_buffer_failed;
+
+    cpuset = malloc(numCpus * sizeof(*cpuset));
+    if (cpuset == NULL)
+        goto memory_error;
+    cpuNums = malloc(numCpus * sizeof(*cpuNums));
+    if (cpuNums == NULL)
+        goto memory_error;
+
+    cur = nodeToCpu;
+    while (*cur != 0) {
+        /*
+         * Find the next NUMA cell described in the xend output
+         */
+        cur = strstr(cur, "node");
+        if (cur == NULL)
+            break;
+        cur += 4;
+        cell = virParseNumber(&cur);
+        if (cell < 0)
+            goto parse_error;
+        virSkipSpaces(&cur);
+        if (*cur != ':')
+            goto parse_error;
+        cur++;
+        virSkipSpaces(&cur);
+        if (!strncmp(cur, "no cpus", 7)) {
+            nb_cpus = 0;
+            for (cpu = 0; cpu < numCpus; cpu++)
+                cpuset[cpu] = 0;
+        } else {
+            nb_cpus = virParseCpuSet(conn, &cur, 'n', cpuset, numCpus);
+            if (nb_cpus < 0)
+                goto error;
+        }
+
+        for (n = 0, cpu = 0; cpu < numCpus; cpu++)
+            if (cpuset[cpu] == 1)
+                cpuNums[n++] = cpu;
+
+        if (virCapabilitiesAddHostNUMACell(caps,
+                                           cell,
+                                           nb_cpus,
+                                           cpuNums) < 0)
+            goto memory_error;
+    }
+    free(cpuNums);
+    free(cpuset);
     return (0);
 
+  parse_error:
+    virXendError(conn, VIR_ERR_XEN_CALL, _("topology syntax error"));
+  error:
+    free(cpuNums);
+    free(cpuset);
 
-vir_buffer_failed:
-    virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate new buffer"));
+    return (-1);
 
-error:
+  memory_error:
+    free(cpuNums);
+    free(cpuset);
+    virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"));
     return (-1);
 }
 
+
 #ifndef PROXY
 /**
  * sexpr_to_domain:
@@ -2720,13 +2766,15 @@ xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
 /**
  * xenDaemonNodeGetTopology:
  * @conn: pointer to the Xen Daemon block
+ * @caps: capabilities info
  *
  * This method retrieves a node's topology information.
  *
  * Returns -1 in case of error, 0 otherwise.
  */
 int
-xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml) {
+xenDaemonNodeGetTopology(virConnectPtr conn,
+                         virCapsPtr caps) {
     int ret = -1;
     struct sexpr *root;
 
@@ -2735,17 +2783,17 @@ xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml) {
         return (-1);
     }
 
-    if (xml == NULL) {
+    if (caps == NULL) {
         virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return (-1);
-        }
+    }
 
     root = sexpr_get(conn, "/xend/node/");
     if (root == NULL) {
         return (-1);
     }
 
-    ret = sexpr_to_xend_topology_xml(conn, root, xml);
+    ret = sexpr_to_xend_topology(conn, root, caps);
     sexpr_free(root);
     return (ret);
 }
index 624c04dc07f852b8daa992b1166a4d2f75b7e61d..fb0306bd6663554d7a3325a0a260662041eb4886 100644 (file)
@@ -19,7 +19,7 @@
 #include <stdbool.h>
 
 #include "libvirt/libvirt.h"
-#include "buf.h"
+#include "capabilities.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -187,7 +187,7 @@ int xenDaemonOpen(virConnectPtr conn, xmlURIPtr uri, virConnectAuthPtr auth, int
 int xenDaemonClose(virConnectPtr conn);
 int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer);
 int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
-int xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml);
+int xenDaemonNodeGetTopology(virConnectPtr conn, virCapsPtr caps);
 int xenDaemonDomainSuspend(virDomainPtr domain);
 int xenDaemonDomainResume(virDomainPtr domain);
 int xenDaemonDomainShutdown(virDomainPtr domain);
index 8bf63305737f1ffc5a7bce8260729b9519212459..475772c73e679d52044d1c1e8a7fa4063e507d5a 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -26,6 +26,7 @@
 #include "sexpr.h"
 #include "xml.h"
 #include "buf.h"
+#include "util.h"
 #include "xs_internal.h"        /* for xenStoreDomainGetNetworkID */
 #include "xen_unified.h"
 
@@ -58,56 +59,6 @@ virXMLError(virConnectPtr conn, virErrorNumber error, const char *info,
  *                                                                     *
  ************************************************************************/
 #if WITH_XEN
-/**
- * skipSpaces:
- * @str: pointer to the char pointer used
- *
- * Skip potential blanks, this includes space tabs, line feed,
- * carriage returns and also '\\' which can be erronously emitted
- * by xend
- */
-static void
-skipSpaces(const char **str)
-{
-    const char *cur = *str;
-
-    while ((*cur == ' ') || (*cur == '\t') || (*cur == '\n') ||
-           (*cur == '\r') || (*cur == '\\'))
-        cur++;
-    *str = cur;
-}
-
-/**
- * parseNumber:
- * @str: pointer to the char pointer used
- *
- * Parse an unsigned number
- *
- * Returns the unsigned number or -1 in case of error. @str will be
- *         updated to skip the number.
- */
-static int
-parseNumber(const char **str)
-{
-    int ret = 0;
-    const char *cur = *str;
-
-    if ((*cur < '0') || (*cur > '9'))
-        return (-1);
-
-    while ((*cur >= '0') && (*cur <= '9')) {
-        unsigned int c = *cur - '0';
-
-        if ((ret > INT_MAX / 10) ||
-            ((ret == INT_MAX / 10) && (c > INT_MAX % 10)))
-            return (-1);
-        ret = ret * 10 + c;
-        cur++;
-    }
-    *str = cur;
-    return (ret);
-}
-
 /**
  * parseCpuNumber:
  * @str: pointer to the char pointer used
@@ -225,7 +176,7 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
         return (-1);
 
     cur = *str;
-    skipSpaces(&cur);
+    virSkipSpaces(&cur);
     if (*cur == 0)
         goto parse_error;
 
@@ -251,7 +202,7 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
         start = parseCpuNumber(&cur, maxcpu);
         if (start < 0)
             goto parse_error;
-        skipSpaces(&cur);
+        virSkipSpaces(&cur);
         if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
             if (neg) {
                 if (cpuset[start] == 1) {
@@ -268,7 +219,7 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
             if (neg)
                 goto parse_error;
             cur++;
-            skipSpaces(&cur);
+            virSkipSpaces(&cur);
             last = parseCpuNumber(&cur, maxcpu);
             if (last < start)
                 goto parse_error;
@@ -278,11 +229,11 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
                     ret++;
                 }
             }
-            skipSpaces(&cur);
+            virSkipSpaces(&cur);
         }
         if (*cur == ',') {
             cur++;
-            skipSpaces(&cur);
+            virSkipSpaces(&cur);
             neg = 0;
         } else if ((*cur == 0) || (*cur == sep)) {
             break;
@@ -298,114 +249,6 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
     return (-1);
 }
 
-/**
- * virParseXenCpuTopology:
- * @conn: connection
- * @xml: XML output buffer
- * @str: the topology string
- * @maxcpu: number of elements available in @cpuset
- *
- * Parse a Xend CPU topology string and build the associated XML
- * format.
- *
- * Returns 0 in case of success, -1 in case of error
- */
-int
-virParseXenCpuTopology(virConnectPtr conn, virBufferPtr xml,
-                       const char *str, int maxcpu)
-{
-    const char *cur;
-    char *cpuset = NULL;
-    int cell, cpu, nb_cpus;
-    int ret;
-
-    if ((str == NULL) || (xml == NULL) || (maxcpu <= 0) || (maxcpu > 100000))
-        return (-1);
-
-    cpuset = malloc(maxcpu * sizeof(*cpuset));
-    if (cpuset == NULL)
-        goto memory_error;
-
-    cur = str;
-    while (*cur != 0) {
-        /*
-         * Find the next NUMA cell described in the xend output
-         */
-        cur = strstr(cur, "node");
-        if (cur == NULL)
-            break;
-        cur += 4;
-        cell = parseNumber(&cur);
-        if (cell < 0)
-            goto parse_error;
-        skipSpaces(&cur);
-        if (*cur != ':')
-            goto parse_error;
-        cur++;
-        skipSpaces(&cur);
-        if (!strncmp(cur, "no cpus", 7)) {
-            nb_cpus = 0;
-            for (cpu = 0; cpu < maxcpu; cpu++)
-                cpuset[cpu] = 0;
-        } else {
-            nb_cpus = virParseCpuSet(conn, &cur, 'n', cpuset, maxcpu);
-            if (nb_cpus < 0)
-                goto error;
-        }
-
-        /*
-         * add xml for all cpus associated with that cell
-         */
-        ret = virBufferVSprintf(xml, "\
-      <cell id='%d'>\n\
-        <cpus num='%d'>\n", cell, nb_cpus);
-#ifdef STANDALONE
-        {
-            char *dump;
-
-            dump = virSaveCpuSet(conn, cpuset, maxcpu);
-            if (dump != NULL) {
-                virBufferVSprintf(xml, "           <dump>%s</dump>\n",
-                                  dump);
-                free(dump);
-            } else {
-                virBufferVSprintf(xml, "           <error>%s</error>\n",
-                                  "Failed to dump CPU set");
-            }
-        }
-#endif
-        if (ret < 0)
-            goto memory_error;
-        for (cpu = 0; cpu < maxcpu; cpu++) {
-            if (cpuset[cpu] == 1) {
-                ret = virBufferVSprintf(xml, "\
-           <cpu id='%d'/>\n", cpu);
-                if (ret < 0)
-                    goto memory_error;
-            }
-        }
-        ret = virBufferAddLit(xml, "\
-        </cpus>\n\
-      </cell>\n");
-        if (ret < 0)
-            goto memory_error;
-
-    }
-    free(cpuset);
-    return (0);
-
-  parse_error:
-    virXMLError(conn, VIR_ERR_XEN_CALL, _("topology syntax error"), 0);
-  error:
-    free(cpuset);
-
-    return (-1);
-
-  memory_error:
-    free(cpuset);
-    virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
-    return (-1);
-}
 
 /**
  * virConvertCpuSet:
index af87abc5042d321bb46646d6ad79aa2c3e412884..f196b27252c2df660b5a24ddb426a6779b8e15a7 100644 (file)
--- a/src/xml.h
+++ b/src/xml.h
@@ -33,10 +33,6 @@ int          virXPathNodeSet (const char *xpath,
                                 xmlNodePtr **list);
 
 #if WITH_XEN
-int            virParseXenCpuTopology(virConnectPtr conn,
-                                virBufferPtr xml,
-                                const char *str,
-                                int maxcpu);
 int            virParseCpuSet  (virConnectPtr conn,
                                 const char **str,
                                 char sep,
index 56067443fc1b2d5818d0c7a428847990b377c1a7..f4b3e32d34d2095a8276b14d894fc2657b25def2 100644 (file)
@@ -125,6 +125,8 @@ main(int argc, char **argv)
     if (!abs_top_srcdir)
       return 1;
 
+    driver.caps = qemudCapsInit();
+
     if (virtTestRun("QEMU XML-2-ARGV minimal",
                     1, testCompareXMLToArgvHelper, "minimal") < 0)
         ret = -1;
@@ -190,6 +192,8 @@ main(int argc, char **argv)
         ret = -1;
 
 
+    virCapabilitiesFree(driver.caps);
+
     exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
index 1be0e464a0fbcf6dd98e4e9d3962001e087f5a50..f37f948360948a2d06efb4439bb19c9e2e256722 100644 (file)
@@ -88,6 +88,9 @@ main(int argc, char **argv)
     if (!abs_top_srcdir)
       return 1;
 
+
+    driver.caps = qemudCapsInit();
+
     if (virtTestRun("QEMU XML-2-ARGV minimal",
                     1, testCompareXMLToXMLHelper, "minimal") < 0)
         ret = -1;
@@ -152,6 +155,7 @@ main(int argc, char **argv)
                     1, testCompareXMLToXMLHelper, "net-user") < 0)
         ret = -1;
 
+    virCapabilitiesFree(driver.caps);
 
     exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
 }
index 8bff3bd56f08badcee6f48273204fd2335abf7ae..42b099c9b465431be79f91622659e2cf1dedf869 100644 (file)
@@ -1,4 +1,5 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>i686</arch>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="i686">
+    <arch name='i686'>
       <wordsize>32</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <pae/>
 
   <guest>
     <os_type>hvm</os_type>
-    <arch name="i686">
+    <arch name='i686'>
       <wordsize>32</wordsize>
-      <domain type="xen"></domain>
       <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
-      <machine>pc</machine>
-      <machine>isapc</machine>
       <loader>/usr/lib/xen/boot/hvmloader</loader>
+      <machine>xenfv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <pae/>
@@ -42,4 +46,5 @@
       <apic default='on' toggle='yes'/>
     </features>
   </guest>
+
 </capabilities>
index 03deb989a4f461f7140283e47775ab1cb7ee8bdf..a6cec8a617a683e94321f93db5f45e3177852f6b 100644 (file)
@@ -1,4 +1,5 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>i686</arch>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="i686">
+    <arch name='i686'>
       <wordsize>32</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <pae/>
     </features>
   </guest>
+
 </capabilities>
index 6f25a1d35c7fbecf63128b8659387d1d6817d259..907121215f308b228250b223363e0954bbf09c00 100644 (file)
@@ -1,9 +1,8 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>i686</arch>
-      <features>
-      </features>
     </cpu>
     <migration_features>
       <live/>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="i686">
+    <arch name='i686'>
       <wordsize>32</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <nonpae/>
     </features>
   </guest>
+
 </capabilities>
index 426ccfac566d560617b5c7748ffac1fa11db5e1d..732b6937273a075a23e944be3627fb6a769e06a7 100644 (file)
@@ -1,9 +1,8 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>ia64</arch>
-      <features>
-      </features>
     </cpu>
     <migration_features>
       <live/>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="ia64">
+    <arch name='ia64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <ia64_be/>
 
   <guest>
     <os_type>hvm</os_type>
-    <arch name="ia64">
+    <arch name='ia64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
-      <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
-      <machine>pc</machine>
-      <machine>isapc</machine>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
       <loader>/usr/lib/xen/boot/hvmloader</loader>
+      <machine>xenfv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <ia64_be/>
@@ -40,4 +42,5 @@
       <apic default='on' toggle='yes'/>
     </features>
   </guest>
+
 </capabilities>
index 125448a0cbdf3b4a3312b51d2b2e9fcd07652a1e..4f133ec60d305b1ddabaf4373ab3192d3790a171 100644 (file)
@@ -1,9 +1,8 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>ia64</arch>
-      <features>
-      </features>
     </cpu>
     <migration_features>
       <live/>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="ia64">
+    <arch name='ia64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <ia64_be/>
     </features>
   </guest>
+
 </capabilities>
index 730db4b0c0ac448c8c5cdbd29ba4761bc55e0a46..ef48a95e39694d260499762f6e718abf8c4e5f5c 100644 (file)
@@ -1,9 +1,8 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>ia64</arch>
-      <features>
-      </features>
     </cpu>
     <migration_features>
       <live/>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="ia64">
+    <arch name='ia64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
-    <features>
-    </features>
   </guest>
 
   <guest>
     <os_type>hvm</os_type>
-    <arch name="ia64">
+    <arch name='ia64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
-      <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
-      <machine>pc</machine>
-      <machine>isapc</machine>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
       <loader>/usr/lib/xen/boot/hvmloader</loader>
+      <machine>xenfv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <acpi default='on' toggle='yes'/>
       <apic default='on' toggle='yes'/>
     </features>
   </guest>
+
 </capabilities>
index 12266dd3bdb83932ce2fa0b8428b852c94ea4bba..5570f4dfd97f79784217c7367d4aad7fec87206e 100644 (file)
@@ -1,9 +1,8 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>ia64</arch>
-      <features>
-      </features>
     </cpu>
     <migration_features>
       <live/>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="ia64">
+    <arch name='ia64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
-    <features>
-    </features>
   </guest>
+
 </capabilities>
index 96e566fc89e1675445c8d1485108b2813365709f..627d79c1419b8411119bea8a99a0e9e07f74c517 100644 (file)
@@ -1,9 +1,8 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>ppc64</arch>
-      <features>
-      </features>
     </cpu>
     <migration_features>
       <live/>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="ppc64">
+    <arch name='ppc64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
-    <features>
-    </features>
   </guest>
+
 </capabilities>
index c7fa802f27ea87f1b114320d855b57a47cf1dc3b..52c12c616e6775b8d8d77c6e0dff81dce5e8ab5e 100644 (file)
@@ -1,4 +1,5 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>x86_64</arch>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="x86_64">
+    <arch name='x86_64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
-    <features>
-    </features>
   </guest>
 
   <guest>
     <os_type>hvm</os_type>
-    <arch name="i686">
+    <arch name='i686'>
       <wordsize>32</wordsize>
-      <domain type="xen"></domain>
-      <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
-      <machine>pc</machine>
-      <machine>isapc</machine>
+      <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
       <loader>/usr/lib/xen/boot/hvmloader</loader>
+      <machine>xenfv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <pae/>
 
   <guest>
     <os_type>hvm</os_type>
-    <arch name="x86_64">
+    <arch name='x86_64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
       <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
-      <machine>pc</machine>
-      <machine>isapc</machine>
       <loader>/usr/lib/xen/boot/hvmloader</loader>
+      <machine>xenfv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
     <features>
       <acpi default='on' toggle='yes'/>
       <apic default='on' toggle='yes'/>
     </features>
   </guest>
+
 </capabilities>
index 7c73d0ece54e07dc58c88b6f40189d21ce5dffcb..0faa43c79167955357a1d2affd76c20ab7e74bce 100644 (file)
@@ -1,4 +1,5 @@
 <capabilities>
+
   <host>
     <cpu>
       <arch>x86_64</arch>
 
   <guest>
     <os_type>xen</os_type>
-    <arch name="x86_64">
+    <arch name='x86_64'>
       <wordsize>64</wordsize>
-      <domain type="xen"></domain>
+      <emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
+      <machine>xenpv</machine>
+      <domain type='xen'>
+      </domain>
     </arch>
-    <features>
-    </features>
   </guest>
+
 </capabilities>
index 1307d80af771e7ee73f15ccc31f00b60e458da51..ff9ed33362a02a466dc78c3c08e3310a8df39b5b 100644 (file)
@@ -50,7 +50,8 @@ static int testCompareFiles(const char *hostmachine,
   if (!(actualxml = xenHypervisorMakeCapabilitiesXML(NULL, hostmachine, fp1, fp2)))
     goto fail;
 
-  if (getenv("DEBUG_TESTS")) {
+  if (getenv("DEBUG_TESTS") &&
+      STRNEQ(expectxml, actualxml)) {
     printf("In test file %s:\n", capabilities);
     printf("Expect %d '%s'\n", (int)strlen(expectxml), expectxml);
     printf("Actual %d '%s'\n", (int)strlen(actualxml), actualxml);