feat: get_system_identity for matching a host to its BMC (0.7.0)
Mixes in napalm-device-types 4.9's SystemIdentityMixin: the host's SMBIOS system UUID, product serial and board serial, read as root on an exec channel, vendor placeholders empty. netOrk links a server's BMC to the host on these.
This commit is contained in:
1 parent
350e3a6d6e
commit
c98dd928e6
4 files changed
+49
-2
No files matched your search
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `get_system_identity()` (napalm-device-types 4.9 `SystemIdentityMixin`): the host's
|
||||||
|
SMBIOS system UUID, product serial and board serial, read as root on an exec channel,
|
||||||
|
vendor placeholders empty. netOrk matches a server to its BMC on these. Requires
|
||||||
|
napalm-device-types 4.9.0 or later; version 0.7.0.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Requires napalm-device-types 4.7.1 or later; version 0.6.0.
|
- Requires napalm-device-types 4.7.1 or later; version 0.6.0.
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ from napalm_device_types import (
|
|||||||
ListeningSocketsMixin,
|
ListeningSocketsMixin,
|
||||||
OpenSshServerMixin,
|
OpenSshServerMixin,
|
||||||
OSDriver,
|
OSDriver,
|
||||||
|
SystemIdentityMixin,
|
||||||
SystemdServicesMixin,
|
SystemdServicesMixin,
|
||||||
SystemdUnavailable,
|
SystemdUnavailable,
|
||||||
VirtualIpsMixin,
|
VirtualIpsMixin,
|
||||||
@@ -245,6 +246,7 @@ class LinuxDriver(
|
|||||||
KernelFactsMixin,
|
KernelFactsMixin,
|
||||||
ListeningSocketsMixin,
|
ListeningSocketsMixin,
|
||||||
VirtualIpsMixin,
|
VirtualIpsMixin,
|
||||||
|
SystemIdentityMixin,
|
||||||
OpenSshServerMixin,
|
OpenSshServerMixin,
|
||||||
SystemdServicesMixin,
|
SystemdServicesMixin,
|
||||||
HostStatusMixin,
|
HostStatusMixin,
|
||||||
@@ -1131,6 +1133,11 @@ class LinuxDriver(
|
|||||||
"""
|
"""
|
||||||
return self.run_command(command, privileged=privileged, timeout=60).stdout
|
return self.run_command(command, privileged=privileged, timeout=60).stdout
|
||||||
|
|
||||||
|
def _run_system_identity_command(self, command: str, *, privileged: bool) -> str:
|
||||||
|
"""The transport for ``SystemIdentityMixin.get_system_identity``: an exec channel,
|
||||||
|
as root, since ``product_uuid`` and ``product_serial`` are root's."""
|
||||||
|
return self.run_command(command, privileged=privileged, timeout=30).stdout
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# OSDriver – package management
|
# OSDriver – package management
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "napalm-linux"
|
name = "napalm-linux"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
description = "NAPALM driver for generic Linux systems via SSH"
|
description = "NAPALM driver for generic Linux systems via SSH"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
@@ -37,7 +37,7 @@ classifiers = [
|
|||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"napalm>=4.0",
|
"napalm>=4.0",
|
||||||
"napalm-device-types>=4.7.1",
|
"napalm-device-types>=4.9.0",
|
||||||
"netmiko>=4.0.0",
|
"netmiko>=4.0.0",
|
||||||
"paramiko>=5.0.0", # CVE-2026-44405
|
"paramiko>=5.0.0", # CVE-2026-44405
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1725,6 +1725,39 @@ class TestGetListeningSockets:
|
|||||||
assert plain.startswith("sh -c '")
|
assert plain.startswith("sh -c '")
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# get_system_identity (napalm-device-types SystemIdentityMixin)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetSystemIdentity:
|
||||||
|
"""What ties a host to its BMC: SMBIOS UUID and serials, read as root on an exec
|
||||||
|
channel (product_uuid and product_serial are root's)."""
|
||||||
|
|
||||||
|
def test_it_reads_the_shared_command_as_root_on_an_exec_channel(self, driver):
|
||||||
|
from napalm_device_types import SYSTEM_IDENTITY_COMMAND, CommandResult, SystemIdentityMixin
|
||||||
|
|
||||||
|
assert isinstance(driver, SystemIdentityMixin)
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
def run_command(command, *, privileged=False, timeout=60, stdin=None):
|
||||||
|
calls.append((command, privileged))
|
||||||
|
out = "IDBEGIN\n31303043-534D-C40C-7A72-6F1300000000\n0123456789\nZM155S026022\nIDEND\n"
|
||||||
|
return CommandResult(out, "", 0)
|
||||||
|
|
||||||
|
driver.run_command = run_command
|
||||||
|
|
||||||
|
identity = driver.get_system_identity()
|
||||||
|
|
||||||
|
assert identity == {
|
||||||
|
"system_uuid": "31303043-534d-c40c-7a72-6f1300000000",
|
||||||
|
"product_serial": "", # Supermicro's placeholder
|
||||||
|
"board_serial": "ZM155S026022",
|
||||||
|
}
|
||||||
|
assert calls == [(SYSTEM_IDENTITY_COMMAND, True)]
|
||||||
|
driver._device.send_command.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# get_virtual_ips (napalm-device-types VirtualIpsMixin)
|
# get_virtual_ips (napalm-device-types VirtualIpsMixin)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in new issue
Block a user