Commit Graph
12 Commits
Author SHA1 Message Date
Christian Manivong 779b42c193 chore: adopt the NAPALM driver standard
driver / standard (pull_request) Successful in 13s
driver / lint (pull_request) Successful in 11s
driver / types (pull_request) Successful in 44s
driver / test (3.10) (pull_request) Successful in 45s
driver / test (3.11) (pull_request) Successful in 44s
driver / test (3.12) (pull_request) Successful in 43s
driver / test (3.13) (pull_request) Successful in 37s
driver / lowest (pull_request) Successful in 22s
driver / security (pull_request) Successful in 46s
driver / build (pull_request) Successful in 22s
CI / driver (pull_request) Successful in 5m28s
driver / publish (pull_request) Skipped
- CI moves to .gitea/workflows/ci.yml and calls the shared driver workflow
  of NAPALM/driver-standard; .github/ goes.
- requires-python >=3.10 (napalm-device-types needs it), LICENSE file,
  CHANGELOG, py.typed, SPDX license string, links to git.netork.io;
  napalm-device-types >=4.21.1, a dev extra with floors.
- [tool.napalm-standard] names the import package napalm_procurve, which is
  not the distribution name.
- True floors for netaddr (>=0.7.10) and urllib3 (>=1.23): unbounded, the
  lowest job installed versions that do not import on Python 3.10.
- mypy strict for the package; napalm_procurve.api_client, .parsers and
  .procurve are exempt for now (136 errors), recorded in the quality
  baseline with their long functions and the 1400-line procurve.py.
  Coverage floor 54 % (measured 54.28 %).
2026-10-23 08:40:11 +02:00
Christian Manivong fc24495b83 fix: what bandit and the remaining lint rules found
- The six except Exception: pass (REST logout, the extra-ports lookup, the
  per-port detail in get_interfaces, closing CLI and REST sessions) now log
  at debug level (B110), so a swallowed failure leaves a trace.
- nosec for comparing a reported address with 0.0.0.0 (B104) and for the
  empty password field of get_users (B105, now a named constant); both are
  false positives.
- A long error message is split into adjacent f-strings; the unused ARP
  entry type is named _entry_type.
- tests: the failed-open test expects ConnectionException instead of any
  Exception; raise ... from exc.
