2008-05-22 16:18:40 +00:00
|
|
|
#include <config.h>
|
2008-06-26 09:37:51 +00:00
|
|
|
#ifdef WITH_QEMU
|
2010-03-09 18:22:22 +00:00
|
|
|
# include <stdlib.h>
|
2008-05-16 16:51:30 +00:00
|
|
|
|
2010-03-09 18:22:22 +00:00
|
|
|
# include "testutilsqemu.h"
|
|
|
|
# include "testutils.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
# include "viralloc.h"
|
2010-04-16 06:01:59 +00:00
|
|
|
# include "cpu_conf.h"
|
2010-04-20 21:22:49 +00:00
|
|
|
# include "qemu/qemu_driver.h"
|
2010-12-17 16:41:51 +00:00
|
|
|
# include "qemu/qemu_domain.h"
|
2013-05-03 12:52:21 +00:00
|
|
|
# include "virstring.h"
|
|
|
|
|
|
|
|
# define VIR_FROM_THIS VIR_FROM_QEMU
|
2008-05-16 16:51:30 +00:00
|
|
|
|
2009-09-10 09:16:27 +00:00
|
|
|
static virCapsGuestMachinePtr *testQemuAllocMachines(int *nmachines)
|
|
|
|
{
|
|
|
|
virCapsGuestMachinePtr *machines;
|
|
|
|
static const char *const x86_machines[] = {
|
|
|
|
"pc", "isapc"
|
|
|
|
};
|
|
|
|
|
|
|
|
machines = virCapabilitiesAllocMachines(x86_machines,
|
|
|
|
ARRAY_CARDINALITY(x86_machines));
|
|
|
|
if (machines == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*nmachines = ARRAY_CARDINALITY(x86_machines);
|
|
|
|
|
|
|
|
return machines;
|
|
|
|
}
|
|
|
|
|
2009-09-10 10:19:12 +00:00
|
|
|
/* Newer versions of qemu have versioned machine types to allow
|
|
|
|
* compatibility with older releases.
|
|
|
|
* The 'pc' machine type is an alias of the newest machine type.
|
|
|
|
*/
|
|
|
|
static virCapsGuestMachinePtr *testQemuAllocNewerMachines(int *nmachines)
|
|
|
|
{
|
|
|
|
virCapsGuestMachinePtr *machines;
|
|
|
|
char *canonical;
|
|
|
|
static const char *const x86_machines[] = {
|
|
|
|
"pc-0.11", "pc", "pc-0.10", "isapc"
|
|
|
|
};
|
|
|
|
|
2013-05-03 12:52:21 +00:00
|
|
|
if (VIR_STRDUP(canonical, x86_machines[0]) < 0)
|
2009-09-10 10:19:12 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
machines = virCapabilitiesAllocMachines(x86_machines,
|
|
|
|
ARRAY_CARDINALITY(x86_machines));
|
|
|
|
if (machines == NULL) {
|
|
|
|
VIR_FREE(canonical);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
machines[1]->canonical = canonical;
|
|
|
|
|
|
|
|
*nmachines = ARRAY_CARDINALITY(x86_machines);
|
|
|
|
|
|
|
|
return machines;
|
|
|
|
}
|
|
|
|
|
Fix default console type setting
The default console type may vary based on the OS type. ie a Xen
paravirt guests wants a 'xen' console, while a fullvirt guests
wants a 'serial' console.
A plain integer default console type in the capabilities does
not suffice. Instead introduce a callback that is passed the
OS type.
* src/conf/capabilities.h: Use a callback for default console
type
* src/conf/domain_conf.c, src/conf/domain_conf.h: Use callback
for default console type. Add missing LXC/OpenVZ console types.
* src/esx/esx_driver.c, src/libxl/libxl_conf.c,
src/lxc/lxc_conf.c, src/openvz/openvz_conf.c,
src/phyp/phyp_driver.c, src/qemu/qemu_capabilities.c,
src/uml/uml_conf.c, src/vbox/vbox_tmpl.c,
src/vmware/vmware_conf.c, src/xen/xen_hypervisor.c,
src/xenapi/xenapi_driver.c: Set default console type callback
2011-10-20 13:56:20 +00:00
|
|
|
|
2011-12-12 23:39:33 +00:00
|
|
|
static int testQemuAddPPC64Guest(virCapsPtr caps)
|
|
|
|
{
|
|
|
|
static const char *machine[] = { "pseries" };
|
|
|
|
virCapsGuestMachinePtr *machines = NULL;
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
|
|
|
|
machines = virCapabilitiesAllocMachines(machine, 1);
|
|
|
|
if (!machines)
|
|
|
|
goto error;
|
|
|
|
|
2012-12-18 19:32:23 +00:00
|
|
|
guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_PPC64,
|
2011-12-12 23:39:33 +00:00
|
|
|
"/usr/bin/qemu-system-ppc64", NULL,
|
|
|
|
1, machines);
|
|
|
|
if (!guest)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
error:
|
2011-12-12 23:39:33 +00:00
|
|
|
/* No way to free a guest? */
|
|
|
|
virCapabilitiesFreeMachines(machines, 1);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-03-14 04:49:43 +00:00
|
|
|
static int testQemuAddPPCGuest(virCapsPtr caps)
|
|
|
|
{
|
|
|
|
static const char *machine[] = { "g3beige",
|
|
|
|
"mac99",
|
|
|
|
"prep",
|
2014-05-27 05:44:13 +00:00
|
|
|
"ppce500" };
|
2013-03-14 04:49:43 +00:00
|
|
|
virCapsGuestMachinePtr *machines = NULL;
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
|
|
|
|
machines = virCapabilitiesAllocMachines(machine, 1);
|
|
|
|
if (!machines)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_PPC,
|
|
|
|
"/usr/bin/qemu-system-ppc", NULL,
|
|
|
|
1, machines);
|
|
|
|
if (!guest)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
error:
|
2013-03-14 04:49:43 +00:00
|
|
|
/* No way to free a guest? */
|
|
|
|
virCapabilitiesFreeMachines(machines, 1);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-06-29 15:02:07 +00:00
|
|
|
static int testQemuAddS390Guest(virCapsPtr caps)
|
|
|
|
{
|
2013-03-05 15:44:23 +00:00
|
|
|
static const char *s390_machines[] = { "s390-virtio",
|
|
|
|
"s390-ccw-virtio" };
|
2012-06-29 15:02:07 +00:00
|
|
|
virCapsGuestMachinePtr *machines = NULL;
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
|
|
|
|
machines = virCapabilitiesAllocMachines(s390_machines,
|
|
|
|
ARRAY_CARDINALITY(s390_machines));
|
|
|
|
if (!machines)
|
|
|
|
goto error;
|
|
|
|
|
2012-12-18 19:32:23 +00:00
|
|
|
guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_S390X,
|
2012-06-29 15:02:07 +00:00
|
|
|
"/usr/bin/qemu-system-s390x", NULL,
|
|
|
|
ARRAY_CARDINALITY(s390_machines),
|
|
|
|
machines);
|
|
|
|
if (!guest)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
error:
|
2012-06-29 15:02:07 +00:00
|
|
|
virCapabilitiesFreeMachines(machines, ARRAY_CARDINALITY(s390_machines));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-07-30 19:41:14 +00:00
|
|
|
static int testQemuAddArmGuest(virCapsPtr caps)
|
|
|
|
{
|
|
|
|
static const char *machines[] = { "vexpress-a9",
|
|
|
|
"vexpress-a15",
|
|
|
|
"versatilepb" };
|
|
|
|
virCapsGuestMachinePtr *capsmachines = NULL;
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
|
|
|
|
capsmachines = virCapabilitiesAllocMachines(machines,
|
|
|
|
ARRAY_CARDINALITY(machines));
|
|
|
|
if (!capsmachines)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_ARMV7L,
|
|
|
|
"/usr/bin/qemu-system-arm", NULL,
|
|
|
|
ARRAY_CARDINALITY(machines),
|
|
|
|
capsmachines);
|
|
|
|
if (!guest)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
error:
|
2013-07-30 19:41:14 +00:00
|
|
|
virCapabilitiesFreeMachines(capsmachines, ARRAY_CARDINALITY(machines));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-01-02 10:42:56 +00:00
|
|
|
static int testQemuAddAARCH64Guest(virCapsPtr caps)
|
|
|
|
{
|
|
|
|
static const char *machines[] = { "virt"};
|
|
|
|
virCapsGuestMachinePtr *capsmachines = NULL;
|
|
|
|
virCapsGuestPtr guest;
|
|
|
|
|
|
|
|
capsmachines = virCapabilitiesAllocMachines(machines,
|
|
|
|
ARRAY_CARDINALITY(machines));
|
|
|
|
if (!capsmachines)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_AARCH64,
|
|
|
|
"/usr/bin/qemu-system-aarch64", NULL,
|
|
|
|
ARRAY_CARDINALITY(machines),
|
|
|
|
capsmachines);
|
|
|
|
if (!guest)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!virCapabilitiesAddGuestDomain(guest, "qemu", NULL, NULL, 0, NULL))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
error:
|
2014-01-02 10:42:56 +00:00
|
|
|
virCapabilitiesFreeMachines(capsmachines, ARRAY_CARDINALITY(machines));
|
|
|
|
return -1;
|
|
|
|
}
|
2013-03-05 15:17:24 +00:00
|
|
|
|
2014-03-18 08:13:43 +00:00
|
|
|
virCapsPtr testQemuCapsInit(void)
|
|
|
|
{
|
2008-05-16 16:51:30 +00:00
|
|
|
virCapsPtr caps;
|
|
|
|
virCapsGuestPtr guest;
|
2010-04-22 15:00:30 +00:00
|
|
|
virCapsGuestMachinePtr *machines = NULL;
|
|
|
|
int nmachines = 0;
|
2008-05-16 16:51:30 +00:00
|
|
|
static const char *const xen_machines[] = {
|
|
|
|
"xenner"
|
|
|
|
};
|
2010-04-16 06:01:59 +00:00
|
|
|
static virCPUFeatureDef host_cpu_features[] = {
|
|
|
|
{ (char *) "lahf_lm", -1 },
|
|
|
|
{ (char *) "xtpr", -1 },
|
|
|
|
{ (char *) "cx16", -1 },
|
|
|
|
{ (char *) "tm2", -1 },
|
|
|
|
{ (char *) "est", -1 },
|
|
|
|
{ (char *) "vmx", -1 },
|
|
|
|
{ (char *) "ds_cpl", -1 },
|
|
|
|
{ (char *) "pbe", -1 },
|
|
|
|
{ (char *) "tm", -1 },
|
|
|
|
{ (char *) "ht", -1 },
|
|
|
|
{ (char *) "ss", -1 },
|
|
|
|
{ (char *) "acpi", -1 },
|
|
|
|
{ (char *) "ds", -1 }
|
|
|
|
};
|
|
|
|
static virCPUDef host_cpu = {
|
|
|
|
VIR_CPU_TYPE_HOST, /* type */
|
2011-08-18 10:14:36 +00:00
|
|
|
0, /* mode */
|
2010-04-16 06:01:59 +00:00
|
|
|
0, /* match */
|
2012-12-18 19:32:23 +00:00
|
|
|
VIR_ARCH_X86_64, /* arch */
|
2010-04-16 06:01:59 +00:00
|
|
|
(char *) "core2duo", /* model */
|
2012-06-28 10:21:17 +00:00
|
|
|
NULL, /* vendor_id */
|
2011-12-21 13:27:16 +00:00
|
|
|
0, /* fallback */
|
2010-07-02 15:51:59 +00:00
|
|
|
(char *) "Intel", /* vendor */
|
2010-04-16 06:01:59 +00:00
|
|
|
1, /* sockets */
|
|
|
|
2, /* cores */
|
|
|
|
1, /* threads */
|
|
|
|
ARRAY_CARDINALITY(host_cpu_features), /* nfeatures */
|
2010-08-17 21:41:51 +00:00
|
|
|
ARRAY_CARDINALITY(host_cpu_features), /* nfeatures_max */
|
2012-04-06 02:04:23 +00:00
|
|
|
host_cpu_features, /* features */
|
2010-04-16 06:01:59 +00:00
|
|
|
};
|
2008-05-16 16:51:30 +00:00
|
|
|
|
2011-02-15 14:24:39 +00:00
|
|
|
if ((caps = virCapabilitiesNew(host_cpu.arch,
|
2014-07-14 12:56:13 +00:00
|
|
|
false, false)) == NULL)
|
2008-05-16 16:51:30 +00:00
|
|
|
return NULL;
|
|
|
|
|
2014-09-03 17:06:55 +00:00
|
|
|
/* Add dummy 'none' security_driver. This is equal to setting
|
|
|
|
* security_driver = "none" in qemu.conf. */
|
|
|
|
if (VIR_ALLOC_N(caps->host.secModels, 1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
caps->host.nsecModels = 1;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(caps->host.secModels[0].model, "none") < 0 ||
|
|
|
|
VIR_STRDUP(caps->host.secModels[0].doi, "0") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2010-04-16 06:01:59 +00:00
|
|
|
if ((caps->host.cpu = virCPUDefCopy(&host_cpu)) == NULL ||
|
|
|
|
(machines = testQemuAllocMachines(&nmachines)) == NULL)
|
2009-07-23 17:31:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-12-18 19:32:23 +00:00
|
|
|
if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686,
|
2008-05-16 16:51:30 +00:00
|
|
|
"/usr/bin/qemu", NULL,
|
2011-02-15 14:24:39 +00:00
|
|
|
nmachines, machines)) == NULL ||
|
2014-07-14 12:56:13 +00:00
|
|
|
!virCapabilitiesAddGuestFeature(guest, "cpuselection", true, false))
|
2008-05-16 16:51:30 +00:00
|
|
|
goto cleanup;
|
2009-07-23 17:31:34 +00:00
|
|
|
machines = NULL;
|
|
|
|
|
2008-05-16 16:51:30 +00:00
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"qemu",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
2009-09-10 10:19:12 +00:00
|
|
|
if ((machines = testQemuAllocNewerMachines(&nmachines)) == NULL)
|
2009-07-23 17:31:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-12-18 19:32:23 +00:00
|
|
|
if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64,
|
2008-05-16 16:51:30 +00:00
|
|
|
"/usr/bin/qemu-system-x86_64", NULL,
|
2011-02-15 14:24:39 +00:00
|
|
|
nmachines, machines)) == NULL ||
|
2014-07-14 12:56:13 +00:00
|
|
|
!virCapabilitiesAddGuestFeature(guest, "cpuselection", true, false))
|
2008-05-16 16:51:30 +00:00
|
|
|
goto cleanup;
|
2009-07-23 17:31:34 +00:00
|
|
|
machines = NULL;
|
|
|
|
|
2008-05-16 16:51:30 +00:00
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"qemu",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
goto cleanup;
|
2009-09-10 10:22:32 +00:00
|
|
|
|
|
|
|
if ((machines = testQemuAllocMachines(&nmachines)) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-05-16 16:51:30 +00:00
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"kvm",
|
|
|
|
"/usr/bin/kvm",
|
|
|
|
NULL,
|
2009-09-10 10:22:32 +00:00
|
|
|
nmachines,
|
|
|
|
machines) == NULL)
|
2008-05-16 16:51:30 +00:00
|
|
|
goto cleanup;
|
2009-09-10 10:22:32 +00:00
|
|
|
machines = NULL;
|
2008-05-16 16:51:30 +00:00
|
|
|
|
2009-09-10 09:16:27 +00:00
|
|
|
nmachines = ARRAY_CARDINALITY(xen_machines);
|
2009-07-23 17:31:34 +00:00
|
|
|
if ((machines = virCapabilitiesAllocMachines(xen_machines, nmachines)) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-12-18 19:32:23 +00:00
|
|
|
if ((guest = virCapabilitiesAddGuest(caps, "xen", VIR_ARCH_X86_64,
|
2008-05-16 16:51:30 +00:00
|
|
|
"/usr/bin/xenner", NULL,
|
2009-09-10 09:16:27 +00:00
|
|
|
nmachines, machines)) == NULL)
|
2008-05-16 16:51:30 +00:00
|
|
|
goto cleanup;
|
2009-07-23 17:31:34 +00:00
|
|
|
machines = NULL;
|
|
|
|
|
2008-05-16 16:51:30 +00:00
|
|
|
if (virCapabilitiesAddGuestDomain(guest,
|
|
|
|
"kvm",
|
|
|
|
"/usr/bin/kvm",
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL) == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
2011-12-12 23:39:33 +00:00
|
|
|
if (testQemuAddPPC64Guest(caps))
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-03-14 04:49:43 +00:00
|
|
|
if (testQemuAddPPCGuest(caps))
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-06-29 15:02:07 +00:00
|
|
|
if (testQemuAddS390Guest(caps))
|
|
|
|
goto cleanup;
|
|
|
|
|
2013-07-30 19:41:14 +00:00
|
|
|
if (testQemuAddArmGuest(caps))
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-01-02 10:42:56 +00:00
|
|
|
if (testQemuAddAARCH64Guest(caps))
|
|
|
|
goto cleanup;
|
|
|
|
|
2009-11-30 19:01:31 +00:00
|
|
|
if (virTestGetDebug()) {
|
2009-09-10 10:07:20 +00:00
|
|
|
char *caps_str;
|
|
|
|
|
|
|
|
caps_str = virCapabilitiesFormatXML(caps);
|
|
|
|
if (!caps_str)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
fprintf(stderr, "QEMU driver capabilities:\n%s", caps_str);
|
|
|
|
|
|
|
|
VIR_FREE(caps_str);
|
|
|
|
}
|
|
|
|
|
2008-05-16 16:51:30 +00:00
|
|
|
return caps;
|
|
|
|
|
2014-03-25 06:53:44 +00:00
|
|
|
cleanup:
|
2009-07-23 17:31:34 +00:00
|
|
|
virCapabilitiesFreeMachines(machines, nmachines);
|
2013-02-01 12:26:18 +00:00
|
|
|
virObjectUnref(caps);
|
2008-05-16 16:51:30 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2013-05-17 10:34:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
static char *
|
2014-01-30 07:05:59 +00:00
|
|
|
testSCSIDeviceGetSgName(const char *sysfs_prefix ATTRIBUTE_UNUSED,
|
|
|
|
const char *adapter ATTRIBUTE_UNUSED,
|
2013-05-17 10:34:24 +00:00
|
|
|
unsigned int bus ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int target ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int unit ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
char *sg = NULL;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(sg, "sg0") < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return sg;
|
|
|
|
}
|
|
|
|
|
|
|
|
qemuBuildCommandLineCallbacks testCallbacks = {
|
|
|
|
.qemuGetSCSIDeviceSgName = testSCSIDeviceGetSgName,
|
|
|
|
};
|
2014-06-27 14:39:27 +00:00
|
|
|
|
|
|
|
virQEMUCapsPtr
|
|
|
|
qemuTestParseCapabilities(const char *capsFile)
|
|
|
|
{
|
|
|
|
virQEMUCapsPtr qemuCaps = NULL;
|
|
|
|
xmlDocPtr xml;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
ssize_t i, n;
|
|
|
|
xmlNodePtr *nodes = NULL;
|
|
|
|
|
|
|
|
if (!(xml = virXMLParseFileCtxt(capsFile, &ctxt)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if ((n = virXPathNodeSet("/qemuCaps/flag", ctxt, &nodes)) < 0) {
|
|
|
|
fprintf(stderr, "failed to parse qemu capabilities flags");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n > 0) {
|
|
|
|
if (!(qemuCaps = virQEMUCapsNew()))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
char *str = virXMLPropString(nodes[i], "name");
|
|
|
|
if (str) {
|
|
|
|
int flag = virQEMUCapsTypeFromString(str);
|
|
|
|
if (flag < 0) {
|
|
|
|
fprintf(stderr, "Unknown qemu capabilities flag %s", str);
|
|
|
|
VIR_FREE(str);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(str);
|
|
|
|
virQEMUCapsSet(qemuCaps, flag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(nodes);
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
return qemuCaps;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(nodes);
|
|
|
|
virObjectUnref(qemuCaps);
|
|
|
|
xmlFreeDoc(xml);
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-06-26 09:37:51 +00:00
|
|
|
#endif
|