summaryrefslogtreecommitdiffstats
path: root/modules.d/bas-python/scripts/00collect_hw_info_json.py
blob: 8176bdc585207b1205652bc2992e4eea3a077c6a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
from dmiparser import DmiParser
import json
import subprocess
from subprocess import PIPE
import shlex
import sys
import argparse
from os import listdir

__debug = False

# Run dmi command as subprocess and get the stdout
def run_subprocess(_cmd):
    global __debug
    proc = subprocess.run(_cmd, shell=True, stdout=PIPE, stderr=PIPE)
    stdout = proc.stdout
    stderr = proc.stderr

    if __debug:
        print(_cmd + ':')
        print()
        print('Errors:')
        print(stderr.decode())
        print()
    # 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 json.loads(str(_dmiparsed))
    else:
        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 ip data in json format
def get_ip():
    result = []
    ip_raw = run_subprocess('ip --json addr show')
    if isinstance(ip_raw, str):
        result = json.loads(ip_raw)
    return result

# 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 get_lshw():
    result = []
    lshw_raw = run_subprocess('lshw -json')
    if isinstance(lshw_raw, str):
        result = json.loads(lshw_raw)
    return result

def main():
    global __debug
    
    # Create and parse arguments
    parser = argparse.ArgumentParser(description='Collects hardware data from different tools and returns it as json.')
    parser.add_argument('-d', '--debug', action='store_true', help='Prints all STDERR messages. (Non critical included)')
    args = parser.parse_args()

    if args.debug:
        __debug = True

    # Run the tools
    _collecthw = {}
    _collecthw['dmidecode'] = get_dmidecode()
    _collecthw['smartctl'] = get_smartctl()
    _collecthw['lspci'] = get_lspci()
    _collecthw['ip'] = get_ip()
    _collecthw['edid'] = get_edid()
    _collecthw['lshw'] = get_lshw()
    
    # Print out the final json
    print(json.dumps(_collecthw))

if __name__ == "__main__":
    main()