[libvirt] [PATCHv2 0/9] New API to retrieve host node CPU map

V2 Changes: Added python binding for virNodeGetCPUMapFlags. Removed RFC stanza. --- Viktor Mihajlovski (9): virNodeGetCPUMapFlags: Define public API. virNodeGetCPUMapFlags: Define driver API. virNodeGetCPUMapFlags: Implement public API. virNodeGetCPUMapFlags: Implement wire protocol. libvirt.h.in: Add new cpumap macro VIR_CPU_USED virNodeGetCPUMapFlags: Implement virsh support. virNodeGetCPUMapFlags: Implement support function in nodeinfo virNodeGetCPUMapFlags: Implement driver support virNodeGetCPUMapFlags: Add python binding daemon/remote.c | 44 ++++++++++++++++++++++++++++++ include/libvirt/libvirt.h.in | 28 ++++++++++++++++--- python/generator.py | 1 + python/libvirt-override-api.xml | 6 ++++ python/libvirt-override.c | 56 +++++++++++++++++++++++++++++++++++++++ src/driver.h | 7 +++++ src/libvirt.c | 56 +++++++++++++++++++++++++++++++++++++++ src/libvirt_private.syms | 1 + src/libvirt_public.syms | 5 +++ src/nodeinfo.c | 49 ++++++++++++++++++++++++++++++++++ src/nodeinfo.h | 6 ++++ src/qemu/qemu_driver.c | 1 + src/remote/remote_driver.c | 49 ++++++++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 13 ++++++++- src/remote_protocol-structs | 12 ++++++++ src/test/test_driver.c | 30 +++++++++++++++++++++ tools/virsh-host.c | 41 ++++++++++++++++++++++++++++ tools/virsh.pod | 5 +++ 18 files changed, 405 insertions(+), 5 deletions(-)

Adding a new API to obtain information about the host node's present, online and offline CPUs. int virNodeGetCPUMapFlags(virConnectPtr conn, unsigned char **cpumap, unsigned int *online, unsigned int flags); The function will return the number of CPUs present on the host or -1 on failure; If cpumap is non-NULL virNodeGetCPUMapFlags will allocate an array containing a bit map representation of the online CPUs. It's the callers responsibility to deallocate cpumap using free(). If online is non-NULL, the variable pointed to will contain the number of online host node CPUs. The variable flags has been added to support future extensions and must be set to 0. Note: the name virNodeGetCPUMapFlags has been chosen to avoid confusion with the nodeinfo function nodeGetCPUmap. Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- include/libvirt/libvirt.h.in | 8 ++++++++ python/generator.py | 1 + src/libvirt_public.syms | 5 +++++ 3 files changed, 14 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index a4e8ca9..6b72159 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -4500,6 +4500,14 @@ int virNodeSetMemoryParameters(virConnectPtr conn, int nparams, unsigned int flags); +/* + * node CPU map + */ +int virNodeGetCPUMapFlags(virConnectPtr conn, + unsigned char **cpumap, + unsigned int *online, + unsigned int flags); + #ifdef __cplusplus } #endif diff --git a/python/generator.py b/python/generator.py index ced7e41..8591b8d 100755 --- a/python/generator.py +++ b/python/generator.py @@ -429,6 +429,7 @@ skip_impl = ( 'virConnectRegisterCloseCallback', 'virNodeGetMemoryParameters', 'virNodeSetMemoryParameters', + 'virNodeGetCPUMapFlags', ) qemu_skip_impl = ( diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 2c924d5..0c8f4ff 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -569,4 +569,9 @@ LIBVIRT_0.10.2 { virStoragePoolListAllVolumes; } LIBVIRT_0.10.0; +LIBVIRT_1.0.0 { + global: + virNodeGetCPUMapFlags; +} LIBVIRT_0.10.2; + # .... define new API here using predicted next version number .... -- 1.7.0.4

