+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.
@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 =
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 \
--- /dev/null
+/*
+ * 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:
+ */
--- /dev/null
+/*
+ * 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:
+ */
/* 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;
}
}
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;
}
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;
}
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;
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)) {
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");
#include "internal.h"
#include "bridge.h"
#include "iptables.h"
+#include "capabilities.h"
#include <netinet/in.h>
#define qemudDebug(fmt, ...) do {} while(0)
unsigned int vncTLSx509verify : 1;
char *vncTLSx509certdir;
char vncListen[BR_INET_ADDR_MAXLEN];
+
+ virCapsPtr caps;
};
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,
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 */
#include "qemu_conf.h"
#include "nodeinfo.h"
#include "stats_linux.h"
+#include "capabilities.h"
static int qemudShutdown(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();
if (!qemu_driver)
return -1;
+ virCapabilitiesFree(qemu_driver->caps);
+
/* shutdown active VMs */
vm = qemu_driver->vms;
while (vm) {
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;
}
#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
*/
typedef struct _testConn *testConnPtr;
#define TEST_MODEL "i686"
-#define TEST_MODEL_WORDSIZE "32"
+#define TEST_MODEL_WORDSIZE 32
static const virNodeInfo defaultNodeInfo = {
TEST_MODEL,
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)
#define virLog(msg...) fprintf(stderr, msg)
+#ifndef PROXY
static void
ReportError(virConnectPtr conn,
virDomainPtr dom,
*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:
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__ */
#include <xen/sched.h>
#include "buf.h"
+#include "capabilities.h"
/* #define DEBUG */
/*
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
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));
}
}
- /* 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;
}
#include "sexpr.h"
#include "xml.h"
#include "buf.h"
+#include "capabilities.h"
#include "uuid.h"
#include "xen_unified.h"
#include "xend_internal.h"
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:
/**
* 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;
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);
}
#include <stdbool.h>
#include "libvirt/libvirt.h"
-#include "buf.h"
+#include "capabilities.h"
#ifdef __cplusplus
extern "C" {
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);
#include "sexpr.h"
#include "xml.h"
#include "buf.h"
+#include "util.h"
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
#include "xen_unified.h"
* *
************************************************************************/
#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
return (-1);
cur = *str;
- skipSpaces(&cur);
+ virSkipSpaces(&cur);
if (*cur == 0)
goto parse_error;
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) {
if (neg)
goto parse_error;
cur++;
- skipSpaces(&cur);
+ virSkipSpaces(&cur);
last = parseCpuNumber(&cur, maxcpu);
if (last < start)
goto parse_error;
ret++;
}
}
- skipSpaces(&cur);
+ virSkipSpaces(&cur);
}
if (*cur == ',') {
cur++;
- skipSpaces(&cur);
+ virSkipSpaces(&cur);
neg = 0;
} else if ((*cur == 0) || (*cur == sep)) {
break;
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:
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,
if (!abs_top_srcdir)
return 1;
+ driver.caps = qemudCapsInit();
+
if (virtTestRun("QEMU XML-2-ARGV minimal",
1, testCompareXMLToArgvHelper, "minimal") < 0)
ret = -1;
ret = -1;
+ virCapabilitiesFree(driver.caps);
+
exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
if (!abs_top_srcdir)
return 1;
+
+ driver.caps = qemudCapsInit();
+
if (virtTestRun("QEMU XML-2-ARGV minimal",
1, testCompareXMLToXMLHelper, "minimal") < 0)
ret = -1;
1, testCompareXMLToXMLHelper, "net-user") < 0)
ret = -1;
+ virCapabilitiesFree(driver.caps);
exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
<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/>
<apic default='on' toggle='yes'/>
</features>
</guest>
+
</capabilities>
<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>
<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>
<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/>
<apic default='on' toggle='yes'/>
</features>
</guest>
+
</capabilities>
<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>
<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>
<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>
<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>
<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>
<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>
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);