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.
This commit is contained in:
1 parent
363f93c895
commit
98df0e21ca
5 files changed
+44
-2
No files matched your search
@@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Added
|
### 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
|
- 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
|
`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=`),
|
`other` and a network-config v2 snippet of its own (`cicustom network=`),
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ from napalm_device_types import (
|
|||||||
KernelFactsMixin,
|
KernelFactsMixin,
|
||||||
ListeningSocketsMixin,
|
ListeningSocketsMixin,
|
||||||
PortSpec,
|
PortSpec,
|
||||||
|
SystemIdentityMixin,
|
||||||
SystemdServicesMixin,
|
SystemdServicesMixin,
|
||||||
)
|
)
|
||||||
from napalm.base.exceptions import ConnectionException
|
from napalm.base.exceptions import ConnectionException
|
||||||
@@ -86,6 +87,7 @@ class ProxmoxDriver(
|
|||||||
ProxmoxSystemMixin,
|
ProxmoxSystemMixin,
|
||||||
KernelFactsMixin,
|
KernelFactsMixin,
|
||||||
ListeningSocketsMixin,
|
ListeningSocketsMixin,
|
||||||
|
SystemIdentityMixin,
|
||||||
SystemdServicesMixin,
|
SystemdServicesMixin,
|
||||||
HostStatusMixin,
|
HostStatusMixin,
|
||||||
HypervisorDriver,
|
HypervisorDriver,
|
||||||
|
|||||||
@@ -235,6 +235,11 @@ class ProxmoxSystemMixin:
|
|||||||
# Listening sockets (ListeningSocketsMixin supplies get_listening_sockets)
|
# 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:
|
def _run_listening_sockets_command(self, command: str, *, privileged: bool) -> str:
|
||||||
"""The transport for ``ListeningSocketsMixin.get_listening_sockets``:
|
"""The transport for ``ListeningSocketsMixin.get_listening_sockets``:
|
||||||
the exec path, which runs as root either way."""
|
the exec path, which runs as root either way."""
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "napalm-proxmox"
|
name = "napalm-proxmox"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
description = "NAPALM driver for Proxmox VE (classic Linux networking, SDN, OVS)"
|
description = "NAPALM driver for Proxmox VE (classic Linux networking, SDN, OVS)"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = { text = "Apache-2.0" }
|
license = { text = "Apache-2.0" }
|
||||||
@@ -25,7 +25,7 @@ classifiers = [
|
|||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"napalm>=5.0.0",
|
"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)
|
"paramiko>=5.0.0", # CVE-2026-44405; imported directly for SSH fallback (driver.py)
|
||||||
"proxmoxer>=2.0.0",
|
"proxmoxer>=2.0.0",
|
||||||
"netaddr>=0.9.0",
|
"netaddr>=0.9.0",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
}
|
||||||
Reference in new issue
Block a user