napalm-qnap-qts

NAPALM driver for QNAP NAS systems running QTS, over SSH.

QTS is a Linux distribution, so this driver inherits the whole OS surface from napalm-linux — packages, services, users, processes, Docker — and adds QNAP's storage, QPKG and virtualisation layers on top.

Targets QTS 4.x and QTS 5.x.

Status

The class scaffold, discovery fingerprints and version/tool detection are in place. The storage, QPKG and VM parsers are not written yet: they are blocked on capturing real command output from hardware (see Harvesting fixtures). Writing parsers against guessed output is how a driver ends up passing its own tests and failing on a real NAS.

Method Source Status
get_facts getcfg, getsysinfo, /proc/uptime pending harvest
get_interfaces, get_interfaces_ip ip / ifconfig pending harvest
get_disks qcli_storage -d, get_hd_smartinfo pending harvest
get_disk_pools qcli_storage -p, /proc/mdstat pending harvest
get_volumes qcli_storage -v, df pending harvest
get_shares /etc/config/smb.conf, /etc/exports pending harvest
get_storage_services getcfg, ss -lntup pending harvest
get_disk_smart get_hd_smartinfo pending harvest
get_packages QPKG (qpkg.conf / qpkg_cli) pending harvest
get_vms virsh (Virtualization Station) pending harvest
start_vm, stop_vm, reboot_vm virsh pending harvest
set_service_enabled setcfg, /etc/init.d pending harvest
get_device_warnings derived from the above pending harvest
get_docker_info inherited, via _docker_bin() ✅
get_services, get_users, get_processes inherited from LinuxDriver ✅
get_health_metrics inherited (UCD-MIB over SNMP) ✅
ping, ping_sweep inherited from LinuxDriver ✅
Snapshots, quotas, replication, QPKG install/remove — out of scope for v1

Requirements

SSH must be enabled on the NAS: Control Panel → Telnet/SSH → Allow SSH connection. The driver connects on port 22 by default; the QTS web UI on 443/8080 is not used.

Install

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

Usage

from napalm_qnap_qts import QnapQtsDriver

driver = QnapQtsDriver("nas.example.lan", "admin", "secret")
driver.open()
print(driver.get_facts())
driver.close()

Recognised optional_args: everything napalm-linux accepts (port, sudo_password, secret, …). Unknown keys are ignored.

Design notes

Inheritance order

class QnapQtsDriver(StorageDriver, LinuxDriver):

StorageDriver precedes LinuxDriver in the MRO, so its NotImplementedError stubs shadow LinuxDriver's working implementations wherever the names collide — get_services, get_packages, install_package. Each collision is resolved with an explicit forwarding method; TestMroForwarding guards that they stay resolved.

NAS services are exposed as get_storage_services(), not get_services(): netOrk's poller reads the former for the storage snapshot and the latter for the OS service list. Same convention as napalm-openmediavault.

Device class

The driver sets DEVICE_CLASS = "storage" explicitly. Without it netOrk's issubclass chain reaches OSDriver before StorageDriver and would file a QNAP under "linux", hiding its Storage tab. VMs and containers stay visible through capability introspection (supports_vms), not through this key — a QNAP running Virtualization Station is a NAS and a hypervisor, and device_class only holds one of those.

Docker

Container Station does not put docker on PATH; it lives under /share/<pool>/.qpkg/container-station/. The Docker logic stays in LinuxDriver and only the path is overridden here, via the _docker_bin() hook.

Harvesting fixtures

./tools/harvest.sh admin@nas4.example.lan qts4
./tools/harvest.sh admin@nas5.example.lan qts5
./tools/sanitize.py tools/harvest-out/qts5 --extra-host mynas

harvest.sh runs the command set this driver parses over a single SSH session and writes one file per command. sanitize.py replaces serial numbers, MACs, IP addresses and hostnames with stable placeholders — cross-references between files survive, so the fixtures still describe one coherent device.

Read the sanitised output before committing it. The sanitiser catches patterns, not judgement, and fixtures live in git forever. Raw harvest output is gitignored and must never be committed.

Where QTS 4 and QTS 5 differ, keep both fixtures and parametrise the test over the pair, so the version divergence is part of the test matrix rather than a later surprise.

Development

pip install -e ".[dev]"
python -m pytest -q
ruff check .

License

Apache-2.0

S
Description
NAPALM driver for QNAP NAS systems running QTS (4.x / 5.x) over SSH
Readme
58 KiB
Languages
Python 80.7%
Shell 19.3%