Returns CPU flags in the CPU inventory

These flags will be processed in a new ironic-inspector plugin
to support setting capabilities like cpu_vt (virtualization enabled).

Change-Id: I5fe9310c316841eabdd2d5e2ef2ae30afa03d29a
Partial-Bug: #1571580
This commit is contained in:
Dmitry Tantsur 2016-04-20 13:58:14 +02:00
parent 015fad6054
commit 6670da4ed1
5 changed files with 74 additions and 9 deletions

View File

@ -87,8 +87,8 @@ The inventory is a dictionary (JSON object), containing at least the following
fields:
``cpu``
CPU information: ``model_name``, ``frequency``, ``count`` and
``architecture``.
CPU information: ``model_name``, ``frequency``, ``count``,
``architecture`` and ``flags``.
``memory``
RAM information: ``total`` (total size in bytes), ``physical_mb``

View File

@ -189,13 +189,16 @@ class NetworkInterface(encoding.SerializableComparable):
class CPU(encoding.SerializableComparable):
serializable_fields = ('model_name', 'frequency', 'count', 'architecture')
serializable_fields = ('model_name', 'frequency', 'count', 'architecture',
'flags')
def __init__(self, model_name, frequency, count, architecture):
def __init__(self, model_name, frequency, count, architecture,
flags=None):
self.model_name = model_name
self.frequency = frequency
self.count = count
self.architecture = architecture
self.flags = flags or []
class Memory(encoding.SerializableComparable):
@ -446,11 +449,25 @@ class GenericHardwareManager(HardwareManager):
# 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 = 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(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'))
architecture=cpu_info.get('architecture'),
flags=flags)
def get_memory(self):
# psutil returns a long, so we force it to an int

View File

@ -224,6 +224,11 @@ L3 cache: 15360K
NUMA node0 CPU(s): 0-11
"""
# NOTE(dtanstur): flags list stripped down for sanity reasons
CPUINFO_FLAGS_OUTPUT = """
flags : fpu vme de pse
"""
class FakeHardwareManager(hardware.GenericHardwareManager):
def __init__(self, hardware_support):
@ -437,7 +442,10 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
@mock.patch.object(utils, 'execute')
def test_get_cpus(self, mocked_execute):
mocked_execute.return_value = LSCPU_OUTPUT, ''
mocked_execute.side_effect = [
(LSCPU_OUTPUT, ''),
(CPUINFO_FLAGS_OUTPUT, '')
]
cpus = self.hardware.get_cpus()
self.assertEqual('Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz',
@ -445,10 +453,14 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
self.assertEqual('2400.0000', cpus.frequency)
self.assertEqual(4, cpus.count)
self.assertEqual('x86_64', cpus.architecture)
self.assertEqual(['fpu', 'vme', 'de', 'pse'], cpus.flags)
@mock.patch.object(utils, 'execute')
def test_get_cpus2(self, mocked_execute):
mocked_execute.return_value = LSCPU_OUTPUT_NO_MAX_MHZ, ''
mocked_execute.side_effect = [
(LSCPU_OUTPUT_NO_MAX_MHZ, ''),
(CPUINFO_FLAGS_OUTPUT, '')
]
cpus = self.hardware.get_cpus()
self.assertEqual('Intel(R) Xeon(R) CPU E5-1650 v3 @ 3.50GHz',
@ -456,6 +468,37 @@ class TestGenericHardwareManager(test_base.BaseTestCase):
self.assertEqual('1794.433', cpus.frequency)
self.assertEqual(12, cpus.count)
self.assertEqual('x86_64', cpus.architecture)
self.assertEqual(['fpu', 'vme', 'de', 'pse'], cpus.flags)
@mock.patch.object(utils, 'execute')
def test_get_cpus_no_flags(self, mocked_execute):
mocked_execute.side_effect = [
(LSCPU_OUTPUT, ''),
processutils.ProcessExecutionError()
]
cpus = self.hardware.get_cpus()
self.assertEqual('Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz',
cpus.model_name)
self.assertEqual('2400.0000', cpus.frequency)
self.assertEqual(4, cpus.count)
self.assertEqual('x86_64', cpus.architecture)
self.assertEqual([], cpus.flags)
@mock.patch.object(utils, 'execute')
def test_get_cpus_illegal_flags(self, mocked_execute):
mocked_execute.side_effect = [
(LSCPU_OUTPUT, ''),
('I am not a flag', '')
]
cpus = self.hardware.get_cpus()
self.assertEqual('Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz',
cpus.model_name)
self.assertEqual('2400.0000', cpus.frequency)
self.assertEqual(4, cpus.count)
self.assertEqual('x86_64', cpus.architecture)
self.assertEqual([], cpus.flags)
@mock.patch('psutil.version_info', (2, 0))
@mock.patch('psutil.phymem_usage', autospec=True)

View File

@ -176,7 +176,8 @@ class TestBaseIronicPythonAgent(test_base.BaseTestCase):
u'model_name': u'Awesome Jay CPU x10 9001',
u'frequency': u'9001',
u'count': u'10',
u'architecture': u'ARMv9'
u'architecture': u'ARMv9',
u'flags': [],
},
u'disks': [
{
@ -313,7 +314,8 @@ class TestBaseIronicPythonAgent(test_base.BaseTestCase):
u'model_name': u'Awesome Jay CPU x10 9001',
u'frequency': u'9001',
u'count': u'10',
u'architecture': u'ARMv9'
u'architecture': u'ARMv9',
u'flags': [],
},
u'disks': [
{

View File

@ -0,0 +1,3 @@
---
features:
- Return CPU flags with the CPU inventory.