CI / test (3.10) (push) Successful in 26s
CI / test (3.11) (push) Successful in 25s
CI / test (3.12) (push) Successful in 26s
CI / test (3.10) (pull_request) Successful in 25s
CI / test (3.11) (pull_request) Successful in 24s
CI / test (3.12) (pull_request) Successful in 26s
netOrk reads an empty update list as "no updates" and closes every patch clock on the host. A refused sudo, a failing pkg, syspatch or freebsd-update, or a pkg database pkg cannot read used to come back as that empty list. Each of these now raises. Only pkg's "is not installed" still means no packages. BsdDriver takes on napalm-device-types' HostStatusMixin. On FreeBSD it reports a host whose installed kernel differs from the running one as needing a reboot (device-types 4.1). OpenBSD stays unknown. Closes #4
94 lines
5.2 KiB
Markdown
94 lines
5.2 KiB
Markdown
# napalm-bsd
|
|
|
|
NAPALM drivers for **FreeBSD** (`freebsd`) and **OpenBSD** (`openbsd`) hosts,
|
|
over SSH, built on [napalm-device-types](https://git.netork.io/NAPALM/napalm-device-types)'
|
|
`OSDriver`. Written for netOrk, which provisions and manages BSD VMs
|
|
(NetOrk/netork#792).
|
|
|
|
## Design
|
|
|
|
- One shared `BsdDriver` (`napalm_bsd/base.py`) holds the SSH layer and every
|
|
reader whose tools agree between the BSDs. `FreeBSDDriver` and
|
|
`OpenBSDDriver` name only the commands that differ (hostname, release,
|
|
kernel, hardware, `netstat -rnW` vs `-rn`).
|
|
- Every command runs on its own SSH **exec channel** (`run_on_transport` from
|
|
napalm-device-types): no PTY to parse a prompt from, stdout and stderr apart,
|
|
a real exit status. `run_command()` / `open_stream()` are public
|
|
(`CommandChannelMixin`).
|
|
- Root comes from `sudo -S` with the sudo password on stdin (never on a command
|
|
line), or `sudo -n` without one, as in napalm-linux. netOrk provisions `sudo`
|
|
on BSD VMs for that reason; `doas` cannot read a password from stdin.
|
|
- Parsing is in `napalm_bsd/parse.py`, pure functions tested on output recorded
|
|
from real systems (`tests/fixtures/`, each directory's `COMMANDS.txt` lists
|
|
what produced it).
|
|
|
|
## Supported getters
|
|
|
|
| Getter | FreeBSD | OpenBSD | Source |
|
|
|---|---|---|---|
|
|
| `get_facts` | ✓ | ✓ | `kern.hostname`/`hostname`, `freebsd-version`/`uname`, `kenv smbios.*`/`hw.*`, `kern.boottime` |
|
|
| `get_interfaces`, `get_interfaces_ip` | ✓ | ✓ | `ifconfig -a` |
|
|
| `get_route_to` | ✓ | ✓ | `netstat -rnW` / `netstat -rn` |
|
|
| `get_arp_table` | ✓ | ✓ | `arp -an` |
|
|
| `get_lldp_neighbors` | `{}` | `{}` | no LLDP daemon in either base system |
|
|
| `get_users`, `get_processes`, `get_cron_jobs` | ✓ | ✓ | `/etc/passwd`+`/etc/group`, `ps … lstart`, system crontab + `crontab -l` |
|
|
| `get_listening_sockets` | ✓ | ✓ | `sockstat -46lq` / `fstat -n` as root, `netstat -an` without |
|
|
| `get_packages`, `install_package`, `uninstall_package` | ✓ | ✓ | `pkg query` / `pkg install`, `pkg delete`; `pkg_info` / `pkg_add -I`, `pkg_delete` |
|
|
| `get_available_updates` | ✓ | ✓ | `pkg upgrade -n` + `pkg audit` (VuXML); `pkg_add -u -n -v` + `syspatch -c` |
|
|
| `get_services`, `manage_service` | ✓ | ✓ | `service -e` + `service … status` / `service … <action>`; `rcctl ls on` + `rcctl check` / `rcctl <action>` |
|
|
| `run_device_action("fix_snmp")`, `get_snmp_config` | ✓ | ✓ | net-snmp from packages: `/usr/local/etc/snmp/snmpd.conf` + `service snmpd`; `/etc/snmp/snmpd.conf` + `rcctl … netsnmpd` |
|
|
| `get_host_status` | ✓ | unknown | napalm-device-types' host status: on FreeBSD `freebsd-version -k` vs `-r` (4.1+) |
|
|
|
|
`get_listening_sockets` has the shape of napalm-device-types'
|
|
`ListeningSocketsMixin` (whose `ss`/cgroup reading is Linux's) and its rule:
|
|
read as root first, without root when that brings nothing back
|
|
(`attributed: False`). FreeBSD's `sockstat` sees every socket either way;
|
|
OpenBSD's `fstat` shows a user only their own processes, so without root the
|
|
sockets come from `netstat -an`, unnamed.
|
|
|
|
There is deliberately no `get_kernel_facts`: `KernelFactsMixin` reports a
|
|
Linux kernel's modules and `CONFIG_*` options, which a BSD kernel does not
|
|
have, and `hasattr(driver, "get_kernel_facts")` has to stay truthful.
|
|
|
|
**Updates.** `security` on FreeBSD comes from VuXML (`pkg audit`): True for a
|
|
package it lists as vulnerable, False for one it does not, None when the audit
|
|
could not run. OpenBSD's tools do not say, so it is None there. Base-system
|
|
patches are one entry, `base-system` (NetOrk/netork#799): OpenBSD's
|
|
`syspatch` applies its patches together and in order; a classic FreeBSD base
|
|
reports what `freebsd-update` has fetched (`updatesready`). On FreeBSD with
|
|
pkgbase the base system is packages from the `FreeBSD-base` repository and
|
|
needs no extra entry.
|
|
|
|
A reader that cannot read **raises** rather than return an empty list: netOrk
|
|
takes `[]` as "no updates" and would close every patch clock on the host. That
|
|
covers a refused sudo, a failing `pkg`, `syspatch` or `freebsd-update`, and a pkg
|
|
database pkg cannot read (only pkg's "not installed" means no packages).
|
|
|
|
**Reboot.** `get_host_status` reports a FreeBSD host whose installed kernel
|
|
(`freebsd-version -k`) differs from the running one (`-r`) as needing a reboot.
|
|
OpenBSD has no such reading yet, so it stays unknown there.
|
|
|
|
**Services** are the enabled ones. FreeBSD reads their status as root, as
|
|
root-only pidfiles hide a daemon from anyone else, and without root when sudo
|
|
refuses; OpenBSD's `rcctl check` needs no root. Actions run as root.
|
|
|
|
**SNMP** is net-snmp from packages (NetOrk/netork#800), configured as netOrk does
|
|
on Linux (v2c, community `public`, every address), so the agent answers
|
|
UCD-SNMP-MIB for netOrk's health metrics. Memory, swap and load are right on
|
|
both systems. CPU: FreeBSD reports `ssCpuIdle` about a minute after the
|
|
agent starts; on OpenBSD net-snmp's CPU figures are wrong (0 % idle on an idle
|
|
machine, also in `hrProcessorLoad`).
|
|
|
|
## Connection arguments
|
|
|
|
`optional_args`: `port` (22), `key_file`, `sudo_password`, `allow_agent`,
|
|
`look_for_keys` (both off by default).
|
|
|
|
## Development
|
|
|
|
```bash
|
|
pip install "napalm-device-types @ git+https://git.netork.io/NAPALM/napalm-device-types.git"
|
|
pip install -e ".[dev]"
|
|
pytest
|
|
```
|