install
install
¶
Install + uninstall the OCI hook that spawns the supervisor.
Single-root layout: scripts, ballast, and the JSON descriptor all
live under state_root() (which
honours the operator's paths.root config). containers.conf
is patched to list state_root() / "hooks" in hooks_dir so
podman scans the canonical terok-owned directory rather than the
default ~/.config/containers/oci/hooks.d/.
Files written:
<state_root>/hooks/supervisor_hook.py<state_root>/hooks/_supervisor_state.py<state_root>/hooks/terok-sandbox-supervisor-createRuntime.json<state_root>/hooks/terok-sandbox-supervisor-poststop.json(one OCI hook descriptor per stage — podman/crun reuse the samehook.argsfor every stage listed in a single descriptor, so each stage gets its own JSON; both match on theterok.sandbox.sidecarannotation)<state_root>/supervisor_wrapper.py(templated — embeds the resolvedterok-sandboxargv)
The supervisor flow is annotation-driven from here on: the launch
path emits --annotation terok.sandbox.sidecar=<abspath> and the
hook reads the sidecar at that path. No $XDG_* discovery,
no stamp files, no parallel root resolution.
install_supervisor_hooks(*, hooks_dir=None)
¶
Lay down hook scripts, wrapper, and the OCI descriptor.
hooks_dir — override for tests; defaults to
state_root() / "hooks", where the role scripts already live.
Scripts + ballast + descriptor share one terok-owned directory so
a teardown is a clean rm -rf. containers.conf is patched
to register that path.
Idempotent — every file write overwrites silently, and the
descriptor JSON gets re-rendered each time so a moved install
location is picked up on the next terok-sandbox setup.
Source code in src/terok_sandbox/supervisor/install.py
uninstall_supervisor_hooks(*, hooks_dir=None)
¶
Remove every file install_supervisor_hooks writes.
Idempotent — missing files are tolerated. Does not touch
per-container state (sidecar/, logs/, pids/ under the
state root) — those are sweep-able with a separate operator
command if needed.
Source code in src/terok_sandbox/supervisor/install.py
kill_all_supervisors()
¶
SIGKILL every live host-side supervisor process; return one row per PID file.
Iterates <state_root>/pids/supervisor-*.pid. For each file:
read the PID, SIGKILL if alive, then unlink the stale file.
Each returned row is (container_id, error_or_None) — None
means the process is no longer there, whether we killed it or it
had already exited.
Designed for the panic path: the OCI poststop reap does a
graceful SIGTERM → poll → SIGKILL dance for a normal
container stop; panic skips straight to SIGKILL because the
whole point is to deny the supervisor any more cycles to answer
socket calls from a misbehaving container.
PID-recycle check is intentional but tight: the file name carries
the container ID, so a stale PID that's been recycled into an
unrelated process can still be matched by reading
/proc/<pid>/cmdline for the wrapper path before signalling.