Skip to content

Commit c5544fb

Browse files
committed
Collect processor, memory and BIOS output of dmidecode
Implements an optional collector 'collect_dmidecode_info' for collecting detailed info of processor, memory and BIOS and adds it to the inspection data. Collects BIOS, processor, memory info and adds under the 'dmi' key. Change-Id: Ida9b418ca579b15de70d17886631f3b21697987e Closes-Bug: #1635057
1 parent 7dbe9b5 commit c5544fb

4 files changed

Lines changed: 820 additions & 0 deletions

File tree

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Copyright (C) 2017 Intel Corporation
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from oslo_concurrency import processutils
16+
from oslo_log import log as logging
17+
18+
from ironic_python_agent import utils
19+
20+
21+
LOG = logging.getLogger(__name__)
22+
23+
24+
def collect_dmidecode_info(data, failures):
25+
"""Collect detailed processor, memory and bios info.
26+
27+
The data is gathered using dmidecode utility.
28+
29+
:param data: mutable dict that we'll send to inspector
30+
:param failures: AccumulatedFailures object
31+
"""
32+
try:
33+
shret, _err = utils.execute('dmidecode', '-t', 'bios',
34+
'-t', 'processor', '-t', 'memory')
35+
except (processutils.ProcessExecutionError, OSError) as exc:
36+
failures.add('failed to run dmidecode: %s', exc)
37+
return
38+
39+
data['dmi'] = {}
40+
try:
41+
data['dmi'] = parse_dmi(shret)
42+
except (ValueError, IndexError) as exc:
43+
LOG.warning('Failed to collect dmidecode info %s:', exc)
44+
45+
46+
def parse_dmi(data):
47+
"""Parse the dmidecode output.
48+
49+
Returns a dict.
50+
"""
51+
TYPE = {
52+
'bios': 0,
53+
'cpu': 4,
54+
'memory': 16,
55+
'devices': 17,
56+
}
57+
58+
dmi_info = {
59+
'bios': {},
60+
'cpu': [],
61+
'memory': {'devices': []},
62+
}
63+
64+
memorydata, devicedata = [], []
65+
66+
# Dmi data blocks are separated by a blank line.
67+
# First line in each block starts with 'Handle 0x'.
68+
for infoblock in data.split('\n\n'):
69+
if not len(infoblock):
70+
continue
71+
72+
if infoblock.startswith('Handle 0x'):
73+
try:
74+
# Determine DMI type value. Handle line will look like this:
75+
# Handle 0x0018, DMI type 17, 27 bytes
76+
dmi_type = int(infoblock.split(',', 2)[1].strip()[
77+
len('DMI type'):])
78+
except (ValueError, IndexError) as exc:
79+
LOG.warning('Failed to parse Handle type in dmi output: %s',
80+
exc)
81+
continue
82+
83+
if dmi_type in TYPE.values():
84+
sectiondata = _parse_handle_block(infoblock)
85+
86+
if dmi_type == TYPE['bios']:
87+
dmi_info['bios'] = sectiondata
88+
elif dmi_type == TYPE['cpu']:
89+
dmi_info['cpu'].append(sectiondata)
90+
elif dmi_type == TYPE['memory']:
91+
memorydata.append(sectiondata)
92+
elif dmi_type == TYPE['devices']:
93+
devicedata.append(sectiondata)
94+
95+
return _save_data(dmi_info, memorydata, devicedata)
96+
97+
98+
def _parse_handle_block(lines):
99+
rows = {}
100+
list_value = False
101+
for line in lines.splitlines():
102+
line = line.strip()
103+
if ':' in line:
104+
list_value = False
105+
k, v = [i.strip() for i in line.split(':', 1)]
106+
if v:
107+
rows[k] = v
108+
else:
109+
rows[k] = []
110+
list_value = True
111+
elif 'Handle 0x' in line:
112+
rows['Handle'] = line
113+
elif list_value:
114+
rows[k].append(line)
115+
116+
return rows
117+
118+
119+
def _save_data(dmi_info, memorydata, devicedata):
120+
if memorydata:
121+
try:
122+
device_count = sum([int(d['Number Of Devices'])
123+
for d in memorydata])
124+
dmi_info['memory'] = memorydata[0]
125+
dmi_info['memory']['Number Of Devices'] = device_count
126+
dmi_info['memory'].pop('Handle')
127+
except (KeyError) as exc:
128+
LOG.warning('Failed to process memory dmi data: %s', exc)
129+
raise
130+
131+
if devicedata:
132+
dmi_info['memory']['devices'] = devicedata
133+
134+
return dmi_info

0 commit comments

Comments
 (0)