mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
Add formal internal capabilities API and update drivers to use it
This commit is contained in:
parent
727c5601ec
commit
63bc5dd3e1
13
ChangeLog
13
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>
|
Tue Feb 26 18:38:00 UTC 2008 Richard W.M. Jones <rjones@redhat.com>
|
||||||
|
|
||||||
Implement virDomainBlockStats for QEMU/KVM.
|
Implement virDomainBlockStats for QEMU/KVM.
|
||||||
|
@ -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/xen_internal.c @top_srcdir@/src/virterror.c \
|
||||||
@top_srcdir@/src/sexpr.c @top_srcdir@/src/xml.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/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
|
@top_srcdir@/src/uuid.c
|
||||||
libvirt_proxy_LDFLAGS = $(WARN_CFLAGS)
|
libvirt_proxy_LDFLAGS = $(WARN_CFLAGS)
|
||||||
libvirt_proxy_DEPENDENCIES =
|
libvirt_proxy_DEPENDENCIES =
|
||||||
|
@ -37,6 +37,7 @@ CLIENT_SOURCES = \
|
|||||||
test.c test.h \
|
test.c test.h \
|
||||||
buf.c buf.h \
|
buf.c buf.h \
|
||||||
qparams.c qparams.h \
|
qparams.c qparams.h \
|
||||||
|
capabilities.c capabilities.h \
|
||||||
xml.c xml.h \
|
xml.c xml.h \
|
||||||
event.c event.h \
|
event.c event.h \
|
||||||
xen_unified.c xen_unified.h \
|
xen_unified.c xen_unified.h \
|
||||||
|
696
src/capabilities.c
Normal file
696
src/capabilities.c
Normal file
@ -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:
|
||||||
|
*/
|
183
src/capabilities.h
Normal file
183
src/capabilities.h
Normal file
@ -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:
|
||||||
|
*/
|
250
src/qemu_conf.c
250
src/qemu_conf.c
@ -232,104 +232,186 @@ void qemudFreeVM(struct qemud_vm *vm) {
|
|||||||
|
|
||||||
/* The list of possible machine types for various architectures,
|
/* The list of possible machine types for various architectures,
|
||||||
as supported by QEMU - taken from 'qemu -M ?' for each arch */
|
as supported by QEMU - taken from 'qemu -M ?' for each arch */
|
||||||
static const char *const arch_info_x86_machines[] = {
|
static const char *const arch_info_hvm_x86_machines[] = {
|
||||||
"pc", "isapc", NULL
|
"pc", "isapc"
|
||||||
};
|
};
|
||||||
static const char *const arch_info_mips_machines[] = {
|
static const char *const arch_info_hvm_mips_machines[] = {
|
||||||
"mips", NULL
|
"mips"
|
||||||
};
|
};
|
||||||
static const char *const arch_info_sparc_machines[] = {
|
static const char *const arch_info_hvm_sparc_machines[] = {
|
||||||
"sun4m", NULL
|
"sun4m"
|
||||||
};
|
};
|
||||||
static const char *const arch_info_ppc_machines[] = {
|
static const char *const arch_info_hvm_ppc_machines[] = {
|
||||||
"g3bw", "mac99", "prep", NULL
|
"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 */
|
/* Feature flags for the architecture info */
|
||||||
static const struct qemu_feature_flags const arch_info_i686_flags [] = {
|
static const struct qemu_feature_flags const arch_info_i686_flags [] = {
|
||||||
{ "pae", 1, 1 },
|
{ "pae", 1, 0 },
|
||||||
|
{ "nonpae", 1, 0 },
|
||||||
{ "acpi", 1, 1 },
|
{ "acpi", 1, 1 },
|
||||||
{ "apic", 1, 0 },
|
{ "apic", 1, 0 },
|
||||||
{ NULL, -1, -1 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qemu_feature_flags const arch_info_x86_64_flags [] = {
|
static const struct qemu_feature_flags const arch_info_x86_64_flags [] = {
|
||||||
{ "acpi", 1, 1 },
|
{ "acpi", 1, 1 },
|
||||||
{ "apic", 1, 0 },
|
{ "apic", 1, 0 },
|
||||||
{ NULL, -1, -1 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The archicture tables for supported QEMU archs */
|
/* The archicture tables for supported QEMU archs */
|
||||||
const struct qemu_arch_info const qemudArchs[] = {
|
static const struct qemu_arch_info const arch_info_hvm[] = {
|
||||||
/* i686 must be in position 0 */
|
{ "i686", 32, arch_info_hvm_x86_machines, 2,
|
||||||
{ "i686", 32, arch_info_x86_machines, "qemu", arch_info_i686_flags },
|
"/usr/bin/qemu", arch_info_i686_flags, 4 },
|
||||||
/* x86_64 must be in position 1 */
|
{ "x86_64", 64, arch_info_hvm_x86_machines, 2,
|
||||||
{ "x86_64", 64, arch_info_x86_machines, "qemu-system-x86_64", arch_info_x86_64_flags },
|
"/usr/bin/qemu-system-x86_64", arch_info_x86_64_flags, 2 },
|
||||||
{ "mips", 32, arch_info_mips_machines, "qemu-system-mips", NULL },
|
{ "mips", 32, arch_info_hvm_mips_machines, 1,
|
||||||
{ "mipsel", 32, arch_info_mips_machines, "qemu-system-mipsel", NULL },
|
"/usr/bin/qemu-system-mips", NULL, 0 },
|
||||||
{ "sparc", 32, arch_info_sparc_machines, "qemu-system-sparc", NULL },
|
{ "mipsel", 32, arch_info_hvm_mips_machines, 1,
|
||||||
{ "ppc", 32, arch_info_ppc_machines, "qemu-system-ppc", NULL },
|
"/usr/bin/qemu-system-mipsel", NULL, 0 },
|
||||||
{ NULL, -1, NULL, NULL, NULL }
|
{ "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 struct qemu_arch_info const arch_info_xen[] = {
|
||||||
static const char *qemudDefaultArch(void) {
|
{ "i686", 32, arch_info_xen_x86_machines, 1,
|
||||||
return qemudArchs[0].arch;
|
"/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 int
|
||||||
static const char *qemudDefaultMachineForArch(const char *arch) {
|
qemudCapsInitGuest(virCapsPtr caps,
|
||||||
|
const char *hostmachine,
|
||||||
|
const struct qemu_arch_info *info,
|
||||||
|
int hvm) {
|
||||||
|
virCapsGuestPtr guest;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; qemudArchs[i].arch; i++) {
|
if ((guest = virCapabilitiesAddGuest(caps,
|
||||||
if (!strcmp(qemudArchs[i].arch, arch)) {
|
hvm ? "hvm" : "xen",
|
||||||
return qemudArchs[i].machines[0];
|
info->arch,
|
||||||
|
info->wordsize,
|
||||||
|
info->binary,
|
||||||
|
NULL,
|
||||||
|
info->nmachines,
|
||||||
|
info->machines)) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the default binary name for a particular architecture */
|
virCapsPtr qemudCapsInit(void) {
|
||||||
static const char *qemudDefaultBinaryForArch(const char *arch) {
|
struct utsname utsname;
|
||||||
|
virCapsPtr caps;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0 ; qemudArchs[i].arch; i++) {
|
/* Really, this never fails - look at the man-page. */
|
||||||
if (!strcmp(qemudArchs[i].arch, arch)) {
|
uname (&utsname);
|
||||||
return qemudArchs[i].binary;
|
|
||||||
|
if ((caps = virCapabilitiesNew(utsname.machine,
|
||||||
|
0, 0)) == NULL)
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
|
||||||
|
no_memory:
|
||||||
|
virCapabilitiesFree(caps);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
if (virtType == QEMUD_VIRT_KVM)
|
|
||||||
name = "qemu-kvm";
|
|
||||||
else
|
|
||||||
name = qemudDefaultBinaryForArch(arch);
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot determin binary for architecture %s", arch);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
strcpy(path, "/usr/bin/");
|
|
||||||
strcat(path, name);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
|
static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
|
||||||
pid_t child;
|
pid_t child;
|
||||||
@ -429,31 +511,31 @@ static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int qemudExtractVersion(virConnectPtr conn,
|
int qemudExtractVersion(virConnectPtr conn,
|
||||||
struct qemud_driver *driver ATTRIBUTE_UNUSED) {
|
struct qemud_driver *driver) {
|
||||||
char *binary = NULL;
|
const char *binary;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
int ignored;
|
int ignored;
|
||||||
|
|
||||||
if (driver->qemuVersion > 0)
|
if (driver->qemuVersion > 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(binary = qemudLocateBinaryForArch(conn, QEMUD_VIRT_QEMU, "i686")))
|
if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps,
|
||||||
|
"hvm",
|
||||||
|
"i686",
|
||||||
|
"qemu")) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (stat(binary, &sb) < 0) {
|
if (stat(binary, &sb) < 0) {
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
"Cannot find QEMU binary %s: %s", binary,
|
"Cannot find QEMU binary %s: %s", binary,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
free(binary);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) {
|
if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) {
|
||||||
free(binary);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(binary);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1086,7 +1168,7 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn,
|
|||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE, NULL);
|
qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE, NULL);
|
||||||
goto error;
|
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);
|
qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE, "%s", obj->stringval);
|
||||||
goto error;
|
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);
|
obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@arch)", ctxt);
|
||||||
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
||||||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
(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)) {
|
if (strlen(defaultArch) >= (QEMUD_OS_TYPE_MAX_LEN-1)) {
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "architecture type too long");
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "architecture type too long");
|
||||||
goto error;
|
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);
|
obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@machine)", ctxt);
|
||||||
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
||||||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
||||||
const char *defaultMachine = qemudDefaultMachineForArch(def->os.arch);
|
const char *defaultMachine = virCapabilitiesDefaultGuestMachine(driver->caps,
|
||||||
if (!defaultMachine) {
|
def->os.type,
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "unsupported arch %s", def->os.arch);
|
def->os.arch);
|
||||||
|
if (defaultMachine == NULL) {
|
||||||
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported architecture");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (strlen(defaultMachine) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) {
|
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);
|
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
|
||||||
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
||||||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
||||||
char *tmp = qemudLocateBinaryForArch(conn, def->virtType, def->os.arch);
|
const char *type = (def->virtType == QEMUD_VIRT_QEMU ? "qemu" :
|
||||||
if (!tmp) {
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
strcpy(def->os.binary, tmp);
|
strcpy(def->os.binary, emulator);
|
||||||
free(tmp);
|
|
||||||
} else {
|
} else {
|
||||||
if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
|
if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) {
|
||||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "emulator path too long");
|
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "emulator path too long");
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "bridge.h"
|
#include "bridge.h"
|
||||||
#include "iptables.h"
|
#include "iptables.h"
|
||||||
|
#include "capabilities.h"
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#define qemudDebug(fmt, ...) do {} while(0)
|
#define qemudDebug(fmt, ...) do {} while(0)
|
||||||
@ -314,6 +315,8 @@ struct qemud_driver {
|
|||||||
unsigned int vncTLSx509verify : 1;
|
unsigned int vncTLSx509verify : 1;
|
||||||
char *vncTLSx509certdir;
|
char *vncTLSx509certdir;
|
||||||
char vncListen[BR_INET_ADDR_MAXLEN];
|
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,
|
struct qemud_network *qemudFindNetworkByName(const struct qemud_driver *driver,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
|
||||||
|
virCapsPtr qemudCapsInit (void);
|
||||||
|
|
||||||
int qemudExtractVersion (virConnectPtr conn,
|
int qemudExtractVersion (virConnectPtr conn,
|
||||||
struct qemud_driver *driver);
|
struct qemud_driver *driver);
|
||||||
int qemudBuildCommandLine (virConnectPtr conn,
|
int qemudBuildCommandLine (virConnectPtr conn,
|
||||||
@ -418,20 +423,6 @@ char * qemudGenerateNetworkXML (virConnectPtr conn,
|
|||||||
struct qemud_network *network,
|
struct qemud_network *network,
|
||||||
struct qemud_network_def *def);
|
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 */
|
#endif /* WITH_QEMU */
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#include "qemu_conf.h"
|
#include "qemu_conf.h"
|
||||||
#include "nodeinfo.h"
|
#include "nodeinfo.h"
|
||||||
#include "stats_linux.h"
|
#include "stats_linux.h"
|
||||||
|
#include "capabilities.h"
|
||||||
|
|
||||||
static int qemudShutdown(void);
|
static int qemudShutdown(void);
|
||||||
|
|
||||||
@ -214,6 +215,10 @@ qemudStartup(void) {
|
|||||||
goto out_of_memory;
|
goto out_of_memory;
|
||||||
|
|
||||||
free(base);
|
free(base);
|
||||||
|
base = NULL;
|
||||||
|
|
||||||
|
if ((qemu_driver->caps = qemudCapsInit()) == NULL)
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
|
if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
|
||||||
qemudShutdown();
|
qemudShutdown();
|
||||||
@ -297,6 +302,8 @@ qemudShutdown(void) {
|
|||||||
if (!qemu_driver)
|
if (!qemu_driver)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
virCapabilitiesFree(qemu_driver->caps);
|
||||||
|
|
||||||
/* shutdown active VMs */
|
/* shutdown active VMs */
|
||||||
vm = qemu_driver->vms;
|
vm = qemu_driver->vms;
|
||||||
while (vm) {
|
while (vm) {
|
||||||
@ -1479,191 +1486,17 @@ static int qemudGetNodeInfo(virConnectPtr conn,
|
|||||||
return virNodeInfoPopulate(conn, nodeinfo);
|
return virNodeInfoPopulate(conn, nodeinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qemudGetFeatures(virBufferPtr xml,
|
|
||||||
const struct qemu_feature_flags *flags) {
|
|
||||||
int i, r;
|
|
||||||
|
|
||||||
if (flags == NULL)
|
static char *qemudGetCapabilities(virConnectPtr conn) {
|
||||||
return 0;
|
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
|
||||||
|
char *xml;
|
||||||
|
|
||||||
r = virBufferAddLit(xml, "\
|
if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) {
|
||||||
<features>\n");
|
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "capabilities");
|
||||||
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = virBufferVSprintf (xml,
|
return 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);
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
83
src/test.c
83
src/test.c
@ -44,6 +44,7 @@
|
|||||||
#include "buf.h"
|
#include "buf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
|
#include "capabilities.h"
|
||||||
|
|
||||||
/* Flags that determine the action to take on a shutdown or crash of a domain
|
/* 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;
|
typedef struct _testConn *testConnPtr;
|
||||||
|
|
||||||
#define TEST_MODEL "i686"
|
#define TEST_MODEL "i686"
|
||||||
#define TEST_MODEL_WORDSIZE "32"
|
#define TEST_MODEL_WORDSIZE 32
|
||||||
|
|
||||||
static const virNodeInfo defaultNodeInfo = {
|
static const virNodeInfo defaultNodeInfo = {
|
||||||
TEST_MODEL,
|
TEST_MODEL,
|
||||||
@ -978,39 +979,61 @@ static int testNodeGetInfo(virConnectPtr conn,
|
|||||||
|
|
||||||
static char *testGetCapabilities (virConnectPtr conn)
|
static char *testGetCapabilities (virConnectPtr conn)
|
||||||
{
|
{
|
||||||
static char caps[] = "\
|
virCapsPtr caps;
|
||||||
<capabilities>\n\
|
virCapsGuestPtr guest;
|
||||||
<host>\n\
|
char *xml;
|
||||||
<cpu>\n\
|
int cell1[] = { 0, 2, 4, 6, 8, 10, 12, 14 };
|
||||||
<arch>" TEST_MODEL "</arch>\n\
|
int cell2[] = { 1, 3, 5, 7, 9, 11, 13, 15 };
|
||||||
<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 = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL)
|
||||||
if (!caps_copy) {
|
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__);
|
testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return caps_copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int testNumOfDomains(virConnectPtr conn)
|
static int testNumOfDomains(virConnectPtr conn)
|
||||||
{
|
{
|
||||||
|
52
src/util.c
52
src/util.c
@ -52,6 +52,7 @@
|
|||||||
|
|
||||||
#define virLog(msg...) fprintf(stderr, msg)
|
#define virLog(msg...) fprintf(stderr, msg)
|
||||||
|
|
||||||
|
#ifndef PROXY
|
||||||
static void
|
static void
|
||||||
ReportError(virConnectPtr conn,
|
ReportError(virConnectPtr conn,
|
||||||
virDomainPtr dom,
|
virDomainPtr dom,
|
||||||
@ -601,6 +602,57 @@ __virStrToLong_ull(char const *s, char **end_ptr, int base, unsigned long long *
|
|||||||
*result = val;
|
*result = val;
|
||||||
return 0;
|
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:
|
* Local variables:
|
||||||
|
@ -79,4 +79,8 @@ int __virStrToLong_ull(char const *s,
|
|||||||
unsigned long long *result);
|
unsigned long long *result);
|
||||||
#define virStrToLong_ull(s,e,b,r) __virStrToLong_ull((s),(e),(b),(r))
|
#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__ */
|
#endif /* __VIR_UTIL_H__ */
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include <xen/sched.h>
|
#include <xen/sched.h>
|
||||||
|
|
||||||
#include "buf.h"
|
#include "buf.h"
|
||||||
|
#include "capabilities.h"
|
||||||
|
|
||||||
/* #define DEBUG */
|
/* #define DEBUG */
|
||||||
/*
|
/*
|
||||||
@ -2154,6 +2155,121 @@ xenHypervisorGetVersion(virConnectPtr conn, unsigned long *hvVer)
|
|||||||
return(0);
|
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:
|
* xenHypervisorGetCapabilities:
|
||||||
* @conn: pointer to the connection block
|
* @conn: pointer to the connection block
|
||||||
@ -2170,25 +2286,17 @@ xenHypervisorMakeCapabilitiesXML(virConnectPtr conn,
|
|||||||
char line[1024], *str, *token;
|
char line[1024], *str, *token;
|
||||||
regmatch_t subs[4];
|
regmatch_t subs[4];
|
||||||
char *saveptr = NULL;
|
char *saveptr = NULL;
|
||||||
int i, r, topology;
|
int i;
|
||||||
|
|
||||||
char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */
|
char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */
|
||||||
int host_pae = 0;
|
int host_pae = 0;
|
||||||
struct guest_arch {
|
struct guest_arch guest_archs[32];
|
||||||
const char *model;
|
|
||||||
int bits;
|
|
||||||
int hvm;
|
|
||||||
int pae;
|
|
||||||
int nonpae;
|
|
||||||
int ia64_be;
|
|
||||||
} guest_archs[32];
|
|
||||||
int nr_guest_archs = 0;
|
int nr_guest_archs = 0;
|
||||||
|
|
||||||
virBufferPtr xml;
|
char *xml;
|
||||||
char *xml_str;
|
|
||||||
|
|
||||||
int hv_major = hv_version >> 16;
|
|
||||||
int hv_minor = hv_version & 0xFFFF;
|
virCapsPtr caps = NULL;
|
||||||
|
|
||||||
memset(guest_archs, 0, sizeof(guest_archs));
|
memset(guest_archs, 0, sizeof(guest_archs));
|
||||||
|
|
||||||
@ -2306,129 +2414,22 @@ xenHypervisorMakeCapabilitiesXML(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct the final XML. */
|
if ((caps = xenHypervisorBuildCapabilities(conn,
|
||||||
xml = virBufferNew (1024);
|
hostmachine,
|
||||||
if (!xml) {
|
host_pae,
|
||||||
|
hvm_type,
|
||||||
|
guest_archs,
|
||||||
|
nr_guest_archs)) == NULL)
|
||||||
|
goto no_memory;
|
||||||
|
if ((xml = virCapabilitiesFormatXML(caps)) == NULL)
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
|
virCapabilitiesFree(caps);
|
||||||
|
return xml;
|
||||||
|
|
||||||
|
no_memory:
|
||||||
virXenError(conn, VIR_ERR_NO_MEMORY, __FUNCTION__, 0);
|
virXenError(conn, VIR_ERR_NO_MEMORY, __FUNCTION__, 0);
|
||||||
return NULL;
|
virCapabilitiesFree(caps);
|
||||||
}
|
|
||||||
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);
|
|
||||||
|
|
||||||
return xml_str;
|
|
||||||
|
|
||||||
vir_buffer_failed:
|
|
||||||
virXenError(conn, VIR_ERR_NO_MEMORY, __FUNCTION__, 0);
|
|
||||||
topology_failed:
|
|
||||||
virBufferFree (xml);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "sexpr.h"
|
#include "sexpr.h"
|
||||||
#include "xml.h"
|
#include "xml.h"
|
||||||
#include "buf.h"
|
#include "buf.h"
|
||||||
|
#include "capabilities.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
#include "xen_unified.h"
|
#include "xen_unified.h"
|
||||||
#include "xend_internal.h"
|
#include "xend_internal.h"
|
||||||
@ -1952,59 +1953,104 @@ sexpr_to_xend_node_info(const struct sexpr *root, virNodeInfoPtr info)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sexpr_to_xend_topology_xml:
|
* sexpr_to_xend_topology
|
||||||
* @root: an S-Expression describing a node
|
* @root: an S-Expression describing a node
|
||||||
|
* @caps: capability info
|
||||||
*
|
*
|
||||||
* Internal routine creating an XML string with the values from
|
* Internal routine populating capability info with
|
||||||
* the node root provided.
|
* NUMA node mapping details
|
||||||
*
|
*
|
||||||
* Returns 0 in case of success, -1 in case of error
|
* Returns 0 in case of success, -1 in case of error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
sexpr_to_xend_topology_xml(virConnectPtr conn, const struct sexpr *root,
|
sexpr_to_xend_topology(virConnectPtr conn,
|
||||||
virBufferPtr xml)
|
const struct sexpr *root,
|
||||||
|
virCapsPtr caps)
|
||||||
{
|
{
|
||||||
const char *nodeToCpu;
|
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 numCpus;
|
||||||
int r;
|
|
||||||
|
|
||||||
nodeToCpu = sexpr_node(root, "node/node_to_cpu");
|
nodeToCpu = sexpr_node(root, "node/node_to_cpu");
|
||||||
if (nodeToCpu == NULL) {
|
if (nodeToCpu == NULL) {
|
||||||
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
|
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("failed to parse topology information"));
|
_("failed to parse topology information"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
numCpus = sexpr_int(root, "node/nr_cpus");
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
numCells = sexpr_int(root, "node/nr_nodes");
|
for (n = 0, cpu = 0; cpu < numCpus; cpu++)
|
||||||
numCpus = sexpr_int(root, "node/nr_cpus");
|
if (cpuset[cpu] == 1)
|
||||||
|
cpuNums[n++] = cpu;
|
||||||
|
|
||||||
/* start filling in xml */
|
if (virCapabilitiesAddHostNUMACell(caps,
|
||||||
r = virBufferVSprintf (xml,
|
cell,
|
||||||
"\
|
nb_cpus,
|
||||||
<topology>\n\
|
cpuNums) < 0)
|
||||||
<cells num='%d'>\n",
|
goto memory_error;
|
||||||
numCells);
|
}
|
||||||
if (r < 0) goto vir_buffer_failed;
|
free(cpuNums);
|
||||||
|
free(cpuset);
|
||||||
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;
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
parse_error:
|
||||||
vir_buffer_failed:
|
virXendError(conn, VIR_ERR_XEN_CALL, _("topology syntax error"));
|
||||||
virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate new buffer"));
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
free(cpuNums);
|
||||||
|
free(cpuset);
|
||||||
|
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
memory_error:
|
||||||
|
free(cpuNums);
|
||||||
|
free(cpuset);
|
||||||
|
virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"));
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef PROXY
|
#ifndef PROXY
|
||||||
/**
|
/**
|
||||||
* sexpr_to_domain:
|
* sexpr_to_domain:
|
||||||
@ -2720,13 +2766,15 @@ xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
|
|||||||
/**
|
/**
|
||||||
* xenDaemonNodeGetTopology:
|
* xenDaemonNodeGetTopology:
|
||||||
* @conn: pointer to the Xen Daemon block
|
* @conn: pointer to the Xen Daemon block
|
||||||
|
* @caps: capabilities info
|
||||||
*
|
*
|
||||||
* This method retrieves a node's topology information.
|
* This method retrieves a node's topology information.
|
||||||
*
|
*
|
||||||
* Returns -1 in case of error, 0 otherwise.
|
* Returns -1 in case of error, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml) {
|
xenDaemonNodeGetTopology(virConnectPtr conn,
|
||||||
|
virCapsPtr caps) {
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct sexpr *root;
|
struct sexpr *root;
|
||||||
|
|
||||||
@ -2735,7 +2783,7 @@ xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml) {
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml == NULL) {
|
if (caps == NULL) {
|
||||||
virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@ -2745,7 +2793,7 @@ xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml) {
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sexpr_to_xend_topology_xml(conn, root, xml);
|
ret = sexpr_to_xend_topology(conn, root, caps);
|
||||||
sexpr_free(root);
|
sexpr_free(root);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "libvirt/libvirt.h"
|
#include "libvirt/libvirt.h"
|
||||||
#include "buf.h"
|
#include "capabilities.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -187,7 +187,7 @@ int xenDaemonOpen(virConnectPtr conn, xmlURIPtr uri, virConnectAuthPtr auth, int
|
|||||||
int xenDaemonClose(virConnectPtr conn);
|
int xenDaemonClose(virConnectPtr conn);
|
||||||
int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer);
|
int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer);
|
||||||
int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
|
int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
|
||||||
int xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml);
|
int xenDaemonNodeGetTopology(virConnectPtr conn, virCapsPtr caps);
|
||||||
int xenDaemonDomainSuspend(virDomainPtr domain);
|
int xenDaemonDomainSuspend(virDomainPtr domain);
|
||||||
int xenDaemonDomainResume(virDomainPtr domain);
|
int xenDaemonDomainResume(virDomainPtr domain);
|
||||||
int xenDaemonDomainShutdown(virDomainPtr domain);
|
int xenDaemonDomainShutdown(virDomainPtr domain);
|
||||||
|
169
src/xml.c
169
src/xml.c
@ -26,6 +26,7 @@
|
|||||||
#include "sexpr.h"
|
#include "sexpr.h"
|
||||||
#include "xml.h"
|
#include "xml.h"
|
||||||
#include "buf.h"
|
#include "buf.h"
|
||||||
|
#include "util.h"
|
||||||
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
|
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
|
||||||
#include "xen_unified.h"
|
#include "xen_unified.h"
|
||||||
|
|
||||||
@ -58,56 +59,6 @@ virXMLError(virConnectPtr conn, virErrorNumber error, const char *info,
|
|||||||
* *
|
* *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
#if WITH_XEN
|
#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:
|
* parseCpuNumber:
|
||||||
* @str: pointer to the char pointer used
|
* @str: pointer to the char pointer used
|
||||||
@ -225,7 +176,7 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
|
|||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
cur = *str;
|
cur = *str;
|
||||||
skipSpaces(&cur);
|
virSkipSpaces(&cur);
|
||||||
if (*cur == 0)
|
if (*cur == 0)
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
|
|
||||||
@ -251,7 +202,7 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
|
|||||||
start = parseCpuNumber(&cur, maxcpu);
|
start = parseCpuNumber(&cur, maxcpu);
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
skipSpaces(&cur);
|
virSkipSpaces(&cur);
|
||||||
if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
|
if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
|
||||||
if (neg) {
|
if (neg) {
|
||||||
if (cpuset[start] == 1) {
|
if (cpuset[start] == 1) {
|
||||||
@ -268,7 +219,7 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
|
|||||||
if (neg)
|
if (neg)
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
cur++;
|
cur++;
|
||||||
skipSpaces(&cur);
|
virSkipSpaces(&cur);
|
||||||
last = parseCpuNumber(&cur, maxcpu);
|
last = parseCpuNumber(&cur, maxcpu);
|
||||||
if (last < start)
|
if (last < start)
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
@ -278,11 +229,11 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
|
|||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
skipSpaces(&cur);
|
virSkipSpaces(&cur);
|
||||||
}
|
}
|
||||||
if (*cur == ',') {
|
if (*cur == ',') {
|
||||||
cur++;
|
cur++;
|
||||||
skipSpaces(&cur);
|
virSkipSpaces(&cur);
|
||||||
neg = 0;
|
neg = 0;
|
||||||
} else if ((*cur == 0) || (*cur == sep)) {
|
} else if ((*cur == 0) || (*cur == sep)) {
|
||||||
break;
|
break;
|
||||||
@ -298,114 +249,6 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
|
|||||||
return (-1);
|
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:
|
* virConvertCpuSet:
|
||||||
|
@ -33,10 +33,6 @@ int virXPathNodeSet (const char *xpath,
|
|||||||
xmlNodePtr **list);
|
xmlNodePtr **list);
|
||||||
|
|
||||||
#if WITH_XEN
|
#if WITH_XEN
|
||||||
int virParseXenCpuTopology(virConnectPtr conn,
|
|
||||||
virBufferPtr xml,
|
|
||||||
const char *str,
|
|
||||||
int maxcpu);
|
|
||||||
int virParseCpuSet (virConnectPtr conn,
|
int virParseCpuSet (virConnectPtr conn,
|
||||||
const char **str,
|
const char **str,
|
||||||
char sep,
|
char sep,
|
||||||
|
@ -125,6 +125,8 @@ main(int argc, char **argv)
|
|||||||
if (!abs_top_srcdir)
|
if (!abs_top_srcdir)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
driver.caps = qemudCapsInit();
|
||||||
|
|
||||||
if (virtTestRun("QEMU XML-2-ARGV minimal",
|
if (virtTestRun("QEMU XML-2-ARGV minimal",
|
||||||
1, testCompareXMLToArgvHelper, "minimal") < 0)
|
1, testCompareXMLToArgvHelper, "minimal") < 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@ -190,6 +192,8 @@ main(int argc, char **argv)
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
|
|
||||||
|
virCapabilitiesFree(driver.caps);
|
||||||
|
|
||||||
exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,9 @@ main(int argc, char **argv)
|
|||||||
if (!abs_top_srcdir)
|
if (!abs_top_srcdir)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
||||||
|
driver.caps = qemudCapsInit();
|
||||||
|
|
||||||
if (virtTestRun("QEMU XML-2-ARGV minimal",
|
if (virtTestRun("QEMU XML-2-ARGV minimal",
|
||||||
1, testCompareXMLToXMLHelper, "minimal") < 0)
|
1, testCompareXMLToXMLHelper, "minimal") < 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@ -152,6 +155,7 @@ main(int argc, char **argv)
|
|||||||
1, testCompareXMLToXMLHelper, "net-user") < 0)
|
1, testCompareXMLToXMLHelper, "net-user") < 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
|
virCapabilitiesFree(driver.caps);
|
||||||
|
|
||||||
exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>i686</arch>
|
<arch>i686</arch>
|
||||||
@ -16,9 +17,12 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="i686">
|
<arch name='i686'>
|
||||||
<wordsize>32</wordsize>
|
<wordsize>32</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<pae/>
|
<pae/>
|
||||||
@ -27,13 +31,13 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>hvm</os_type>
|
<os_type>hvm</os_type>
|
||||||
<arch name="i686">
|
<arch name='i686'>
|
||||||
<wordsize>32</wordsize>
|
<wordsize>32</wordsize>
|
||||||
<domain type="xen"></domain>
|
|
||||||
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
<machine>pc</machine>
|
|
||||||
<machine>isapc</machine>
|
|
||||||
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
||||||
|
<machine>xenfv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<pae/>
|
<pae/>
|
||||||
@ -42,4 +46,5 @@
|
|||||||
<apic default='on' toggle='yes'/>
|
<apic default='on' toggle='yes'/>
|
||||||
</features>
|
</features>
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>i686</arch>
|
<arch>i686</arch>
|
||||||
@ -16,12 +17,16 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="i686">
|
<arch name='i686'>
|
||||||
<wordsize>32</wordsize>
|
<wordsize>32</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<pae/>
|
<pae/>
|
||||||
</features>
|
</features>
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>i686</arch>
|
<arch>i686</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</cpu>
|
</cpu>
|
||||||
<migration_features>
|
<migration_features>
|
||||||
<live/>
|
<live/>
|
||||||
@ -15,12 +14,16 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="i686">
|
<arch name='i686'>
|
||||||
<wordsize>32</wordsize>
|
<wordsize>32</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<nonpae/>
|
<nonpae/>
|
||||||
</features>
|
</features>
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>ia64</arch>
|
<arch>ia64</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</cpu>
|
</cpu>
|
||||||
<migration_features>
|
<migration_features>
|
||||||
<live/>
|
<live/>
|
||||||
@ -15,9 +14,12 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="ia64">
|
<arch name='ia64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<ia64_be/>
|
<ia64_be/>
|
||||||
@ -26,13 +28,13 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>hvm</os_type>
|
<os_type>hvm</os_type>
|
||||||
<arch name="ia64">
|
<arch name='ia64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
<emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
|
|
||||||
<machine>pc</machine>
|
|
||||||
<machine>isapc</machine>
|
|
||||||
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
||||||
|
<machine>xenfv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<ia64_be/>
|
<ia64_be/>
|
||||||
@ -40,4 +42,5 @@
|
|||||||
<apic default='on' toggle='yes'/>
|
<apic default='on' toggle='yes'/>
|
||||||
</features>
|
</features>
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>ia64</arch>
|
<arch>ia64</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</cpu>
|
</cpu>
|
||||||
<migration_features>
|
<migration_features>
|
||||||
<live/>
|
<live/>
|
||||||
@ -15,12 +14,16 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="ia64">
|
<arch name='ia64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<ia64_be/>
|
<ia64_be/>
|
||||||
</features>
|
</features>
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>ia64</arch>
|
<arch>ia64</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</cpu>
|
</cpu>
|
||||||
<migration_features>
|
<migration_features>
|
||||||
<live/>
|
<live/>
|
||||||
@ -15,27 +14,29 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="ia64">
|
<arch name='ia64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>hvm</os_type>
|
<os_type>hvm</os_type>
|
||||||
<arch name="ia64">
|
<arch name='ia64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
<emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
|
|
||||||
<machine>pc</machine>
|
|
||||||
<machine>isapc</machine>
|
|
||||||
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
||||||
|
<machine>xenfv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<acpi default='on' toggle='yes'/>
|
<acpi default='on' toggle='yes'/>
|
||||||
<apic default='on' toggle='yes'/>
|
<apic default='on' toggle='yes'/>
|
||||||
</features>
|
</features>
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>ia64</arch>
|
<arch>ia64</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</cpu>
|
</cpu>
|
||||||
<migration_features>
|
<migration_features>
|
||||||
<live/>
|
<live/>
|
||||||
@ -15,11 +14,13 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="ia64">
|
<arch name='ia64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>ppc64</arch>
|
<arch>ppc64</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</cpu>
|
</cpu>
|
||||||
<migration_features>
|
<migration_features>
|
||||||
<live/>
|
<live/>
|
||||||
@ -15,11 +14,13 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="ppc64">
|
<arch name='ppc64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>x86_64</arch>
|
<arch>x86_64</arch>
|
||||||
@ -16,23 +17,24 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="x86_64">
|
<arch name='x86_64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>hvm</os_type>
|
<os_type>hvm</os_type>
|
||||||
<arch name="i686">
|
<arch name='i686'>
|
||||||
<wordsize>32</wordsize>
|
<wordsize>32</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
|
||||||
<emulator>/usr/lib/xen/bin/qemu-dm</emulator>
|
|
||||||
<machine>pc</machine>
|
|
||||||
<machine>isapc</machine>
|
|
||||||
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
||||||
|
<machine>xenfv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<pae/>
|
<pae/>
|
||||||
@ -44,17 +46,18 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>hvm</os_type>
|
<os_type>hvm</os_type>
|
||||||
<arch name="x86_64">
|
<arch name='x86_64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
|
||||||
<emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
|
<emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
|
||||||
<machine>pc</machine>
|
|
||||||
<machine>isapc</machine>
|
|
||||||
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
<loader>/usr/lib/xen/boot/hvmloader</loader>
|
||||||
|
<machine>xenfv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<acpi default='on' toggle='yes'/>
|
<acpi default='on' toggle='yes'/>
|
||||||
<apic default='on' toggle='yes'/>
|
<apic default='on' toggle='yes'/>
|
||||||
</features>
|
</features>
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<capabilities>
|
<capabilities>
|
||||||
|
|
||||||
<host>
|
<host>
|
||||||
<cpu>
|
<cpu>
|
||||||
<arch>x86_64</arch>
|
<arch>x86_64</arch>
|
||||||
@ -16,11 +17,13 @@
|
|||||||
|
|
||||||
<guest>
|
<guest>
|
||||||
<os_type>xen</os_type>
|
<os_type>xen</os_type>
|
||||||
<arch name="x86_64">
|
<arch name='x86_64'>
|
||||||
<wordsize>64</wordsize>
|
<wordsize>64</wordsize>
|
||||||
<domain type="xen"></domain>
|
<emulator>/usr/lib64/xen/bin/qemu-dm</emulator>
|
||||||
|
<machine>xenpv</machine>
|
||||||
|
<domain type='xen'>
|
||||||
|
</domain>
|
||||||
</arch>
|
</arch>
|
||||||
<features>
|
|
||||||
</features>
|
|
||||||
</guest>
|
</guest>
|
||||||
|
|
||||||
</capabilities>
|
</capabilities>
|
||||||
|
@ -50,7 +50,8 @@ static int testCompareFiles(const char *hostmachine,
|
|||||||
if (!(actualxml = xenHypervisorMakeCapabilitiesXML(NULL, hostmachine, fp1, fp2)))
|
if (!(actualxml = xenHypervisorMakeCapabilitiesXML(NULL, hostmachine, fp1, fp2)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (getenv("DEBUG_TESTS")) {
|
if (getenv("DEBUG_TESTS") &&
|
||||||
|
STRNEQ(expectxml, actualxml)) {
|
||||||
printf("In test file %s:\n", capabilities);
|
printf("In test file %s:\n", capabilities);
|
||||||
printf("Expect %d '%s'\n", (int)strlen(expectxml), expectxml);
|
printf("Expect %d '%s'\n", (int)strlen(expectxml), expectxml);
|
||||||
printf("Actual %d '%s'\n", (int)strlen(actualxml), actualxml);
|
printf("Actual %d '%s'\n", (int)strlen(actualxml), actualxml);
|
||||||
|
Loading…
Reference in New Issue
Block a user