# 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`](https://git.netork.io/christianmanivong/napalm-linux) — packages, services, users, processes, Docker — and adds QNAP's storage, QPKG and virtualisation layers on top. Tested against 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](#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 ```bash pip install -e vendor/napalm-device-types/ -e vendor/napalm-linux/ -e vendor/napalm-qnap-qts/ ``` ## Usage ```python 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 ```python 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//.qpkg/container-station/`. The Docker *logic* stays in `LinuxDriver` and only the path is overridden here, via the `_docker_bin()` hook. ## Harvesting fixtures ```bash ./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 ```bash pip install -e ".[dev]" python -m pytest -q ruff check . ``` ## License Apache-2.0