Commit Graph
20 Commits
Author SHA1 Message Date
Christian Manivong 672bc04261 fix: what bandit and the remaining lint rules found
- Netgear Plus: a failed logout on close() now logs at debug level (B110),
  so a swallowed failure leaves a trace; the module gets its logger.
- nosec for the firmware CDN probe (B310): the URL is built on the fixed
  https base _FW_CDN_BASE, model and version only fill its path, so no
  file:// or custom scheme can reach urlopen.
- nosec for the empty password in get_users (B105): it is NAPALM's field,
  the CLI never shows a password; a false positive.
- The v7 LLDP table in a docstring loses one leading space per line to fit
  line length 100.
- tests: a second TestGetLldpNeighbors class shadowed the first, whose two
  tests never ran; the v7 one is now TestGetLldpNeighborsV7 and both run
  (and pass). raise ... from exc in the netmiko stand-in.
2026-10-23 08:34:17 +02:00
Christian Manivong fa10d6617b style: ruff format and the lint rules of the driver standard
Mechanical: ruff format, and ruff check --fix with the rule set every NAPALM
driver uses (E, F, I, UP, B at line length 100, Python 3.10). What ruff
cannot fix comes in the next commit.
2026-10-23 08:32:43 +02:00
Christian Manivong 2de5844f92 fix(ssh): verify the host key netOrk expects, report the one seen (NetOrk/netork#1167)
CI / test (3.10) (push) Successful in 33s
CI / test (3.11) (push) Successful in 32s
CI / test (3.12) (push) Successful in 31s
CI / test (3.10) (pull_request) Successful in 27s
CI / test (3.11) (pull_request) Successful in 24s
CI / test (3.12) (pull_request) Successful in 26s
The driver accepted any SSH host key. It now verifies through
napalm-device-types' HostKeyCheck (>= 4.19.0): with a known key in
optional_args["ssh_host_keys"] any other key is refused before login, and
every key seen is reported to optional_args["ssh_host_key_observer"].
Without either argument it connects as before (first use).
2026-10-18 21:23:41 +02:00
Christian Manivong 4ccb2b5879 feat: report the firmware Netgear offers, not a warning (0.4.0)
CI / test (3.10) (push) Successful in 25s
CI / test (3.11) (push) Successful in 23s
CI / test (3.12) (push) Successful in 26s
CI / test (3.10) (pull_request) Successful in 24s
CI / test (3.11) (pull_request) Successful in 23s
CI / test (3.12) (pull_request) Successful in 25s
The Plus driver looked the newest firmware up in Netgear's download
catalogue and named firmware_update_available itself. It now reports
get_firmware_offer() (napalm-device-types 4.16 FirmwareOfferMixin): what
runs, the newest offered, whether that is newer by Netgear's versioning,
and the download link; netOrk names the warning (netOrk #1111). The Smart
driver's empty get_device_warnings goes too. Requires
napalm-device-types 4.16.0.
2026-10-17 13:04:36 +02:00
Christian Manivong 34554eade9 feat!: configure_snmp_agent with the caller's values replaces fix_snmp (0.3.0)
CI / test (3.10) (push) Successful in 24s
CI / test (3.11) (push) Successful in 23s
CI / test (3.12) (push) Successful in 25s
CI / test (3.10) (pull_request) Successful in 24s
CI / test (3.11) (pull_request) Successful in 23s
CI / test (3.12) (pull_request) Successful in 24s
fix_snmp hard-coded community "public" and sent its config-mode line
through _send_command, which waits for the exec prompt: in config mode
it ran into its timeout and left the session there (#6).

netgear_smart implements napalm-device-types 4.13's configure_snmp_agent
steps: community (read-only), contact and location from the caller
through _apply_config_lines, which waits for any prompt and reports a
refused line; config mode is left in all cases; the configuration is
saved and the community checked in show snmp. v7 firmware, which has
no SNMP commands in its CLI, says so. A value that would break the CLI
is refused.

napalm-device-types is now declared in pyproject.toml and
requirements.txt (#7).

BREAKING CHANGE: run_device_action is removed.

Closes #6. Part of #7 and #8.
2026-10-17 08:38:07 +02:00
Christian Manivong 6b305c3d47 feat: declare the SNMP health OIDs instead of collecting them (0.2.0)
CI / test (3.10) (push) Successful in 32s
CI / test (3.11) (push) Successful in 32s
CI / test (3.12) (push) Successful in 33s
CI / test (3.10) (pull_request) Successful in 32s
CI / test (3.11) (pull_request) Successful in 29s
CI / test (3.12) (pull_request) Successful in 33s
netgear_smart no longer collects over SNMP. SNMP_HEALTH_PROFILE states
where the switch publishes uptime (standard sysUpTime), memory (total
and free in KiB) and CPU (a text value whose five-second figure
counts); the application polls and computes (napalm-device-types
docs/STRUCTURE.md).

Interface counters now come from the 64-bit ifXTable where the switch
has it, as the application reads them for every device.
2026-10-16 12:03:00 +02:00
Christian Manivong 7103cefc41 refactor!: rename get_dot1x_config to get_dot1x_ports
SwitchDriver and AccessPointDriver both declared get_dot1x_config, but they
meant different things and returned different shapes — Dot1XPortDict per port on
a switch, Dot1XConfigDict per SSID on an access point. A device that is both
could not satisfy both contracts.

napalm-device-types v1.0 names them apart. This is the switch side.

BREAKING CHANGE: get_dot1x_config is now get_dot1x_ports on NetgearPlusDriver.
2026-08-21 12:50:10 +07:00
Christian Manivong efe004a295 fix(lldp): parse the v7 neighbour table, which uses a different command
get_lldp_neighbors() existed but spoke to the older CLI generation: it ran
`show lldp remote-device all` and expected FASTPATH-style `0/1` ports in
whitespace-separated columns. v7 firmware answers `Unknown command` — as it
does for `show lldp remote-device`, a bare `show lldp`, and the plural
`show lldp neighbors`. Only the singular works, though `show ?` lists `lldp`
plainly enough:

     Port |   Device ID       |     Port ID      |      SysName      | ...
     ---- + ----------------- + ---------------- + ----------------- + ...
       g9 | 10:01:02:44:37:26 |10:01:02:44:37:28 | pve-eze.eze.local | ...

Ports are named g9, and the columns are separated by `|` with irregular
padding, so splitting on whitespace tears the values apart. The port ID is
not always a port name either — a neighbour may identify its port by MAC.

_get_lldp_table() now branches on _detect_cli_v7() into a second parser, the
same shape get_mac_address_table() already uses for this divergence.
get_lldp_neighbors() itself is untouched.

Confirmed against a GS110TPv3 on 7.1.1.17: _detect_cli_v7() returns True
there, and the switch reports two neighbours it had never surfaced. Without
them NetOrk's map had nothing to draw for the site this switch serves, so
four APs and a firewall behind it stood unconnected.
2026-08-18 15:18:56 +07:00
Christian Manivong 5317af0be1 fix(config): drop the uptime line from get_config()
`show running-config` is preceded by a header block, and one of its lines
reports the system uptime. That value necessarily differs between any two
reads, so every caller comparing consecutive configs sees a change each
time.

Measured on a GS110TPv3 under NetOrk: 876 of 894 stored config snapshots
marked as changed, one git commit and one config_changed warning per poll,
while every other device at the same installation sat between 2 and 18. The
history was worthless for that switch — a genuine change would have been
invisible among hundreds of uptime diffs.

Only the uptime line is removed. Model, firmware version, serial and MAC are
stable and belong in a config backup; a changed firmware version is exactly
the kind of change worth recording.

netgear_plus is unaffected — its get_config() returns empty strings.

The first read after this lands reports one real change, since the line
disappears from the stored config. That is unavoidable and happens once.
2026-08-18 10:30:11 +07:00
Christian Manivong 20460e7a5a refactor(warnings): report raw signal only, no severity/presentation
get_device_warnings() now returns only {code, meta} — severity, title,
message, and action are resolved centrally by netork's
WARNING_CATALOG (netork/core/device_warnings.py), not by the driver.
Keeps this driver independent of netork and avoids per-vendor drift in
how the same warning code is presented.
2026-07-20 09:58:21 +02:00
Christian Manivong 46e419d232 fix(get_config): use paged send for show running-config/startup-config
"v7" CLI firmware has no "terminal length 0" equivalent (see
_send_paged_command's docstring), so a config long enough to paginate
emits "--More--" prompts that _send_command's expect_string=base_prompt
match never sees. On real hardware (GS110TPv3, 7 VLANs, 10 interfaces)
this hung every scheduled config-backup poll for 30s and failed with
"Pattern not detected: '<prompt>[>#]' in output.", so the config was
never actually backed up. get_mac_address_table()/get_vlans() already
use _send_paged_command() for the same reason on other long outputs;
get_config() now does too.

Also fixed tests/unit/test_driver.py's import/patch target
(napalm_netgear_plus -> napalm_netgear, the actual package name) —
the whole file has been uncollectable since its initial commit, no CI
was wired up here to catch it. And removed a dead unreachable
`return {"success": ..., "output": ...}` line after get_health_metrics's
real return (undefined names, ruff F821), unrelated leftover found
while fixing the above.
2026-07-10 09:54:29 +02:00
Christian ManivongandClaude Sonnet 4.6 17a0b36dce feat: OUI_PREFIXES für MAC/ARP-Fingerprinting
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:41:45 +02:00
Christian ManivongandClaude Sonnet 4.6 36a239692b feat: Fingerprint-Attribute für Discovery-Scoring
Ergänzt DRIVER_NAME, HTTP_FINGERPRINT, SNMP_FINGERPRINT, SSH_FINGERPRINT,
PORT_SPECS und SNMP_OBJECT_ID_PREFIX gemäß docs/DISCOVERY_FINGERPRINTING.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 14:47:08 +02:00
Christian Manivong aef5eb1487 feat: include remote chassis MAC in LLDP neighbor entries
Enables MAC-based topology matching against devices that report their
own MAC but not a usable system name.
2026-06-12 21:08:26 +02:00
Christian ManivongandClaude Sonnet 4.6 96ae50551b fix: case-insensitive config prompt match and fast-fail fix_snmp on v7 CLI
_conf_prompt() only matched the legacy "(Config)" prompt, so on v7
"Cisco-like" CLI (lowercase "(config)") _enter_config_mode() blocked for
the full read_timeout - this was the cause of fix_snmp hanging.

_action_fix_snmp() also never returned a result on the legacy path, and
v7 firmware has no snmp-server/show snmp commands at all. It now detects
v7 CLI up front and returns a clear failure message instead of hanging.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 19:16:47 +02:00
Christian ManivongandClaude Sonnet 4.6 0ba59750d2 feat: add PoE config and LAG/trunk membership support
get_poe_status()/set_poe() implement PoE port config via the ProSafe CLI's
'power inline' interface sub-commands. get_interfaces() now enriches chN
LAG entries and their member ports with trunk_group/lag_members/lag_mode
by parsing 'show port-channel all'. New set_lag_members() adds/removes
members via addport/deleteport.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 14:47:27 +02:00
Christian ManivongandClaude Sonnet 4.6 5e2c6249fb feat: add get_health_metrics() via Netgear proprietary OIDs
SNMP health metrics using Netgear enterprise MIB (OID 4526) for
memory free/total and CPU utilization string parsing, plus IF-MIB counters.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:43:43 +02:00
Christian ManivongandClaude Sonnet 4.6 54fe6ddea1 fix: correct module import path and add SNMP_CAPABLE=False for Plus switches
- __init__.py imported from non-existent napalm_netgear_plus module; fixed to napalm_netgear
- NetgearPlusDriver.SNMP_CAPABLE = False signals HTTP-only device — suppresses
  misleading SNMP-not-configured warnings during device polls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 13:28:04 +02:00
Christian ManivongandClaude Sonnet 4.6 64eb2551a4 feat: SNMP support — get_snmp_config(), fix_snmp for Smart switches
NetgearPlus: get_snmp_config() returns None (SNMP not accessible via HTTP API).
NetgearSmart: get_snmp_config() reads current community, fix_snmp configures
'snmp-server community public ro' via CLI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 13:10:03 +02:00
Christian Manivong a8ce5a8033 initial commit 2026-05-29 09:13:59 +02:00