2026-10-23 08:34:55 +02:00
Christian Manivong c2a788fa7a 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:50 +02:00
Christian Manivong fe0aec9432 fix(ssh): verify the host key netOrk expects, report the one seen (NetOrk/netork#1167)
CI / test (3.10) (push) Successful in 32s
CI / test (3.11) (push) Successful in 37s
CI / test (3.12) (push) Successful in 35s
CI / test (3.10) (pull_request) Successful in 29s
CI / test (3.11) (pull_request) Successful in 28s
CI / test (3.12) (pull_request) Successful in 28s
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:43 +02:00
Christian Manivong 0527cd20c1 feat!: configure_snmp_agent with the caller's values replaces fix_snmp (0.4.0)
CI / test (3.10) (push) Successful in 24s
CI / test (3.11) (push) Successful in 24s
CI / test (3.12) (push) Successful in 24s
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". The driver implements
napalm-device-types 4.13's configure_snmp_agent as a whole, because
over REST a temporary SSH session has to run the config-mode CLI:
community (read-only), contact and location from the caller, saved
and verified in show snmp-server. The agent is built in and the switch
filters nothing for its management plane; the steps say so instead of
pretending. A value that would break the CLI is refused.

The unused _detect_management_vlan goes with it.

BREAKING CHANGE: run_device_action is removed.

Part of #12 and #6 (the dead helper).
2026-10-17 08:35:30 +02:00
Christian Manivong 0c0ab7c988 chore: declare napalm-device-types, stop tracking build artefacts
pyproject.toml did not list napalm-device-types although the code
imports it (CI installed it by hand); it now requires 4.13, whose fix
templates the next commit uses. Seven .pyc and six egg-info files were
tracked; they go, and a .gitignore keeps them out.

Closes #11
2026-10-17 08:35:20 +02:00
Christian Manivong 39d5e69270 feat: declare the SNMP health OIDs instead of collecting them (0.3.0)
CI / test (3.10) (push) Successful in 31s
CI / test (3.11) (push) Successful in 30s
CI / test (3.12) (push) Successful in 33s
CI / test (3.10) (pull_request) Successful in 33s
CI / test (3.11) (pull_request) Successful in 30s
CI / test (3.12) (pull_request) Successful in 32s
The driver no longer collects over SNMP. SNMP_HEALTH_PROFILE states
where the switch publishes its values; the application polls and
computes (napalm-device-types docs/STRUCTURE.md).

This also fixes the memory figure: NETSWITCH-MIB hpLocalMemEntry column
6 is free memory, not used. On swt-l0-3-40 total 58720256 = free
39105640 + allocated 19614616, so the switch showed 66.6 % used instead
of 33.4 %. The profile names column 6 as free.

Interface counters now come from the 64-bit ifXTable where the switch
has it, as the application reads them for every device.

Closes #9
2026-10-16 12:02:00 +02:00
Christian Manivong 7f07da6857 fix(cli): the trunk gets its own row, as over REST
Since f35b59e a CLI poll reports trunk members as `3` with
trunk_group `Trk3`, but `show interfaces brief` has no line for Trk3
itself, so the trunk was missing from the interface list. The REST path
built that row on its own.

Both paths now use napalm_device_types.add_lag_interfaces, and the REST
path's copy is gone. One visible change there: `lag_members` is now in
port order (7, 10) instead of API order; the description already was.

The CLI path does not know the mode yet, so its trunks carry no
lag_mode. That needs `show trunks`, whose output is not at hand.

Needs napalm-device-types f3fa75b.

Closes #5
2026-09-25 10:44:11 +02:00
Christian Manivong f35b59ec2d fix(cli): read J.15 port status, and say why each transport failed
A 2800-series switch on J.15.09 polled over CLI came back with no
interfaces and an empty OS version, while VLANs and ARP parsed fine.

`show interfaces brief` on that firmware has an Intrusion Alert column
between the `|` and Enabled, and puts Mode before MDI rather than after:

      Port   Type      | Alert     Enabled Status Mode       Mode ...
      3-Trk3 100/1000T | No        Yes     Down   1000FDx    MDI  ...

The regex read Alert as Enabled, then failed on Yes where it wanted
Up|Down, so no line matched. It now skips the Alert column where there is
one and takes the speed from either position. Trunk members are listed as
`<port>-Trk<n>`; the port is `<port>` and the suffix becomes its
trunk_group, so the per-port `show interfaces 3` is a command the switch
knows.

The empty OS version was the alternatives list in _send_command. It moved
to the next command on "% Invalid" or "Error", but ProCurve rejects an
unknown command with "Invalid input: system-information" -- so that line
was parsed as system information. "Invalid input" now counts as failure.

Getting there took longer than it should have, because the first symptom
was "Authentication failed: Login failed". That was Telnet's error, the
last transport tried; the REST probe and both SSH attempts had failed
before it and said nothing above debug level. In fact the switch had run
out of CLI sessions and closed SSH straight after the password. open()
now records why each transport failed, and both the auth error and the
final "Cannot connect" carry that list.

Fixtures are that switch's output, with hostname, serial and MAC
replaced.

Closes #2
Closes #3
Closes #4
2026-09-25 08:55:11 +02:00
Christian Manivong e3bbac0656 fix(api): change an existing VLAN membership instead of re-creating it
set_interface() always POSTed to vlans-ports, treating every membership as
new. Moving a port that already carries the VLAN from untagged to tagged is
not a create, though, and the switch says so:

    POST vlans-ports {"vlan_id":10,"port_id":"10","port_mode":"POM_TAGGED_STATIC"}
      -> 400 {"message":"Association exists"}

Only 409 was handled as "already there"; v7 firmware answers 400. The
membership is its own resource named {vlan_id}-{port_id} and takes a PUT:

    PUT vlans-ports/10-10 -> 200

So the exact case anyone hits first failed outright — a port holding VLAN 10
untagged alongside 30/40/50 tagged, with VLAN 10 to become tagged too.

The response body is now carried into both error messages. The ports PUT just
above already did this; here it was dropped, so "Association exists" — which
names the cause outright — never reached the caller. The message read
"vlans-ports POST HTTP 400" and nothing more.

Verified against a 2530-24G-PoEP on REST v7: set_interface("10", trunk
vlan 30), where that membership already exists, now completes and leaves the
port exactly as it was.
2026-08-18 16:22:21 +07:00
Christian ManivongandClaude Sonnet 4.6 247964178a 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 35032fd034 initial commit 2026-05-29 09:30:53 +02:00