This patch refactors the Xen, QEMU and Test drivers to use the new API for dealing with capabilities data. Xen: the code for turning NUMA SEXPR into XML previously split between the xml.c and xend_internal.c file. Since the capabilities APIs now deal with all XML generation, the only code remaining is parsing the SEXPR and calling the appropriate capabilities API. So the stuff from xml.c was moved into the xend_internal.c file and simplified significantly. The xen_internal.c code for generating the domain capabilities XML from XenD capabilities strings has been changed to just call virCapabilitiesAddXXXX and then just do an API call to the resulting virCapsPtr object to XML. The Xen capabilities test suite data files needing some minor edits to deal with enhanced data for Xen. In particular the paravirt guests info now has an <emulator> tag present, since this config param is not HVM specific. There is also some whitespace change / element re-ordering. It also fixes the machine list to match actual Xen usage. It also fixes the bug where 32-on-64 guests would be given /usr/lib/xen instead of the correct /usr/lib64/xen path for the emulator QEMU: the code in qemu_driver.c no longer does anything wrt to formatting XML. It simply invokes the appropriate API to turn virCapsPtr into an XML document. The virCapsPtr object is built when the QEMU driver first starts up by calling qemudCapsInit() in qemud_conf.c. This code is much more dynamic and will check for presence of KVM, KQEMU and validate the presence of each QEMU binary. It also adds support for Xenner which lets you run Xen paravirt guests under KVM. This requires /dev/kvm and a copy of /usr/bin/xenner - the latter is ARGV compatible with QEMU, so no other QEMU driver changes are needed. An application (such as virt-install) using capabilities XML should see presence of Xenner in the XML and just do the right thing automatically. src/qemu_conf.c | 248 +++++++++++++++++++++--------- src/qemu_conf.h | 19 -- src/qemu_driver.c | 193 +---------------------- src/test.c | 89 ++++++----- src/util.c | 51 ++++++ src/util.h | 4 src/xen_internal.c | 267 ++++++++++++++++----------------- src/xend_internal.c | 110 +++++++++---- src/xend_internal.h | 4 src/xml.c | 169 -------------------- src/xml.h | 4 tests/qemuxml2argvtest.c | 4 tests/qemuxml2xmltest.c | 4 tests/xencapsdata/xen-i686-pae-hvm.xml | 17 +- tests/xencapsdata/xen-i686-pae.xml | 9 - tests/xencapsdata/xen-i686.xml | 11 - tests/xencapsdata/xen-ia64-be-hvm.xml | 21 +- tests/xencapsdata/xen-ia64-be.xml | 11 - tests/xencapsdata/xen-ia64-hvm.xml | 23 +- tests/xencapsdata/xen-ia64.xml | 13 - tests/xencapsdata/xen-ppc64.xml | 13 - tests/xencapsdata/xen-x86_64-hvm.xml | 29 +-- tests/xencapsdata/xen-x86_64.xml | 11 - tests/xencapstest.c | 3 24 files changed, 624 insertions(+), 703 deletions(-) Dan Index: src/qemu_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_conf.c,v retrieving revision 1.37 diff -u -p -r1.37 qemu_conf.c --- src/qemu_conf.c 22 Feb 2008 15:55:04 -0000 1.37 +++ src/qemu_conf.c 26 Feb 2008 04:47:03 -0000 @@ -232,102 +232,184 @@ void qemudFreeVM(struct qemud_vm *vm) { /* The list of possible machine types for various architectures, as supported by QEMU - taken from 'qemu -M ?' for each arch */ -static const char *const arch_info_x86_machines[] = { - "pc", "isapc", NULL +static const char *const arch_info_hvm_x86_machines[] = { + "pc", "isapc" }; -static const char *const arch_info_mips_machines[] = { - "mips", NULL +static const char *const arch_info_hvm_mips_machines[] = { + "mips" }; -static const char *const arch_info_sparc_machines[] = { - "sun4m", NULL +static const char *const arch_info_hvm_sparc_machines[] = { + "sun4m" }; -static const char *const arch_info_ppc_machines[] = { - "g3bw", "mac99", "prep", NULL +static const char *const arch_info_hvm_ppc_machines[] = { + "g3bw", "mac99", "prep" +}; + +static const char *const arch_info_xen_x86_machines[] = { + "xenner" +}; + +struct qemu_feature_flags { + const char *name; + const int default_on; + const int toggle; +}; + +struct qemu_arch_info { + const char *arch; + int wordsize; + const char *const *machines; + int nmachines; + const char *binary; + const struct qemu_feature_flags *flags; + int nflags; }; /* Feature flags for the architecture info */ static const struct qemu_feature_flags const arch_info_i686_flags [] = { - { "pae", 1, 1 }, + { "pae", 1, 0 }, + { "nonpae", 1, 0 }, { "acpi", 1, 1 }, { "apic", 1, 0 }, - { NULL, -1, -1 } }; static const struct qemu_feature_flags const arch_info_x86_64_flags [] = { { "acpi", 1, 1 }, { "apic", 1, 0 }, - { NULL, -1, -1 } }; /* The archicture tables for supported QEMU archs */ -const struct qemu_arch_info const qemudArchs[] = { - /* i686 must be in position 0 */ - { "i686", 32, arch_info_x86_machines, "qemu", arch_info_i686_flags }, - /* x86_64 must be in position 1 */ - { "x86_64", 64, arch_info_x86_machines, "qemu-system-x86_64", arch_info_x86_64_flags }, - { "mips", 32, arch_info_mips_machines, "qemu-system-mips", NULL }, - { "mipsel", 32, arch_info_mips_machines, "qemu-system-mipsel", NULL }, - { "sparc", 32, arch_info_sparc_machines, "qemu-system-sparc", NULL }, - { "ppc", 32, arch_info_ppc_machines, "qemu-system-ppc", NULL }, - { NULL, -1, NULL, NULL, NULL } +static const struct qemu_arch_info const arch_info_hvm[] = { + { "i686", 32, arch_info_hvm_x86_machines, 2, + "/usr/bin/qemu", arch_info_i686_flags, 4 }, + { "x86_64", 64, arch_info_hvm_x86_machines, 2, + "/usr/bin/qemu-system-x86_64", arch_info_x86_64_flags, 2 }, + { "mips", 32, arch_info_hvm_mips_machines, 1, + "/usr/bin/qemu-system-mips", NULL, 0 }, + { "mipsel", 32, arch_info_hvm_mips_machines, 1, + "/usr/bin/qemu-system-mipsel", NULL, 0 }, + { "sparc", 32, arch_info_hvm_sparc_machines, 1, + "/usr/bin/qemu-system-sparc", NULL, 0 }, + { "ppc", 32, arch_info_hvm_ppc_machines, 3, + "/usr/bin/qemu-system-ppc", NULL, 0 }, }; -/* Return the default architecture if none is explicitly requested*/ -static const char *qemudDefaultArch(void) { - return qemudArchs[0].arch; -} +static const struct qemu_arch_info const arch_info_xen[] = { + { "i686", 32, arch_info_xen_x86_machines, 1, + "/usr/bin/xenner", arch_info_i686_flags, 4 }, + { "x86_64", 64, arch_info_xen_x86_machines, 1, + "/usr/bin/xenner", arch_info_x86_64_flags, 2 }, +}; -/* Return the default machine type for a given architecture */ -static const char *qemudDefaultMachineForArch(const char *arch) { +static int +qemudCapsInitGuest(virCapsPtr caps, + const char *hostmachine, + const struct qemu_arch_info *info, + int hvm) { + virCapsGuestPtr guest; int i; - for (i = 0; qemudArchs[i].arch; i++) { - if (!strcmp(qemudArchs[i].arch, arch)) { - return qemudArchs[i].machines[0]; - } - } + if ((guest = virCapabilitiesAddGuest(caps, + hvm ? "hvm" : "xen", + info->arch, + info->wordsize, + info->binary, + NULL, + info->nmachines, + info->machines)) == NULL) + return -1; - return NULL; -} + if (hvm) { + /* Check for existance of base emulator */ + if (access(info->binary, X_OK) == 0 && + virCapabilitiesAddGuestDomain(guest, + "qemu", + NULL, + NULL, + 0, + NULL) == NULL) + return -1; -/* Return the default binary name for a particular architecture */ -static const char *qemudDefaultBinaryForArch(const char *arch) { - int i; + /* If guest & host match, then we can accelerate */ + if (STREQ(info->arch, hostmachine)) { + if (access("/dev/kqemu", F_OK) == 0 && + virCapabilitiesAddGuestDomain(guest, + "kqemu", + NULL, + NULL, + 0, + NULL) == NULL) + return -1; + + if (access("/dev/kvm", F_OK) == 0 && + virCapabilitiesAddGuestDomain(guest, + "kvm", + "/usr/bin/qemu-kvm", + NULL, + 0, + NULL) == NULL) + return -1; + } + } else { + if (virCapabilitiesAddGuestDomain(guest, + "kvm", + NULL, + NULL, + 0, + NULL) == NULL) + return -1; + } - for (i = 0 ; qemudArchs[i].arch; i++) { - if (!strcmp(qemudArchs[i].arch, arch)) { - return qemudArchs[i].binary; + if (info->nflags) { + for (i = 0 ; i < info->nflags ; i++) { + if (virCapabilitiesAddGuestFeature(guest, + info->flags[i].name, + info->flags[i].default_on, + info->flags[i].toggle) == NULL) + return -1; } } - return NULL; + return 0; } -/* Find the fully qualified path to the binary for an architecture */ -static char *qemudLocateBinaryForArch(virConnectPtr conn, - int virtType, const char *arch) { - const char *name; - char *path; +virCapsPtr qemudCapsInit(void) { + struct utsname utsname; + virCapsPtr caps; + int i; - if (virtType == QEMUD_VIRT_KVM) - name = "qemu-kvm"; - else - name = qemudDefaultBinaryForArch(arch); + /* Really, this never fails - look at the man-page. */ + uname (&utsname); - if (!name) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot determin binary for architecture %s", arch); - return NULL; - } + if ((caps = virCapabilitiesNew(utsname.machine, + 0, 0)) == NULL) + goto no_memory; - /* XXX lame. should actually use $PATH ... */ - path = malloc(strlen(name) + strlen("/usr/bin/") + 1); - if (!path) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "path"); - return NULL; + for (i = 0 ; i < (sizeof(arch_info_hvm)/sizeof(arch_info_hvm[0])) ; i++) + if (qemudCapsInitGuest(caps, + utsname.machine, + &arch_info_hvm[i], 1) < 0) + goto no_memory; + + if (access("/usr/bin/xenner", X_OK) == 0 && + access("/dev/kvm", F_OK) == 0) { + for (i = 0 ; i < (sizeof(arch_info_xen)/sizeof(arch_info_xen[0])) ; i++) + /* Allow Xen 32-on-32, 32-on-64 and 64-on-64 */ + if (STREQ(arch_info_xen[i].arch, utsname.machine) || + (STREQ(utsname.machine, "x86_64") && + STREQ(arch_info_xen[i].arch, "i686"))) { + if (qemudCapsInitGuest(caps, + utsname.machine, + &arch_info_xen[i], 0) < 0) + goto no_memory; + } } - strcpy(path, "/usr/bin/"); - strcat(path, name); - return path; + + return caps; + + no_memory: + virCapabilitiesFree(caps); + return NULL; } @@ -429,31 +511,31 @@ static int qemudExtractVersionInfo(const } int qemudExtractVersion(virConnectPtr conn, - struct qemud_driver *driver ATTRIBUTE_UNUSED) { - char *binary = NULL; + struct qemud_driver *driver) { + const char *binary; struct stat sb; int ignored; if (driver->qemuVersion > 0) return 0; - if (!(binary = qemudLocateBinaryForArch(conn, QEMUD_VIRT_QEMU, "i686"))) + if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps, + "hvm", + "i686", + "qemu")) == NULL) return -1; if (stat(binary, &sb) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "Cannot find QEMU binary %s: %s", binary, strerror(errno)); - free(binary); return -1; } if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) { - free(binary); return -1; } - free(binary); return 0; } @@ -1086,7 +1168,7 @@ static struct qemud_vm_def *qemudParseXM qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE, NULL); goto error; } - if (strcmp((const char *)obj->stringval, "hvm")) { + if (!virCapabilitiesSupportsGuestOSType(driver->caps, (const char*)obj->stringval)) { qemudReportError(conn, NULL, NULL, VIR_ERR_OS_TYPE, "%s", obj->stringval); goto error; } @@ -1097,7 +1179,11 @@ static struct qemud_vm_def *qemudParseXM obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@arch)", ctxt); if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - const char *defaultArch = qemudDefaultArch(); + const char *defaultArch = virCapabilitiesDefaultGuestArch(driver->caps, def->os.type); + if (defaultArch == NULL) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported architecture"); + goto error; + } if (strlen(defaultArch) >= (QEMUD_OS_TYPE_MAX_LEN-1)) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "architecture type too long"); goto error; @@ -1115,9 +1201,11 @@ static struct qemud_vm_def *qemudParseXM obj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1]/@machine)", ctxt); if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - const char *defaultMachine = qemudDefaultMachineForArch(def->os.arch); - if (!defaultMachine) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "unsupported arch %s", def->os.arch); + const char *defaultMachine = virCapabilitiesDefaultGuestMachine(driver->caps, + def->os.type, + def->os.arch); + if (defaultMachine == NULL) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported architecture"); goto error; } if (strlen(defaultMachine) >= (QEMUD_OS_MACHINE_MAX_LEN-1)) { @@ -1205,12 +1293,18 @@ static struct qemud_vm_def *qemudParseXM obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt); if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - char *tmp = qemudLocateBinaryForArch(conn, def->virtType, def->os.arch); - if (!tmp) { + const char *type = (def->virtType == QEMUD_VIRT_QEMU ? "qemu" : + def->virtType == QEMUD_VIRT_KQEMU ? "kqemu": + "kvm"); + const char *emulator = virCapabilitiesDefaultGuestEmulator(driver->caps, + def->os.type, + def->os.arch, + type); + if (!emulator) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "unsupported guest type"); goto error; } - strcpy(def->os.binary, tmp); - free(tmp); + strcpy(def->os.binary, emulator); } else { if (strlen((const char *)obj->stringval) >= (PATH_MAX-1)) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", "emulator path too long"); Index: src/qemu_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/qemu_conf.h,v retrieving revision 1.17 diff -u -p -r1.17 qemu_conf.h --- src/qemu_conf.h 29 Jan 2008 18:15:54 -0000 1.17 +++ src/qemu_conf.h 26 Feb 2008 04:47:03 -0000 @@ -31,6 +31,7 @@ #include "internal.h" #include "bridge.h" #include "iptables.h" +#include "capabilities.h" #include <netinet/in.h> #define qemudDebug(fmt, ...) do {} while(0) @@ -314,6 +315,8 @@ struct qemud_driver { unsigned int vncTLSx509verify : 1; char *vncTLSx509certdir; char vncListen[BR_INET_ADDR_MAXLEN]; + + virCapsPtr caps; }; @@ -351,6 +354,8 @@ struct qemud_network *qemudFindNetworkBy struct qemud_network *qemudFindNetworkByName(const struct qemud_driver *driver, const char *name); +virCapsPtr qemudCapsInit (void); + int qemudExtractVersion (virConnectPtr conn, struct qemud_driver *driver); int qemudBuildCommandLine (virConnectPtr conn, @@ -418,20 +423,6 @@ char * qemudGenerateNetworkXML struct qemud_network *network, struct qemud_network_def *def); -struct qemu_feature_flags { - const char *name; - const int default_on; - const int toggle; -}; - -struct qemu_arch_info { - const char *arch; - int wordsize; - const char *const *machines; - const char *binary; - const struct qemu_feature_flags *fflags; -}; -extern const struct qemu_arch_info const qemudArchs[]; #endif /* WITH_QEMU */ Index: src/qemu_driver.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_driver.c,v retrieving revision 1.54 diff -u -p -r1.54 qemu_driver.c --- src/qemu_driver.c 22 Feb 2008 16:26:13 -0000 1.54 +++ src/qemu_driver.c 26 Feb 2008 04:47:05 -0000 @@ -56,6 +56,7 @@ #include "qemu_conf.h" #include "nodeinfo.h" #include "stats_linux.h" +#include "capabilities.h" static int qemudShutdown(void); @@ -211,6 +212,10 @@ qemudStartup(void) { goto out_of_memory; free(base); + base = NULL; + + if ((qemu_driver->caps = qemudCapsInit()) == NULL) + goto out_of_memory; if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) { qemudShutdown(); @@ -294,6 +299,8 @@ qemudShutdown(void) { if (!qemu_driver) return -1; + virCapabilitiesFree(qemu_driver->caps); + /* shutdown active VMs */ vm = qemu_driver->vms; while (vm) { @@ -1456,191 +1463,17 @@ static int qemudGetNodeInfo(virConnectPt return virNodeInfoPopulate(conn, nodeinfo); } -static int qemudGetFeatures(virBufferPtr xml, - const struct qemu_feature_flags *flags) { - int i, r; - - if (flags == NULL) - return 0; - r = virBufferAddLit(xml, "\ - <features>\n"); - if (r == -1) return r; - for (i = 0; flags[i].name; ++i) { - if (STREQ(flags[i].name, "pae")) { - int pae = flags[i].default_on || flags[i].toggle; - int nonpae = flags[i].toggle; - if (pae) { - r = virBufferAddLit(xml, " <pae/>\n"); - if (r == -1) return r; - } - if (nonpae) { - r = virBufferAddLit(xml, " <nonpae/>\n"); - if (r == -1) return r; - } - } else { - r = virBufferVSprintf(xml, " <%s default='%s' toggle='%s'/>\n", - flags[i].name, - flags[i].default_on ? "on" : "off", - flags[i].toggle ? "yes" : "no"); - if (r == -1) return r; - } - } - r = virBufferAddLit(xml, " </features>\n"); - return r; -} - -static char *qemudGetCapabilities(virConnectPtr conn ATTRIBUTE_UNUSED) { - struct utsname utsname; - int i, j, r; - int have_kqemu = 0; - int have_kvm = 0; - virBufferPtr xml; - - /* Really, this never fails - look at the man-page. */ - uname (&utsname); - - have_kqemu = access ("/dev/kqemu", F_OK) == 0; - have_kvm = access ("/dev/kvm", F_OK) == 0; +static char *qemudGetCapabilities(virConnectPtr conn) { + struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + char *xml; - /* Construct the XML. */ - xml = virBufferNew (1024); - if (!xml) { - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) { + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "capabilities"); return NULL; } - r = virBufferVSprintf (xml, - "\ -<capabilities>\n\ - <host>\n\ - <cpu>\n\ - <arch>%s</arch>\n\ - </cpu>\n\ - </host>\n", - utsname.machine); - if (r == -1) { - vir_buffer_failed: - virBufferFree (xml); - qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); - return NULL; - } - - i = -1; - if (strcmp (utsname.machine, "i686") == 0) i = 0; - else if (strcmp (utsname.machine, "x86_64") == 0) i = 1; - if (i >= 0) { - /* For the default (PC-like) guest, qemudArchs[0] or [1]. */ - r = virBufferVSprintf (xml, - "\ -\n\ - <guest>\n\ - <os_type>hvm</os_type>\n\ - <arch name=\"%s\">\n\ - <wordsize>%d</wordsize>\n\ - <emulator>/usr/bin/%s</emulator>\n\ - <domain type=\"qemu\"/>\n", - qemudArchs[i].arch, - qemudArchs[i].wordsize, - qemudArchs[i].binary); - if (r == -1) goto vir_buffer_failed; - - for (j = 0; qemudArchs[i].machines[j]; ++j) { - r = virBufferVSprintf (xml, - "\ - <machine>%s</machine>\n", - qemudArchs[i].machines[j]); - if (r == -1) goto vir_buffer_failed; - } - - if (have_kqemu) { - r = virBufferAddLit (xml, - "\ - <domain type=\"kqemu\"/>\n"); - if (r == -1) goto vir_buffer_failed; - } - if (have_kvm) { - r = virBufferAddLit (xml, - "\ - <domain type=\"kvm\">\n\ - <emulator>/usr/bin/qemu-kvm</emulator>\n\ - </domain>\n"); - if (r == -1) goto vir_buffer_failed; - } - r = virBufferAddLit (xml, " </arch>\n"); - if (r == -1) goto vir_buffer_failed; - - r = qemudGetFeatures(xml, qemudArchs[i].fflags); - if (r == -1) goto vir_buffer_failed; - - r = virBufferAddLit (xml, " </guest>\n"); - if (r == -1) goto vir_buffer_failed; - - /* The "other" PC architecture needs emulation. */ - i = i ^ 1; - r = virBufferVSprintf (xml, - "\ -\n\ - <guest>\n\ - <os_type>hvm</os_type>\n\ - <arch name=\"%s\">\n\ - <wordsize>%d</wordsize>\n\ - <emulator>/usr/bin/%s</emulator>\n\ - <domain type=\"qemu\"/>\n", - qemudArchs[i].arch, - qemudArchs[i].wordsize, - qemudArchs[i].binary); - if (r == -1) goto vir_buffer_failed; - for (j = 0; qemudArchs[i].machines[j]; ++j) { - r = virBufferVSprintf (xml, - "\ - <machine>%s</machine>\n", - qemudArchs[i].machines[j]); - if (r == -1) goto vir_buffer_failed; - } - r = virBufferAddLit (xml, " </arch>\n </guest>\n"); - if (r == -1) goto vir_buffer_failed; - } - - /* The non-PC architectures, qemudArchs[>=2]. */ - for (i = 2; qemudArchs[i].arch; ++i) { - r = virBufferVSprintf (xml, - "\ -\n\ - <guest>\n\ - <os_type>hvm</os_type>\n\ - <arch name=\"%s\">\n\ - <wordsize>%d</wordsize>\n\ - <emulator>/usr/bin/%s</emulator>\n\ - <domain type=\"qemu\"/>\n", - qemudArchs[i].arch, - qemudArchs[i].wordsize, - qemudArchs[i].binary); - if (r == -1) goto vir_buffer_failed; - for (j = 0; qemudArchs[i].machines[j]; ++j) { - r = virBufferVSprintf (xml, - "\ - <machine>%s</machine>\n", - qemudArchs[i].machines[j]); - if (r == -1) goto vir_buffer_failed; - } - r = virBufferAddLit (xml, " </arch>\n"); - if (r == -1) goto vir_buffer_failed; - - r = qemudGetFeatures(xml, qemudArchs[i].fflags); - if (r == -1) goto vir_buffer_failed; - - r = virBufferAddLit (xml, " </guest>\n"); - if (r == -1) goto vir_buffer_failed; - } - - /* Finish off. */ - r = virBufferAddLit (xml, - "\ -</capabilities>\n"); - if (r == -1) goto vir_buffer_failed; - - return virBufferContentAndFree(xml); + return xml; } Index: src/test.c =================================================================== RCS file: /data/cvs/libvirt/src/test.c,v retrieving revision 1.66 diff -u -p -r1.66 test.c --- src/test.c 22 Feb 2008 15:55:04 -0000 1.66 +++ src/test.c 26 Feb 2008 04:47:06 -0000 @@ -44,6 +44,7 @@ #include "buf.h" #include "util.h" #include "uuid.h" +#include "capabilities.h" /* Flags that determine the action to take on a shutdown or crash of a domain */ @@ -119,7 +120,7 @@ typedef struct _testConn testConn; typedef struct _testConn *testConnPtr; #define TEST_MODEL "i686" -#define TEST_MODEL_WORDSIZE "32" +#define TEST_MODEL_WORDSIZE 32 static const virNodeInfo defaultNodeInfo = { TEST_MODEL, @@ -978,38 +979,60 @@ static int testNodeGetInfo(virConnectPtr static char *testGetCapabilities (virConnectPtr conn) { - static char caps[] = "\ -<capabilities>\n\ - <host>\n\ - <cpu>\n\ - <arch>" TEST_MODEL "</arch>\n\ - <features>\n\ - <pae/>\n\ - <nonpae/>\n\ - </features>\n\ - </cpu>\n\ - </host>\n\ -\n\ - <guest>\n\ - <os_type>linux</os_type>\n\ - <arch name=\"" TEST_MODEL "\">\n\ - <wordsize>" TEST_MODEL_WORDSIZE "</wordsize>\n\ - <domain type=\"test\"/>\n\ - </arch>\n\ - <features>\n\ - <pae/>\n\ - <nonpae/>\n\ - </features>\n\ - </guest>\n\ -</capabilities>\n\ -"; - - char *caps_copy = strdup (caps); - if (!caps_copy) { - testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__); - return NULL; - } - return caps_copy; + virCapsPtr caps; + virCapsGuestPtr guest; + char *xml; + int cell1[] = { 0, 2, 4, 6, 8, 10, 12, 14 }; + int cell2[] = { 1, 3, 5, 7, 9, 11, 13, 15 }; + + if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL) + goto no_memory; + + if (virCapabilitiesAddHostFeature(caps, "pae") < 0) + goto no_memory; + if (virCapabilitiesAddHostFeature(caps ,"nonpae") < 0) + goto no_memory; + + if (virCapabilitiesAddHostNUMACell(caps, 0, 8, cell1) < 0) + goto no_memory; + if (virCapabilitiesAddHostNUMACell(caps, 1, 8, cell2) < 0) + goto no_memory; + + if ((guest = virCapabilitiesAddGuest(caps, + "linux", + TEST_MODEL, + TEST_MODEL_WORDSIZE, + NULL, + NULL, + 0, + NULL)) == NULL) + goto no_memory; + + if (virCapabilitiesAddGuestDomain(guest, + "test", + NULL, + NULL, + 0, + NULL) == NULL) + goto no_memory; + + + if (virCapabilitiesAddGuestFeature(guest, "pae", 1, 1) == NULL) + goto no_memory; + if (virCapabilitiesAddGuestFeature(guest ,"nonpae", 1, 1) == NULL) + goto no_memory; + + if ((xml = virCapabilitiesFormatXML(caps)) == NULL) + goto no_memory; + + virCapabilitiesFree(caps); + + return xml; + + no_memory: + virCapabilitiesFree(caps); + testError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__); + return NULL; } static int testNumOfDomains(virConnectPtr conn) Index: src/util.c =================================================================== RCS file: /data/cvs/libvirt/src/util.c,v retrieving revision 1.21 diff -u -p -r1.21 util.c --- src/util.c 22 Feb 2008 15:53:13 -0000 1.21 +++ src/util.c 26 Feb 2008 04:47:07 -0000 @@ -593,6 +593,57 @@ __virStrToLong_ull(char const *s, char * return 0; } + +/** + * 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: * indent-tabs-mode: nil Index: src/util.h =================================================================== RCS file: /data/cvs/libvirt/src/util.h,v retrieving revision 1.10 diff -u -p -r1.10 util.h --- src/util.h 22 Feb 2008 15:53:13 -0000 1.10 +++ src/util.h 26 Feb 2008 04:47:07 -0000 @@ -76,4 +76,8 @@ int __virStrToLong_ull(char const *s, unsigned long long *result); #define virStrToLong_ull(s,e,b,r) __virStrToLong_ull((s),(e),(b),(r)) +void virSkipSpaces(const char **str); +int virParseNumber(const char **str); + + #endif /* __VIR_UTIL_H__ */ Index: src/xen_internal.c =================================================================== RCS file: /data/cvs/libvirt/src/xen_internal.c,v retrieving revision 1.112 diff -u -p -r1.112 xen_internal.c --- src/xen_internal.c 7 Feb 2008 10:43:14 -0000 1.112 +++ src/xen_internal.c 26 Feb 2008 04:47:09 -0000 @@ -47,6 +47,7 @@ #include <xen/sched.h> #include "buf.h" +#include "capabilities.h" /* #define DEBUG */ /* @@ -2154,6 +2155,121 @@ xenHypervisorGetVersion(virConnectPtr co return(0); } +struct guest_arch { + const char *model; + int bits; + int hvm; + int pae; + int nonpae; + int ia64_be; +}; + + +static virCapsPtr +xenHypervisorBuildCapabilities(virConnectPtr conn, + const char *hostmachine, + int host_pae, + char *hvm_type, + struct guest_arch *guest_archs, + int nr_guest_archs) { + virCapsPtr caps; + int i; + int hv_major = hv_version >> 16; + int hv_minor = hv_version & 0xFFFF; + + if ((caps = virCapabilitiesNew(hostmachine, 1, 1)) == NULL) + goto no_memory; + if (hvm_type && STRNEQ(hvm_type, "") && + virCapabilitiesAddHostFeature(caps, hvm_type) < 0) + goto no_memory; + if (host_pae && + virCapabilitiesAddHostFeature(caps, "pae") < 0) + goto no_memory; + + + if (virCapabilitiesAddHostMigrateTransport(caps, + "xenmigr") < 0) + goto no_memory; + + + if (sys_interface_version >= 4) { + if (xenDaemonNodeGetTopology(conn, caps) != 0) { + virCapabilitiesFree(caps); + return NULL; + } + } + + for (i = 0; i < nr_guest_archs; ++i) { + virCapsGuestPtr guest; + const char const *machines[] = { guest_archs[i].hvm ? "xenfv" : "xenpv" }; + + if ((guest = virCapabilitiesAddGuest(caps, + guest_archs[i].hvm ? "hvm" : "xen", + guest_archs[i].model, + guest_archs[i].bits, + (STREQ(hostmachine, "x86_64") ? + "/usr/lib64/xen/bin/qemu-dm" : + "/usr/lib/xen/bin/qemu-dm"), + (guest_archs[i].hvm ? + "/usr/lib/xen/boot/hvmloader" : + NULL), + 1, + machines)) == NULL) + goto no_memory; + + if (virCapabilitiesAddGuestDomain(guest, + "xen", + NULL, + NULL, + 0, + NULL) == NULL) + goto no_memory; + + if (guest_archs[i].pae && + virCapabilitiesAddGuestFeature(guest, + "pae", + 1, + 0) == NULL) + goto no_memory; + + if (guest_archs[i].nonpae && + virCapabilitiesAddGuestFeature(guest, + "nonpae", + 1, + 0) == NULL) + goto no_memory; + + if (guest_archs[i].ia64_be && + virCapabilitiesAddGuestFeature(guest, + "ia64_be", + 1, + 0) == NULL) + goto no_memory; + + if (guest_archs[i].hvm) { + if (virCapabilitiesAddGuestFeature(guest, + "acpi", + 1, 1) == NULL) + goto no_memory; + + // In Xen 3.1.0, APIC is always on and can't be toggled + if (virCapabilitiesAddGuestFeature(guest, + "apic", + 1, + (hv_major > 3 && + hv_minor > 0 ? + 0 : 1)) == NULL) + goto no_memory; + } + } + + return caps; + + no_memory: + virCapabilitiesFree(caps); + return NULL; +} + /** * xenHypervisorGetCapabilities: * @conn: pointer to the connection block @@ -2170,25 +2286,17 @@ xenHypervisorMakeCapabilitiesXML(virConn char line[1024], *str, *token; regmatch_t subs[4]; char *saveptr = NULL; - int i, r, topology; + int i; char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */ int host_pae = 0; - struct guest_arch { - const char *model; - int bits; - int hvm; - int pae; - int nonpae; - int ia64_be; - } guest_archs[32]; + struct guest_arch guest_archs[32]; int nr_guest_archs = 0; - virBufferPtr xml; - char *xml_str; + char *xml; - int hv_major = hv_version >> 16; - int hv_minor = hv_version & 0xFFFF; + + virCapsPtr caps = NULL; memset(guest_archs, 0, sizeof(guest_archs)); @@ -2306,129 +2414,22 @@ xenHypervisorMakeCapabilitiesXML(virConn } } - /* Construct the final XML. */ - xml = virBufferNew (1024); - if (!xml) { - virXenError(conn, VIR_ERR_NO_MEMORY, __FUNCTION__, 0); - return NULL; - } - r = virBufferVSprintf (xml, - "\ -<capabilities>\n\ - <host>\n\ - <cpu>\n\ - <arch>%s</arch>\n\ - <features>\n", - hostmachine); - if (r == -1) goto vir_buffer_failed; - - if (strcmp (hvm_type, "") != 0) { - r = virBufferVSprintf (xml, - "\ - <%s/>\n", - hvm_type); - if (r == -1) goto vir_buffer_failed; - } - if (host_pae) { - r = virBufferAddLit (xml, "\ - <pae/>\n"); - if (r == -1) goto vir_buffer_failed; - } - r = virBufferAddLit (xml, - "\ - </features>\n\ - </cpu>\n\ - <migration_features>\n\ - <live/>\n\ - <uri_transports>\n\ - <uri_transport>xenmigr</uri_transport>\n\ - </uri_transports>\n\ - </migration_features>\n\ - </host>\n"); - if (r == -1) goto vir_buffer_failed; - - if (sys_interface_version >= 4) { - topology = xenDaemonNodeGetTopology(conn, xml); - if (topology != 0) - goto topology_failed; - } + if ((caps = xenHypervisorBuildCapabilities(conn, + hostmachine, + host_pae, + hvm_type, + guest_archs, + nr_guest_archs)) == NULL) + goto no_memory; + if ((xml = virCapabilitiesFormatXML(caps)) == NULL) + goto no_memory; - 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; + virCapabilitiesFree(caps); + return xml; - vir_buffer_failed: + no_memory: virXenError(conn, VIR_ERR_NO_MEMORY, __FUNCTION__, 0); - topology_failed: - virBufferFree (xml); + virCapabilitiesFree(caps); return NULL; } Index: src/xend_internal.c =================================================================== RCS file: /data/cvs/libvirt/src/xend_internal.c,v retrieving revision 1.171 diff -u -p -r1.171 xend_internal.c --- src/xend_internal.c 20 Feb 2008 15:29:13 -0000 1.171 +++ src/xend_internal.c 26 Feb 2008 04:47:11 -0000 @@ -39,6 +39,7 @@ #include "sexpr.h" #include "xml.h" #include "buf.h" +#include "capabilities.h" #include "uuid.h" #include "xen_unified.h" #include "xend_internal.h" @@ -1952,59 +1953,104 @@ sexpr_to_xend_node_info(const struct sex return (0); } + /** - * sexpr_to_xend_topology_xml: + * sexpr_to_xend_topology * @root: an S-Expression describing a node + * @caps: capability info * - * Internal routine creating an XML string with the values from - * the node root provided. + * Internal routine populating capability info with + * NUMA node mapping details * * Returns 0 in case of success, -1 in case of error */ static int -sexpr_to_xend_topology_xml(virConnectPtr conn, const struct sexpr *root, - virBufferPtr xml) +sexpr_to_xend_topology(virConnectPtr conn, + const struct sexpr *root, + virCapsPtr caps) { const char *nodeToCpu; - int numCells = 0; + const char *cur; + char *cpuset = NULL; + int *cpuNums = NULL; + int cell, cpu, nb_cpus; + int n = 0; int numCpus; - int r; nodeToCpu = sexpr_node(root, "node/node_to_cpu"); if (nodeToCpu == NULL) { virXendError(conn, VIR_ERR_INTERNAL_ERROR, _("failed to parse topology information")); - goto error; + return -1; } - numCells = sexpr_int(root, "node/nr_nodes"); numCpus = sexpr_int(root, "node/nr_cpus"); - /* start filling in xml */ - r = virBufferVSprintf (xml, - "\ - <topology>\n\ - <cells num='%d'>\n", - numCells); - if (r < 0) goto vir_buffer_failed; - - r = virParseXenCpuTopology(conn, xml, nodeToCpu, numCpus); - if (r < 0) goto error; - - r = virBufferAddLit (xml, "\ - </cells>\n\ - </topology>\n"); - if (r < 0) goto vir_buffer_failed; + + cpuset = malloc(numCpus * sizeof(*cpuset)); + if (cpuset == NULL) + goto memory_error; + cpuNums = malloc(numCpus * sizeof(*cpuNums)); + if (cpuNums == NULL) + goto memory_error; + + cur = nodeToCpu; + while (*cur != 0) { + /* + * Find the next NUMA cell described in the xend output + */ + cur = strstr(cur, "node"); + if (cur == NULL) + break; + cur += 4; + cell = virParseNumber(&cur); + if (cell < 0) + goto parse_error; + virSkipSpaces(&cur); + if (*cur != ':') + goto parse_error; + cur++; + virSkipSpaces(&cur); + if (!strncmp(cur, "no cpus", 7)) { + nb_cpus = 0; + for (cpu = 0; cpu < numCpus; cpu++) + cpuset[cpu] = 0; + } else { + nb_cpus = virParseCpuSet(conn, &cur, 'n', cpuset, numCpus); + if (nb_cpus < 0) + goto error; + } + + for (n = 0, cpu = 0; cpu < numCpus; cpu++) + if (cpuset[cpu] == 1) + cpuNums[n++] = cpu; + + if (virCapabilitiesAddHostNUMACell(caps, + cell, + nb_cpus, + cpuNums) < 0) + goto memory_error; + } + free(cpuNums); + free(cpuset); return (0); + parse_error: + virXendError(conn, VIR_ERR_XEN_CALL, _("topology syntax error")); + error: + free(cpuNums); + free(cpuset); -vir_buffer_failed: - virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate new buffer")); + return (-1); -error: + memory_error: + free(cpuNums); + free(cpuset); + virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer")); return (-1); } + #ifndef PROXY /** * sexpr_to_domain: @@ -2720,13 +2766,15 @@ xenDaemonNodeGetInfo(virConnectPtr conn, /** * xenDaemonNodeGetTopology: * @conn: pointer to the Xen Daemon block + * @caps: capabilities info * * This method retrieves a node's topology information. * * Returns -1 in case of error, 0 otherwise. */ int -xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml) { +xenDaemonNodeGetTopology(virConnectPtr conn, + virCapsPtr caps) { int ret = -1; struct sexpr *root; @@ -2735,17 +2783,17 @@ xenDaemonNodeGetTopology(virConnectPtr c return (-1); } - if (xml == NULL) { + if (caps == NULL) { virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); return (-1); - } + } root = sexpr_get(conn, "/xend/node/"); if (root == NULL) { return (-1); } - ret = sexpr_to_xend_topology_xml(conn, root, xml); + ret = sexpr_to_xend_topology(conn, root, caps); sexpr_free(root); return (ret); } Index: src/xend_internal.h =================================================================== RCS file: /data/cvs/libvirt/src/xend_internal.h,v retrieving revision 1.38 diff -u -p -r1.38 xend_internal.h --- src/xend_internal.h 5 Feb 2008 19:27:37 -0000 1.38 +++ src/xend_internal.h 26 Feb 2008 04:47:12 -0000 @@ -19,7 +19,7 @@ #include <stdbool.h> #include "libvirt/libvirt.h" -#include "buf.h" +#include "capabilities.h" #ifdef __cplusplus extern "C" { @@ -187,7 +187,7 @@ int xenDaemonOpen(virConnectPtr conn, xm int xenDaemonClose(virConnectPtr conn); int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer); int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info); -int xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml); +int xenDaemonNodeGetTopology(virConnectPtr conn, virCapsPtr caps); int xenDaemonDomainSuspend(virDomainPtr domain); int xenDaemonDomainResume(virDomainPtr domain); int xenDaemonDomainShutdown(virDomainPtr domain); Index: src/xml.c =================================================================== RCS file: /data/cvs/libvirt/src/xml.c,v retrieving revision 1.112 diff -u -p -r1.112 xml.c --- src/xml.c 20 Feb 2008 15:29:13 -0000 1.112 +++ src/xml.c 26 Feb 2008 04:47:13 -0000 @@ -26,6 +26,7 @@ #include "sexpr.h" #include "xml.h" #include "buf.h" +#include "util.h" #include "xs_internal.h" /* for xenStoreDomainGetNetworkID */ #include "xen_unified.h" @@ -59,56 +60,6 @@ virXMLError(virConnectPtr conn, virError ************************************************************************/ #if WITH_XEN /** - * skipSpaces: - * @str: pointer to the char pointer used - * - * Skip potential blanks, this includes space tabs, line feed, - * carriage returns and also '\\' which can be erronously emitted - * by xend - */ -static void -skipSpaces(const char **str) -{ - const char *cur = *str; - - while ((*cur == ' ') || (*cur == '\t') || (*cur == '\n') || - (*cur == '\r') || (*cur == '\\')) - cur++; - *str = cur; -} - -/** - * parseNumber: - * @str: pointer to the char pointer used - * - * Parse an unsigned number - * - * Returns the unsigned number or -1 in case of error. @str will be - * updated to skip the number. - */ -static int -parseNumber(const char **str) -{ - int ret = 0; - const char *cur = *str; - - if ((*cur < '0') || (*cur > '9')) - return (-1); - - while ((*cur >= '0') && (*cur <= '9')) { - unsigned int c = *cur - '0'; - - if ((ret > INT_MAX / 10) || - ((ret == INT_MAX / 10) && (c > INT_MAX % 10))) - return (-1); - ret = ret * 10 + c; - cur++; - } - *str = cur; - return (ret); -} - -/** * parseCpuNumber: * @str: pointer to the char pointer used * @maxcpu: maximum CPU number allowed @@ -225,7 +176,7 @@ virParseCpuSet(virConnectPtr conn, const return (-1); cur = *str; - skipSpaces(&cur); + virSkipSpaces(&cur); if (*cur == 0) goto parse_error; @@ -251,7 +202,7 @@ virParseCpuSet(virConnectPtr conn, const start = parseCpuNumber(&cur, maxcpu); if (start < 0) goto parse_error; - skipSpaces(&cur); + virSkipSpaces(&cur); if ((*cur == ',') || (*cur == 0) || (*cur == sep)) { if (neg) { if (cpuset[start] == 1) { @@ -268,7 +219,7 @@ virParseCpuSet(virConnectPtr conn, const if (neg) goto parse_error; cur++; - skipSpaces(&cur); + virSkipSpaces(&cur); last = parseCpuNumber(&cur, maxcpu); if (last < start) goto parse_error; @@ -278,11 +229,11 @@ virParseCpuSet(virConnectPtr conn, const ret++; } } - skipSpaces(&cur); + virSkipSpaces(&cur); } if (*cur == ',') { cur++; - skipSpaces(&cur); + virSkipSpaces(&cur); neg = 0; } else if ((*cur == 0) || (*cur == sep)) { break; @@ -298,114 +249,6 @@ virParseCpuSet(virConnectPtr conn, const return (-1); } -/** - * virParseXenCpuTopology: - * @conn: connection - * @xml: XML output buffer - * @str: the topology string - * @maxcpu: number of elements available in @cpuset - * - * Parse a Xend CPU topology string and build the associated XML - * format. - * - * Returns 0 in case of success, -1 in case of error - */ -int -virParseXenCpuTopology(virConnectPtr conn, virBufferPtr xml, - const char *str, int maxcpu) -{ - const char *cur; - char *cpuset = NULL; - int cell, cpu, nb_cpus; - int ret; - - if ((str == NULL) || (xml == NULL) || (maxcpu <= 0) || (maxcpu > 100000)) - return (-1); - - cpuset = malloc(maxcpu * sizeof(*cpuset)); - if (cpuset == NULL) - goto memory_error; - - cur = str; - while (*cur != 0) { - /* - * Find the next NUMA cell described in the xend output - */ - cur = strstr(cur, "node"); - if (cur == NULL) - break; - cur += 4; - cell = parseNumber(&cur); - if (cell < 0) - goto parse_error; - skipSpaces(&cur); - if (*cur != ':') - goto parse_error; - cur++; - skipSpaces(&cur); - if (!strncmp(cur, "no cpus", 7)) { - nb_cpus = 0; - for (cpu = 0; cpu < maxcpu; cpu++) - cpuset[cpu] = 0; - } else { - nb_cpus = virParseCpuSet(conn, &cur, 'n', cpuset, maxcpu); - if (nb_cpus < 0) - goto error; - } - - /* - * add xml for all cpus associated with that cell - */ - ret = virBufferVSprintf(xml, "\ - <cell id='%d'>\n\ - <cpus num='%d'>\n", cell, nb_cpus); -#ifdef STANDALONE - { - char *dump; - - dump = virSaveCpuSet(conn, cpuset, maxcpu); - if (dump != NULL) { - virBufferVSprintf(xml, " <dump>%s</dump>\n", - dump); - free(dump); - } else { - virBufferVSprintf(xml, " <error>%s</error>\n", - "Failed to dump CPU set"); - } - } -#endif - if (ret < 0) - goto memory_error; - for (cpu = 0; cpu < maxcpu; cpu++) { - if (cpuset[cpu] == 1) { - ret = virBufferVSprintf(xml, "\ - <cpu id='%d'/>\n", cpu); - if (ret < 0) - goto memory_error; - } - } - ret = virBufferAddLit(xml, "\ - </cpus>\n\ - </cell>\n"); - if (ret < 0) - goto memory_error; - - } - free(cpuset); - return (0); - - parse_error: - virXMLError(conn, VIR_ERR_XEN_CALL, _("topology syntax error"), 0); - error: - free(cpuset); - - return (-1); - - memory_error: - free(cpuset); - virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0); - return (-1); -} /** * virConvertCpuSet: Index: src/xml.h =================================================================== RCS file: /data/cvs/libvirt/src/xml.h,v retrieving revision 1.21 diff -u -p -r1.21 xml.h --- src/xml.h 30 Nov 2007 22:51:55 -0000 1.21 +++ src/xml.h 26 Feb 2008 04:47:13 -0000 @@ -33,10 +33,6 @@ int virXPathNodeSet (const char *xpath, xmlNodePtr **list); #if WITH_XEN -int virParseXenCpuTopology(virConnectPtr conn, - virBufferPtr xml, - const char *str, - int maxcpu); int virParseCpuSet (virConnectPtr conn, const char **str, char sep, Index: tests/qemuxml2argvtest.c =================================================================== RCS file: /data/cvs/libvirt/tests/qemuxml2argvtest.c,v retrieving revision 1.12 diff -u -p -r1.12 qemuxml2argvtest.c --- tests/qemuxml2argvtest.c 29 Jan 2008 18:15:54 -0000 1.12 +++ tests/qemuxml2argvtest.c 26 Feb 2008 04:47:13 -0000 @@ -125,6 +125,8 @@ main(int argc, char **argv) if (!abs_top_srcdir) return 1; + driver.caps = qemudCapsInit(); + if (virtTestRun("QEMU XML-2-ARGV minimal", 1, testCompareXMLToArgvHelper, "minimal") < 0) ret = -1; @@ -190,6 +192,8 @@ main(int argc, char **argv) ret = -1; + virCapabilitiesFree(driver.caps); + exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } Index: tests/qemuxml2xmltest.c =================================================================== RCS file: /data/cvs/libvirt/tests/qemuxml2xmltest.c,v retrieving revision 1.10 diff -u -p -r1.10 qemuxml2xmltest.c --- tests/qemuxml2xmltest.c 29 Jan 2008 18:15:54 -0000 1.10 +++ tests/qemuxml2xmltest.c 26 Feb 2008 04:47:13 -0000 @@ -88,6 +88,9 @@ main(int argc, char **argv) if (!abs_top_srcdir) return 1; + + driver.caps = qemudCapsInit(); + if (virtTestRun("QEMU XML-2-ARGV minimal", 1, testCompareXMLToXMLHelper, "minimal") < 0) ret = -1; @@ -152,6 +155,7 @@ main(int argc, char **argv) 1, testCompareXMLToXMLHelper, "net-user") < 0) ret = -1; + virCapabilitiesFree(driver.caps); exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } Index: tests/xencapstest.c =================================================================== RCS file: /data/cvs/libvirt/tests/xencapstest.c,v retrieving revision 1.9 diff -u -p -r1.9 xencapstest.c --- tests/xencapstest.c 29 Jan 2008 18:15:54 -0000 1.9 +++ tests/xencapstest.c 26 Feb 2008 04:47:13 -0000 @@ -50,7 +50,8 @@ static int testCompareFiles(const char * if (!(actualxml = xenHypervisorMakeCapabilitiesXML(NULL, hostmachine, fp1, fp2))) goto fail; - if (getenv("DEBUG_TESTS")) { + if (getenv("DEBUG_TESTS") && + STRNEQ(expectxml, actualxml)) { printf("In test file %s:\n", capabilities); printf("Expect %d '%s'\n", (int)strlen(expectxml), expectxml); printf("Actual %d '%s'\n", (int)strlen(actualxml), actualxml); Index: tests/xencapsdata/xen-i686-pae-hvm.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-i686-pae-hvm.xml,v retrieving revision 1.3 diff -u -p -r1.3 xen-i686-pae-hvm.xml --- tests/xencapsdata/xen-i686-pae-hvm.xml 21 Aug 2007 09:38:00 -0000 1.3 +++ tests/xencapsdata/xen-i686-pae-hvm.xml 26 Feb 2008 04:47:13 -0000 @@ -1,4 +1,5 @@ <capabilities> + <host> <cpu> <arch>i686</arch> @@ -16,9 +17,12 @@ <guest> <os_type>xen</os_type> - <arch name="i686"> + <arch name='i686'> <wordsize>32</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> <features> <pae/> @@ -27,13 +31,13 @@ <guest> <os_type>hvm</os_type> - <arch name="i686"> + <arch name='i686'> <wordsize>32</wordsize> - <domain type="xen"></domain> <emulator>/usr/lib/xen/bin/qemu-dm</emulator> - <machine>pc</machine> - <machine>isapc</machine> <loader>/usr/lib/xen/boot/hvmloader</loader> + <machine>xenfv</machine> + <domain type='xen'> + </domain> </arch> <features> <pae/> @@ -42,4 +46,5 @@ <apic default='on' toggle='yes'/> </features> </guest> + </capabilities> Index: tests/xencapsdata/xen-i686-pae.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-i686-pae.xml,v retrieving revision 1.2 diff -u -p -r1.2 xen-i686-pae.xml --- tests/xencapsdata/xen-i686-pae.xml 21 Aug 2007 09:38:00 -0000 1.2 +++ tests/xencapsdata/xen-i686-pae.xml 26 Feb 2008 04:47:13 -0000 @@ -1,4 +1,5 @@ <capabilities> + <host> <cpu> <arch>i686</arch> @@ -16,12 +17,16 @@ <guest> <os_type>xen</os_type> - <arch name="i686"> + <arch name='i686'> <wordsize>32</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> <features> <pae/> </features> </guest> + </capabilities> Index: tests/xencapsdata/xen-i686.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-i686.xml,v retrieving revision 1.2 diff -u -p -r1.2 xen-i686.xml --- tests/xencapsdata/xen-i686.xml 21 Aug 2007 09:38:00 -0000 1.2 +++ tests/xencapsdata/xen-i686.xml 26 Feb 2008 04:47:13 -0000 @@ -1,9 +1,8 @@ <capabilities> + <host> <cpu> <arch>i686</arch> - <features> - </features> </cpu> <migration_features> <live/> @@ -15,12 +14,16 @@ <guest> <os_type>xen</os_type> - <arch name="i686"> + <arch name='i686'> <wordsize>32</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> <features> <nonpae/> </features> </guest> + </capabilities> Index: tests/xencapsdata/xen-ia64-be-hvm.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-ia64-be-hvm.xml,v retrieving revision 1.3 diff -u -p -r1.3 xen-ia64-be-hvm.xml --- tests/xencapsdata/xen-ia64-be-hvm.xml 21 Aug 2007 09:38:00 -0000 1.3 +++ tests/xencapsdata/xen-ia64-be-hvm.xml 26 Feb 2008 04:47:13 -0000 @@ -1,9 +1,8 @@ <capabilities> + <host> <cpu> <arch>ia64</arch> - <features> - </features> </cpu> <migration_features> <live/> @@ -15,9 +14,12 @@ <guest> <os_type>xen</os_type> - <arch name="ia64"> + <arch name='ia64'> <wordsize>64</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> <features> <ia64_be/> @@ -26,13 +28,13 @@ <guest> <os_type>hvm</os_type> - <arch name="ia64"> + <arch name='ia64'> <wordsize>64</wordsize> - <domain type="xen"></domain> - <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> - <machine>pc</machine> - <machine>isapc</machine> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <loader>/usr/lib/xen/boot/hvmloader</loader> + <machine>xenfv</machine> + <domain type='xen'> + </domain> </arch> <features> <ia64_be/> @@ -40,4 +42,5 @@ <apic default='on' toggle='yes'/> </features> </guest> + </capabilities> Index: tests/xencapsdata/xen-ia64-be.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-ia64-be.xml,v retrieving revision 1.2 diff -u -p -r1.2 xen-ia64-be.xml --- tests/xencapsdata/xen-ia64-be.xml 21 Aug 2007 09:38:00 -0000 1.2 +++ tests/xencapsdata/xen-ia64-be.xml 26 Feb 2008 04:47:13 -0000 @@ -1,9 +1,8 @@ <capabilities> + <host> <cpu> <arch>ia64</arch> - <features> - </features> </cpu> <migration_features> <live/> @@ -15,12 +14,16 @@ <guest> <os_type>xen</os_type> - <arch name="ia64"> + <arch name='ia64'> <wordsize>64</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> <features> <ia64_be/> </features> </guest> + </capabilities> Index: tests/xencapsdata/xen-ia64-hvm.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-ia64-hvm.xml,v retrieving revision 1.3 diff -u -p -r1.3 xen-ia64-hvm.xml --- tests/xencapsdata/xen-ia64-hvm.xml 21 Aug 2007 09:38:00 -0000 1.3 +++ tests/xencapsdata/xen-ia64-hvm.xml 26 Feb 2008 04:47:13 -0000 @@ -1,9 +1,8 @@ <capabilities> + <host> <cpu> <arch>ia64</arch> - <features> - </features> </cpu> <migration_features> <live/> @@ -15,27 +14,29 @@ <guest> <os_type>xen</os_type> - <arch name="ia64"> + <arch name='ia64'> <wordsize>64</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> - <features> - </features> </guest> <guest> <os_type>hvm</os_type> - <arch name="ia64"> + <arch name='ia64'> <wordsize>64</wordsize> - <domain type="xen"></domain> - <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> - <machine>pc</machine> - <machine>isapc</machine> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> <loader>/usr/lib/xen/boot/hvmloader</loader> + <machine>xenfv</machine> + <domain type='xen'> + </domain> </arch> <features> <acpi default='on' toggle='yes'/> <apic default='on' toggle='yes'/> </features> </guest> + </capabilities> Index: tests/xencapsdata/xen-ia64.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-ia64.xml,v retrieving revision 1.2 diff -u -p -r1.2 xen-ia64.xml --- tests/xencapsdata/xen-ia64.xml 21 Aug 2007 09:38:00 -0000 1.2 +++ tests/xencapsdata/xen-ia64.xml 26 Feb 2008 04:47:13 -0000 @@ -1,9 +1,8 @@ <capabilities> + <host> <cpu> <arch>ia64</arch> - <features> - </features> </cpu> <migration_features> <live/> @@ -15,11 +14,13 @@ <guest> <os_type>xen</os_type> - <arch name="ia64"> + <arch name='ia64'> <wordsize>64</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> - <features> - </features> </guest> + </capabilities> Index: tests/xencapsdata/xen-ppc64.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-ppc64.xml,v retrieving revision 1.2 diff -u -p -r1.2 xen-ppc64.xml --- tests/xencapsdata/xen-ppc64.xml 21 Aug 2007 09:38:00 -0000 1.2 +++ tests/xencapsdata/xen-ppc64.xml 26 Feb 2008 04:47:13 -0000 @@ -1,9 +1,8 @@ <capabilities> + <host> <cpu> <arch>ppc64</arch> - <features> - </features> </cpu> <migration_features> <live/> @@ -15,11 +14,13 @@ <guest> <os_type>xen</os_type> - <arch name="ppc64"> + <arch name='ppc64'> <wordsize>64</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> - <features> - </features> </guest> + </capabilities> Index: tests/xencapsdata/xen-x86_64-hvm.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-x86_64-hvm.xml,v retrieving revision 1.3 diff -u -p -r1.3 xen-x86_64-hvm.xml --- tests/xencapsdata/xen-x86_64-hvm.xml 21 Aug 2007 09:38:00 -0000 1.3 +++ tests/xencapsdata/xen-x86_64-hvm.xml 26 Feb 2008 04:47:13 -0000 @@ -1,4 +1,5 @@ <capabilities> + <host> <cpu> <arch>x86_64</arch> @@ -16,23 +17,24 @@ <guest> <os_type>xen</os_type> - <arch name="x86_64"> + <arch name='x86_64'> <wordsize>64</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> - <features> - </features> </guest> <guest> <os_type>hvm</os_type> - <arch name="i686"> + <arch name='i686'> <wordsize>32</wordsize> - <domain type="xen"></domain> - <emulator>/usr/lib/xen/bin/qemu-dm</emulator> - <machine>pc</machine> - <machine>isapc</machine> + <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> <loader>/usr/lib/xen/boot/hvmloader</loader> + <machine>xenfv</machine> + <domain type='xen'> + </domain> </arch> <features> <pae/> @@ -44,17 +46,18 @@ <guest> <os_type>hvm</os_type> - <arch name="x86_64"> + <arch name='x86_64'> <wordsize>64</wordsize> - <domain type="xen"></domain> <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> - <machine>pc</machine> - <machine>isapc</machine> <loader>/usr/lib/xen/boot/hvmloader</loader> + <machine>xenfv</machine> + <domain type='xen'> + </domain> </arch> <features> <acpi default='on' toggle='yes'/> <apic default='on' toggle='yes'/> </features> </guest> + </capabilities> Index: tests/xencapsdata/xen-x86_64.xml =================================================================== RCS file: /data/cvs/libvirt/tests/xencapsdata/xen-x86_64.xml,v retrieving revision 1.2 diff -u -p -r1.2 xen-x86_64.xml --- tests/xencapsdata/xen-x86_64.xml 21 Aug 2007 09:38:00 -0000 1.2 +++ tests/xencapsdata/xen-x86_64.xml 26 Feb 2008 04:47:13 -0000 @@ -1,4 +1,5 @@ <capabilities> + <host> <cpu> <arch>x86_64</arch> @@ -16,11 +17,13 @@ <guest> <os_type>xen</os_type> - <arch name="x86_64"> + <arch name='x86_64'> <wordsize>64</wordsize> - <domain type="xen"></domain> + <emulator>/usr/lib64/xen/bin/qemu-dm</emulator> + <machine>xenpv</machine> + <domain type='xen'> + </domain> </arch> - <features> - </features> </guest> + </capabilities> -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list