Mixes in napalm-device-types' ListeningSocketsMixin (2.5.0): without ss the shared command reads busybox netstat, and each process's cgroup names its procd service. The driver only carries the command across. Over an SSH exec channel of its own, not the interactive shell: busybox ash cuts a typed line at 512 characters, the command is longer, and the cut line left the shell waiting for a closing quote. OpenWrt logs in as root; a login other than root cannot become root, so its reading says it is not attributed. Checked against a real OpenWrt 25.12.2 access point. For netOrk#673.
119 lines
2.7 KiB
Markdown
119 lines
2.7 KiB
Markdown
# napalm-openwrt
|
|
|
|
NAPALM community driver for **OpenWrt** routers and access-points.
|
|
|
|
Communicates over SSH using [Netmiko](https://github.com/ktbyers/netmiko) (`linux` device type).
|
|
Requires OpenWrt **19.07** or newer.
|
|
|
|
## Tested devices
|
|
|
|
| Model | OpenWrt version | Tested |
|
|
|---|---|---|
|
|
| TP-Link TL-WR1043N/ND v5 | 23.05.3 | ✅ |
|
|
|
|
> Contributions for additional devices and firmware versions are welcome.
|
|
|
|
## Requirements
|
|
|
|
| Dependency | Minimum version |
|
|
|---|---|
|
|
| Python | 3.8 |
|
|
| NAPALM | 4.0 |
|
|
| Netmiko | 4.0 |
|
|
|
|
## Installation
|
|
|
|
From source:
|
|
|
|
```bash
|
|
git clone https://github.com/napalm-automation-community/napalm-openwrt
|
|
cd napalm-openwrt
|
|
pip install -e .
|
|
```
|
|
|
|
## Quick start
|
|
|
|
```python
|
|
from napalm import get_network_driver
|
|
|
|
driver = get_network_driver("openwrt")
|
|
device = driver("192.168.1.1", "root", "")
|
|
|
|
device.open()
|
|
|
|
facts = device.get_facts()
|
|
print(facts)
|
|
|
|
interfaces = device.get_interfaces()
|
|
print(interfaces)
|
|
|
|
device.close()
|
|
```
|
|
|
|
## Supported NAPALM getters
|
|
|
|
| Getter | Supported | Notes |
|
|
|---|---|---|
|
|
| `get_facts` | ✅ | Uses `/etc/openwrt_release`, `/tmp/sysinfo/model`, `/proc/uptime` |
|
|
| `get_interfaces` | ✅ | Uses `ip link show` |
|
|
| `get_interfaces_ip` | ✅ | Uses `ip addr show` |
|
|
| `get_interfaces_counters` | ✅ | Uses `/proc/net/dev` |
|
|
| `get_arp_table` | ✅ | Uses `ip neigh show` |
|
|
| `get_mac_address_table` | ✅ | Uses `bridge fdb show` |
|
|
| `get_config` | ✅ | Uses `uci export` |
|
|
| `get_environment` | ✅ | CPU from `/proc/stat`, memory from `/proc/meminfo` |
|
|
| `get_lldp_neighbors` | ✅ | Requires `lldpd` package installed on device |
|
|
| `get_lldp_neighbors_detail` | ✅ | Requires `lldpd` package installed on device |
|
|
| `get_listening_sockets` | ✅ | busybox `netstat -lntup`, procd service from the process's cgroup (napalm-device-types `ListeningSocketsMixin`); over an SSH exec channel |
|
|
|
|
## Configuration management
|
|
|
|
Configuration is managed via [UCI](https://openwrt.org/docs/guide-user/base-system/uci)
|
|
(Unified Configuration Interface).
|
|
|
|
### Merge candidate
|
|
|
|
```python
|
|
device.load_merge_candidate(config="""
|
|
uci set system.@system[0].hostname='my-router'
|
|
uci set network.lan.ipaddr='10.0.0.1'
|
|
""")
|
|
|
|
print(device.compare_config())
|
|
device.commit_config()
|
|
```
|
|
|
|
### Replace candidate
|
|
|
|
```python
|
|
with open("full-config.uci") as f:
|
|
device.load_replace_candidate(config=f.read())
|
|
|
|
print(device.compare_config())
|
|
device.commit_config()
|
|
```
|
|
|
|
### Rollback
|
|
|
|
```python
|
|
# Reverts to the config state before the last commit_config call
|
|
device.rollback()
|
|
```
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# Create and activate a virtual environment
|
|
python -m venv .venv
|
|
source .venv/bin/activate
|
|
|
|
# Install with dev dependencies
|
|
pip install -e ".[dev]"
|
|
|
|
# Run tests
|
|
pytest
|
|
|
|
# Lint
|
|
ruff check napalm_openwrt/
|
|
```
|