diff --git a/README.md b/README.md index 5e6adf4..06a2ba6 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,9 @@ The goal is to generate an existing infrastructure on Netbox and have the abilit * Generic ability to guess datacenters and rack location through drivers (`cmd` and `file` and custom ones) * Update existing `Device` and `Interface` * Handle blade moving (new slot, new chassis) +* Handle blade GPU expansions * Automatic cabling (server's interface to switch's interface) using lldp -* Local inventory using `Inventory Item` for CPU, RAM, RAID cards, physical disks (behind raid cards) +* Local inventory using `Inventory Item` for CPU, GPU, RAM, RAID cards, physical disks (behind raid cards) * PSUs creation and power consumption reporting (based on vendor's tools) # Requirements diff --git a/netbox_agent/inventory.py b/netbox_agent/inventory.py index d571e6a..97e7ec4 100644 --- a/netbox_agent/inventory.py +++ b/netbox_agent/inventory.py @@ -13,6 +13,7 @@ from netbox_agent.raid.storcli import StorcliRaid INVENTORY_TAG = { 'cpu': {'name': 'hw:cpu', 'slug': 'hw-cpu'}, + 'gpu': {'name': 'hw:gpu', 'slug': 'hw-gpu'}, 'disk': {'name': 'hw:disk', 'slug': 'hw-disk'}, 'interface': {'name': 'hw:interface', 'slug': 'hw-interface'}, 'memory': {'name': 'hw:memory', 'slug': 'hw-memory'}, @@ -32,6 +33,7 @@ class Inventory(): * cpu * raid cards * disks + * gpus methods that: * get local item @@ -438,6 +440,34 @@ class Inventory(): if memory.get('serial') not in [x.serial for x in nb_memories]: self.create_netbox_memory(memory) + def create_netbox_gpus(self): + for gpu in self.lshw.get_hw_linux('gpu'): + manufacturer = self.find_or_create_manufacturer(gpu["vendor"]) + _ = nb.dcim.inventory_items.create( + device=self.device_id, + manufacturer=manufacturer.id, + discovered=True, + tags=[INVENTORY_TAG['gpu']['name']], + name=gpu['product'], + description='GPU {}'.format(gpu['product']), + ) + + logging.info('Creating GPU model {}'.format(gpu['product'])) + + def do_netbox_gpus(self): + gpus = self.lshw.get_hw_linux('gpu') + nb_gpus = self.get_netbox_inventory( + device_id=self.device_id, + tag=INVENTORY_TAG['gpu']['slug'], + ) + + if not len(nb_gpus) or \ + len(nb_gpus) and len(gpus) != len(nb_gpus): + for x in nb_gpus: + x.delete() + + self.create_netbox_gpus() + def create_or_update(self): if config.inventory is None or config.update_inventory is None: return False @@ -447,4 +477,5 @@ class Inventory(): self.do_netbox_disks() self.do_netbox_interfaces() self.do_netbox_motherboard() + self.do_netbox_gpus() return True diff --git a/netbox_agent/lshw.py b/netbox_agent/lshw.py index dadc818..112c489 100644 --- a/netbox_agent/lshw.py +++ b/netbox_agent/lshw.py @@ -22,6 +22,7 @@ class LSHW(): self.cpus = [] self.power = [] self.disks = [] + self.gpus = [] self.vendor = self.hw_info["vendor"] self.product = self.hw_info["product"] self.chassis_serial = self.hw_info["serial"] @@ -53,6 +54,8 @@ class LSHW(): def get_hw_linux(self, hwclass): if hwclass == "cpu": return self.cpus + if hwclass == "gpu": + return self.gpus if hwclass == "network": return self.interfaces if hwclass == 'storage': @@ -132,6 +135,15 @@ class LSHW(): self.memories.append(d) + def find_gpus(self, obj): + if "product" in obj: + c = {} + c["product"] = obj["product"] + c["vendor"] = obj["vendor"] + c["description"] = obj["description"] + + self.gpus.append(c) + def walk_bridge(self, obj): if "children" not in obj: return @@ -139,6 +151,8 @@ class LSHW(): for bus in obj["children"]: if bus["class"] == "storage": self.find_storage(bus) + if bus["class"] == "display": + self.find_gpus(bus) if "children" in bus: for b in bus["children"]: @@ -146,6 +160,8 @@ class LSHW(): self.find_storage(b) if b["class"] == "network": self.find_network(b) + if b["class"] == "display": + self.find_gpus(b) if __name__ == "__main__":