From 98df0e21ca31d1d4c322b26ef94261abbfc11a12 Mon Sep 17 00:00:00 2001 From: Christian Manivong Date: Tue, 13 Oct 2026 12:20:14 +0200 Subject: [PATCH] feat: get_system_identity for matching a node to its BMC (0.2.0) Mixes in napalm-device-types 4.9's SystemIdentityMixin over the exec path, which runs as root: the node's SMBIOS system UUID, product serial and board serial, vendor placeholders empty. pve-dual, a Supermicro X10DRL-i, reports the product serial 0123456789; its board serial and UUID are what tie it to its BMC. --- CHANGELOG.md | 4 ++++ napalm_proxmox/driver.py | 2 ++ napalm_proxmox/system_mixin.py | 5 +++++ pyproject.toml | 4 ++-- tests/test_system_identity.py | 31 +++++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 tests/test_system_identity.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 52a73da..91eb1d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- `get_system_identity()` (napalm-device-types 4.9 `SystemIdentityMixin`): the node's SMBIOS + system UUID, product serial and board serial over the exec path, vendor placeholders + empty. netOrk matches a server to its BMC on these. Requires napalm-device-types 4.9.0; + version 0.2.0. - FreeBSD and OpenBSD guests: `create_vm_from_cloud_init(guest_os=...)` with `GUEST_AGENTS` from napalm-device-types 3.0. A BSD guest gets OS type `other` and a network-config v2 snippet of its own (`cicustom network=`), diff --git a/napalm_proxmox/driver.py b/napalm_proxmox/driver.py index 49b53ad..13e737e 100644 --- a/napalm_proxmox/driver.py +++ b/napalm_proxmox/driver.py @@ -41,6 +41,7 @@ from napalm_device_types import ( KernelFactsMixin, ListeningSocketsMixin, PortSpec, + SystemIdentityMixin, SystemdServicesMixin, ) from napalm.base.exceptions import ConnectionException @@ -86,6 +87,7 @@ class ProxmoxDriver( ProxmoxSystemMixin, KernelFactsMixin, ListeningSocketsMixin, + SystemIdentityMixin, SystemdServicesMixin, HostStatusMixin, HypervisorDriver, diff --git a/napalm_proxmox/system_mixin.py b/napalm_proxmox/system_mixin.py index f476e35..05f8fc2 100644 --- a/napalm_proxmox/system_mixin.py +++ b/napalm_proxmox/system_mixin.py @@ -235,6 +235,11 @@ class ProxmoxSystemMixin: # Listening sockets (ListeningSocketsMixin supplies get_listening_sockets) # ------------------------------------------------------------------ # + def _run_system_identity_command(self, command: str, *, privileged: bool) -> str: + """The transport for ``SystemIdentityMixin.get_system_identity``: the exec path, + which runs as root either way.""" + return str(self._exec_ssh_command(command)) + def _run_listening_sockets_command(self, command: str, *, privileged: bool) -> str: """The transport for ``ListeningSocketsMixin.get_listening_sockets``: the exec path, which runs as root either way.""" diff --git a/pyproject.toml b/pyproject.toml index f941417..8587146 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "napalm-proxmox" -version = "0.1.0" +version = "0.2.0" description = "NAPALM driver for Proxmox VE (classic Linux networking, SDN, OVS)" readme = "README.md" license = { text = "Apache-2.0" } @@ -25,7 +25,7 @@ classifiers = [ requires-python = ">=3.9" dependencies = [ "napalm>=5.0.0", - "napalm_device_types>=3.0.0", + "napalm_device_types>=4.9.0", "paramiko>=5.0.0", # CVE-2026-44405; imported directly for SSH fallback (driver.py) "proxmoxer>=2.0.0", "netaddr>=0.9.0", diff --git a/tests/test_system_identity.py b/tests/test_system_identity.py new file mode 100644 index 0000000..d837c10 --- /dev/null +++ b/tests/test_system_identity.py @@ -0,0 +1,31 @@ +"""`get_system_identity`: the node's SMBIOS identity, what ties it to its BMC. + +The command, its parse and the placeholder filter are napalm-device-types'; the driver +only carries the command over its exec path, which runs as root. +""" + +from __future__ import annotations + +from unittest.mock import patch + +from napalm_device_types import SYSTEM_IDENTITY_COMMAND, SystemIdentityMixin +from napalm_proxmox.driver import ProxmoxDriver + +# pve-dual, a Supermicro X10DRL-i: the product serial is the board vendor's default. +WIRE = "IDBEGIN\n31303043-534D-C40C-7A72-6F1300000000\n0123456789\nZM155S026022\nIDEND\n" + + +def test_the_driver_declares_the_contract(): + assert issubclass(ProxmoxDriver, SystemIdentityMixin) + + +def test_it_runs_the_shared_command(driver): + with patch.object(driver, "_exec_ssh_command", return_value=WIRE) as exec_: + identity = driver.get_system_identity() + + exec_.assert_called_once_with(SYSTEM_IDENTITY_COMMAND) + assert identity == { + "system_uuid": "31303043-534d-c40c-7a72-6f1300000000", + "product_serial": "", + "board_serial": "ZM155S026022", + }