# Host Lifecycle Step Logging Design ## Goal Provide granular, live progress feedback in the web GUI during lifecycle operations (`initialize`, `start`, `stop`, `delete`) without exposing sensitive internal paths or raw subprocess mechanics unless they fail. ## Approach Currently, `l4d2ctl` executes operations silently unless a subprocess fails. `l4d2web` captures `stdout` and `stderr` from `l4d2ctl` and pushes it to the browser via Server-Sent Events. We will modify `l4d2host/instances.py` to emit safe, high-level step markers to `stdout`. Since `l4d2web` uses `subprocess.Popen(..., stdout=subprocess.PIPE)` to execute `l4d2ctl`, any standard Python `print(..., flush=True)` in `l4d2host` will be naturally captured by `job_worker.py` and forwarded to the GUI as `stdout` events. ## Logging Strategy We will introduce an explicit `_emit_step(msg: str, on_stdout: Callable | None, passthrough: bool)` helper in `l4d2host/instances.py` to correctly route step output based on the calling context: - If `on_stdout` is provided (e.g. programmatic use), call it. - If `passthrough` is true (e.g. `l4d2ctl` CLI), `print(..., flush=True)`. ### Step Messages **`initialize_instance`** - `creating instance directories...` - `writing instance.env...` - `writing server.cfg...` - `initialization complete.` **`start_instance`** - `mounting runtime overlay...` - `copying server.cfg to runtime...` - `starting systemd service...` - `start complete.` **`stop_instance`** - `stopping systemd service...` - `unmounting runtime overlay...` - `stop complete.` **`delete_instance`** - `stopping systemd service (if running)...` - `unmounting runtime overlay (if mounted)...` - `removing instance files...` - `delete complete.` ## File Changes - **`l4d2host/instances.py`** - Add `_emit_step` helper. - Insert calls to `_emit_step` at key locations in all lifecycle functions. - **`l4d2web/services/job_worker.py`** - Add synthetic web-layer boundary logs (`starting initialize for test-server`, `finished initialize successfully`) to clearly distinguish the boundaries between multiple `l4d2ctl` operations in compound jobs like `start` (which calls initialize then start). ## Safety & Secrets - `print` statements must **not** include full absolute paths (e.g. avoid printing `/var/lib/left4me/runtime/alpha/merged`). - `print` statements must **not** echo spec data or env vars that might contain future RCON passwords or sensitive args. ## Test Impact - `test_l4d2_facade.py` and `test_job_worker.py` that use fake `run_command` handlers might need to explicitly emit stdout if tests assert exact sequences. - Existing tests that call `initialize_instance` without `passthrough` will silently ignore steps as expected.