FiWiControl/docs/install.md

214 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Installing FiWiControl
**Repository:** **FiWiControl** (checkout directory, mixed case).
**Python package / `pip` name:** `**fiwicontrol`** (lowercase). See the **Naming** paragraph at the top of `**README.md`** if that split is confusing.
**Design:** `**docs/architecture.md**` (system architecture, package map, alignment with **`html/Fi-Wi-L4S.html`**). **Faults / FDIR:** `**docs/fdir.md**` (detection, isolation, recovery, exit codes).
**Requirements:** Python **3.11+**. For SSH automation to rigs, **passwordless** `**root@<host>`** — see `**docs/node-control-asyncio-design.md**`.
`**fiwicontrol` import layout:** besides `**commands`**, `**lab**`, and `**power**` (this guides focus), the distribution includes `**fronthaul**`, `**telemetry**`, `**radio**`, `**concentrator**` (local workstation CPU / PCIe / DMI snapshot; not fabric JSON — see `**docs/system-test-scripts.md**`), `**fabric**` (fabric JSON + optional `**[fabric]**` / `**[fabric.rrh.*]**` lab INI merge, then `**Fabric**` for harnesses), `**flows**`, and `**spc**` — see the numbered package list and `**src/fiwicontrol/**` tree in `**README.md**`. Long-running hardware harness scripts belong under `**scripts/system/**` (not `**pytest**`); fabric binding for the bench is `**python3 -m fiwicontrol.fabric bind**` (needs `**pip install -e ".[power]"**` on the host that sees Acroname USB). See `**docs/fabric-builder.md**`, `**docs/system-test-scripts.md**`, `**docs/power-control-and-inventory.md**` (`[fabric]`), and `**docs/pcie-hotswap-setup.md**` (PCIe hot-swap harness).
---
## Environment variables (quick reference)
| Variable | Purpose |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `**FIWI_LAB_INI**` | Default lab INI path when tools are run without `**-c**`. |
| `**FIWI_SSH_CONFIG**` | Path passed to `**ssh -F**` (Fedora `**ssh_config.d**` quirks; see `**tests/conftest.py**`). |
| `**FIWI_RUN_REMOTE_TESTS**` | Set to `**1**` / `**true**` / `**yes**` to run SSH integration tests in `**tests/test_node_control.py**` and `**tests/test_remote_power_dependencies.py**` under pytest. |
| `**FIWI_REMOTE_IP**` | Rig IP for those tests and some scripts (default `**192.168.1.39**` where a default exists). |
| `**FIWI_REMOTE_PYTHON**` | Remote interpreter for SSH discovery / tests when `**python3**` on the rig is not the one with `**fiwicontrol**`. |
| `**FIWI_REMOTE_PIP_FLAGS**` | Extra args for remote `**pip**` (e.g. `**--break-system-packages**` on Pi OS). |
| `**FIWI_REMOTE_REPO**` | Remote checkout path for `**python3 -m fiwicontrol.commands …**` (default `**/root/Code/FiWiControl**`). |
| `**FIWI_VERIFY_POWER_INI**` | Set to `**1**` to run live INI verification in `**tests/test_inventory_verify_live.py**`. |
| `**FIWI_TEST_INI**` | Optional path for `**tests/test_fabric_instantiation.py**` (default `**configs/default.ini**` in repo). |
Running `**python3 tests/test_node_control.py …**` or `**python3 tests/test_remote_power_dependencies.py**` directly (not via pytest) sets `**FIWI_RUN_REMOTE_TESTS=1**` if it is unset, so a deliberate script run still exercises SSH without extra env.
---
## Security and trust boundaries
FiWiControl is **operator-driven lab and deployment tooling**, not a hardened multi-tenant service. Keep these boundaries explicit:
| Topic | What to assume |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Process identity** | Commands run as **your** workstation user. They read and write paths you pass (`**-c`**, `**--fabric-json**`, `**--patch-panel-json**`, INI/JSON under `**configs/**`). |
| **SSH** | `**ssh_node`** runs `**ssh**` with a fixed argument vector (no shell). Targets come from INI `**ipaddr**`, `**FIWI_REMOTE_IP**`, or flags. You are trusting **SSH host keys** and `**~/.ssh`** the same way as normal OpenSSH use. |
| **Remote code** | Integration tests and remote discovery execute **fixed** remote command lines (e.g. `**python3 -m fiwicontrol.power --discovery-json`**). Do not point automation at hosts you do not control unless that is intentional. |
| **JSON / INI** | Lab files are **data**. Very large patch-panel map files are **ignored** (size and entry limits in `**fiwicontrol.fabric.patch_panel_json`**) so a bad file cannot exhaust memory as easily. Do not store secrets in these files. |
| **CI / pytest** | Remote tests require `**FIWI_RUN_REMOTE_TESTS=1`** so CI does not open outbound SSH by default. |
| **Life support / safety-critical** | FiWiControl is **not** intended, validated, or cleared for **life support**, **patient-connected**, or other **safety-critical** applications. Using it in those contexts would require a **separate** regulated development lifecycle, hazard analysis, verification, and organizational controls—none of which this open-source project provides. |
---
## Bring up systems (new workstation + lab rig)
Use this order the first time you (or someone else) joins the project or replaces a machine. Replace `**192.168.1.39`** with your rigs IP when needed.
| Step | Where | What to do |
| ---- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1 | Workstation | **Clone** this repo and `**cd`** into it. |
| 2 | Workstation | **Python 3.11+** and an **editable install**: `**python3 -m pip install -e ".[dev]"`**, then `**python3 -m pip install -e ".[power]"**` if you use Acroname/Monsoon or remote power tests. Add `**".[flows]"**` / `**".[spc]"**` when you use `**fiwicontrol.flows**` or `**fiwicontrol.spc**` (see **Workstation** below and `**docs/flows.md`** / `**docs/spc.md**`). |
| 3 | Workstation → rig | **Passwordless SSH as root:** `**ssh -o BatchMode=yes root@192.168.1.39 true`** must exit **0** with no password prompt. On the rig, install your workstations **public key** in `**/root/.ssh/authorized_keys`** and ensure `**sshd**` allows `**root**` with pubkey auth. |
| 4 | Rig (e.g. Pi) | `**git clone**` the same repo where you will run power/discovery (often `**/root/Code/FiWiControl**`). Your `**--remote-repo**` path must match. |
| 5 | Workstation | From your clone, run `**python3 -m fiwicontrol.commands**` with the Pi IP and `**--remote-repo**` (PEP 668 / Raspberry Pi OS needs `**--break-system-packages**` or `**FIWI_REMOTE_PIP_FLAGS**`). See **Remote host setup** below (numbered subsections **3** and **4**: install `**fiwicontrol[power]`** on the rig, then align `**python3**` with `**pip**`). |
| 6 | Workstation | **Verify** (minimal): `**python3 -m pytest -q tests/test_package_layout.py`** (imports `**fiwicontrol.commands**`, `**lab**`, `**power**`, `**flows**`, `**spc**`, `**fronthaul**`, `**telemetry**`, `**radio**`, `**concentrator**`, `**fabric**`). Full tree: `**python3 -m pytest tests/ -q**` (expect **skipped** tests: live INI unless `**FIWI_VERIFY_POWER_INI=1`**, SSH integration unless `**FIWI_RUN_REMOTE_TESTS=1**`). With a reachable rig: `**FIWI_RUN_REMOTE_TESTS=1 FIWI_REMOTE_IP=… python3 -m pytest -q tests/test_node_control.py tests/test_remote_power_dependencies.py**` (default `**FIWI_REMOTE_IP**` is `**192.168.1.39**` if unset). For INI / `**--verify-inventory**`, see `**docs/power-control-and-inventory.md**`**“Verification checklist (after install)”**. |
**SSH user:** `**ssh_node`** ( `**sshtype="ssh"**` ) always uses an explicit `**root@<ipaddr>**` (or whatever `**ssh_session**` `**user**` is set to). It does **not** open `**ssh 192.168.1.39`** with your local login name, so your manual tests should use `**root@…**` as well.
**After a `git pull` on the rig:** if the Pi uses an **editable** `**pip install -e`**, pull there before expecting new Python code on the node.
---
## Workstation (e.g. Fedora): recommended install
From your clone of this repo, use an **editable install** so `**python3 -m fiwicontrol…`**, `**pytest**`, and `**import fiwicontrol.***` work from any working directory (use a **venv** if you prefer not to touch system Python):
```bash
cd ~/Code/FiWiControl
python3 -m pip install -U pip setuptools wheel
python3 -m pip install -e ".[dev]"
```
Add **power / USB** dependencies when you work with Acroname or Monsoon discovery locally:
```bash
python3 -m pip install -e ".[power]"
```
Or in one line:
```bash
python3 -m pip install -e ".[dev,power]"
```
**Flows** (async **iperf** over SSH, SciPy / Matplotlib stack) and **SPC** (**Shewhart** / **Hotelling** *T*² helpers) are separate optional extras:
```bash
python3 -m pip install -e ".[flows]" # NumPy, SciPy, Matplotlib — see docs/flows.md
python3 -m pip install -e ".[spc]" # NumPy, SciPy — see docs/spc.md
```
Or combined with dev and power:
```bash
python3 -m pip install -e ".[dev,power,flows,spc]"
```
**Why this is the default:** you avoid remembering `**PYTHONPATH=src`**, IDEs and `**python -m**` behave predictably, and it matches how `**pyproject.toml**` / `**pytest**` are meant to be used.
### Without a local install (one-off)
If you have **not** run `**pip install -e .`**, you can still run modules from the repo root:
```bash
cd ~/Code/FiWiControl
PYTHONPATH=src python3 -m pytest tests/test_package_layout.py -q
PYTHONPATH=src python3 -m fiwicontrol.power --discovery-json
```
This is easy to **forget** after you `**cd`** elsewhere, so prefer an editable install for day-to-day work.
**Summary (workstation):** use **editable install** on your main dev box; use `**PYTHONPATH=src`** when you deliberately skip a local install.
---
## Remote host setup
End-to-end steps for a **lab rig** (e.g. Raspberry Pi 5) that `**ssh_node`** and `**fiwicontrol.power**` talk to over `**ssh root@<ip>**`. Same SSH user and rules as in `**docs/node-control-asyncio-design.md**` (passwordless `**BatchMode=yes**`).
### 1. SSH from your workstation
```bash
ssh -o BatchMode=yes -i ~/.ssh/id_ed25519 root@192.168.1.39 true
```
(no output, exit **0**). If this fails, fix keys and `**/root/.ssh/authorized_keys`** on the rig first.
On some Linux workstations, OpenSSH aborts before connecting with `**Bad owner or permissions on …/ssh_config.d/…**` (for example Fedoras `**20-systemd-ssh-proxy.conf**`). FiWiControls pytest session sets `**FIWI_SSH_CONFIG**` to a minimal client file under `**tests/fixtures/**` so `**ssh -F**` skips the system `**/etc/ssh/ssh_config**`. For ad hoc runs (inventory, scripts), export `**FIWI_SSH_CONFIG**` to that same file, or to your own minimal `**ssh_config**` that does not `**Include**` the broken drop-in.
### 2. Repo on the remote
The Pi needs a **git checkout** of FiWiControl (same tree you pushed). Example for `**root`**:
```bash
# on the Pi (as root)
mkdir -p /root/Code
cd /root/Code
git clone <YOUR_FIWICONTROL_REPO_URL> FiWiControl
```
Use your teams real clone URL. `**--remote-repo**` below must be that directory (e.g. `**/root/Code/FiWiControl**`).
### 3. Install `**fiwicontrol[power]**` on the remote from Fedora
Your **Fedora** machine must already run `**python3 -m fiwicontrol.power`** (usually `**pip install -e .**` from your local clone — see above).
Then:
```bash
cd ~/Code/FiWiControl
python3 -m fiwicontrol.commands 192.168.1.39 --remote-repo /root/Code/FiWiControl --break-system-packages
```
**Raspberry Pi OS / Debian (PEP 668):** system Python blocks `**pip install`** without `**--break-system-packages**`. Prefer the `**--break-system-packages**` flag above.
**Do not** pass a *separate* token after `**--pip-flags`** if it starts with `**--**` (argparse will treat it as another option). Use either:
- `**--break-system-packages**`, or
- `**--pip-flags=--break-system-packages**` (equals form), or
- `**export FIWI_REMOTE_PIP_FLAGS='--break-system-packages'**` and omit `**--pip-flags**`.
**Wrapper:** `**scripts/setup_pi_power.sh`** sets `**PYTHONPATH=src**` on Fedora if needed, then runs `**python3 -m fiwicontrol.commands**` (`**--setup-remote**`-style args) using `**FIWI_REMOTE_IP**` and `**FIWI_REMOTE_REPO**`:
```bash
cd ~/Code/FiWiControl
chmod +x scripts/setup_pi_power.sh # once
export FIWI_REMOTE_IP=192.168.1.39
export FIWI_REMOTE_REPO=/root/Code/FiWiControl
export FIWI_REMOTE_PIP_FLAGS='--break-system-packages'
./scripts/setup_pi_power.sh
```
(You can extend the script or pass `**--**` args if you add `**--break-system-packages**` to the script later.)
### 4. Python on the remote (one interpreter for pip and for SSH)
If `**pip show fiwicontrol**` reports `**Location: …/python3.11/…**` but plain `**python3**` on the rig is a different version, imports over SSH will fail even though the package is installed. Install and run with the **same** binary, or on Fedora set:
```bash
export FIWI_REMOTE_PYTHON=python3.11 # or full path, e.g. /usr/bin/python3.11
```
That variable is read by `**discover_devices_remote_async**`, `**tests/test_remote_power_dependencies.py**`, and `**python3 -m fiwicontrol.commands … --remote-python …**` (remote setup).
### 5. Verify after install
Quick remote sanity (imports + `**python3 -m fiwicontrol.power --discovery-json**` over SSH; needs `**FIWI_REMOTE_IP**` if not `**192.168.1.39**`; opt-in `**FIWI_RUN_REMOTE_TESTS=1**`):
```bash
FIWI_RUN_REMOTE_TESTS=1 python3 -m pytest -q tests/test_remote_power_dependencies.py
```
**Full checklist for a new machine** (local discovery, `**ssh root@…`**, remote `**fiwicontrol**`, INI editing, `**--list-power-devices**`, `**--verify-inventory**`, optional pytest): `**docs/power-control-and-inventory.md**`**“Verification checklist (after install)”**.
**INI layout** (`**[site]`**, `**[machine.*]**`, `**[fabric]**` / `**[fabric.rrh.*]**`, `**acroname**` / `**monsoon**`): `**docs/power-control-and-inventory.md**`.
---
## Quick import check
```bash
python3 -c "import fiwicontrol.commands, fiwicontrol.power; print('ok')"
```
With only `**[dev]**` installed, `**fiwicontrol.power**` still imports; hardware discovery needs `**[power]**` ( `**brainstem**`, `**pyserial**` ).