Extend the driver structure by nodeGetCPUMapFlags entry in support of the new API virNodeGetCPUMapFlags. Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- src/driver.h | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index bdcaa01..1af9568 100644 --- a/src/driver.h +++ b/src/driver.h @@ -898,6 +898,12 @@ typedef int int nparams, unsigned int flags); +typedef int + (*virDrvNodeGetCPUMapFlags)(virConnectPtr conn, + unsigned char **cpumap, + unsigned int *online, + unsigned int flags); + /** * _virDriver: * @@ -1087,6 +1093,7 @@ struct _virDriver { virDrvDomainGetMetadata domainGetMetadata; virDrvNodeGetMemoryParameters nodeGetMemoryParameters; virDrvNodeSetMemoryParameters nodeSetMemoryParameters; + virDrvNodeGetCPUMapFlags nodeGetCPUMapFlags; }; typedef int -- 1.7.0.4

Added implementation of virNodeGetCPUMapFlags to libvirt.c Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- src/libvirt.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 56 insertions(+), 0 deletions(-) diff --git a/src/libvirt.c b/src/libvirt.c index 3c6d67d..25c37d3 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -20098,3 +20098,59 @@ error: virDispatchError(domain->conn); return NULL; } + +/** + * virNodeGetCPUMapFlags: + * @conn: pointer to the hypervisor connection + * @cpumap: optional pointer to a bit map of real CPUs on the host node + * (in 8-bit bytes) (OUT) + * In case of success each bit set to 1 means that corresponding + * CPU is online. + * Bytes are stored in little-endian order: CPU0-7, 8-15... + * In each byte, lowest CPU number is least significant bit. + * The bit map is allocated by virNodeGetCPUMapFlags and needs + * to be released using free() by the caller. + * @online: optional number of online CPUs in cpumap (OUT) + * Contains the number of online CPUs if the call was successful. + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Get CPU map of host node CPUs. + * + * Returns number of CPUs present on the host node, + * or -1 if there was an error. + */ +int +virNodeGetCPUMapFlags (virConnectPtr conn, + unsigned char **cpumap, + unsigned int *online, + unsigned int flags) +{ + VIR_DEBUG("conn=%p, cpumap=%p, online=%p, flags=%x", + conn, cpumap, online, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECT (conn)) { + virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (conn->driver->nodeGetCPUMapFlags) { + int ret = conn->driver->nodeGetCPUMapFlags (conn, + cpumap, + online, + flags); + if (ret < 0) + goto error; + VIR_DEBUG("conn=%p, cpumap=%p, online=%u, flags=%x, ret=%d", + conn, cpumap, online ? *online : 0 , flags, ret); + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} -- 1.7.0.4

- Defined the wire protocol format for virNodeGetCPUMapFlags and its arguments - Implemented remote method invocation (remoteNodeGetCPUMapFlags) - Implemented method dispacher (remoteDispatchNodeGetCPUMapFlags) Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- daemon/remote.c | 44 +++++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 49 ++++++++++++++++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 13 ++++++++++- src/remote_protocol-structs | 12 ++++++++++ 4 files changed, 117 insertions(+), 1 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index e7fe128..36291d1 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -4544,6 +4544,50 @@ cleanup: return rv; } +static int +remoteDispatchNodeGetCPUMapFlags(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client ATTRIBUTE_UNUSED, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_node_get_cpu_map_flags_args *args, + remote_node_get_cpu_map_flags_ret *ret) +{ + unsigned char *cpumap; + unsigned int online; + unsigned int flags; + int cpunum; + int rv = -1; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + flags = args->flags; + + cpunum = virNodeGetCPUMapFlags(priv->conn, &cpumap, &online, flags); + if (cpunum < 0) + goto cleanup; + + /* 'serialize' return cpumap */ + ret->cpumap.cpumap_len = VIR_CPU_MAPLEN(cpunum); + ret->cpumap.cpumap_val = (char *) cpumap; + cpumap = NULL; + + ret->online = online; + ret->ret = cpunum; + + rv = 0; + +cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + VIR_FREE(cpumap); + return rv; +} + /*----- Helpers. -----*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index fc4c696..7c89477 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -5749,6 +5749,54 @@ done: return rv; } +int +remoteNodeGetCPUMapFlags(virConnectPtr conn, + unsigned char **cpumap, + unsigned int *online, + unsigned int flags) +{ + int rv = -1; + remote_node_get_cpu_map_flags_args args; + remote_node_get_cpu_map_flags_ret ret; + struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); + + /* IMPROVEME: send info about optional args */ + args.flags = flags; + + memset (&ret, 0, sizeof(ret)); + if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_CPU_MAP_FLAGS, + (xdrproc_t) xdr_remote_node_get_cpu_map_flags_args, + (char *) &args, + (xdrproc_t) xdr_remote_node_get_cpu_map_flags_ret, + (char *) &ret) == -1) + goto done; + + if (ret.ret < 0) + goto cleanup; + + if (cpumap) { + if (VIR_ALLOC_N(*cpumap, ret.cpumap.cpumap_len) < 0) { + virReportOOMError(); + goto cleanup; + } + memcpy(*cpumap, ret.cpumap.cpumap_val, ret.cpumap.cpumap_len); + } + + if (online) + *online = ret.online; + + rv = ret.ret; + +cleanup: + xdr_free ((xdrproc_t) xdr_remote_node_get_cpu_map_flags_ret, + (char *) &ret); +done: + remoteDriverUnlock(priv); + return rv; +} + static void remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event) { @@ -6063,6 +6111,7 @@ static virDriver remote_driver = { .domainGetHostname = remoteDomainGetHostname, /* 0.10.0 */ .nodeSetMemoryParameters = remoteNodeSetMemoryParameters, /* 0.10.2 */ .nodeGetMemoryParameters = remoteNodeGetMemoryParameters, /* 0.10.2 */ + .nodeGetCPUMapFlags = remoteNodeGetCPUMapFlags, /* 1.0.0 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index b0b530c..bc5e70f 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2666,6 +2666,16 @@ struct remote_node_get_memory_parameters_ret { int nparams; }; +struct remote_node_get_cpu_map_flags_args { + unsigned int flags; +}; + +struct remote_node_get_cpu_map_flags_ret { + opaque cpumap<REMOTE_CPUMAP_MAX>; + unsigned int online; + int ret; +}; + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -3008,7 +3018,8 @@ enum remote_procedure { REMOTE_PROC_NODE_GET_MEMORY_PARAMETERS = 289, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_BLOCK_COMMIT = 290, /* autogen autogen */ - REMOTE_PROC_NETWORK_UPDATE = 291 /* autogen autogen priority:high */ + REMOTE_PROC_NETWORK_UPDATE = 291, /* autogen autogen priority:high */ + REMOTE_PROC_NODE_GET_CPU_MAP_FLAGS = 292 /* skipgen skipgen */ /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 4d2627a..8f1e678 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -2123,6 +2123,17 @@ struct remote_node_get_memory_parameters_ret { } params; int nparams; }; +struct remote_node_get_cpu_map_flags_args { + u_int flags; +}; +struct remote_node_get_cpu_map_flags_ret { + struct { + u_int cpumap_len; + char * cpumap_val; + } cpumap; + u_int online; + int ret; +}; enum remote_procedure { REMOTE_PROC_OPEN = 1, REMOTE_PROC_CLOSE = 2, @@ -2415,4 +2426,5 @@ enum remote_procedure { REMOTE_PROC_NODE_GET_MEMORY_PARAMETERS = 289, REMOTE_PROC_DOMAIN_BLOCK_COMMIT = 290, REMOTE_PROC_NETWORK_UPDATE = 291, + REMOTE_PROC_NODE_GET_CPU_MAP_FLAGS = 292, }; -- 1.7.0.4

New macro VIR_CPU_USED added to facilitate the interpretation of cpu maps. Further, hardened the other cpumap macros against invocations like VIR_CPU_USE(cpumap + 1, cpu) Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- include/libvirt/libvirt.h.in | 20 ++++++++++++++++---- 1 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 6b72159..3e8e4f8 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1954,7 +1954,7 @@ int virDomainGetEmulatorPinInfo (virDomainPtr domain, * USE_CPU macro set the bit (CPU usable) of the related cpu in cpumap. */ -#define VIR_USE_CPU(cpumap,cpu) (cpumap[(cpu)/8] |= (1<<((cpu)%8))) +#define VIR_USE_CPU(cpumap,cpu) ((cpumap)[(cpu)/8] |= (1<<((cpu)%8))) /** * VIR_UNUSE_CPU: @@ -1965,7 +1965,19 @@ int virDomainGetEmulatorPinInfo (virDomainPtr domain, * USE_CPU macro reset the bit (CPU not usable) of the related cpu in cpumap. */ -#define VIR_UNUSE_CPU(cpumap,cpu) (cpumap[(cpu)/8] &= ~(1<<((cpu)%8))) +#define VIR_UNUSE_CPU(cpumap,cpu) ((cpumap)[(cpu)/8] &= ~(1<<((cpu)%8))) + +/** + * VIR_CPU_USED: + * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) + * @cpu: the physical CPU number + * + * This macro can be used in conjunction with virNodeGetCPUMapFlags() API. + * VIR_CPU_USED returns true if the bit of the related CPU is set. + * + */ + +#define VIR_CPU_USED(cpumap,cpu) ((cpumap)[(cpu)/8] & (1<<((cpu)%8))) /** * VIR_CPU_MAPLEN: @@ -1976,7 +1988,7 @@ int virDomainGetEmulatorPinInfo (virDomainPtr domain, * CPU map between a single virtual & all physical CPUs of a domain. */ -#define VIR_CPU_MAPLEN(cpu) (((cpu)+7)/8) +#define VIR_CPU_MAPLEN(cpu) (((cpu)+7)/8) int virDomainGetVcpus (virDomainPtr domain, @@ -1998,7 +2010,7 @@ int virDomainGetVcpus (virDomainPtr domain, */ #define VIR_CPU_USABLE(cpumaps,maplen,vcpu,cpu) \ - (cpumaps[((vcpu)*(maplen))+((cpu)/8)] & (1<<((cpu)%8))) + ((cpumaps)[((vcpu)*(maplen))+((cpu)/8)] & (1<<((cpu)%8))) /** * VIR_COPY_CPUMAP: -- 1.7.0.4

- Added a new host command nodecpumap - Added documentation Example: $ virsh nodecpumap CPUs present: 8 CPUs online: 3 CPU map: 10101000 Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- tools/virsh-host.c | 41 +++++++++++++++++++++++++++++++++++++++++ tools/virsh.pod | 5 +++++ 2 files changed, 46 insertions(+), 0 deletions(-) diff --git a/tools/virsh-host.c b/tools/virsh-host.c index 5cf192d..e4f9327 100644 --- a/tools/virsh-host.c +++ b/tools/virsh-host.c @@ -271,6 +271,46 @@ cmdNodeinfo(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) } /* + * "nodecpumap" command + */ +static const vshCmdInfo info_node_cpumap[] = { + {"help", N_("node cpu map")}, + {"desc", N_("Displays the node's total number of CPUs, the number of" + " online CPUs and the list of online CPUs.")}, + {NULL, NULL} +}; + +static bool +cmdNodeCpuMap(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ + int cpu, cpunum; + unsigned char *cpumap = NULL; + unsigned int online; + bool ret = false; + + cpunum = virNodeGetCPUMapFlags(ctl->conn, &cpumap, &online, 0); + if (cpunum < 0) { + vshError(ctl, "%s", _("Unable to get cpu map")); + goto cleanup; + } + + vshPrint(ctl, "%-15s %d\n", _("CPUs present:"), cpunum); + vshPrint(ctl, "%-15s %d\n", _("CPUs online:"), online); + + vshPrint(ctl, "%-15s ", _("CPU map:")); + for (cpu = 0; cpu < cpunum; cpu++) { + vshPrint(ctl, "%d", VIR_CPU_USED(cpumap, cpu) ? 1 : 0); + } + vshPrint(ctl, "\n"); + + ret = true; + + cleanup: + VIR_FREE(cpumap); + return ret; +} + +/* * "nodecpustats" command */ static const vshCmdInfo info_nodecpustats[] = { @@ -1026,6 +1066,7 @@ const vshCmdDef hostAndHypervisorCmds[] = { {"hostname", cmdHostname, NULL, info_hostname, 0}, {"node-memory-tune", cmdNodeMemoryTune, opts_node_memory_tune, info_node_memory_tune, 0}, + {"nodecpumap", cmdNodeCpuMap, NULL, info_node_cpumap, 0}, {"nodecpustats", cmdNodeCpuStats, opts_node_cpustats, info_nodecpustats, 0}, {"nodeinfo", cmdNodeinfo, NULL, info_nodeinfo, 0}, {"nodememstats", cmdNodeMemStats, opts_node_memstats, info_nodememstats, 0}, diff --git a/tools/virsh.pod b/tools/virsh.pod index 2d90b7b..9a2c0e1 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -277,6 +277,11 @@ and size of the physical memory. The output corresponds to virNodeInfo structure. Specifically, the "CPU socket(s)" field means number of CPU sockets per NUMA cell. +=item B<nodecpumap> + +Displays the node's total number of CPUs, the number of online CPUs +and the list of online CPUs. + =item B<nodecpustats> [I<cpu>] [I<--percent>] Returns cpu stats of the node. -- 1.7.0.4

Added an implemention of virNodeGetCPUMapFlags to nodeinfo.c, (nodeGetCPUMapFlags) which can be used by all drivers for a Linux hypervisor host. Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- src/libvirt_private.syms | 1 + src/nodeinfo.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ src/nodeinfo.h | 6 +++++ 3 files changed, 56 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fe31bbe..44d5927 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -900,6 +900,7 @@ virNodeDeviceObjUnlock; # nodeinfo.h nodeCapsInitNUMA; nodeGetCPUmap; +nodeGetCPUMapFlags; nodeGetCPUStats; nodeGetCellsFreeMemory; nodeGetFreeMemory; diff --git a/src/nodeinfo.c b/src/nodeinfo.c index c0e60d8..84cf796 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -1203,6 +1203,55 @@ nodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, #endif } +int nodeGetCPUMapFlags(virConnectPtr conn, + unsigned char **cpumap, + unsigned int *online, + unsigned int flags) +{ + virBitmapPtr cpusPresent = NULL; + virBitmapPtr cpusOnline = NULL; + int maxpresent, maxonline, i; + int ret = -1; + + virCheckFlags(0, 1); + + if (!(cpusPresent = nodeGetCPUmap(conn, &maxpresent, "present"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to retrieve 'present' CPU map")); + goto cleanup; + } + + if (!(cpusOnline = nodeGetCPUmap(conn, &maxonline, "online"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to retrieve 'online' CPU map")); + goto cleanup; + } + + if (cpumap && VIR_ALLOC_N(*cpumap, VIR_CPU_MAPLEN(maxpresent)) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (online) + *online = 0; + + i = -1; + while ((i=virBitmapNextSetBit(cpusOnline, i)) >= 0) { + if (online) + (*online)++; + + if (cpumap) + VIR_USE_CPU(*cpumap,i); + } + + ret = maxpresent + 1; + +cleanup: + virBitmapFree(cpusPresent); + virBitmapFree(cpusOnline); + return ret; +} + #if HAVE_NUMACTL # if LIBNUMA_API_VERSION <= 1 # define NUMA_MAX_N_CPUS 4096 diff --git a/src/nodeinfo.h b/src/nodeinfo.h index 2eda846..e210e6b 100644 --- a/src/nodeinfo.h +++ b/src/nodeinfo.h @@ -59,4 +59,10 @@ int nodeSetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int nparams, unsigned int flags); + +int nodeGetCPUMapFlags(virConnectPtr conn, + unsigned char **cpumap, + unsigned int *online, + unsigned int flags); + #endif /* __VIR_NODEINFO_H__*/ -- 1.7.0.4

Driver support added for: - test, pretending 8 host CPUS, 3 being online - qemu, using nodeGetCPUMapFlags Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- src/qemu/qemu_driver.c | 1 + src/test/test_driver.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0787039..2c6364b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -13928,6 +13928,7 @@ static virDriver qemuDriver = { .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */ .nodeGetMemoryParameters = nodeGetMemoryParameters, /* 0.10.2 */ .nodeSetMemoryParameters = nodeSetMemoryParameters, /* 0.10.2 */ + .nodeGetCPUMapFlags = nodeGetCPUMapFlags, /* 1.0.0 */ }; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index c9f9115..24f3b11 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -5687,6 +5687,35 @@ static int testListAllDomains(virConnectPtr conn, return ret; } +static int testNodeGetCPUMapFlags(virConnectPtr conn, + unsigned char **cpumap, + unsigned int *online, + unsigned int flags) +{ + testConnPtr privconn = conn->privateData; + int ret = -1; + + virCheckFlags(0, -1); + + testDriverLock(privconn); + if (cpumap) { + if (VIR_ALLOC_N(*cpumap, 1) < 0) { + virReportOOMError(); + goto cleanup; + } + *cpumap[0] = 0x15; + } + + if (online) + *online = 3; + + ret = 8; + +cleanup: + testDriverUnlock(privconn); + return ret; +} + static virDriver testDriver = { .no = VIR_DRV_TEST, @@ -5756,6 +5785,7 @@ static virDriver testDriver = { .domainEventRegisterAny = testDomainEventRegisterAny, /* 0.8.0 */ .domainEventDeregisterAny = testDomainEventDeregisterAny, /* 0.8.0 */ .isAlive = testIsAlive, /* 0.9.8 */ + .nodeGetCPUMapFlags = testNodeGetCPUMapFlags, /* 1.0.0 */ }; static virNetworkDriver testNetworkDriver = { -- 1.7.0.4

Added a method getCPUMapFlags to virConnect. It can be used as follows: import libvirt import sys import os conn = libvirt.openReadOnly(None) if conn == None: print 'Failed to open connection to the hypervisor' sys.exit(1) try: (cpus, cpumap, online) = conn.getCPUMapFlags(0) except: print 'Failed to extract the node cpu map information' sys.exit(1) print 'CPUs total %d, online %d' % (cpus, online) print 'CPU map %s' % str(cpumap) del conn print "OK" sys.exit(0) Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> --- python/libvirt-override-api.xml | 6 ++++ python/libvirt-override.c | 56 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 0 deletions(-) diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index b76fb4e..59ac190 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -542,5 +542,11 @@ <arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/> <arg name='flags' type='int' info='unused, always pass 0'/> </function> + <function name='virNodeGetCPUMapFlags' file='python'> + <info>Get node CPU information</info> + <return type='str *' info='(cpunum, online, cpumap) on success, None on error'/> + <arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/> + <arg name='flags' type='int' info='unused, pass 0'/> + </function> </symbols> </api> diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 81099b1..9d86964 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -6347,6 +6347,61 @@ cleanup: return ret; } +static PyObject * +libvirt_virNodeGetCPUMapFlags(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) +{ + virConnectPtr conn; + PyObject *pyobj_conn; + PyObject *ret = NULL; + PyObject *pycpumap = NULL; + PyObject *pyused = NULL; + int i_retval; + unsigned char *cpumap = NULL; + unsigned int online = 0; + unsigned int flags; + int i; + + if (!PyArg_ParseTuple(args, (char *)"Oi:virNodeGetCPUMapFlags", + &pyobj_conn, &flags)) + return NULL; + conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virNodeGetCPUMapFlags(conn, &cpumap, &online, flags); + LIBVIRT_END_ALLOW_THREADS; + + if (i_retval < 0) + goto error; + + if ((ret = PyTuple_New(3)) == NULL) + goto error; + + if ((pycpumap = PyList_New(i_retval)) == NULL) + goto error; + + for (i = 0; i < i_retval; i++) { + if ((pyused = PyBool_FromLong(VIR_CPU_USED(cpumap, i))) == NULL) + goto error; + if (PyList_SetItem(pycpumap, i, pyused) < 0) + goto error; + } + + PyTuple_SetItem(ret, 0, PyLong_FromLong(i_retval)); + PyTuple_SetItem(ret, 1, pycpumap); + PyTuple_SetItem(ret, 2, PyLong_FromLong(online)); + +cleanup: + VIR_FREE(cpumap); + return ret; +error: + Py_XDECREF(ret); + Py_XDECREF(pycpumap); + Py_XDECREF(pyused); + ret = VIR_PY_NONE; + goto cleanup; +} + /************************************************************************ * * @@ -6464,6 +6519,7 @@ static PyMethodDef libvirtMethods[] = { {(char *) "virDomainGetDiskErrors", libvirt_virDomainGetDiskErrors, METH_VARARGS, NULL}, {(char *) "virNodeGetMemoryParameters", libvirt_virNodeGetMemoryParameters, METH_VARARGS, NULL}, {(char *) "virNodeSetMemoryParameters", libvirt_virNodeSetMemoryParameters, METH_VARARGS, NULL}, + {(char *) "virNodeGetCPUMapFlags", libvirt_virNodeGetCPUMapFlags, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; -- 1.7.0.4
participants (1)
-
Viktor Mihajlovski