Files
bf-infra/docs/nas-vlan20/nautobot-image/allnet_sg8316m_driver.py
Christoph Emsenhuber 1578de50c3 TP15/TP16.1: kein RB5009, WG-Mesh auf CRS326; TP21: Golden-Config-Image im Repo
- RB5009 final gestrichen (User-Entscheid 2026-07-22) — Router bleibt ap1/ap2,
  Referenzen in teilprojekte.md + hw-refresh-requirements.md bereinigt.
- TP16.1 Ziel-Device von ap1 auf CRS326 Core-Switch retargeted (Doku-only,
  Scharfschalten bleibt gated bis TP21 den CRS326 abdeckt), Runbook umbenannt
  auf tp16.1-warp-mesh-native-crs326.md, cf-tunnel-mapping.md §14 + Handoff-
  Prompt mitgezogen.
- TP21: docs/nas-vlan20/nautobot-image/ neu — der Dockerfile/nautobot_config.py/
  allnet_sg8316m_driver.py, aus denen das laufende Custom-Image tatsächlich
  gebaut ist (der bisherige Verweis auf scratch/nautobot-gc-build existierte
  nirgends). Ergänzt napalm-ros + nornir-napalm + librouteros + gepinntes
  setuptools<81 (pkg_resources-Regression), Nornir-Credentials auf
  CredentialsNautobotSecrets umgestellt, Compliance/Intended-Config/SoT-Agg
  aktiviert. Backup/Intended/Compliance-Pipeline live gegen ap1 verifiziert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 19:46:24 +02:00

90 lines
3.5 KiB
Python

"""Custom Netmiko driver for the ALL-SG8316M (sw1) -- Telnet-only, IOS-like but
non-standard CLI (no `terminal length`, `--More--` paging, `end` from
config-vlan skips straight to the top level). No stock Netmiko/NAPALM driver
matches this device.
NOT YET WIRED IN: this module is imported nowhere yet. The `claudecode`
Telnet account on sw1 is currently rejected ("Incorrect User Name!!", found
2026-07-16) so this driver is unverified against the real device. Once
working credentials exist, activate it from nautobot_config.py:
import importlib
import allnet_sg8316m_driver # noqa: F401 (registers itself on import)
and add to PLUGINS_CONFIG["nautobot_plugin_nornir"]["dispatcher_mapping"]:
"allnet_sg8316m": "allnet_sg8316m_driver.GoldenConfigAllnetSg8316m"
(dispatcher class still needs writing once the connection class below is
confirmed to log in cleanly -- see project_nautobot_allnet_cudy_scope_20260716
memory for the full status and the two netmiko gotchas that cost the most
time: device_type must contain the literal substring "_telnet" for Netmiko to
pick the Telnet transport at all (BaseConnection.__init__ checks this by
string, not by class hierarchy), and `netmiko.ssh_dispatcher` at package level
is the dispatcher *function*, not the submodule -- reach CLASS_MAPPER via
`importlib.import_module("netmiko.ssh_dispatcher")`.
"""
import importlib
import time
from netmiko.cisco_base_connection import CiscoBaseConnection
_nm_dispatch = importlib.import_module("netmiko.ssh_dispatcher")
class AllnetSg8316mTelnet(CiscoBaseConnection):
def session_preparation(self):
self._test_channel_read(pattern=r"[>#]")
self.set_base_prompt()
self.ansi_escape_codes = True
def disable_paging(self, *args, **kwargs):
# No config knob for this on this firmware; paging is handled
# per-command in send_command_paged() below instead.
return ""
def telnet_login(
self,
pri_prompt_terminator=r"#\s*$",
alt_prompt_terminator=r">\s*$",
username_pattern=r"Username",
pwd_pattern=r"Password",
delay_factor=1,
max_loops=20,
):
return super().telnet_login(
pri_prompt_terminator=pri_prompt_terminator,
alt_prompt_terminator=alt_prompt_terminator,
username_pattern=username_pattern,
pwd_pattern=pwd_pattern,
delay_factor=delay_factor,
max_loops=max_loops,
)
def send_command_paged(self, command_string, max_pages=200, delay=0.3):
"""sg8316m paginates with '--More--' and has no length-0 setting;
page through by sending a space each time it appears."""
self.write_channel(command_string + self.RETURN)
time.sleep(delay)
output = ""
for _ in range(max_pages):
chunk = self.read_channel()
output += chunk
if "--More--" in chunk:
self.write_channel(" ")
time.sleep(delay)
continue
if any(p in chunk for p in ["sw1#", "sw1>"]) and "--More--" not in chunk:
break
if chunk == "":
time.sleep(delay)
return output.replace("--More--", "")
# Registered under the "_telnet" suffix required by Netmiko's own transport
# selection (see module docstring) -- registration is safe/inert on its own,
# nothing calls ConnectHandler(device_type="allnet_sg8316m_telnet") yet.
_nm_dispatch.CLASS_MAPPER["allnet_sg8316m_telnet"] = AllnetSg8316mTelnet
_nm_dispatch.platforms = list(_nm_dispatch.CLASS_MAPPER.keys())