feat: read the host's listening sockets through napalm-device-types

LinuxDriver mixes in ListeningSocketsMixin (napalm-device-types 2.4.0) and
supplies its transport: privileged readings go through _run_privileged --
as they are for a root login, through sudo with a password, sudo -n
without one -- and the rest through _send. The command arrives as one
sh -c argument, so sudo covers the whole script; when sudo refuses, the
mixin reads again without it.

OpenMediaVault and QNAP QTS inherit it; a host without ss raises
ListeningSocketsUnavailable.

For netOrk#658.
This commit is contained in:
Christian Manivong
2026-10-06 18:19:31 +02:00
parent 3571149639
commit 79e52f060e
3 changed files with 80 additions and 2 deletions
+17 -1
View File
@@ -37,6 +37,7 @@ from napalm_device_types import (
FingerprintRule,
HostStatusMixin,
KernelFactsMixin,
ListeningSocketsMixin,
OSDriver,
SystemdServicesMixin,
SystemdUnavailable,
@@ -214,7 +215,9 @@ def _short_image_id(raw: str) -> str:
return raw.strip().removeprefix("sha256:")[:12]
class LinuxDriver(KernelFactsMixin, SystemdServicesMixin, HostStatusMixin, OSDriver):
class LinuxDriver(
KernelFactsMixin, ListeningSocketsMixin, SystemdServicesMixin, HostStatusMixin, OSDriver
):
"""NAPALM driver for generic Linux systems.
Connects via SSH (netmiko ``linux`` device type) and auto-detects the
@@ -969,6 +972,19 @@ class LinuxDriver(KernelFactsMixin, SystemdServicesMixin, HostStatusMixin, OSDri
"""The transport for ``KernelFactsMixin.get_kernel_facts``: read-only, no sudo."""
return self._send(command, read_timeout=60)
# ------------------------------------------------------------------
# ListeningSocketsMixin – the transport for get_listening_sockets
# ------------------------------------------------------------------
def _run_listening_sockets_command(self, command: str, *, privileged: bool) -> str:
"""The transport for ``ListeningSocketsMixin.get_listening_sockets``.
Read-only either way; root only so that ``ss`` names every process.
"""
if privileged:
return self._run_privileged(command, 60)
return self._send(command, read_timeout=60)
# ------------------------------------------------------------------
# OSDriver – package management
# ------------------------------------------------------------------