Blame SOURCES/libvirt-python-examples-Introduce-nodestats-example.patch

b06491
From 3d040733d21991fb8141b6a32dca2eca29652ace Mon Sep 17 00:00:00 2001
b06491
Message-Id: <3d040733d21991fb8141b6a32dca2eca29652ace@dist-git>
b06491
From: Michal Privoznik <mprivozn@redhat.com>
b06491
Date: Fri, 17 Jul 2015 11:45:33 +0200
b06491
Subject: [PATCH] examples: Introduce nodestats example
b06491
b06491
https://bugzilla.redhat.com/show_bug.cgi?id=1051494
b06491
b06491
So, this is an exercise to show libvirt capabilities. Firstly, for
b06491
each host NUMA nodes some statistics are printed out, i.e. total
b06491
memory and free memory. Then, for each running domain, that has memory
b06491
strictly bound to certain host nodes, a small statistics of how much
b06491
memory it takes is printed out too. For instance:
b06491
b06491
        # ./examples/nodestats.py
b06491
        NUMA stats
b06491
        NUMA nodes:     0       1       2       3
b06491
        MemTotal:       3950    3967    3937    3943
b06491
        MemFree:        66      56      42      41
b06491
        Domain 'fedora':
b06491
                Overall memory: 1536 MiB
b06491
        Domain 'fedora22':
b06491
                Overall memory: 2048 MiB
b06491
        Domain 'fedora21':
b06491
                Overall memory: 1024 MiB nodes 0-1
b06491
                Node 0: 1024 MiB nodes 0-1
b06491
        Domain 'gentoo':
b06491
                Overall memory: 4096 MiB nodes 0-3
b06491
                Node 0: 1024 MiB nodes 0
b06491
                Node 1: 1024 MiB nodes 1
b06491
                Node 2: 1024 MiB nodes 2
b06491
                Node 3: 1024 MiB nodes 3
b06491
b06491
We can see 4 host NUMA nodes, all of them having roughly 4GB of RAM.
b06491
Yeah, all of them has nearly all the memory consumed. Then, there are
b06491
four domains running. For instance, domain 'fedora' has 1.5GB memory
b06491
which is not pinned onto any specific host NUMA node. Domain 'gentoo' on
b06491
the other hand has 4GB memory and has 4 NUMA nodes which are pinned 1:1
b06491
to host nodes.
b06491
b06491
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
b06491
(cherry picked from commit fa21f3d927b29991741e2d7a8ebc2a920778ecba)
b06491
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
b06491
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
b06491
---
b06491
 examples/nodestats.py | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++
b06491
 1 file changed, 87 insertions(+)
b06491
 create mode 100755 examples/nodestats.py
b06491
b06491
diff --git a/examples/nodestats.py b/examples/nodestats.py
b06491
new file mode 100755
b06491
index 0000000..c01dead
b06491
--- /dev/null
b06491
+++ b/examples/nodestats.py
b06491
@@ -0,0 +1,87 @@
b06491
+#!/usr/bin/env python
b06491
+# Print some host NUMA node statistics
b06491
+#
b06491
+# Authors:
b06491
+#   Michal Privoznik <mprivozn@redhat.com>
b06491
+
b06491
+import libvirt
b06491
+import sys
b06491
+from xml.dom import minidom
b06491
+import libxml2
b06491
+
b06491
+def xpath_eval(ctxt, path):
b06491
+    res = ctxt.xpathEval(path)
b06491
+    if res is None or len(res) == 0:
b06491
+        value = None
b06491
+    else:
b06491
+        value = res[0].content
b06491
+    return value
b06491
+
b06491
+try:
b06491
+    conn = libvirt.openReadOnly(None)
b06491
+except libvirt.libvirtError:
b06491
+    print("Failed to connect to the hypervisor")
b06491
+    sys.exit(1)
b06491
+
b06491
+try:
b06491
+    capsXML = conn.getCapabilities()
b06491
+except libvirt.libvirtError:
b06491
+    print("Failed to request capabilities")
b06491
+    sys.exit(1)
b06491
+
b06491
+caps = minidom.parseString(capsXML)
b06491
+cells = caps.getElementsByTagName("cells")[0]
b06491
+
b06491
+nodesIDs = [ int(proc.getAttribute("id"))
b06491
+             for proc in cells.getElementsByTagName("cell") ]
b06491
+
b06491
+nodesMem = [ conn.getMemoryStats(int(proc))
b06491
+             for proc in nodesIDs]
b06491
+
b06491
+doms = conn.listAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE)
b06491
+
b06491
+domsStrict = [ proc
b06491
+               for proc in doms
b06491
+               if proc.numaParameters()["numa_mode"] == libvirt.VIR_DOMAIN_NUMATUNE_MEM_STRICT ]
b06491
+
b06491
+domsStrictCfg = {}
b06491
+for dom in domsStrict:
b06491
+    xmlStr = dom.XMLDesc()
b06491
+    doc = libxml2.parseDoc(xmlStr)
b06491
+    ctxt = doc.xpathNewContext()
b06491
+
b06491
+    domsStrictCfg[dom] = {}
b06491
+
b06491
+    pin = ctxt.xpathEval("string(/domain/numatune/memory/@nodeset)")
b06491
+    memsize = ctxt.xpathEval("string(/domain/memory)")
b06491
+    domsStrictCfg[dom]["memory"] = {"size": int(memsize), "pin": pin}
b06491
+
b06491
+    for memnode in ctxt.xpathEval("/domain/numatune/memnode"):
b06491
+        ctxt.setContextNode(memnode)
b06491
+        cellid = xpath_eval(ctxt, "@cellid")
b06491
+        nodeset = xpath_eval(ctxt, "@nodeset")
b06491
+
b06491
+        nodesize = xpath_eval(ctxt, "/domain/cpu/numa/cell[@id='%s']/@memory" % cellid)
b06491
+        domsStrictCfg[dom][cellid] = {"size": int(nodesize), "pin": nodeset}
b06491
+
b06491
+
b06491
+print("NUMA stats")
b06491
+print("NUMA nodes:\t" + "\t".join(str(node) for node in nodesIDs))
b06491
+print("MemTotal:\t" + "\t".join(str(i.get("total") // 1024) for i in nodesMem))
b06491
+print("MemFree:\t" + "\t".join(str(i.get("free") // 1024) for i in nodesMem))
b06491
+
b06491
+for dom, v in domsStrictCfg.items():
b06491
+    print("Domain '%s':\t" % dom.name())
b06491
+
b06491
+    toPrint = "\tOverall memory: %d MiB" % (v["memory"]["size"] // 1024)
b06491
+    if v["memory"]["pin"] is not None and v["memory"]["pin"] is not "":
b06491
+        toPrint = toPrint + " nodes %s" % v["memory"]["pin"]
b06491
+    print(toPrint)
b06491
+
b06491
+    for k, node in sorted(v.items()):
b06491
+        if k is "memory":
b06491
+            continue
b06491
+        toPrint = "\tNode %s:\t%d MiB" % (k, node["size"] // 1024)
b06491
+        if node["pin"] is not None and node["pin"] is not "":
b06491
+            toPrint = toPrint + " nodes %s" % node["pin"]
b06491
+        print(toPrint)
b06491
-- 
b06491
2.5.0
b06491