diff --git a/netbox_agent/inventory.py b/netbox_agent/inventory.py index 61abb5f..f4f8cb6 100644 --- a/netbox_agent/inventory.py +++ b/netbox_agent/inventory.py @@ -1,16 +1,18 @@ import logging -import subprocess -import re +import pynetbox from netbox_agent.config import netbox_instance as nb, config -from netbox_agent.misc import is_tool +from netbox_agent.misc import is_tool, get_vendor from netbox_agent.raid.hp import HPRaid from netbox_agent.raid.storcli import StorcliRaid +from netbox_agent.lshw import LSHW INVENTORY_TAG = { 'cpu': {'name': 'hw:cpu', 'slug': 'hw-cpu'}, - 'memory': {'name': 'hw:memory', 'slug': 'hw-memory'}, 'disk': {'name': 'hw:disk', 'slug': 'hw-disk'}, + 'interface': {'name': 'hw:interface', 'slug': 'hw-interface'}, + 'memory': {'name': 'hw:memory', 'slug': 'hw-memory'}, + 'motherboard': {'name': 'hw:motherboard', 'slug': 'hw-motherboard'}, 'raid_card': {'name': 'hw:raid_card', 'slug': 'hw-raid-card'}, } @@ -42,10 +44,13 @@ class Inventory(): self.create_netbox_tags() self.server = server netbox_server = self.server.get_netbox_server() + self.device_id = netbox_server.id if netbox_server else None self.raid = None self.disks = [] + self.lshw = LSHW() + def create_netbox_tags(self): for key, tag in INVENTORY_TAG.items(): nb_tag = nb.extras.tags.get( @@ -58,42 +63,155 @@ class Inventory(): comments=tag['name'], ) - def get_cpus(self): - model = None - nb = None + def find_or_create_manufacturer(self, name): + if name is None: + return None - output = subprocess.getoutput('lscpu') - model_re = re.search(r'Model name: (.*)', output) - if len(model_re.groups()) > 0: - model = model_re.groups()[0].strip() - socket_re = re.search(r'Socket\(s\): (.*)', output) - if len(socket_re.groups()) > 0: - nb = int(socket_re.groups()[0].strip()) - return nb, model + manufacturer = nb.dcim.manufacturers.get( + name=name, + ) + if not manufacturer: + logging.info('Creating missing manufacturer {name}'.format(name=name)) + manufacturer = nb.dcim.manufacturers.create( + name=name, + slug=name.replace(' ', '-').replace('.', '').lower(), + ) + + logging.info('Creating missing manufacturer {name}'.format(name=name)) + + return manufacturer + + def get_netbox_inventory(self, device_id, tag): + try: + items = nb.dcim.inventory_items.filter( + device_id=device_id, + tag=tag + ) + except pynetbox.core.query.RequestError: + logging.info('Tag {tag} is missing, returning empty array.'.format(tag=tag)) + items = [] + + return items + + def create_netbox_inventory_item(self, device_id, tags, vendor, name, serial, description): + manufacturer = self.find_or_create_manufacturer(vendor) + + _ = nb.dcim.inventory_items.create( + device=device_id, + manufacturer=manufacturer.id, + discovered=True, + tags=tags, + name='{}'.format(name), + serial='{}'.format(serial), + description=description + ) + + logging.info('Creating inventory item {} {}/{} {} '.format( + vendor, + name, + serial, + description) + ) + + def get_hw_motherboards(self): + motherboards = [] + + m = {} + m['serial'] = self.lshw.motherboard_serial + m['vendor'] = self.lshw.vendor + m['name'] = '{} {}'.format(self.lshw.vendor, self.lshw.motherboard) + m['description'] = '{} Motherboard'.format(self.lshw.motherboard) + + motherboards.append(m) + + return motherboards + + def do_netbox_motherboard(self): + + motherboards = self.get_hw_motherboards() + nb_motherboards = self.get_netbox_inventory( + device_id=self.device_id, + tag=INVENTORY_TAG['motherboard']['slug']) + + for nb_motherboard in nb_motherboards: + if nb_motherboard.serial not in [x['serial'] for x in motherboards]: + logging.info('Deleting unknown motherboard {vendor} {motherboard}/{serial}'.format( + motherboard=self.lshw.motherboard, + serial=nb_motherboard.serial, + )) + nb_motherboard.delete() + + # create interfaces that are not in netbox + for motherboard in motherboards: + if motherboard.get('serial') not in [x.serial for x in nb_motherboards]: + self.create_netbox_inventory_item( + device_id=self.device_id, + tags=[INVENTORY_TAG['motherboard']['name']], + vendor='{}'.format(motherboard.get('vendor', 'N/A')), + serial='{}'.format(motherboard.get('serial', 'No SN')), + name='{}'.format(motherboard.get('name')), + description='{}'.format(motherboard.get('description')) + ) + + def create_netbox_interface(self, iface): + manufacturer = self.find_or_create_manufacturer(iface["vendor"]) + _ = nb.dcim.inventory_items.create( + device=self.device_id, + manufacturer=manufacturer.id, + discovered=True, + tags=[INVENTORY_TAG['interface']['name']], + name="{}".format(iface['product']), + serial='{}'.format(iface['serial']), + description='{} {}'.format(iface['description'], iface['name']) + ) + + def do_netbox_interfaces(self): + nb_interfaces = self.get_netbox_inventory( + device_id=self.device_id, + tag=INVENTORY_TAG['interface']['slug']) + interfaces = self.lshw.interfaces + + # delete interfaces that are in netbox but not locally + # use the serial_number has the comparison element + for nb_interface in nb_interfaces: + if nb_interface.serial not in [x['serial'] for x in interfaces]: + logging.info('Deleting unknown interface {serial}'.format( + serial=nb_interface.serial, + )) + nb_interface.delete() + + # create interfaces that are not in netbox + for iface in interfaces: + if iface.get('serial') not in [x.serial for x in nb_interfaces]: + self.create_netbox_interface(iface) def create_netbox_cpus(self): - nb_cpus, model = self.get_cpus() - for i in range(nb_cpus): + for cpu in self.lshw.get_hw_linux('cpu'): + manufacturer = self.find_or_create_manufacturer(cpu["vendor"]) _ = nb.dcim.inventory_items.create( device=self.device_id, - tags=[INVENTORY_TAG['cpu']['name']], - name=model, + manufacturer=manufacturer.id, discovered=True, - description='CPU', + tags=[INVENTORY_TAG['cpu']['name']], + name=cpu['product'], + description='CPU {}'.format(cpu['location']), + # asset_tag=cpu['location'] ) - logging.info('Creating CPU model {model}'.format(model=model)) - def update_netbox_cpus(self): - cpus_number, model = self.get_cpus() - nb_cpus = nb.dcim.inventory_items.filter( + logging.info('Creating CPU model {}'.format(cpu['product'])) + + def do_netbox_cpus(self): + cpus = self.lshw.get_hw_linux('cpu') + nb_cpus = self.get_netbox_inventory( device_id=self.device_id, tag=INVENTORY_TAG['cpu']['slug'], ) if not len(nb_cpus) or \ - len(nb_cpus) and cpus_number != len(nb_cpus): + len(nb_cpus) and len(cpus) != len(nb_cpus): for x in nb_cpus: x.delete() + self.create_netbox_cpus() def get_raid_cards(self): @@ -111,31 +229,11 @@ class Inventory(): if len(self.raid.get_controllers()): return controllers - def get_netbox_raid_cards(self): - raid_cards = nb.dcim.inventory_items.filter( - device_id=self.device_id, - tag=INVENTORY_TAG['raid_card']['slug'], - ) - return raid_cards - - def find_or_create_manufacturer(self, name): - if name is None: - return None - manufacturer = nb.dcim.manufacturers.get( - name=name, - ) - if not manufacturer: - manufacturer = nb.dcim.manufacturers.create( - name=name, - slug=name.lower(), - ) - logging.info('Creating missing manufacturer {name}'.format(name=name)) - return manufacturer - def create_netbox_raid_card(self, raid_card): manufacturer = self.find_or_create_manufacturer( raid_card.get_manufacturer() ) + name = raid_card.get_product_name() serial = raid_card.get_serial_number() nb_raid_card = nb.dcim.inventory_items.create( @@ -154,7 +252,10 @@ class Inventory(): return nb_raid_card def create_netbox_raid_cards(self): - for raid_card in self.get_raid_cards(): + for raid_card in self.get_netbox_inventory( + device_id=self.device_id, + tag=[INVENTORY_TAG['raid_card']['slug']] + ): self.create_netbox_raid_card(raid_card) def update_netbox_raid_cards(self): @@ -168,7 +269,10 @@ class Inventory(): We only need to handle destroy and new cards """ - nb_raid_cards = self.get_netbox_raid_cards() + nb_raid_cards = self.get_netbox_inventory( + device_id=self.device_id, + tag=[INVENTORY_TAG['raid_card']['slug']] + ) raid_cards = self.get_raid_cards() # delete cards that are in netbox but not locally @@ -185,41 +289,104 @@ class Inventory(): if raid_card.get_serial_number() not in [x.serial for x in nb_raid_cards]: self.create_netbox_raid_card(raid_card) - def get_disks(self): - ret = [] + def is_virtual_disk(self, disk): + logicalname = disk.get('logicalname') + description = disk.get('description') + size = disk.get('size') + product = disk.get('product') + + non_raid_disks = [ + 'MR9361-8i', + ] + + if size is None and logicalname is None or \ + 'virtual' in product.lower() or 'logical' in product.lower() or \ + product in non_raid_disks or \ + description == 'SCSI Enclosure' or \ + 'volume' in description.lower(): + return True + return False + + def get_hw_disks(self): + disks = [] + + for disk in self.lshw.get_hw_linux("storage"): + if self.is_virtual_disk(disk): + continue + + logicalname = disk.get('logicalname') + description = disk.get('description') + size = disk.get('size', 0) + product = disk.get('product') + serial = disk.get('serial') + + d = {} + d["name"] = "" + d['Size'] = '{} GB'.format(int(size/1024/1024/1024)) + d['logicalname'] = logicalname + d['description'] = description + d['SN'] = serial + d['Model'] = product + if disk.get('vendor'): + d['Vendor'] = disk['vendor'] + else: + d['Vendor'] = get_vendor(disk['product']) + disks.append(d) + for raid_card in self.get_raid_cards(): - ret += raid_card.get_physical_disks() - return ret + disks += raid_card.get_physical_disks() - def get_netbox_disks(self): - disks = nb.dcim.inventory_items.filter( - device_id=self.device_id, - tag=INVENTORY_TAG['disk']['slug'], - ) - return disks + # remove duplicate serials + seen = set() + uniq = [x for x in disks if x['SN'] not in seen and not seen.add(x['SN'])] + return uniq - def create_netbox_disks(self): - for disk in self.get_disks(): - _ = nb.dcim.inventory_items.create( - device=self.device_id, - discovered=True, - tags=[INVENTORY_TAG['disk']['name']], - name='{} ({})'.format(disk['Model'], disk['Size']), - serial=disk['SN'], - ) - logging.info('Creating Disk {model} {serial}'.format( - model=disk['Model'], - serial=disk['SN'], - )) + def create_netbox_disk(self, disk): + manufacturer = None + if "Vendor" in disk: + manufacturer = self.find_or_create_manufacturer(disk["Vendor"]) - def update_netbox_disks(self): - nb_disks = self.get_netbox_disks() - disks = self.get_disks() + logicalname = disk.get('logicalname') + desc = disk.get('description') + # nonraid disk + if logicalname and desc: + if type(logicalname) is list: + logicalname = logicalname[0] + name = '{} - {} ({})'.format( + desc, + logicalname, + disk.get('Size', 0)) + description = 'Device {}'.format(disk.get('logicalname', 'Unknown')) + else: + name = '{} ({})'.format(disk['Model'], disk['Size']) + description = '{}'.format(disk['Type']) + + _ = nb.dcim.inventory_items.create( + device=self.device_id, + discovered=True, + tags=[INVENTORY_TAG['disk']['name']], + name=name, + serial=disk['SN'], + part_id=disk['Model'], + description=description, + manufacturer=manufacturer.id if manufacturer else None + ) + + logging.info('Creating Disk {model} {serial}'.format( + model=disk['Model'], + serial=disk['SN'], + )) + + def do_netbox_disks(self): + nb_disks = self.get_netbox_inventory( + device_id=self.device_id, + tag=INVENTORY_TAG['disk']['slug']) + disks = self.get_hw_disks() # delete disks that are in netbox but not locally # use the serial_number has the comparison element for nb_disk in nb_disks: - if nb_disk.serial not in [x['SN'] for x in disks]: + if nb_disk.serial not in [x['SN'] for x in disks if x.get('SN')]: logging.info('Deleting unknown locally Disk {serial}'.format( serial=nb_disk.serial, )) @@ -227,105 +394,67 @@ class Inventory(): # create disks that are not in netbox for disk in disks: - if disk['SN'] not in [x.serial for x in nb_disks]: - nb_disk = nb.dcim.inventory_items.create( - device=self.device_id, - discovered=True, - tags=[INVENTORY_TAG['disk']['name']], - name='{} ({})'.format(disk['Model'], disk['Size']), - serial=disk['SN'], - description=disk.get('Type', ''), - ) - logging.info('Creating Disk {model} {serial}'.format( - model=disk['Model'], - serial=disk['SN'], - )) - - def get_memory(self): - memories = [] - for _, value in self.server.dmi.parse().items(): - if value['DMIName'] == 'Memory Device' and \ - value['Size'] != 'No Module Installed': - memories.append({ - 'Manufacturer': value['Manufacturer'].strip(), - 'Size': value['Size'].strip(), - 'PN': value['Part Number'].strip(), - 'SN': value['Serial Number'].strip(), - 'Locator': value['Locator'].strip(), - 'Type': value['Type'].strip(), - }) - return memories - - def get_memory_total_size(self): - total_size = 0 - for memory in self.get_memory(): - total_size += int(memory['Size'].split()[0]) - return total_size - - def get_netbox_memory(self): - memories = nb.dcim.inventory_items.filter( - device_id=self.device_id, - tag=INVENTORY_TAG['memory']['slug'], - ) - return memories + if disk.get('SN') not in [x.serial for x in nb_disks]: + self.create_netbox_disk(disk) def create_netbox_memory(self, memory): - manufacturer = nb.dcim.manufacturers.get( - name=memory['Manufacturer'] - ) - if not manufacturer: - manufacturer = nb.dcim.manufacturers.create( - name=memory['Manufacturer'], - slug=memory['Manufacturer'].lower(), - ) + manufacturer = self.find_or_create_manufacturer(memory['vendor']) + nb_memory = nb.dcim.inventory_items.create( device=self.device_id, discovered=True, manufacturer=manufacturer.id, tags=[INVENTORY_TAG['memory']['name']], - name='{} ({} {})'.format(memory['Locator'], memory['Size'], memory['Type']), - part_id=memory['PN'], - serial=memory['SN'], - description='RAM', + name='{} ({}GB)'.format(memory['description'], memory['size']), + part_id=memory['product'], + serial=memory['serial'], + description='Slot {}'.format(memory['slot']), ) - logging.info('Creating Memory {type} {size}'.format( - type=memory['Type'], - size=memory['Size'], + + logging.info('Creating Memory {location} {type} {size}GB'.format( + location=memory['slot'], + type=memory['product'], + size=memory['size'], )) + return nb_memory - def create_netbox_memories(self): - for memory in self.get_memory(): - self.create_netbox_memory(memory) - - def update_netbox_memory(self): - memories = self.get_memory() - nb_memories = self.get_netbox_memory() + def do_netbox_memories(self): + memories = self.lshw.memories + nb_memories = self.get_netbox_inventory( + device_id=self.device_id, + tag=INVENTORY_TAG['memory']['slug'] + ) for nb_memory in nb_memories: - if nb_memory.serial not in [x['SN'] for x in memories]: + if nb_memory.serial not in [x['serial'] for x in memories]: logging.info('Deleting unknown locally Memory {serial}'.format( serial=nb_memory.serial, )) nb_memory.delete() + for memory in memories: - if memory['SN'] not in [x.serial for x in nb_memories]: + if memory.get('serial') not in [x.serial for x in nb_memories]: self.create_netbox_memory(memory) def create(self): if config.inventory is None: return False - self.create_netbox_cpus() - self.create_netbox_memory() + self.do_netbox_cpus() + self.do_netbox_memories() self.create_netbox_raid_cards() - self.create_netbox_disks() + self.do_netbox_disks() + self.do_netbox_interfaces() + self.do_netbox_motherboard() return True def update(self): if config.inventory is None or config.update_inventory is None: return False - self.update_netbox_cpus() - self.update_netbox_memory() + self.do_netbox_cpus() + self.do_netbox_memories() self.update_netbox_raid_cards() - self.update_netbox_disks() + self.do_netbox_disks() + self.do_netbox_interfaces() + self.do_netbox_motherboard() return True diff --git a/netbox_agent/lshw.py b/netbox_agent/lshw.py new file mode 100644 index 0000000..9a50c1f --- /dev/null +++ b/netbox_agent/lshw.py @@ -0,0 +1,151 @@ +import subprocess +import json +import logging +import sys + +from netbox_agent.misc import is_tool + + +class LSHW(): + def __init__(self): + if not is_tool('lshw'): + logging.error('lshw does not seem to be installed') + sys.exit(1) + + data = subprocess.getoutput( + 'lshw -quiet -json' + ) + self.hw_info = json.loads(data) + self.info = {} + self.memories = [] + self.interfaces = [] + self.cpus = [] + self.power = [] + self.disks = [] + self.vendor = self.hw_info["vendor"] + self.product = self.hw_info["product"] + self.chassis_serial = self.hw_info["serial"] + self.motherboard_serial = self.hw_info["children"][0].get("serial", "No S/N") + self.motherboard = self.hw_info["children"][0].get("product", "Motherboard") + + for k in self.hw_info["children"]: + if k["class"] == "power": + # self.power[k["id"]] = k + self.power.append(k) + + if "children" in k: + for j in k["children"]: + if j["class"] == "generic": + continue + + if j["class"] == "storage": + self.find_storage(j) + + if j["class"] == "memory": + self.find_memories(j) + + if j["class"] == "processor": + self.find_cpus(j) + + if j["class"] == "bridge": + self.walk_bridge(j) + + def get_hw_linux(self, hwclass): + if hwclass == "cpu": + return self.cpus + if hwclass == "network": + return self.interfaces + if hwclass == 'storage': + return self.disks + if hwclass == 'memory': + return self.memories + + def find_network(self, obj): + d = {} + d["name"] = obj["logicalname"] + d["macaddress"] = obj["serial"] + d["serial"] = obj["serial"] + d["product"] = obj["product"] + d["vendor"] = obj["vendor"] + d["description"] = obj["description"] + + self.interfaces.append(d) + + def find_storage(self, obj): + if "children" in obj: + for device in obj["children"]: + d = {} + d["logicalname"] = device.get("logicalname") + d["product"] = device.get("product") + d["serial"] = device.get("serial") + d["version"] = device.get("version") + d["size"] = device.get("size") + d["description"] = device.get("description") + + self.disks.append(d) + + elif "nvme" in obj["configuration"]["driver"]: + nvme = json.loads( + subprocess.check_output(["nvme", '-list', '-o', 'json'], + encoding='utf8')) # noqa: E128 + + d = {} + d["vendor"] = obj["vendor"] + d["version"] = obj["version"] + d["product"] = obj["product"] + + d['description'] = "NVME Disk" + d['product'] = nvme["Devices"][0]["ModelNumber"] + d['size'] = nvme["Devices"][0]["PhysicalSize"] + d['serial'] = nvme["Devices"][0]["SerialNumber"] + d['logicalname'] = nvme["Devices"][0]["DevicePath"] + + self.disks.append(d) + + def find_cpus(self, obj): + c = {} + c["product"] = obj["product"] + c["vendor"] = obj["vendor"] + c["description"] = obj["description"] + c["location"] = obj["slot"] + + self.cpus.append(c) + + def find_memories(self, obj): + if "children" not in obj: + # print("not a DIMM memory.") + return + + for dimm in obj["children"]: + if "empty" in dimm["description"]: + continue + + d = {} + d["slot"] = dimm.get("slot") + d["description"] = dimm.get("description") + d["id"] = dimm.get("id") + d["serial"] = dimm.get("serial", 'N/A') + d["vendor"] = dimm.get("vendor") + d["product"] = dimm.get("product") + d["size"] = dimm.get("size", 0) / 2 ** 20 / 1024 + + self.memories.append(d) + + def walk_bridge(self, obj): + if "children" not in obj: + return + + for bus in obj["children"]: + if bus["class"] == "storage": + self.find_storage(bus) + + if "children" in bus: + for b in bus["children"]: + if b["class"] == "storage": + self.find_storage(b) + if b["class"] == "network": + self.find_network(b) + + +if __name__ == "__main__": + pass diff --git a/netbox_agent/misc.py b/netbox_agent/misc.py index b28e4b3..fe36410 100644 --- a/netbox_agent/misc.py +++ b/netbox_agent/misc.py @@ -4,3 +4,25 @@ from shutil import which def is_tool(name): '''Check whether `name` is on PATH and marked as executable.''' return which(name) is not None + + +def get_vendor(name): + vendors = { + 'ST': 'Seagate', + 'CRUCIAL': 'Crucial', + 'MICRON': 'Micron', + 'INTEL': 'Intel', + 'SAMSUNG': 'Samsung', + 'EH0': 'HP', + 'HGST': 'HGST', + 'HUH': 'HGST', + 'MB': 'Toshiba', + 'MC': 'Toshiba', + 'MD': 'Toshiba', + 'MG': 'Toshiba', + 'WD': 'WDC' + } + for key, value in vendors.items(): + if name.upper().startswith(key): + return value + return name diff --git a/netbox_agent/raid/hp.py b/netbox_agent/raid/hp.py index b2a4858..0768377 100644 --- a/netbox_agent/raid/hp.py +++ b/netbox_agent/raid/hp.py @@ -2,6 +2,7 @@ import re import subprocess from netbox_agent.raid.base import Raid, RaidController +from netbox_agent.misc import get_vendor REGEXP_CONTROLLER_HP = re.compile(r'Smart Array ([a-zA-Z0-9- ]+) in Slot ([0-9]+)') @@ -120,12 +121,23 @@ class HPRaidController(RaidController): key = next(iter(info_dict)) for array, physical_disk in info_dict[key].items(): for _, pd_attr in physical_disk.items(): + model = pd_attr.get('Model', '').strip() + vendor = None + if model.startswith('HP'): + vendor = 'HP' + elif len(model.split()) > 1: + vendor = get_vendor(model.split()[1]) + else: + vendor = get_vendor(model) + ret.append({ - 'Model': pd_attr.get('Model', '').strip(), + 'Model': model, + 'Vendor': vendor, 'SN': pd_attr.get('Serial Number', '').strip(), 'Size': pd_attr.get('Size', '').strip(), 'Type': 'SSD' if pd_attr.get('Interface Type') == 'Solid State SATA' else 'HDD', + '_src': self.__class__.__name__, }) return ret diff --git a/netbox_agent/raid/storcli.py b/netbox_agent/raid/storcli.py index 48989b8..5f16838 100644 --- a/netbox_agent/raid/storcli.py +++ b/netbox_agent/raid/storcli.py @@ -1,6 +1,7 @@ import subprocess import json +from netbox_agent.misc import get_vendor from netbox_agent.raid.base import Raid, RaidController @@ -38,11 +39,14 @@ class StorcliController(RaidController): ) drive_attr = drive_infos['{} - Detailed Information'.format(drive_identifier)][ '{} Device attributes'.format(drive_identifier)] + model = drive_attr.get('Model Number', '').strip() ret.append({ - 'Model': drive_attr.get('Model Number', '').strip(), + 'Model': model, + 'Vendor': get_vendor(model), 'SN': drive_attr.get('SN', '').strip(), 'Size': size, 'Type': media_type, + '_src': self.__class__.__name__, }) return ret diff --git a/netbox_agent/server.py b/netbox_agent/server.py index a567816..6b6c9b1 100644 --- a/netbox_agent/server.py +++ b/netbox_agent/server.py @@ -16,8 +16,11 @@ class ServerBase(): self.dmi = dmi else: self.dmi = dmidecode.parse() - self.system = self.dmi.get_by_type('System') + + self.baseboard = self.dmi.get_by_type('Baseboard') self.bios = self.dmi.get_by_type('BIOS') + self.chassis = self.dmi.get_by_type('Chassis') + self.system = self.dmi.get_by_type('System') self.network = None diff --git a/netbox_agent/vendors/supermicro.py b/netbox_agent/vendors/supermicro.py index 18b03c6..a2087ea 100644 --- a/netbox_agent/vendors/supermicro.py +++ b/netbox_agent/vendors/supermicro.py @@ -1,6 +1,20 @@ + from netbox_agent.location import Slot from netbox_agent.server import ServerBase +""" + Supermicro DMI can be messed up. They depend on the vendor + to set the correct values. The endusers cannot + change them without buying a license from Supermicro. + + There are 3 serial numbers in the system + + 1) System - this is used for the chassis information. + 2) Baseboard - this is used for the blade. + 3) Chassis - this is ignored. + +""" + class SupermicroHost(ServerBase): def __init__(self, *args, **kwargs): @@ -8,8 +22,8 @@ class SupermicroHost(ServerBase): self.manufacturer = 'Supermicro' def is_blade(self): - blade = self.get_product_name().startswith('SBI') - blade |= self.get_product_name().startswith('SYS') + blade = self.system[0]['Product Name'].startswith('SBI') + blade |= self.system[0]['Product Name'].startswith('SYS') return blade def get_blade_slot(self): @@ -21,17 +35,25 @@ class SupermicroHost(ServerBase): # No supermicro on hands return None - def get_chassis_name(self): - if not self.is_blade(): - return None - return 'Chassis {}'.format(self.get_service_tag()) + def get_service_tag(self): + return self.baseboard[0]['Serial Number'].strip() + + def get_product_name(self): + if self.is_blade(): + return self.baseboard[0]['Product Name'].strip() + return self.system[0]['Product Name'].strip() def get_chassis(self): if self.is_blade(): - return self.dmi.get_by_type('Chassis')[0]['Version'] + return self.system[0]['Product Name'].strip() return self.get_product_name() def get_chassis_service_tag(self): if self.is_blade(): - return self.dmi.get_by_type('Chassis')[0]['Serial Number'] + return self.system[0]['Serial Number'].strip() return self.get_service_tag() + + def get_chassis_name(self): + if not self.is_blade(): + return None + return 'Chassis {}'.format(self.get_chassis_service_tag())