fix: preserve guest network identities and refresh session profiles

This commit is contained in:
Codex
2026-10-13 05:15:06 +03:00
parent ccc521b9e1
commit 2f48de0aa2
10 changed files with 493 additions and 26 deletions
+44
View File
@@ -12,6 +12,8 @@ python3 -m unittest discover -s tests -v
nix-build dev/tools.nix -A viewer --no-out-link
nix-build dev/tools.nix -A qemu --no-out-link
nix-shell dev/tools.nix --run 'python3 dev/smoke.py'
nix-shell dev/tools.nix --run 'python3 dev/session-refresh-smoke.py --keyboard "$(dev/build-input-probe.sh)"'
nix-shell dev/tools.nix --run 'python3 dev/check-network.py'
```
The smoke test builds a private input helper with an ordinary evdev/pc105 US
@@ -53,6 +55,48 @@ suppress viewer errors or compiler/test diagnostics. The viewer build's upstream
Meson boolean-check and compiler-warning-option guidance are build noise; the four-test
result, compiler errors and process exit status remain the build acceptance gate.
## Fresh-session recovery and profile changes
A session with no profiles opens recovery with first-use guidance. Enter `:shell`
to run `hydra add NAME --iso PATH` and `hydra start NAME`; leave the shell and enter
`:refresh`. After adding or removing profiles, refresh reloads the profile list,
rebuilds workspace rules, restarts only the session's own compositor, and attaches
new isolated viewers to running guests. QEMU processes and workloads survive.
The recovery prompt can then reconnect the new names; reserved Left/Right chords
switch between their workspaces. `:quit` closes the recovery prompt.
`dev/session-refresh-smoke.py` exercises the actual product launch loop, recovery
helper, `:shell` and `:refresh`, starting with an empty profile directory. A
test-only labwc wrapper selects private headless backends; a terminal command
feeder drives recovery and a scratch shell adds and starts two counter guests.
Actual labwc and native Wayland viewers then demonstrate fresh keyboard focus
transitions in both directions, hidden workload continuity, unchanged QEMU
PIDs/UUIDs through refresh, and guest survival after normal compositor exit.
This checks the recovery command flow, not physical terminal rendering/usability.
It leaves snapshots, recovery output, protocol logs and `result.json` in
`/tmp/hydra-session-refresh-*` and stops only its verified scratch QEMU processes.
## Bridge identities
New profiles persist a locally administered unicast `mac` in their TOML file.
It remains stable across stop/start, media changes and runtime socket-directory
changes. The generated address incorporates the VM disk path and user identity,
so separate profiles/users avoid QEMU's identical default MAC on a shared bridge.
Existing profiles without `mac` use the same deterministic calculation without
rewriting their file. Relocating a legacy disk or changing its owner changes
that fallback; explicitly persisting its current address retains the identity.
Explicit TOML addresses must also be locally administered unicast, and users
copying profiles must assign distinct addresses to concurrently used copies.
`dev/check-network.py` requires unprivileged user/network/mount namespaces. It
asserts all three namespace identities changed before creating a private
`hydrabr0` and mounting a private QEMU bridge-helper ACL over `/etc` within that
namespace. Two actual scratch QEMUs must report different configured NIC MACs,
both bridge TAP ports must exist, and restart must preserve the first guest's
address. Evidence remains under `/tmp/hydra-network-*`; host bridges, host `/etc`
and existing guests are unchanged. This does not prove guest network drivers,
DHCP leases or external connectivity; those need the installed-guest harness.
## Installed guest workflow
`--iso` is optional. Attach or detach media only while the VM is stopped: