From 0105bad3ec72cc69dc92ce6eec7deb8c744e65ae Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Mon, 9 Feb 2009 10:41:21 +0000
Subject: [PATCH] Export the cpu nodes and sockets from Xen
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is a hand-picked forward patch of commit 1755 on the 1.2 branch
(hand-picked since the trees diverged too much since then):

    The patch changed the xen hypervisor to compute the number of cpu
    sockets/nodes and enables the command line and the RAPI to show this
    information (for RAPI is enabled by default in node details, for gnt-one
    one can use the new β€œcnodes” and β€œcsockets” fields).

    Originally-Reviewed-by: ultrotter

For the KVM and fake hypervisors, the patch just exports 1 for both
nodes and sockets. This can be fixed, by looking at the
/sys/devices/system/cpu/cpuN/topology directories, and computing the
actual information, but that should be done in a separate patch.

Reviewed-by: imsnah
---
 lib/cmdlib.py             |  4 +++-
 lib/hypervisor/hv_fake.py |  3 +++
 lib/hypervisor/hv_kvm.py  |  5 +++--
 lib/hypervisor/hv_xen.py  | 19 +++++++++++++++++--
 lib/rapi/rlib2.py         |  4 +++-
 scripts/gnt-node          |  2 +-
 6 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 7bde6234c..f4067517b 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -1759,7 +1759,7 @@ class LUQueryNodes(NoHooksLU):
     "dtotal", "dfree",
     "mtotal", "mnode", "mfree",
     "bootid",
-    "ctotal",
+    "ctotal", "cnodes", "csockets",
     )
 
   _FIELDS_STATIC = utils.FieldSet(
@@ -1838,6 +1838,8 @@ class LUQueryNodes(NoHooksLU):
             "dfree": fn(int, nodeinfo.get('vg_free', None)),
             "ctotal": fn(int, nodeinfo.get('cpu_total', None)),
             "bootid": nodeinfo.get('bootid', None),
+            "cnodes": fn(int, nodeinfo.get('cpu_nodes', None)),
+            "csockets": fn(int, nodeinfo.get('cpu_sockets', None)),
             }
         else:
           live_data[name] = {}
diff --git a/lib/hypervisor/hv_fake.py b/lib/hypervisor/hv_fake.py
index a1daf0173..1211cbd95 100644
--- a/lib/hypervisor/hv_fake.py
+++ b/lib/hypervisor/hv_fake.py
@@ -200,6 +200,9 @@ class FakeHypervisor(hv_base.BaseHypervisor):
     except EnvironmentError, err:
       raise errors.HypervisorError("Failed to list node info: %s" % err)
     result['cpu_total'] = cpu_total
+    # FIXME: export correct data here
+    result['cpu_nodes'] = 1
+    result['cpu_sockets'] = 1
 
     return result
 
diff --git a/lib/hypervisor/hv_kvm.py b/lib/hypervisor/hv_kvm.py
index e43a24cc4..c3d1db515 100644
--- a/lib/hypervisor/hv_kvm.py
+++ b/lib/hypervisor/hv_kvm.py
@@ -639,6 +639,9 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     except EnvironmentError, err:
       raise errors.HypervisorError("Failed to list node info: %s" % err)
     result['cpu_total'] = cpu_total
+    # FIXME: export correct data here
+    result['cpu_nodes'] = 1
+    result['cpu_sockets'] = 1
 
     return result
 
@@ -779,5 +782,3 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     if iso_path and not os.path.isfile(iso_path):
       raise errors.HypervisorError("Instance cdrom image '%s' not found or"
                                    " not a file" % iso_path)
-
-
diff --git a/lib/hypervisor/hv_xen.py b/lib/hypervisor/hv_xen.py
index b34b221d5..fb5a28d24 100644
--- a/lib/hypervisor/hv_xen.py
+++ b/lib/hypervisor/hv_xen.py
@@ -199,10 +199,13 @@ class XenHypervisor(hv_base.BaseHypervisor):
   def GetNodeInfo(self):
     """Return information about the node.
 
-    @return: a dict with the following keys (values in MiB):
+    @return: a dict with the following keys (memory values in MiB):
           - memory_total: the total memory size on the node
           - memory_free: the available memory on the node for instances
           - memory_dom0: the memory used by the node itself, if available
+          - nr_cpus: total number of CPUs
+          - nr_nodes: in a NUMA system, the number of domains
+          - nr_sockets: the number of physical CPU sockets in the node
 
     """
     # note: in xen 3, memory has changed to total_memory
@@ -214,6 +217,7 @@ class XenHypervisor(hv_base.BaseHypervisor):
 
     xmoutput = result.stdout.splitlines()
     result = {}
+    cores_per_socket = threads_per_core = nr_cpus = None
     for line in xmoutput:
       splitfields = line.split(":", 1)
 
@@ -225,7 +229,18 @@ class XenHypervisor(hv_base.BaseHypervisor):
         elif key == 'free_memory':
           result['memory_free'] = int(val)
         elif key == 'nr_cpus':
-          result['cpu_total'] = int(val)
+          nr_cpus = result['cpu_total'] = int(val)
+        elif key == 'nr_nodes':
+          result['cpu_nodes'] = int(val)
+        elif key == 'cores_per_socket':
+          cores_per_socket = int(val)
+        elif key == 'threads_per_core':
+          threads_per_core = int(val)
+
+    if (cores_per_socket is not None and
+        threads_per_core is not None and nr_cpus is not None):
+      result['cpu_sockets'] = nr_cpus / (cores_per_socket * threads_per_core)
+
     dom0_info = self.GetInstanceInfo("Domain-0")
     if dom0_info is not None:
       result['memory_dom0'] = dom0_info[2]
diff --git a/lib/rapi/rlib2.py b/lib/rapi/rlib2.py
index 050ab660a..67d802d10 100644
--- a/lib/rapi/rlib2.py
+++ b/lib/rapi/rlib2.py
@@ -42,7 +42,9 @@ I_FIELDS = ["name", "admin_state", "os",
 N_FIELDS = ["name", "offline", "master_candidate",
             "dtotal", "dfree",
             "mtotal", "mnode", "mfree",
-            "pinst_cnt", "sinst_cnt", "tags"]
+            "pinst_cnt", "sinst_cnt", "tags",
+            "ctotal", "cnodes", "csockets",
+            ]
 
 
 class R_version(baserlib.R_Generic):
diff --git a/scripts/gnt-node b/scripts/gnt-node
index 606b7c874..b6552abf3 100755
--- a/scripts/gnt-node
+++ b/scripts/gnt-node
@@ -50,7 +50,7 @@ _LIST_HEADERS = {
   "dtotal": "DTotal", "dfree": "DFree",
   "mtotal": "MTotal", "mnode": "MNode", "mfree": "MFree",
   "bootid": "BootID",
-  "ctotal": "CTotal",
+  "ctotal": "CTotal", "cnodes": "CNodes", "csockets": "CSockets",
   "tags": "Tags",
   "serial_no": "SerialNo",
   "master_candidate": "MasterC",
-- 
GitLab