Christian Manivong ce40299033 fix(tests): repair the fixture and doubles that made seven tests fail
Closes netork#110.

The seven failures had two causes, neither of them in the driver.

The `driver` fixture builds a LinuxDriver with `__new__`, bypassing `__init__`,
and never set `_sudo_password`. Every call through `_sudo()` therefore raised
AttributeError, which the callers' broad `except Exception` reported as
`{"success": False}` — so six apply_updates tests failed for a reason unrelated
to what they were asserting.

`test_apply_updates_apt_all_packages` had a second one: its `capture_send(cmd)`
double accepted no keyword arguments, while `_sudo()` passes `read_timeout`.

The seventh, the apt update listing test, supplied `side_effect=["",
APT_UPGRADABLE]` — two values for a cache refresh that never existed.
`_get_updates_apt` has made exactly one `_send` call since it was written in
2712389, so the empty first value was consumed and parsed as the package list.
Checked out that commit and ran it: the test failed there too. It was committed
red and never passed.

That settles the open question in netork#110: the implementation was not changed,
the tests were written against one that never existed. `get_available_updates`
reads the local apt cache deliberately — refreshing it needs sudo and would cost
a round trip on every poll — so there is no stale-cache bug behind the
`updates_available` warning.
2026-08-21 12:57:11 +07:00

napalm-linux

NAPALM driver for generic Linux systems — Debian, Ubuntu, RHEL, Rocky, Alpine, Arch and any other distribution reachable via SSH.

Connects over SSH using Netmiko (linux device type) and automatically detects the installed package manager (apt, dnf, yum, apk, pacman).

Requirements

Dependency Minimum version
Python 3.9
NAPALM 4.0
Netmiko 4.0
napalm-device-types 0.2.0

Installation

pip install napalm napalm-linux

Or from source:

git clone https://github.com/chrismanivong/napalm-linux
pip install -e napalm-linux/

When working in the NetOrk monorepo, install both packages as editable:

pip install -e vendor/napalm-device-types/ -e vendor/napalm-linux/

Quick start

from napalm import get_network_driver

Driver = get_network_driver("linux")

with Driver(
    "10.0.0.5",
    "admin",
    "s3cr3t",
    optional_args={
        # "port": 22,
        # "pkg_manager": "apt",   # force package manager; auto-detected by default
        # "secret": "sudo-pass",  # password for sudo / enable (defaults to login password)
        # "debugging": True,      # enable verbose logging
    },
) as dev:
    facts = dev.get_facts()
    print(facts)

    # OS-specific methods (from napalm-device-types OSDriver)
    packages = dev.get_packages()
    updates  = dev.get_pending_updates()
    services = dev.get_services()
    users    = dev.get_users()
    procs    = dev.get_processes()
    jobs     = dev.get_cron_jobs()

    # Upgrade specific packages
    result = dev.apply_updates(["openssh-server", "curl"])
    print(result)  # {"success": True, "output": "..."}

    # Upgrade everything with pending updates
    result = dev.apply_updates([])

Supported NAPALM methods

Standard NAPALM

Method Supported Notes
open() / close() ✅ SSH via netmiko linux
is_alive() ✅
get_facts() ✅ DMI / /proc/uptime / ip link
get_interfaces() ✅ ip link show
get_interfaces_ip() ✅ ip addr show
get_arp_table() ✅ ip neigh show
get_config() ✅ Returns ip addr + ip route output
ping() ✅ Executes ping on the remote host
load_merge_candidate() ❌ Not applicable for generic Linux
load_replace_candidate() ❌ Not applicable for generic Linux
compare_config() ❌ Not applicable for generic Linux
commit_config() ❌ Not applicable for generic Linux
discard_config() ❌ Not applicable for generic Linux
rollback() ❌ Not applicable for generic Linux

OSDriver extensions (napalm-device-types)

Method Supported Package managers
get_packages() ✅ apt, dnf, yum, apk, pacman
get_pending_updates() ✅ apt, dnf, yum, apk, pacman
apply_updates(packages) ✅ apt, dnf, yum, apk, pacman
get_services() ✅ systemd (fallback: SysV service)
get_users() ✅ /etc/passwd + /etc/group
get_processes() ✅ ps axo
get_cron_jobs() ✅ user crontabs + /etc/cron.d/

Package manager auto-detection

The driver probes for each binary in order via command -v:

apt → dnf → yum → apk → pacman

Force a specific package manager:

optional_args={"pkg_manager": "dnf"}

SSH user permissions

The SSH user needs read access to:

Data Required permission
/etc/passwd, /etc/group world-readable (default)
/proc/uptime, /sys/class/dmi/… world-readable (default)
User crontabs (/var/spool/cron/…) root or sudo required
systemctl is-enabled <unit> unprivileged on most distros
apt list --upgradable may require apt-get update (root)
dnf check-update / yum check-update unprivileged, but slower without cache

For full functionality it is recommended to run as root or grant passwordless sudo for the above commands.

Tested distributions

Distribution Version Package manager Tested
Debian 12 (Bookworm) apt ✅
Ubuntu 22.04 LTS apt ✅
Rocky Linux 9 dnf planned
Alpine Linux 3.19 apk planned
Arch Linux rolling pacman planned

Contributions for additional distributions and versions are welcome.

Development

# Create venv
python -m venv .venv
source .venv/bin/activate

# Install in editable mode with dev dependencies
pip install -e ../napalm-device-types/ -e ".[dev]"

# Run tests
pytest tests/ -v

# Lint / format
ruff check napalm_linux/
ruff format napalm_linux/

License

Apache 2.0

S
Description
No description provided
Readme
733 KiB
Languages
Python 100%