214 lines
20 KiB
Markdown
214 lines
20 KiB
Markdown
# 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 guide’s 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 rig’s 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 workstation’s **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 Fedora’s `**20-systemd-ssh-proxy.conf**`). FiWiControl’s 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 team’s 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**` ). |