Adding support to view indiv. cpu-core info
Closes-Bug: #1639340 This commit adds the relevant changes to the get_cpu function, keeping it backwards compatible with the old method. Change-Id: I3c3a792e88e9a041236eca7283ebfdf1026910d8
This commit is contained in:
parent
df7eccd7f1
commit
c79d74eaf7
|
@ -806,6 +806,16 @@ class NetworkInterface(encoding.SerializableComparable):
|
|||
self.client_id = client_id
|
||||
|
||||
|
||||
class CPUInfo(encoding.SerializableComparable):
|
||||
serializable_fields = ('cpus')
|
||||
|
||||
def __init__(self, cpus=None):
|
||||
self.cpus = cpus or []
|
||||
|
||||
def cpus(self):
|
||||
return self.cpus
|
||||
|
||||
|
||||
class CPU(encoding.SerializableComparable):
|
||||
serializable_fields = ('model_name', 'frequency', 'count', 'architecture',
|
||||
'flags', 'socket_count')
|
||||
|
@ -1470,35 +1480,74 @@ class GenericHardwareManager(HardwareManager):
|
|||
|
||||
return network_interfaces_list
|
||||
|
||||
def get_cpus(self):
|
||||
lines = il_utils.execute('lscpu')[0]
|
||||
@staticmethod
|
||||
def create_cpu_info_dict(lines):
|
||||
cpu_info = {k.strip().lower(): v.strip() for k, v in
|
||||
(line.split(':', 1)
|
||||
for line in lines.split('\n')
|
||||
if line.strip())}
|
||||
# Current CPU frequency can be different from maximum one on modern
|
||||
# processors
|
||||
freq = cpu_info.get('cpu max mhz', cpu_info.get('cpu mhz'))
|
||||
for line in lines.split('\n')
|
||||
if line.strip())}
|
||||
|
||||
flags = []
|
||||
out = il_utils.try_execute('grep', '-Em1', '^flags', '/proc/cpuinfo')
|
||||
if out:
|
||||
try:
|
||||
# Example output (much longer for a real system):
|
||||
# flags : fpu vme de pse
|
||||
flags = out[0].strip().split(':', 1)[1].strip().split()
|
||||
except (IndexError, ValueError):
|
||||
LOG.warning('Malformed CPU flags information: %s', out)
|
||||
else:
|
||||
LOG.warning('Failed to get CPU flags')
|
||||
return cpu_info
|
||||
|
||||
return CPU(model_name=cpu_info.get('model name'),
|
||||
frequency=freq,
|
||||
# this includes hyperthreading cores
|
||||
count=int(cpu_info.get('cpu(s)')),
|
||||
architecture=cpu_info.get('architecture'),
|
||||
flags=flags,
|
||||
socket_count=int(cpu_info.get('socket(s)', 0)))
|
||||
def get_cpus(self):
|
||||
cpu_info_dicts = []
|
||||
cpus = []
|
||||
# Try the new method, if it fails fall back to the old one
|
||||
try:
|
||||
cores = il_utils.execute('cat /proc/cpuinfo')[0]
|
||||
|
||||
cores = cores.replace("\t", "")
|
||||
cores = cores.split("\n\n")
|
||||
|
||||
for lines in cores:
|
||||
cpu_info = self.create_cpu_info_dict(lines)
|
||||
|
||||
if cpu_info is not None:
|
||||
cpu_info_dicts.append(cpu_info)
|
||||
|
||||
if len(cpu_info_dicts) == 0:
|
||||
raise Exception
|
||||
|
||||
except Exception:
|
||||
lines = il_utils.execute('lscpu')[0]
|
||||
cpu_info = self.create_cpu_info_dict(lines)
|
||||
cpu_info_dicts.append(cpu_info)
|
||||
|
||||
for cpu_info in cpu_info_dicts:
|
||||
# Current CPU frequency can be different from maximum one on modern
|
||||
# processors
|
||||
freq = cpu_info.get('cpu max mhz', cpu_info.get('cpu mhz'))
|
||||
|
||||
flags = []
|
||||
out = il_utils.try_execute(
|
||||
'grep', '-Em1', '^flags', '/proc/cpuinfo'
|
||||
)
|
||||
if out:
|
||||
try:
|
||||
# Example output (much longer for a real system):
|
||||
# flags : fpu vme de pse
|
||||
flags = out[0].strip().split(':', 1)[1].strip().split()
|
||||
except (IndexError, ValueError):
|
||||
LOG.warning('Malformed CPU flags information: %s', out)
|
||||
else:
|
||||
LOG.warning('Failed to get CPU flags')
|
||||
|
||||
cpu = CPU(
|
||||
model_name=cpu_info.get('model name'),
|
||||
frequency=freq,
|
||||
# this includes hyperthreading cores
|
||||
count=int(cpu_info.get('cpu(s)', 0)),
|
||||
architecture=cpu_info.get('architecture'),
|
||||
flags=flags,
|
||||
socket_count=int(cpu_info.get('socket(s)', 0))
|
||||
)
|
||||
|
||||
cpus.append(cpu)
|
||||
|
||||
if len(cpus) == 1:
|
||||
return cpus[0]
|
||||
|
||||
return CPUInfo(cpus=cpus)
|
||||
|
||||
def get_memory(self):
|
||||
# psutil returns a long, so we force it to an int
|
||||
|
|
|
@ -338,6 +338,64 @@ L3 cache: 15360K
|
|||
NUMA node0 CPU(s): 0-11
|
||||
"""
|
||||
|
||||
|
||||
PROC_CPUINFO_OUTPUT = """
|
||||
processor : 0
|
||||
vendor_id : AuthenticAMD
|
||||
cpu family : 23
|
||||
model : 49
|
||||
model name : AMD EPYC 7282 16-Core Processor
|
||||
stepping : 0
|
||||
microcode : 0x8301055
|
||||
cpu MHz : 2794.748
|
||||
cache size : 512 KB
|
||||
physical id : 0
|
||||
siblings : 6
|
||||
core id : 0
|
||||
cpu cores : 6
|
||||
apicid : 0
|
||||
initial apicid : 0
|
||||
fpu : yes
|
||||
fpu_exception : yes
|
||||
cpuid level : 16
|
||||
wp : yes
|
||||
flags : fpu vme de pse
|
||||
bugs : sysret_ss_attrs
|
||||
bogomips : 5589.49
|
||||
TLB size : 1024 4K pages
|
||||
clflush size : 64
|
||||
cache_alignment : 64
|
||||
address sizes : 40 bits physical, 48 bits virtual
|
||||
power management:
|
||||
|
||||
processor : 1
|
||||
vendor_id : AuthenticAMD
|
||||
cpu family : 23
|
||||
model : 49
|
||||
model name : AMD EPYC 7282 16-Core Processor
|
||||
stepping : 0
|
||||
microcode : 0x8301055
|
||||
cpu MHz : 2794.748
|
||||
cache size : 512 KB
|
||||
physical id : 0
|
||||
siblings : 6
|
||||
core id : 1
|
||||
cpu cores : 6
|
||||
apicid : 1
|
||||
initial apicid : 1
|
||||
fpu : yes
|
||||
fpu_exception : yes
|
||||
cpuid level : 16
|
||||
wp : yes
|
||||
flags : fpu vme de pse
|
||||
bogomips : 5589.49
|
||||
TLB size : 1024 4K pages
|
||||
clflush size : 64
|
||||
cache_alignment : 64
|
||||
address sizes : 40 bits physical, 48 bits virtual
|
||||
power management:
|
||||
"""
|
||||
|
||||
# NOTE(dtanstur): flags list stripped down for sanity reasons
|
||||
CPUINFO_FLAGS_OUTPUT = """
|
||||
flags : fpu vme de pse
|
||||
|
|
|
@ -889,6 +889,19 @@ class TestGenericHardwareManager(base.IronicAgentTest):
|
|||
self.assertEqual('x86_64', cpus.architecture)
|
||||
self.assertEqual(['fpu', 'vme', 'de', 'pse'], cpus.flags)
|
||||
|
||||
@mock.patch.object(il_utils, 'execute', autospec=True)
|
||||
def test_get_cpus_multi(self, mocked_execute):
|
||||
mocked_execute.side_effect = [(hws.PROC_CPUINFO_OUTPUT, ''),
|
||||
(hws.CPUINFO_FLAGS_OUTPUT, ''),
|
||||
(hws.CPUINFO_FLAGS_OUTPUT, '')]
|
||||
|
||||
cpus = self.hardware.get_cpus()
|
||||
clock_speeds = ["2794.748", "2794.748"]
|
||||
for i, cpu in enumerate(cpus.cpus):
|
||||
self.assertEqual('AMD EPYC 7282 16-Core Processor',
|
||||
cpu.model_name)
|
||||
self.assertEqual(clock_speeds[i], cpu.frequency)
|
||||
|
||||
@mock.patch.object(il_utils, 'execute', autospec=True)
|
||||
def test_get_cpus_no_flags(self, mocked_execute):
|
||||
mocked_execute.side_effect = [(hws.LSCPU_OUTPUT, ''),
|
||||
|
|
Loading…
Reference in New Issue