2022-03-24 12:13:28 +00:00
|
|
|
import json
|
|
|
|
|
|
|
|
from dmidecode import DMIParse
|
|
|
|
|
|
|
|
from ereuse_devicehub.parser.computer import (
|
|
|
|
Display,
|
|
|
|
GraphicCard,
|
|
|
|
NetworkAdapter,
|
|
|
|
SoundCard,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class ParseSnapshot:
|
|
|
|
def __init__(self, snapshot, default="n/a"):
|
|
|
|
self.default = default
|
2022-03-25 12:55:05 +00:00
|
|
|
self.dmidecode_raw = snapshot["data"]["dmidecode"]
|
2022-03-24 12:13:28 +00:00
|
|
|
self.smart_raw = snapshot["data"]["smart"]
|
|
|
|
self.hwinfo_raw = snapshot["data"]["hwinfo"]
|
|
|
|
self.device = {"actions": []}
|
|
|
|
self.components = []
|
|
|
|
|
|
|
|
self.dmi = DMIParse(self.dmidecode_raw)
|
|
|
|
self.smart = self.loads(self.smart_raw)
|
|
|
|
self.hwinfo = self.parse_hwinfo()
|
|
|
|
|
|
|
|
self.set_basic_datas()
|
2022-03-25 12:55:05 +00:00
|
|
|
self.set_components()
|
2022-03-24 12:30:53 +00:00
|
|
|
self.snapshot_json = {
|
2022-03-24 12:13:28 +00:00
|
|
|
"device": self.device,
|
|
|
|
"software": "Workbench",
|
2022-03-25 12:55:05 +00:00
|
|
|
"components": self.components,
|
2022-03-24 12:13:28 +00:00
|
|
|
"uuid": snapshot['uuid'],
|
|
|
|
"type": snapshot['type'],
|
|
|
|
"version": snapshot["version"],
|
2022-03-25 12:55:05 +00:00
|
|
|
"endTime": snapshot["timestamp"],
|
|
|
|
"elapsed": 1,
|
2022-03-24 12:13:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
def set_basic_datas(self):
|
|
|
|
self.device['manufacturer'] = self.dmi.manufacturer()
|
|
|
|
self.device['model'] = self.dmi.model()
|
|
|
|
self.device['serialNumber'] = self.dmi.serial_number()
|
|
|
|
self.device['type'] = self.get_type()
|
|
|
|
self.device['sku'] = self.get_sku()
|
|
|
|
self.device['version'] = self.get_version()
|
2022-03-25 12:55:05 +00:00
|
|
|
# self.device['uuid'] = self.get_uuid()
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def set_components(self):
|
|
|
|
self.get_cpu()
|
|
|
|
self.get_ram()
|
|
|
|
self.get_mother_board()
|
2022-03-25 12:55:05 +00:00
|
|
|
self.get_data_storage()
|
|
|
|
self.get_networks()
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_cpu(self):
|
|
|
|
# TODO @cayop generation, brand and address not exist in dmidecode
|
|
|
|
for cpu in self.dmi.get('Processor'):
|
|
|
|
self.components.append(
|
|
|
|
{
|
|
|
|
"actions": [],
|
|
|
|
"type": "Processor",
|
2022-03-25 12:55:05 +00:00
|
|
|
"speed": self.get_cpu_speed(cpu),
|
2022-03-24 12:13:28 +00:00
|
|
|
"cores": int(cpu.get('Core Count', 1)),
|
|
|
|
"model": cpu.get('Version'),
|
|
|
|
"threads": int(cpu.get('Thread Count', 1)),
|
|
|
|
"manufacturer": cpu.get('Manufacturer'),
|
|
|
|
"serialNumber": cpu.get('Serial Number'),
|
|
|
|
"generation": cpu.get('Generation'),
|
|
|
|
"brand": cpu.get('Brand'),
|
|
|
|
"address": cpu.get('Address'),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_ram(self):
|
|
|
|
# TODO @cayop format and model not exist in dmidecode
|
|
|
|
for ram in self.dmi.get("Memory Device"):
|
|
|
|
self.components.append(
|
|
|
|
{
|
|
|
|
"actions": [],
|
|
|
|
"type": "RamModule",
|
|
|
|
"size": self.get_ram_size(ram),
|
|
|
|
"speed": self.get_ram_speed(ram),
|
|
|
|
"manufacturer": ram.get("Manufacturer", self.default),
|
|
|
|
"serialNumber": ram.get("Serial Number", self.default),
|
2022-03-25 12:55:05 +00:00
|
|
|
"interface": ram.get("Type", "DDR"),
|
|
|
|
"format": ram.get("Format", "DIMM"), # "DIMM",
|
2022-03-24 12:13:28 +00:00
|
|
|
"model": ram.get(
|
|
|
|
"Model", self.default
|
|
|
|
), # "48594D503131325336344350362D53362020",
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_mother_board(self):
|
|
|
|
# TODO @cayop model, not exist in dmidecode
|
|
|
|
for moder_board in self.dmi.get("Baseboard"):
|
|
|
|
self.components.append(
|
|
|
|
{
|
|
|
|
"actions": [],
|
|
|
|
"type": "Motherboard",
|
|
|
|
"version": moder_board.get("Version"),
|
|
|
|
"serialNumber": moder_board.get("Serial Number"),
|
|
|
|
"manufacturer": moder_board.get("Manufacturer"),
|
|
|
|
"biosDate": self.get_bios_date(),
|
|
|
|
"firewire": self.get_firmware(),
|
2022-03-25 12:55:05 +00:00
|
|
|
"ramMaxSize": self.get_max_ram_size(),
|
|
|
|
"ramSlots": len(self.dmi.get("Memory Device")),
|
|
|
|
"slots": self.get_ram_slots(),
|
2022-03-24 12:13:28 +00:00
|
|
|
"model": moder_board.get("Product Name"), # ??
|
|
|
|
"pcmcia": self.get_pcmcia_num(), # ??
|
|
|
|
"serial": self.get_serial_num(), # ??
|
|
|
|
"usb": self.get_usb_num(),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_usb_num(self):
|
|
|
|
return len(
|
2022-03-25 12:55:05 +00:00
|
|
|
[u for u in self.dmi.get("Port Connector") if u.get("Port Type") == "USB"]
|
2022-03-24 12:13:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
def get_serial_num(self):
|
|
|
|
return len(
|
2022-03-25 12:55:05 +00:00
|
|
|
[
|
|
|
|
u
|
|
|
|
for u in self.dmi.get("Port Connector")
|
|
|
|
if u.get("Port Type") == "SERIAL"
|
|
|
|
]
|
2022-03-24 12:13:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
def get_pcmcia_num(self):
|
|
|
|
return len(
|
2022-03-25 12:55:05 +00:00
|
|
|
[
|
|
|
|
u
|
|
|
|
for u in self.dmi.get("Port Connector")
|
|
|
|
if u.get("Port Type") == "PCMCIA"
|
|
|
|
]
|
2022-03-24 12:13:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
def get_bios_date(self):
|
2022-03-25 12:55:05 +00:00
|
|
|
return self.dmi.get("BIOS")[0].get("Release Date", self.default)
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_firmware(self):
|
2022-03-25 12:55:05 +00:00
|
|
|
return int(float(self.dmi.get("BIOS")[0].get("Firmware Revision", 1)))
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_max_ram_size(self):
|
2022-03-25 12:55:05 +00:00
|
|
|
size = 0
|
|
|
|
for slot in self.dmi.get("Physical Memory Array"):
|
|
|
|
capacity = slot.get("Maximum Capacity", '0').split(" ")[0]
|
|
|
|
size += int(capacity)
|
2022-03-24 12:13:28 +00:00
|
|
|
|
2022-03-25 12:55:05 +00:00
|
|
|
return size
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_ram_slots(self):
|
2022-03-25 12:55:05 +00:00
|
|
|
slots = 0
|
|
|
|
for x in self.dmi.get("Physical Memory Array"):
|
|
|
|
slots += int(x.get("Number Of Devices", 0))
|
|
|
|
return slots
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_ram_size(self, ram):
|
2022-03-25 12:55:05 +00:00
|
|
|
size = ram.get("Size", "0")
|
|
|
|
return int(size.split(" ")[0])
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_ram_speed(self, ram):
|
2022-03-25 12:55:05 +00:00
|
|
|
size = ram.get("Speed", "0")
|
|
|
|
return int(size.split(" ")[0])
|
|
|
|
|
|
|
|
def get_cpu_speed(self, cpu):
|
|
|
|
speed = cpu.get('Max Speed', "0")
|
|
|
|
return float(speed.split(" ")[0]) / 1024
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_sku(self):
|
2022-03-25 12:55:05 +00:00
|
|
|
return self.dmi.get("System")[0].get("SKU Number", self.default)
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_version(self):
|
2022-03-25 12:55:05 +00:00
|
|
|
return self.dmi.get("System")[0].get("Version", self.default)
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_uuid(self):
|
2022-03-25 12:55:05 +00:00
|
|
|
return self.dmi.get("System")[0].get("UUID", self.default)
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_chassis(self):
|
2022-03-25 12:55:05 +00:00
|
|
|
return self.dmi.get("Chassis")[0].get("Type", self.default)
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def get_type(self):
|
|
|
|
chassis_type = self.get_chassis()
|
|
|
|
return self.translation_to_devicehub(chassis_type)
|
|
|
|
|
|
|
|
def translation_to_devicehub(self, original_type):
|
|
|
|
lower_type = original_type.lower()
|
|
|
|
CHASSIS_TYPE = {
|
|
|
|
'Desktop': [
|
|
|
|
'desktop',
|
|
|
|
'low-profile',
|
|
|
|
'tower',
|
|
|
|
'docking',
|
|
|
|
'all-in-one',
|
|
|
|
'pizzabox',
|
|
|
|
'mini-tower',
|
|
|
|
'space-saving',
|
|
|
|
'lunchbox',
|
|
|
|
'mini',
|
|
|
|
'stick',
|
|
|
|
],
|
|
|
|
'Laptop': [
|
|
|
|
'portable',
|
|
|
|
'laptop',
|
|
|
|
'convertible',
|
|
|
|
'tablet',
|
|
|
|
'detachable',
|
|
|
|
'notebook',
|
|
|
|
'handheld',
|
|
|
|
'sub-notebook',
|
|
|
|
],
|
|
|
|
'Server': ['server'],
|
|
|
|
'Computer': ['_virtual'],
|
|
|
|
}
|
|
|
|
for k, v in CHASSIS_TYPE.items():
|
|
|
|
if lower_type in v:
|
|
|
|
return k
|
|
|
|
return self.default
|
|
|
|
|
|
|
|
def get_data_storage(self):
|
|
|
|
|
|
|
|
for sm in self.smart:
|
2022-03-25 12:55:05 +00:00
|
|
|
# import pdb; pdb.set_trace()
|
2022-03-24 12:13:28 +00:00
|
|
|
model = sm.get('model_name')
|
|
|
|
manufacturer = None
|
|
|
|
if len(model.split(" ")) == 2:
|
|
|
|
manufacturer, model = model.split(" ")
|
|
|
|
|
|
|
|
self.components.append(
|
|
|
|
{
|
|
|
|
"actions": [],
|
|
|
|
"type": self.get_data_storage_type(sm),
|
|
|
|
"model": model,
|
|
|
|
"manufacturer": manufacturer,
|
|
|
|
"serialNumber": sm.get('serial_number'),
|
|
|
|
"size": self.get_data_storage_size(sm),
|
|
|
|
"variant": sm.get("firmware_version"),
|
|
|
|
"interface": self.get_data_storage_interface(sm),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_data_storage_type(self, x):
|
|
|
|
# TODO @cayop add more SSDS types
|
|
|
|
SSDS = ["nvme"]
|
|
|
|
SSD = 'SolidStateDrive'
|
|
|
|
HDD = 'HardDrive'
|
|
|
|
type_dev = x.get('device', {}).get('type')
|
|
|
|
return SSD if type_dev in SSDS else HDD
|
|
|
|
|
|
|
|
def get_data_storage_interface(self, x):
|
|
|
|
return x.get('device', {}).get('protocol', 'ATA')
|
|
|
|
|
|
|
|
def get_data_storage_size(self, x):
|
|
|
|
type_dev = x.get('device', {}).get('type')
|
|
|
|
total_capacity = "{type}_total_capacity".format(type=type_dev)
|
|
|
|
# convert bytes to Mb
|
|
|
|
return x.get(total_capacity) / 1024**2
|
|
|
|
|
|
|
|
def get_networks(self):
|
2022-03-25 12:55:05 +00:00
|
|
|
hw_class = " Hardware Class: "
|
|
|
|
mac = " Permanent HW Address: "
|
|
|
|
model = " Model: "
|
|
|
|
wireless = "wireless"
|
|
|
|
|
2022-03-24 12:13:28 +00:00
|
|
|
for line in self.hwinfo:
|
2022-03-25 12:55:05 +00:00
|
|
|
iface = {
|
|
|
|
"variant": "1",
|
|
|
|
"actions": [],
|
|
|
|
"speed": 100.0,
|
|
|
|
"type": "NetworkAdapter",
|
|
|
|
"wireless": False,
|
|
|
|
"manufacturer": "Ethernet",
|
|
|
|
}
|
2022-03-24 12:13:28 +00:00
|
|
|
for y in line:
|
2022-03-25 12:55:05 +00:00
|
|
|
if hw_class in y and not y.split(hw_class)[1] == 'network':
|
|
|
|
break
|
|
|
|
|
|
|
|
if mac in y:
|
|
|
|
iface["serialNumber"] = y.split(mac)[1]
|
|
|
|
if model in y:
|
|
|
|
iface["model"] = y.split(model)[1]
|
|
|
|
if wireless in y:
|
|
|
|
iface["wireless"] = True
|
2022-03-24 12:13:28 +00:00
|
|
|
|
2022-03-25 12:55:05 +00:00
|
|
|
if iface.get("serialNumber"):
|
|
|
|
self.components.append(iface)
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
def parse_hwinfo(self):
|
|
|
|
hw_blocks = self.hwinfo_raw.split("\n\n")
|
|
|
|
return [x.split("\n") for x in hw_blocks]
|
|
|
|
|
|
|
|
def loads(self, x):
|
2022-03-25 12:55:05 +00:00
|
|
|
if isinstance(x, str):
|
|
|
|
return json.loads(x)
|
|
|
|
return x
|
2022-03-24 12:13:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
class LsHw:
|
|
|
|
def __init__(self, dmi, jshw, hwinfo, default="n/a"):
|
|
|
|
self.default = default
|
|
|
|
self.hw = self.loads(jshw)
|
|
|
|
self.hwinfo = hwinfo.splitlines()
|
|
|
|
self.childrens = self.hw.get('children', [])
|
|
|
|
self.dmi = dmi
|
|
|
|
self.components = dmi.components
|
|
|
|
self.device = dmi.device
|
|
|
|
self.add_components()
|
|
|
|
|
|
|
|
def add_components(self):
|
|
|
|
self.get_cpu_addr()
|
|
|
|
self.get_networks()
|
|
|
|
self.get_display()
|
|
|
|
self.get_sound_card()
|
|
|
|
self.get_graphic_card()
|
|
|
|
|
|
|
|
def get_cpu_addr(self):
|
|
|
|
for cpu in self.components:
|
|
|
|
if not cpu['type'] == "Processor":
|
|
|
|
continue
|
|
|
|
|
|
|
|
cpu["address"] = self.hw.get("width")
|
|
|
|
|
|
|
|
def get_networks(self):
|
|
|
|
networks = NetworkAdapter.new(self.lshw, self.hwinfo)
|
|
|
|
|
|
|
|
for x in networks:
|
|
|
|
self.components.append(
|
|
|
|
{
|
|
|
|
"actions": [],
|
|
|
|
"type": "NetworkAdapter",
|
|
|
|
"serialNumber": x.serial_number,
|
|
|
|
"speed": x.speed,
|
|
|
|
"model": x.model,
|
|
|
|
"manufacturer": x.manufacturer,
|
|
|
|
"variant": x.variant,
|
|
|
|
"wireless": x.wireless,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_display(self):
|
|
|
|
if not self.device['type'] == 'Laptop':
|
|
|
|
return
|
|
|
|
|
|
|
|
displays = Display.new(self.lshw, self.hwinfo)
|
|
|
|
|
|
|
|
for x in displays:
|
|
|
|
self.components.append(
|
|
|
|
{
|
|
|
|
"actions": [],
|
|
|
|
"type": "Display",
|
|
|
|
"model": x.model,
|
|
|
|
"manufacturer": x.manufacturer,
|
|
|
|
"serialNumber": x.serial_number,
|
|
|
|
"resolutionWidth": x.resolution_width,
|
|
|
|
"resolutionHeight": x.resolution_height,
|
|
|
|
"refreshRate": x.refresh_rate,
|
|
|
|
"technology": x.technology,
|
|
|
|
"productionDate": x.production_date,
|
|
|
|
"size": x.size,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_sound_card(self):
|
|
|
|
soundcards = SoundCard.new(self.lshw, self.hwinfo)
|
|
|
|
|
|
|
|
for x in soundcards:
|
|
|
|
self.components.append(
|
|
|
|
{
|
|
|
|
"actions": [],
|
|
|
|
"type": "SoundCard",
|
|
|
|
"model": x.model,
|
|
|
|
"manufacturer": x.manufacturer,
|
|
|
|
"serialNumber": x.serial_number,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_graphic_card(self):
|
|
|
|
# TODO @cayop memory get info from lspci on fly
|
|
|
|
graphicards = GraphicCard.new(self.lshw, self.hwinfo)
|
|
|
|
|
|
|
|
for x in graphicards:
|
|
|
|
self.components.append(
|
|
|
|
{
|
|
|
|
"actions": [],
|
|
|
|
"type": "GraphicCard",
|
|
|
|
"model": x.model,
|
|
|
|
"manufacturer": x.manufacturer,
|
|
|
|
"serialNumber": x.serial_number,
|
|
|
|
"memory": x.memory,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
def loads(jshw):
|
|
|
|
if isinstance(jshw, dict):
|
|
|
|
return jshw
|
|
|
|
return json.loads(jshw)
|