- Long lines are wrapped: the get_environment awk command is split into
adjacent string literals, the rollback message and the system mixin's
docstring are wrapped; the command and the text are unchanged.
- The two except Exception: pass (the snmpd community in get_snmp_config,
the network VLANs in get_ssids) now log at debug level (B110), so a
swallowed failure leaves a trace.
- tests: raise ... from exc, unused loop variable.
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.
run_command and open_stream (napalm-device-types CommandChannelMixin,
which AccessPointDriver carries) run on an SSH exec channel next to
netmiko's shell: stdin, stderr apart, a real exit code. netOrk sent UCI
scripts and the wifi channel through the private _send_command, typing
a file in base64 chunks or printf lines; with stdin it writes it with
cat, and base64 is needed for nothing (netOrk #1113). OpenWrt has no
sudo, so a privileged command from a login other than root is refused
before it runs.
get_device_warnings goes with it: no_base64 was its last code.
get_device_warnings no longer names lldpd_not_installed,
updates_available or update_notifications_disabled. The packages and
get_available_updates are the facts; netOrk derives the warnings with the
same reach (netOrk #1111). The old update read swallowed failures,
get_available_updates raises them.
no_base64 stays: BusyBox may provide base64 as an applet, so no package
tells the caller whether it is there.
fix_snmp set no community at all and opened the management zone's
udp/161 to every source, with a rule named after an application; a
second fix_snmp in the system mixin was shadowed and never ran (#5).
install_lldpd, install_auc and install_coreutils_base64 were actions of
their own.
The driver implements napalm-device-types 4.13's templates instead:
- configure_snmp_agent(settings): snmpd installed when missing;
community, contact and location in UCI with one com2sec (com2sec6)
per allowed source; the zone-resolving firewall step of the old fix,
now limited to the sources (src_ip) and named Allow-SNMP; snmpd
enabled, restarted and listening;
- get_management_peer() from SSH_CONNECTION;
- ensure_package(name) from the base package, over install_package.
A community, contact or location that would break UCI is refused.
BREAKING CHANGE: run_device_action is removed. Requires
napalm-device-types 4.13.
Closes#5. Part of #13.
OpenWrt keeps its package index in RAM. After a reboot `apk version` only
warns that it cannot open its cached index and exits 0, and `opkg
list-upgradable` prints nothing: both read as "no updates". netOrk keeps
"pending since" per package (MVP 5), so the reader now raises instead:
- apk: on apk's own warning ("opening from cache ... No such file"), or a
failed exit status.
- opkg: when /var/opkg-lists is empty.
- refresh_available_updates(): apk update / opkg update, success from the
exit status.
get_system_config() already parsed the whole system section but returned
only a slice of it, so netOrk had no IST side for three AP-profile fields
and could not compare them at all — the fields were editable, stored and
silently ineffective.
Adds:
* syslog_remote / syslog_ip / syslog_port / syslog_proto — read from the
system section that was already being parsed. log_remote gates the
others: OpenWrt ships nothing without it, so a leftover log_ip must
not read as an active target.
* luci_enabled — from the uhttpd init script rather than its listener
config, so the answer stays "is the web UI served" and re-enabling
restores whatever was configured before.
* bridge_stp — None when there is no br-ap at all, which is a different
statement from "bridge without STP" and has to stay distinguishable.
netOrk #164
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.
Two bugs prevented the firewall step from working:
1. `netstat` was used to detect the SSH peer IP — not installed on
OpenWrt by default, so raw_conn was empty and the entire firewall
step was silently skipped.
2. Even if detection had worked, `src='*'` is wrong when zones have
`input='REJECT'`. The rule only takes effect before the zone policy
if `src` is the exact zone name.
Fix: switch to `ss` (always present), strip any IPv6-mapped prefix,
then walk `uci show firewall` to find the zone whose network interface
shares the same /24 as the peer IP. Use that zone name as `src`.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>