From 5678297d39c9c745721ac8c0735b4e17ae1baf63 Mon Sep 17 00:00:00 2001 From: Jannik Schönartz Date: Tue, 20 Oct 2020 20:30:24 +0200 Subject: Add smartctl error handling, lspci, edid hex data and cleanup main function --- .../bas-python/scripts/00collect_hw_info_json.py | 94 ++++++++++++++++++---- 1 file changed, 79 insertions(+), 15 deletions(-) diff --git a/modules.d/bas-python/scripts/00collect_hw_info_json.py b/modules.d/bas-python/scripts/00collect_hw_info_json.py index 552840bc..6c835b3e 100755 --- a/modules.d/bas-python/scripts/00collect_hw_info_json.py +++ b/modules.d/bas-python/scripts/00collect_hw_info_json.py @@ -1,6 +1,7 @@ from dmiparser import DmiParser import json import subprocess +import shlex import sys import argparse from os import listdir @@ -10,31 +11,98 @@ __debug = False # Run dmi command as subprocess and get the stdout def run_subprocess(_cmd): global __debug - proc = subprocess.Popen(_cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE) - stdout, stderr = proc.communicate() + proc = subprocess.run(_cmd, shell=True, capture_output=True) + stdout = proc.stdout + stderr = proc.stderr + if __debug: print(_cmd + ':') print() print('Errors:') print(stderr.decode()) print() - if proc.returncode > 0: - print('Critical Error:') + # stderr len instead of proc.returncode > 0 is used because some have returncode 2 but are still valid + if len(stderr.decode()) > 0: + print('Critical Error: ' + str(proc.returncode)) print('Failed with error: ' + stderr.decode()) print() return False else: return stdout.decode() +# Get and parse dmidecode using dmiparser def get_dmidecode(): _dmiraw = run_subprocess('dmidecode') _dmiparsed = '' if _dmiraw: # Parse dmidecode _dmiparsed = DmiParser(_dmiraw) - return str(_dmiparsed) + return json.loads(str(_dmiparsed)) else: - return False + return [] + +# Get smartctl output in json format +def get_smartctl(): + # Get and filter all disks + disks = listdir('/dev/disk/by-path/') + filteredDisks = [i for i in disks if (not "-part" in i) and (not "-usb-" in i)] + smartctl = {} + for d in filteredDisks: + output = run_subprocess('smartctl -x --json /dev/disk/by-path/' + d) + if isinstance(output, str): + smartctl[d] = json.loads(output) + return smartctl + +# Get and process "lspci -mn" output +def get_lspci(): + lspci = [] + lspci_raw = run_subprocess('lspci -mn').split('\n') + for line in lspci_raw: + if len(line) <= 0: continue + + # Parsing shell like command parameters + parse = shlex.split(line) + lspci_parsed = {} + arguments = [] + values = [] + for parameter in parse: + # Split values from arguments + if parameter.startswith('-'): + arguments.append(parameter) + else: + values.append(parameter) + + # Prepare values positions are in order + if len(values) >= 6: + lspci_parsed['slot'] = values[0] + lspci_parsed['class'] = values[1] + lspci_parsed['vendor'] = values[2] + lspci_parsed['device'] = values[3] + lspci_parsed['subsystem_vendor'] = values[4] + lspci_parsed['subsystem'] = values[5] + + # Prepare arguments + if len(arguments) > 0: + for arg in arguments: + if arg.startswith('-p'): + lspci_parsed['progif'] = arg[2:] + elif arg.startswith('-r'): + lspci_parsed['rev'] = arg[2:] + else: continue + + lspci.append(lspci_parsed) + return lspci + +# Get and convert EDID data to hex +def get_edid(): + edid = [] + display_paths = run_subprocess('ls /sys/class/drm/*/edid').split('\n') + for dp in display_paths: + if dp == '': continue + edid_hex = open(dp, 'rb').read().hex() + if len(edid_hex) > 0: + edid.append(edid_hex) + return edid def main(): global __debug @@ -49,16 +117,12 @@ def main(): # Run the tools _collecthw = {} + _collecthw['dmidecode'] = get_dmidecode() + _collecthw['smartctl'] = get_smartctl() + _collecthw['lspci'] = get_lspci() + _collecthw['edit'] = get_edid() - _dmidecode = get_dmidecode() - if isinstance(_dmidecode, str): - _collecthw['dmidecode'] = json.loads(_dmidecode) - - # Get Smartcontrol info - # TODO: error handling - disks = listdir('/dev/disk/by-path/') - filteredDisks = [i for i in disks if (not "-part" in i) and (not "-usb-" in i)] - _collecthw['smartctl'] = [json.loads(subprocess.run('smartctl -x --json /dev/disk/by-path/' + d, shell=True, capture_output=True).stdout.decode()) for d in filteredDisks] + # Print out the final json print(json.dumps(_collecthw)) if __name__ == "__main__": -- cgit v1.2.3-55-g7522