Patch for accessing topology information. -- Elizabeth Kon (Beth) IBM Linux Technology Center Open Hypervisor Team email: eak@xxxxxxxxxx
diff -urpN libvirt.cellsMemory/src/xend_internal.c libvirt.topology/src/xend_internal.c --- libvirt.cellsMemory/src/xend_internal.c 2007-09-27 18:39:52.000000000 -0400 +++ libvirt.topology/src/xend_internal.c 2007-09-28 00:26:47.000000000 -0400 @@ -30,6 +30,7 @@ #include <arpa/inet.h> #include <netdb.h> #include <libxml/uri.h> +#include <ctype.h> #include <errno.h> #include "libvirt/libvirt.h" @@ -1869,6 +1870,198 @@ sexpr_to_xend_node_info(struct sexpr *ro return (0); } +/** + * getNumber: + * @pointer: pointer to string beginning with numerical characters + * @result: pointer to integer for storing the numerical result + * + * Internal routine extracting a number from the beginning of a string + * + * Returns the number of characters that were extracted as digits + * or -1 if no digits were found. + */ +static int +getNumber (const char * pointer, int * result) { + int len = 0; + while (isdigit(*(pointer + len))) + len++; + if (len == 0) + return -1; + *(result) = atoi(pointer); + return (len); +} + +/** + * sexpr_to_xend_topology_xml: + * @root: an S-Expression describing a node + * + * Internal routine creating an XML string with the values from + * the node root provided. + * + * Returns 0 in case of success, -1 in case of error + */ +static int +sexpr_to_xend_topology_xml(virConnectPtr conn, struct sexpr *root, virBufferPtr xml) +{ + const char *nodeToCpu; + const char *offset; + int cellNum; + int numCells = 0; + int numCpus; + int cellCpuCount = 0; + int nodeCpuCount = 0; + int start; + int finish; + int r; + int i; + int len; + int cpuNum; + int *cpuIdsPtr = NULL; + int *iCpuIdsPtr = NULL; + char next; + + nodeToCpu = sexpr_node(root, "node/node_to_cpu"); + if (nodeToCpu == NULL) { + virXendError(conn, VIR_ERR_INTERNAL_ERROR, + _("failed to parse topology information")); + goto error; + } + + numCells = sexpr_int(root, "node/nr_nodes"); + numCpus = sexpr_int(root, "node/nr_cpus"); + + /* array for holding all cpu numbers associated with a single cell. + * Should never need more than numCpus (which is total number of + * cpus for the node) + */ + cpuIdsPtr = iCpuIdsPtr = malloc(numCpus * sizeof(int)); + if (cpuIdsPtr == NULL) { + goto vir_buffer_failed; + } + + /* start filling in xml */ + r = virBufferVSprintf (xml, + "\ + <topology>\n\ + <cells num='%d'>\n", + numCells); + if (r == -1) goto vir_buffer_failed; + + offset = nodeToCpu; + /* now iterate through all cells and find associated cpu ids */ + /* example of string being parsed: "node0:0-3,7,9-10\n node1:11-14\n" */ + while ((offset = strstr(offset, "node")) != NULL) { + cpuIdsPtr = iCpuIdsPtr; + cellCpuCount = 0; + offset +=4; + if ((len = getNumber(offset, &cellNum)) < 0) { + virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error"); + goto error; + } + offset += len; + if (*(offset) != ':') { + virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error"); + goto error; + } + offset++; + /* get list of cpus associated w/ single cell */ + while (1) { + if ((len = getNumber(offset, &cpuNum)) < 0) { + virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error"); + goto error; + } + offset += len; + next = *(offset); + if (next == '-') { + offset++; + start = cpuNum; + if ((len = getNumber(offset, &finish)) < 0) { + virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error"); + goto error; + } + if (start > finish) { + virXendError(conn, VIR_ERR_XEN_CALL, " topology string syntax error"); + goto error; + + } + for (i=start; i<=finish && nodeCpuCount<numCpus; i++) { + *(cpuIdsPtr++) = i; + cellCpuCount++; + nodeCpuCount++; + } + if (nodeCpuCount > numCpus) { + virXendError(conn, VIR_ERR_XEN_CALL, + "conflicting cpu counts"); + goto error; + } + offset += len; + next = *(offset); + offset++; + if (next == ',') { + continue; + } else if ((next == '\\') || (next =='\0')) { + break; + } else { + virXendError(conn, VIR_ERR_XEN_CALL, + " topology string syntax error"); + goto error; + } + } else { + /* add the single number */ + if (nodeCpuCount >= numCpus) { + virXendError(conn, VIR_ERR_XEN_CALL, + "conflicting cpu counts"); + goto error; + } + *(cpuIdsPtr++) = cpuNum; + cellCpuCount++; + nodeCpuCount++; + if (next == ',') { + offset++; + continue; + } else if ((next == '\\') || (next =='\0')) { + break; + } else { + virXendError(conn, VIR_ERR_XEN_CALL, + " topology string syntax error"); + goto error; + } + } + } + + /* add xml for all cpus associated with one cell */ + r = virBufferVSprintf (xml, "\ + <cell id='%d'>\n\ + <cpus num='%d'>\n", cellNum, cellCpuCount); + if (r == -1) goto vir_buffer_failed; + + for (i = 0; i < cellCpuCount; i++) { + r = virBufferVSprintf (xml, "\ + <cpu id='%d'/>\n", *(iCpuIdsPtr + i)); + if (r == -1) goto vir_buffer_failed; + } + r = virBufferAdd (xml, "\ + </cpus>\n\ + </cell>\n", -1); + if (r == -1) goto vir_buffer_failed; + } + r = virBufferAdd (xml, "\ + </cells>\n\ + </topology>\n", -1); + if (r == -1) goto vir_buffer_failed; + free(iCpuIdsPtr); + return (0); + + +vir_buffer_failed: + virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate new buffer")); + +error: + if (iCpuIdsPtr) + free(iCpuIdsPtr); + return (-1); +} + #ifndef PROXY /** * sexpr_to_domain: @@ -2589,6 +2782,39 @@ xenDaemonNodeGetInfo(virConnectPtr conn, return (ret); } +/** + * xenDaemonNodeGetTopology: + * @conn: pointer to the Xen Daemon block + * + * This method retrieves a node's topology information. + * + * Returns -1 in case of error, 0 otherwise. + */ +int +xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml) { + int ret = -1; + struct sexpr *root; + + if (!VIR_IS_CONNECT(conn)) { + virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if (xml == 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); + sexpr_free(root); + return (ret); +} + #ifndef PROXY /** * xenDaemonGetType: diff -urpN libvirt.cellsMemory/src/xend_internal.h libvirt.topology/src/xend_internal.h --- libvirt.cellsMemory/src/xend_internal.h 2007-09-10 17:35:39.000000000 -0400 +++ libvirt.topology/src/xend_internal.h 2007-09-28 00:26:53.000000000 -0400 @@ -19,6 +19,7 @@ #include <stdbool.h> #include "libvirt/libvirt.h" +#include "buf.h" #ifdef __cplusplus extern "C" { @@ -182,6 +183,7 @@ int xenDaemonOpen(virConnectPtr conn, co int xenDaemonClose(virConnectPtr conn); int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer); int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info); +int xenDaemonNodeGetTopology(virConnectPtr conn, virBufferPtr xml); int xenDaemonDomainSuspend(virDomainPtr domain); int xenDaemonDomainResume(virDomainPtr domain); int xenDaemonDomainShutdown(virDomainPtr domain); diff -urpN libvirt.cellsMemory/src/xen_internal.c libvirt.topology/src/xen_internal.c --- libvirt.cellsMemory/src/xen_internal.c 2007-09-27 22:23:50.000000000 -0400 +++ libvirt.topology/src/xen_internal.c 2007-09-28 00:27:02.000000000 -0400 @@ -2228,7 +2228,7 @@ xenHypervisorMakeCapabilitiesXML(virConn char line[1024], *str, *token; regmatch_t subs[4]; char *saveptr = NULL; - int i, r; + int i, r, topology; char hvm_type[4] = ""; /* "vmx" or "svm" (or "" if not in CPU). */ int host_pae = 0; @@ -2405,6 +2405,12 @@ xenHypervisorMakeCapabilitiesXML(virConn </host>\n", -1); 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, "\ @@ -2466,6 +2472,7 @@ xenHypervisorMakeCapabilitiesXML(virConn </guest>\n", -1); if (r == -1) goto vir_buffer_failed; } + r = virBufferAdd (xml, "\ </capabilities>\n", -1); @@ -2478,6 +2485,7 @@ xenHypervisorMakeCapabilitiesXML(virConn vir_buffer_failed: virXenError(VIR_ERR_NO_MEMORY, __FUNCTION__, 0); + topology_failed: virBufferFree (xml); return NULL; }
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list