get_config() hangs 30s and fails on "v7" CLI switches with long running-config output #1

Closed
opened 2026-07-10 08:21:30 +00:00 by christianmanivong · 0 comments
Owner

Symptom (production, 10.10.0.100, device 10.10.40.20 / GS110TPv3, 7 VLANs, 10 interfaces): the main NAPALM poll succeeds completely (interfaces, VLANs, MAC table, SNMP all fine), then the scheduled config-backup step calls get_config() and fails after ~30s:

get_config() failed for 10.10.40.20:
Pattern not detected: 'GS110TPv3[>#]' in output.

Root cause: get_config() (napalm_netgear/netgear_smart.py) called self._send_command("show running-config") / self._send_command("show startup-config"). _send_command() uses Netmiko's send_command() with expect_string=<base_prompt>[>#]. "v7" CLI firmware (e.g. 7.1.1.17) has no terminal length 0 equivalent (see _send_paged_command's own docstring), so a config long enough to paginate emits --More-- prompts that this expect_string never matches — Netmiko just waits until read_timeout (30s) and raises. get_mac_address_table()/get_vlans() already route through _send_paged_command() (raw write_channel/read_channel, manually drains --More--) for exactly this reason; get_config() was the one place still using the broken path.

Fix: get_config() now uses _send_paged_command() for both running and startup config. Commit 46e419d, deployed and verified live on 172.22.8.50.

Regression test: tests/unit/test_driver.py::TestGetConfig::test_uses_paged_command_not_plain_send_command — asserts get_config() never calls _send_command() and calls _send_paged_command() exactly twice. Red/Green verified.

Also found + fixed in the same commit (unrelated, found via ruff check while working on the above):

  • tests/unit/test_driver.py imported/patched napalm_netgear_plus (a module that doesn't exist — the real package is napalm_netgear). The entire test file has been uncollectable since its initial commit; there's no .gitea/workflows/ in this repo, so nothing ever caught it. Fixed the import/patch target; all 66 tests now collect and pass.
  • get_health_metrics() had a dead, unreachable return {"success": success, "output": ...} line after its real return metrics (undefined names, ruff F821, zero runtime impact since unreachable). Removed.

Follow-up worth doing separately: this repo has no Gitea Actions workflow at all, which is how the broken test import went unnoticed. Consider adding one (see netork's .gitea/workflows/ci.yml for the pattern used elsewhere).

**Symptom (production, 10.10.0.100, device 10.10.40.20 / GS110TPv3, 7 VLANs, 10 interfaces):** the main NAPALM poll succeeds completely (interfaces, VLANs, MAC table, SNMP all fine), then the scheduled config-backup step calls `get_config()` and fails after ~30s: ``` get_config() failed for 10.10.40.20: Pattern not detected: 'GS110TPv3[>#]' in output. ``` **Root cause:** `get_config()` (`napalm_netgear/netgear_smart.py`) called `self._send_command("show running-config")` / `self._send_command("show startup-config")`. `_send_command()` uses Netmiko's `send_command()` with `expect_string=<base_prompt>[>#]`. "v7" CLI firmware (e.g. 7.1.1.17) has no `terminal length 0` equivalent (see `_send_paged_command`'s own docstring), so a config long enough to paginate emits `--More--` prompts that this expect_string never matches — Netmiko just waits until `read_timeout` (30s) and raises. `get_mac_address_table()`/`get_vlans()` already route through `_send_paged_command()` (raw `write_channel`/`read_channel`, manually drains `--More--`) for exactly this reason; `get_config()` was the one place still using the broken path. **Fix:** `get_config()` now uses `_send_paged_command()` for both running and startup config. Commit `46e419d`, deployed and verified live on 172.22.8.50. **Regression test:** `tests/unit/test_driver.py::TestGetConfig::test_uses_paged_command_not_plain_send_command` — asserts `get_config()` never calls `_send_command()` and calls `_send_paged_command()` exactly twice. Red/Green verified. **Also found + fixed in the same commit (unrelated, found via `ruff check` while working on the above):** - `tests/unit/test_driver.py` imported/patched `napalm_netgear_plus` (a module that doesn't exist — the real package is `napalm_netgear`). The entire test file has been uncollectable since its initial commit; there's no `.gitea/workflows/` in this repo, so nothing ever caught it. Fixed the import/patch target; all 66 tests now collect and pass. - `get_health_metrics()` had a dead, unreachable `return {"success": success, "output": ...}` line after its real `return metrics` (undefined names, `ruff F821`, zero runtime impact since unreachable). Removed. **Follow-up worth doing separately:** this repo has no Gitea Actions workflow at all, which is how the broken test import went unnoticed. Consider adding one (see `netork`'s `.gitea/workflows/ci.yml` for the pattern used elsewhere).
christianmanivong added the bug label 2026-07-10 08:21:30 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: NAPALM/napalm-netgear#1