From 7fc3a74e19d5302563e702acbdef2a98dcfbb54d Mon Sep 17 00:00:00 2001 From: Stefan Mayr Date: Sun, 12 Oct 2025 22:42:02 +0200 Subject: [PATCH] Add pci slot as unique key to vga card inventory --- .../agent_based/inventory_lnx_video.py | 26 ++++++--- .../collection/inventory_ui/hardware.py | 1 + .../gui/views/inventory/test_display_hints.py | 1 + .../agent_based/test_inventory_lnx_video.py | 57 +++++++++++++++++-- 4 files changed, 74 insertions(+), 11 deletions(-) diff --git a/cmk/plugins/collection/agent_based/inventory_lnx_video.py b/cmk/plugins/collection/agent_based/inventory_lnx_video.py index 85ab5f28532..b0c305f6744 100644 --- a/cmk/plugins/collection/agent_based/inventory_lnx_video.py +++ b/cmk/plugins/collection/agent_based/inventory_lnx_video.py @@ -24,11 +24,18 @@ from collections.abc import Mapping from dataclasses import dataclass -from cmk.agent_based.v2 import AgentSection, InventoryPlugin, InventoryResult, StringTable, TableRow +from cmk.agent_based.v2 import ( + AgentSection, + InventoryPlugin, + InventoryResult, + StringTable, + TableRow, +) @dataclass class GraphicsCard: + slot: str name: str subsystem: str | None = None driver: str | None = None @@ -40,20 +47,24 @@ class GraphicsCard: def parse_lnx_video(string_table: StringTable) -> Section: parsed_section: dict[str, GraphicsCard] = {} + current_slot: str = "" current_name: str = "" for line in string_table: if len(line) <= 1: continue if "VGA compatible controller" in line[-2]: + current_slot = ":".join(line).split()[0] current_name = line[-1].strip() - if current_name: - parsed_section.setdefault(current_name, GraphicsCard(name=current_name)) - elif current_name: + if current_slot: + parsed_section.setdefault( + current_slot, GraphicsCard(slot=current_slot, name=current_name) + ) + elif current_slot: if line[0] == "Subsystem": - parsed_section[current_name].subsystem = line[1].strip() + parsed_section[current_slot].subsystem = line[1].strip() elif line[0] == "Kernel driver in use": - parsed_section[current_name].driver = line[1].strip() + parsed_section[current_slot].driver = line[1].strip() return parsed_section @@ -70,9 +81,10 @@ def inventory_lnx_video(section: Section) -> InventoryResult: yield TableRow( path=["hardware", "video"], key_columns={ - "name": graphics_card.name, + "slot": graphics_card.slot, }, inventory_columns={ + "name": graphics_card.name, "subsystem": graphics_card.subsystem, "driver": graphics_card.driver, }, diff --git a/cmk/plugins/collection/inventory_ui/hardware.py b/cmk/plugins/collection/inventory_ui/hardware.py index 29c46ba0548..ad4201c8905 100644 --- a/cmk/plugins/collection/inventory_ui/hardware.py +++ b/cmk/plugins/collection/inventory_ui/hardware.py @@ -454,6 +454,7 @@ title=Title("Graphic cards"), table=Table( columns={ + "slot": TextField(Title("Slot")), "name": TextField(Title("Graphic card name")), "subsystem": TextField(Title("Vendor and device ID")), "driver": TextField(Title("Driver")), diff --git a/tests/unit/cmk/gui/views/inventory/test_display_hints.py b/tests/unit/cmk/gui/views/inventory/test_display_hints.py index daaeea37964..4030ff5b511 100644 --- a/tests/unit/cmk/gui/views/inventory/test_display_hints.py +++ b/tests/unit/cmk/gui/views/inventory/test_display_hints.py @@ -588,6 +588,7 @@ def test_paths() -> None: "physical_volume_free_partitions", ], ("hardware", "video"): [ + "slot", "name", "subsystem", "driver", diff --git a/tests/unit/cmk/plugins/collection/agent_based/test_inventory_lnx_video.py b/tests/unit/cmk/plugins/collection/agent_based/test_inventory_lnx_video.py index f944cbe5714..9b1c076e6fb 100644 --- a/tests/unit/cmk/plugins/collection/agent_based/test_inventory_lnx_video.py +++ b/tests/unit/cmk/plugins/collection/agent_based/test_inventory_lnx_video.py @@ -30,9 +30,10 @@ TableRow( path=["hardware", "video"], key_columns={ - "name": "Advanced Micro Devices [AMD] nee ATI Cape Verde PRO [Radeon HD 7700 Series] (prog-if 00 [VGA controller])", + "slot": "05:00.0", }, inventory_columns={ + "name": "Advanced Micro Devices [AMD] nee ATI Cape Verde PRO [Radeon HD 7700 Series] (prog-if 00 [VGA controller])", "subsystem": "Hightech Information System Ltd. Device 200b", "driver": "fglrx_pci", }, @@ -53,9 +54,10 @@ TableRow( path=["hardware", "video"], key_columns={ - "name": "Advanced Micro Devices [AMD] nee ATI Cape Verde PRO [Radeon HD 7700 Series] (prog-if 00 [VGA controller])", + "slot": "05:00.0", }, inventory_columns={ + "name": "Advanced Micro Devices [AMD] nee ATI Cape Verde PRO [Radeon HD 7700 Series] (prog-if 00 [VGA controller])", "subsystem": None, "driver": None, }, @@ -88,9 +90,10 @@ TableRow( path=["hardware", "video"], key_columns={ - "name": "Intel Corporation Device 9a49 (rev 01) (prog-if 00 [VGA controller])", + "slot": "0000:00:02.0", }, inventory_columns={ + "name": "Intel Corporation Device 9a49 (rev 01) (prog-if 00 [VGA controller])", "subsystem": "Dell Device 0a38", "driver": "i915", }, @@ -99,9 +102,10 @@ TableRow( path=["hardware", "video"], key_columns={ - "name": "Second graphics card", + "slot": "00:03.0", }, inventory_columns={ + "name": "Second graphics card", "subsystem": "Some subsystem", "driver": "Some driver", }, @@ -110,6 +114,51 @@ ], id="Two graphics cards", ), + pytest.param( + [ + [ + "00", + "08.0 VGA compatible controller", + " Microsoft Corporation Hyper-V virtual VGA (prog-if 00 [VGA controller])", + ], + ["Subsystem", " Hightech Information System Ltd. Device 200b"], + ["Kernel driver in use", " hyperv_drm"], + [ + "00", + "08.1 VGA compatible controller", + " Microsoft Corporation Hyper-V virtual VGA (prog-if 00 [VGA controller])", + ], + ["Subsystem", " Hightech Information System Ltd. Device 200c"], + ["Kernel driver in use", " hyperv_drm"], + ], + [ + TableRow( + path=["hardware", "video"], + key_columns={ + "slot": "00:08.0", + }, + inventory_columns={ + "name": "Microsoft Corporation Hyper-V virtual VGA (prog-if 00 [VGA controller])", + "subsystem": "Hightech Information System Ltd. Device 200b", + "driver": "hyperv_drm", + }, + status_columns={}, + ), + TableRow( + path=["hardware", "video"], + key_columns={ + "slot": "00:08.1", + }, + inventory_columns={ + "name": "Microsoft Corporation Hyper-V virtual VGA (prog-if 00 [VGA controller])", + "subsystem": "Hightech Information System Ltd. Device 200c", + "driver": "hyperv_drm", + }, + status_columns={}, + ), + ], + id="Two identical graphics cards", + ), pytest.param( [ [