diff options
Diffstat (limited to 'core/modules/hardware-stats/data/opt/openslx/hardware-stats/dmiparser.py')
-rw-r--r-- | core/modules/hardware-stats/data/opt/openslx/hardware-stats/dmiparser.py | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/core/modules/hardware-stats/data/opt/openslx/hardware-stats/dmiparser.py b/core/modules/hardware-stats/data/opt/openslx/hardware-stats/dmiparser.py new file mode 100644 index 00000000..9e3a0bfa --- /dev/null +++ b/core/modules/hardware-stats/data/opt/openslx/hardware-stats/dmiparser.py @@ -0,0 +1,201 @@ +import re +import json +from itertools import takewhile +from enum import Enum + +__all__ = ['DmiParser'] + +DmiParserState = Enum ( + 'DmiParserState', + ( + 'GET_SECT', + 'GET_PROP', + 'GET_PROP_ITEM', + ) +) + +class DmiParserSectionHandle(object): + '''A handle looks like this + + Handle 0x0066, DMI type 148, 48 bytes + ''' + def __init__(self): + self.id= '' + self.type = '' + self.bytes = 0 + + def __str__(self): + return json.dumps(self.__dict__) + +class DmiParserSectionProp(object): + '''A property looks like this + + Characteristics: + 3.3 V is provided + PME signal is supported + SMBus signal is supported + ''' + def __init__(self, value:str): + self.values = [] + + if value: + self.append(value) + + def __str__(self): + return json.dumps(self.__dict__) + + def append(self, item:str): + self.values.append(item) + +class DmiParserSection(object): + '''A section looks like this + + On Board Device 1 Information + Type: Video + Status: Enabled + Description: ServerEngines Pilot III + ''' + def __init__(self): + self.handle = None + self.name = '' + self.props = {} + + def __str__(self): + return json.dumps(self.__dict__) + + def append(self, key:str, prop:str): + self.props[key] = prop + +class DmiParser(object): + '''This parse dmidecode output to JSON + ''' + + def __init__(self, text:str, **kwargs): + ''' + text: output of command dmidecode + kwargs: these will pass to json.dumps + ''' + self._text = text + self._kwargs = kwargs + self._indentLv = lambda l: len(list(takewhile(lambda c: "\t" == c, l))) + self._sections = [] + + if type(text) is not str: + raise TypeError("%s want a %s but got %s" %( + self.__class__, type(__name__), type(text))) + + self._parse(text) + + def __str__(self): + return json.dumps(self._sections, **self._kwargs) + + def _parse(self, text:str): + lines = self._text.splitlines() + rhandle = r'^Handle\s(.+?),\sDMI\stype\s(\d+?),\s(\d+?)\sbytes$' + section = None + prop = None + state = None + k, v = None, None + + for i, l in enumerate(lines): + if i == len(lines) - 1 or DmiParserState.GET_SECT == state: + # Add previous section if exist + if section: + # Add previous prop if exist + if prop: + section.append(k, json.loads(str(prop))) + prop = None + + self._sections.append(json.loads(str(section))) + section = None + + if not l: + continue + + if l.startswith('Handle'): + state = DmiParserState.GET_SECT + handle = DmiParserSectionHandle() + match = re.match(rhandle, l) + handle.id, handle.type, handle.bytes = match.groups() + continue + + if DmiParserState.GET_SECT == state: + section = DmiParserSection() + section.handle = json.loads(str(handle)) + section.name = l + state = DmiParserState.GET_PROP + continue + + if DmiParserState.GET_PROP == state: + k, v = [x.strip() for x in l.split(':', 1)] + prop = DmiParserSectionProp(v) + lv = self._indentLv(l) - self._indentLv(lines[i+1]) + + if v: + if not lv: + section.append(k, json.loads(str(prop))) + prop = None + elif -1 == lv: + state = DmiParserState.GET_PROP_ITEM + continue + else: + if -1 == lv: + state = DmiParserState.GET_PROP_ITEM + continue + + # Next section for this handle + if not self._indentLv(lines[i+1]): + state = DmiParserState.GET_SECT + + if DmiParserState.GET_PROP_ITEM == state: + prop.append(l.strip()) + + lv = self._indentLv(l) - self._indentLv(lines[i+1]) + + if lv: + section.append(k, json.loads(str(prop))) + prop = None + + if lv > 1: + state = DmiParserState.GET_SECT + else: + state = DmiParserState.GET_PROP + +if '__main__' == __name__: + text='''# dmidecode 3.0 +Getting SMBIOS data from sysfs. +SMBIOS 2.7 present. + +Handle 0x0003, DMI type 2, 17 bytes +Base Board Information + Manufacturer: Intel Corporation + Product Name: S2600WT2R + Version: H21573-372 + Serial Number: BQWL81150522 + Asset Tag: Base Board Asset Tag + Features: + Board is a hosting board + Board is replaceable + Location In Chassis: Part Component + Chassis Handle: 0x0000 + Type: Motherboard + Contained Object Handles: 0 + + ''' + + # just print + parser = DmiParser(text) + #parser = DmiParser(text, sort_keys=True, indent=2) + print("parser is %s" %(type(parser))) + print(parser) + + # if you want a string + dmistr = str(parser) + print("dmistr is %s" %(type(dmistr))) + print(dmistr) + + # if you want a data structure + dmidata = json.loads(str(parser)) + print("dmidata is %s" %(type(dmidata))) + print(dmidata) + |