blob: 1c903e106a44695720ee4b2af4ce8024f30d0d49 [file] [log] [blame]
# -*- python -*-
# -*- coding: utf-8 -*-
"""
classes for /sys/devices/system/cpu/
so we can get topology information and do CPU hotplug operations
"""
import os
class cpu:
"""
class to query if a cpu is online or not
and to bring a cpu online or to take it offline
"""
def __init__(self, basedir, name):
self.name = name
self.dir = os.path.join(basedir, name)
self.online = None
self.reload()
def __lt__(self, other):
# Previously it is assumed that name[:3] == "cpu" and name[3].isdigit(), so:
return int(self.name[3:]) < int(other.name[3:])
def readfile(self, name):
""" read file "name", typically the per cpu "online" file """
try:
with open(os.path.join(self.dir, name)) as f:
value = f.readline().strip()
return value
except:
raise
def __repr__(self):
return f'name={self.name}, online={self.online}, physical_package_id={self.physical_package_id}'
def reload_online(self):
""" read the "online" file """
self.online = True
try:
self.online = self.readfile("online") == "1"
except FileNotFoundError:
# boot CPU, usually cpu0, can't be brought offline, so
# lacks the file and non root users can't read. In both
# cases assume CPU is online.
pass
def reload(self):
""" Load or reload the values of this class """
self.reload_online()
if self.online:
try:
self.physical_package_id = self.readfile("topology/physical_package_id")
except:
self.physical_package_id = "0"
else:
self.physical_package_id = None
def set_online(self, online=True):
""" Turn a cpu on or off using the online file """
try:
with open(os.path.join(self.dir, "online"), "w") as f:
f.write("1" if online else "0")
except:
pass
self.reload_online()
return online == self.online
class cpus:
""" a class that creates a dictionary of cpu information keyed by cpu """
def __init__(self, basedir="/sys/devices/system/cpu"):
self.basedir = basedir
self.cpus = {}
self.sockets = {}
self.reload()
self.nr_cpus = len(self.cpus)
def __getitem__(self, key):
return self.cpus[key]
def keys(self):
""" Returns a list of keys, for example a key could be cpu9 """
return list(self.cpus.keys())
def __contains__(self, key):
return key in self.cpus
def __repr__(self):
return f'cpus={self.cpus}, sockets={self.sockets}, nr_cpus={self.nr_cpus}'
def reload(self):
""" load or reload the values of this class """
sockets_to_sort = []
for name in os.listdir(self.basedir):
if name[:3] != "cpu" or not name[3].isdigit():
continue
if name in self.cpus:
self.cpus[name].reload(self.basedir)
else:
c = cpu(self.basedir, name)
self.cpus[name] = c
try:
socket = c.physical_package_id
except:
socket = "0"
if socket in self.sockets:
self.sockets[socket].insert(0, c)
else:
self.sockets[socket] = [c, ]
if socket not in sockets_to_sort:
sockets_to_sort.append(socket)
for socket in sockets_to_sort:
self.sockets[socket].sort(key=lambda x: int(x.name[3:]))
if __name__ == '__main__':
cpus = cpus()
print(f'{cpus}')
for socket in list(cpus.sockets.keys()):
print("Socket %s" % socket)
for c in cpus.sockets[socket]:
print(" %s" % c.name)
print(" online: %s" % c.online)
c.set_online(False)
print(" online: %s" % c.online)
c.set_online()
print(" online: %s" % c.online)