This commit is contained in:
Jonas Bengtsson
2026-10-07 07:40:56 +02:00
parent c8b655111e
commit 9f3272094e
17 changed files with 2243 additions and 89 deletions
+65 -22
View File
@@ -44,14 +44,15 @@ a virtual node whose I/O behavior is driven by scripted scenarios.
config, 255 = DHCP), WBM-equivalent pages (Port/Ethernet, Modbus
settings, Modbus Mapping, I/O Config), and device-state persistence
with factory reset.
- **Host network settings** *(requested, planned — spec §15)*: a
- **Host network settings** *(implemented 2026-10-06 — spec §15)*: a
Docker-gated, opt-in settings page (`WAGO_SIM_HOSTNET=1` **and**
container detection) that lists the host OS's network interfaces
and adds/removes/changes their IPv4 addresses through a
whitelisted host-side agent — so simulated node re-addressing
(DIP dedicated-IP mode) and network-loss fault cases become real
on the bench network. Runtime-only changes, snapshot/undo, and an
audit log; fully absent (404) when the flag is off.
on the bench network. Runtime-only changes, auto-snapshot with
restore, and an operator-tagged audit log; fully absent (404, tab
hidden) when the flag is off.
- **Long-duration (continuous) simulation** *(requested, planned — see
`docs/spec/software-spec.md` §8)*: endurance/soak testing over days or
weeks of simulated time. Designated inputs are driven from streaming
@@ -193,6 +194,42 @@ Configuration options: `--no-web`, `--web-port <n>` or env
benches (all mutating endpoints answer 403). Plain HTTP — keep the
port inside the bench network.
### Host network settings (spec §15, Docker only)
An additional **Host network** tab can list and manipulate the
**host OS's** IPv4 addresses from the browser — for FAT cases that
need network-level re-addressing or address-loss faults on the bench
network. It exists only when both gates pass:
1. `WAGO_SIM_HOSTNET=1` on the simulator container (opt-in flag), and
2. running inside Docker (compose sets `WAGO_SIM_IN_DOCKER=1`).
The container itself stays non-root and unprivileged: changes go
through a whitelisted **agent on the host**:
```bash
# once, on the Linux host:
sudo cp deploy/wago-sim-hostnet-agent.service /etc/systemd/system/
sudo cp deploy/hostnet-agent.yaml /etc/wago-sim/hostnet.yaml
# edit the whitelist to your bench NIC(s), then:
sudo systemctl enable --now wago-sim-hostnet-agent
# journalctl -u wago-sim-hostnet-agent -f (audit trail lands here)
# compose: uncomment in docker-compose.yml —
# WAGO_SIM_HOSTNET: "1"
# - /run/wago-sim:/run/wago-sim
# and align the container user's group with the socket (0660).
docker compose up -d
```
Safety rails: only whitelisted interfaces are mutable (refusals are
shown and audited); every change is preceded by an auto-snapshot with
a **Restore last change** button; changes are runtime-only — a host
reboot restores the deployed addressing; every mutation and refusal is
logged with the logged-in operator's name. If the agent is down the
tab shows a "host control unavailable" banner and mutations answer
503 — the simulator itself is unaffected.
## Plant environments (continuous simulation)
A **plant environment** simulates the physical world around the
@@ -351,33 +388,39 @@ requirement ID for each item in parentheses.
protocol tracing, diagnostics and fault injection (FR-14.2.5–
14.2.6); scoping questions to answer before planning (§14.3).
### Requested — host network settings (spec §15, not yet scheduled)
### Host network settings (spec §15) — IMPLEMENTED 2026-10-06
- [ ] Host OS IP settings page (FR-15.2.1–15.2.3): exposed in the web
The §15 feature is implemented (v1 core operations): the
Docker-gated settings page with add/remove/change/restore, the
host-side agent, the safety rails, and the audit trail. 58 dedicated
tests (`tests/test_hostnet.py`); full suite 339 passing.
- [x] Host OS IP settings page (FR-15.2.1–15.2.3): exposed in the web
UI only when `WAGO_SIM_HOSTNET=1` **and** running inside Docker
(compose sets `WAGO_SIM_IN_DOCKER=1`; `/.dockerenv` as a
supplementary signal); authenticated page listing the host's
interfaces with link state and current IPv4 addresses, read
from live host state, with add/remove/change-address operations
validated client- and agent-side; routes answer 404 when
disabled — no dormant surface.
- [ ] Host-side agent + safety rails (FR-15.2.4–15.2.8): a
whitelisted companion service on the host (Unix socket mounted
into the container; `pyroute2`/`ip` on Linux v1, systemd unit in
`deploy/`) — interface whitelist, runtime-only (non-persistent)
address changes so a host reboot restores deployed addressing,
snapshot before every mutation with undo/restore, single-line
audit log; degraded state (agent unreachable) shows a banner
and answers 503 without affecting the rest of the UI; readonly
mode hides the page and 403s mutations.
validated client- and agent-side; routes answer 404 and the tab
stays hidden when disabled — no dormant surface.
- [x] Host-side agent + safety rails (FR-15.2.4–15.2.8):
`wago-sim hostnet-agent --config deploy/hostnet-agent.yaml`
runs on the host (systemd unit
`deploy/wago-sim-hostnet-agent.service`, root or `CAP_NET_ADMIN`,
hardened) — Unix socket mounted into the container
(`/run/wago-sim`), interface whitelist, runtime-only
(non-persistent) address changes so a host reboot restores
deployed addressing, auto-snapshot before every mutation with
restore, single-line audit log (operator-tagged, refusals
included; journald + optional file); degraded state (agent
unreachable) shows a banner and answers 503 without affecting
the rest of the UI; readonly mode keeps status readable and
403s every mutation.
- [ ] DIP dedicated-IP integration (FR-15.2.9): applying a DIP-switch
address change in dedicated-IP mode routes through the agent so
the derived IP lands on the host NIC — the PLC on the bench
network must genuinely re-connect to the new node address, like
a physical coupler after a DIP change (ties into §11
FR-11.3.3); scoping questions (platform scope, bridge vs host
networking, agent auth, IPv6, link up/down) in §15.4 before
planning.
the derived IP lands on the host NIC — deferred until the §11
DIP-switch model ships; link up/down (cable pull) also deferred
(v2, FR-15.2.4).
### Web UI (spec §10) — in implementation