263 lines
7.9 KiB
Diff
263 lines
7.9 KiB
Diff
From 59d3912d71832092c4daadf31fb3184f50aaa8b0 Mon Sep 17 00:00:00 2001
|
|
From: John Kacur <jkacur@redhat.com>
|
|
Date: Thu, 18 May 2017 14:49:03 +0200
|
|
Subject: [PATCH 09/18] rteval: Remove rteval/sysinfo/systopology.py
|
|
|
|
Remove rteval/sysinfo/systopology.py as it is replaced by
|
|
rteval/systopology.py
|
|
|
|
As was intended by 6e4d54b8c6d3697efba0e3d
|
|
|
|
Signed-off-by: John Kacur <jkacur@redhat.com>
|
|
---
|
|
rteval/sysinfo/systopology.py | 237 ------------------------------------------
|
|
1 file changed, 237 deletions(-)
|
|
delete mode 100644 rteval/sysinfo/systopology.py
|
|
|
|
diff --git a/rteval/sysinfo/systopology.py b/rteval/sysinfo/systopology.py
|
|
deleted file mode 100644
|
|
index a6e5c1a8b409..000000000000
|
|
--- a/rteval/sysinfo/systopology.py
|
|
+++ /dev/null
|
|
@@ -1,237 +0,0 @@
|
|
-# -*- coding: utf-8 -*-
|
|
-#
|
|
-# Copyright 2016 - Clark Williams <williams@redhat.com>
|
|
-#
|
|
-# This program is free software; you can redistribute it and/or modify
|
|
-# it under the terms of the GNU General Public License as published by
|
|
-# the Free Software Foundation; either version 2 of the License, or
|
|
-# (at your option) any later version.
|
|
-#
|
|
-# This program is distributed in the hope that it will be useful,
|
|
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-# GNU General Public License for more details.
|
|
-#
|
|
-# You should have received a copy of the GNU General Public License along
|
|
-# with this program; if not, write to the Free Software Foundation, Inc.,
|
|
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
-#
|
|
-# For the avoidance of doubt the "preferred form" of this code is one which
|
|
-# is in an open unpatent encumbered format. Where cryptographic key signing
|
|
-# forms part of the process of creating an executable the information
|
|
-# including keys needed to generate an equivalently functional executable
|
|
-# are deemed to be part of the source code.
|
|
-#
|
|
-
|
|
-import os, sys
|
|
-import os.path
|
|
-import glob
|
|
-
|
|
-def _sysread(path, obj):
|
|
- fp = open(os.path.join(path,obj), "r")
|
|
- return fp.readline().strip()
|
|
-
|
|
-#
|
|
-# class to provide access to a list of cpus
|
|
-#
|
|
-
|
|
-class CpuList(object):
|
|
- "Object that represents a group of system cpus"
|
|
-
|
|
- cpupath = '/sys/devices/system/cpu'
|
|
-
|
|
- def __init__(self, cpulist):
|
|
- if type(cpulist) is list:
|
|
- self.cpulist = cpulist
|
|
- elif type(cpulist) is str:
|
|
- self.cpulist = self.__expand_cpulist(cpulist)
|
|
- self.cpulist.sort()
|
|
-
|
|
- def __str__(self):
|
|
- return self.__collapse_cpulist(self.cpulist)
|
|
-
|
|
- def __contains__(self, cpu):
|
|
- return cpu in self.cpulist
|
|
-
|
|
- def __len__(self):
|
|
- return len(self.cpulist)
|
|
-
|
|
-
|
|
- # return the index of the last element of a sequence
|
|
- # that steps by one
|
|
- def __longest_sequence(self, cpulist):
|
|
- lim = len(cpulist)
|
|
- for idx,val in enumerate(cpulist):
|
|
- if idx+1 == lim:
|
|
- break
|
|
- if int(cpulist[idx+1]) != (int(cpulist[idx])+1):
|
|
- return idx
|
|
- return lim - 1
|
|
-
|
|
-
|
|
- #
|
|
- # collapse a list of cpu numbers into a string range
|
|
- # of cpus (e.g. 0-5, 7, 9)
|
|
- #
|
|
- def __collapse_cpulist(self, cpulist):
|
|
- if len(cpulist) == 0:
|
|
- return ""
|
|
- idx = self.__longest_sequence(cpulist)
|
|
- if idx == 0:
|
|
- seq = str(cpulist[0])
|
|
- else:
|
|
- if idx == 1:
|
|
- seq = "%d,%d" % (cpulist[0], cpulist[idx])
|
|
- else:
|
|
- seq = "%d-%d" % (cpulist[0], cpulist[idx])
|
|
-
|
|
- rest = self.__collapse_cpulist(cpulist[idx+1:])
|
|
- if rest == "":
|
|
- return seq
|
|
- return ",".join((seq, rest))
|
|
-
|
|
- # expand a string range into a list
|
|
- # don't error check against online cpus
|
|
- def __expand_cpulist(self, cpulist):
|
|
- '''expand a range string into an array of cpu numbers'''
|
|
- result = []
|
|
- for part in cpulist.split(','):
|
|
- if '-' in part:
|
|
- a, b = part.split('-')
|
|
- a, b = int(a), int(b)
|
|
- result.extend(range(a, b + 1))
|
|
- else:
|
|
- a = int(part)
|
|
- result.append(a)
|
|
- return [ int(i) for i in list(set(result)) ]
|
|
-
|
|
- # returns the list of cpus tracked
|
|
- def getcpulist(self):
|
|
- return self.cpulist
|
|
-
|
|
- # check whether cpu n is online
|
|
- def isonline(self, n):
|
|
- if n not in self.cpulist:
|
|
- raise RuntimeError, "invalid cpu number %d" % n
|
|
- if n == 0:
|
|
- return True
|
|
- path = os.path.join(CpuList.cpupath,'cpu%d' % n)
|
|
- if os.path.exists(path):
|
|
- return _sysread(path, "online") == 1
|
|
- return False
|
|
-
|
|
-#
|
|
-# class to abstract access to NUMA nodes in /sys filesystem
|
|
-#
|
|
-
|
|
-class NumaNode(object):
|
|
- "class representing a system NUMA node"
|
|
-
|
|
- # constructor argument is the full path to the /sys node file
|
|
- # e.g. /sys/devices/system/node/node0
|
|
- def __init__(self, path):
|
|
- self.path = path
|
|
- self.nodeid = int(os.path.basename(path)[4:].strip())
|
|
- self.cpus = CpuList(_sysread(self.path, "cpulist"))
|
|
- self.getmeminfo()
|
|
-
|
|
- # function for the 'in' operator
|
|
- def __contains__(self, cpu):
|
|
- return cpu in self.cpus
|
|
-
|
|
- # allow the 'len' builtin
|
|
- def __len__(self):
|
|
- return len(self.cpus)
|
|
-
|
|
- # string representation of the cpus for this node
|
|
- def __str__(self):
|
|
- return self.getcpustr()
|
|
-
|
|
- # read info about memory attached to this node
|
|
- def getmeminfo(self):
|
|
- self.meminfo = {}
|
|
- for l in open(os.path.join(self.path, "meminfo"), "r"):
|
|
- elements = l.split()
|
|
- key=elements[2][0:-1]
|
|
- val=int(elements[3])
|
|
- if len(elements) == 5 and elements[4] == "kB":
|
|
- val *= 1024
|
|
- self.meminfo[key] = val
|
|
-
|
|
- # return list of cpus for this node as a string
|
|
- def getcpustr(self):
|
|
- return str(self.cpus)
|
|
-
|
|
- # return list of cpus for this node
|
|
- def getcpulist(self):
|
|
- return self.cpus.getcpulist()
|
|
-
|
|
-#
|
|
-# Class to abstract the system topology of numa nodes and cpus
|
|
-#
|
|
-class SysTopology(object):
|
|
- "Object that represents the system's NUMA-node/cpu topology"
|
|
-
|
|
- cpupath = '/sys/devices/system/cpu'
|
|
- nodepath = '/sys/devices/system/node'
|
|
-
|
|
- def __init__(self):
|
|
- self.nodes = {}
|
|
- self.getinfo()
|
|
-
|
|
- def __len__(self):
|
|
- return len(self.nodes.keys())
|
|
-
|
|
- # inplement the 'in' function
|
|
- def __contains__(self, node):
|
|
- for n in self.nodes:
|
|
- if self.nodes[n].nodeid == node:
|
|
- return True
|
|
- return False
|
|
-
|
|
- # allow indexing for the nodes
|
|
- def __getitem__(self, key):
|
|
- return self.nodes[key]
|
|
-
|
|
- # allow iteration over the cpus for the node
|
|
- def __iter__(self):
|
|
- self.current = 0
|
|
- return self
|
|
-
|
|
- # iterator function
|
|
- def next(self):
|
|
- if self.current >= len(self.nodes):
|
|
- raise StopIteration
|
|
- n = self.nodes[self.current]
|
|
- self.current += 1
|
|
- return n
|
|
-
|
|
- def getinfo(self):
|
|
- nodes = glob.glob(os.path.join(SysTopology.nodepath, 'node[0-9]*'))
|
|
- if not nodes:
|
|
- raise RuntimeError, "No valid nodes found in %s!" % SysTopology.nodepath
|
|
- nodes.sort()
|
|
- for n in nodes:
|
|
- node = int(os.path.basename(n)[4:])
|
|
- self.nodes[node] = NumaNode(n)
|
|
-
|
|
- def getnodes(self):
|
|
- return self.nodes.keys()
|
|
-
|
|
- def getcpus(self, node):
|
|
- return self.nodes[node]
|
|
-
|
|
-
|
|
-
|
|
-if __name__ == "__main__":
|
|
-
|
|
- def unit_test():
|
|
- s = SysTopology()
|
|
- print "number of nodes: %d" % len(s)
|
|
- for n in s:
|
|
- print "node[%d]: %s" % (n.nodeid, n)
|
|
- print "system has numa node 0: %s" % (0 in s)
|
|
- print "system has numa node 2: %s" % (2 in s)
|
|
- print "system has numa node 24: %s" % (24 in s)
|
|
-
|
|
- unit_test()
|
|
--
|
|
2.14.3
|
|
|