diff --git a/napalm_netgear/netgear_plus.py b/napalm_netgear/netgear_plus.py index 989d078..a338a93 100644 --- a/napalm_netgear/netgear_plus.py +++ b/napalm_netgear/netgear_plus.py @@ -21,6 +21,7 @@ The ``username`` parameter is accepted but ignored. from __future__ import annotations +import logging import threading import time from typing import Any @@ -28,6 +29,8 @@ from typing import Any from napalm.base.exceptions import ConnectionException from napalm_device_types import FingerprintRule, FirmwareOfferMixin, SwitchDriver +logger = logging.getLogger(__name__) + # --------------------------------------------------------------------------- # Firmware update check — module-level constants and cache # --------------------------------------------------------------------------- @@ -69,7 +72,8 @@ def _fw_cdn_exists(model: str, version: str) -> bool: ctx = ssl.create_default_context() req = urllib.request.Request(url, method="HEAD", headers={"User-Agent": "Mozilla/5.0"}) try: - with urllib.request.urlopen(req, timeout=3, context=ctx): + # The URL is always https on _FW_CDN_BASE; model and version only fill the path. + with urllib.request.urlopen(req, timeout=3, context=ctx): # nosec B310 return True except Exception: return False @@ -220,7 +224,7 @@ class NetgearPlusDriver(FirmwareOfferMixin, SwitchDriver): try: self._connector.delete_login_cookie() except Exception: - pass + logger.debug("Logging out of the switch failed: ignored", exc_info=True) self._connector = None self._switch_infos_cache = None diff --git a/napalm_netgear/netgear_smart.py b/napalm_netgear/netgear_smart.py index 5b2d748..915d21f 100644 --- a/napalm_netgear/netgear_smart.py +++ b/napalm_netgear/netgear_smart.py @@ -1115,9 +1115,9 @@ class NetgearSmartDriver(ConfigLifecycleMixin, SnmpAgentMixin, SwitchDriver): ``show lldp`` — both answer "Unknown command". Only the singular ``neighbor`` works, and it lays the table out differently:: - Port | Device ID | Port ID | SysName | Capabilities | TTL - ---- + ----------------- + ---------------- + ----------------- + -------------- + ----- - g9 | 10:01:02:44:37:26 |10:01:02:44:37:28 | pve-eze.eze.local | Bridge | 97 + Port | Device ID | Port ID | SysName | Capabilities | TTL + ---- + ----------------- + ---------------- + ----------------- + -------------- + ----- + g9 | 10:01:02:44:37:26 |10:01:02:44:37:28 | pve-eze.eze.local | Bridge | 97 Ports are named ``g9`` rather than ``0/1``, and the columns are separated by ``|`` with irregular padding — splitting on whitespace @@ -1629,7 +1629,8 @@ class NetgearSmartDriver(ConfigLifecycleMixin, SnmpAgentMixin, SwitchDriver): username = parts[0] role = parts[1].lower() level = 15 if "write" in role or "admin" in role else 1 - users[username] = {"level": level, "password": "", "sshkeys": []} + # NAPALM's get_users shape: the CLI never shows a password, so it is empty. + users[username] = {"level": level, "password": "", "sshkeys": []} # nosec B105 return users diff --git a/tests/unit/test_driver.py b/tests/unit/test_driver.py index 5dc8da5..d684dbe 100644 --- a/tests/unit/test_driver.py +++ b/tests/unit/test_driver.py @@ -745,7 +745,7 @@ GS110TPv3# """ -class TestGetLldpNeighbors: +class TestGetLldpNeighborsV7: """`show lldp neighbor` — the switch does speak LLDP, the driver did not. Without this the map has nothing to draw for the site this switch serves: diff --git a/tests/unit/test_ssh_host_key.py b/tests/unit/test_ssh_host_key.py index 648ef87..b77d227 100644 --- a/tests/unit/test_ssh_host_key.py +++ b/tests/unit/test_ssh_host_key.py @@ -76,7 +76,7 @@ def test_a_changed_key_is_refused(): try: raise paramiko.BadHostKeyException("10.0.0.8", SERVER_KEY, OTHER_KEY) except paramiko.SSHException as exc: # what netmiko does with it - raise NetmikoTimeoutException(f"A paramiko SSHException occurred: {exc}") + raise NetmikoTimeoutException(f"A paramiko SSHException occurred: {exc}") from exc driver = _driver(seen, SshHostKey.of(OTHER_KEY)) with patch(HANDLER, side_effect=refuse):