krun
krun
¶
Krun backend for ContainerRuntime —
microVM isolation peer of PodmanRuntime.
Launches unmodified OCI images inside KVM microVMs via podman --runtime
krun. Container lifecycle (state, logs, force-remove, image inspection)
delegates to a held PodmanRuntime
because podman --runtime krun honours every other verb that doesn't
need to reach into the running guest.
exec is the one verb that diverges and the reason this module exists:
podman exec can't enter krun microVMs (libkrun can't inject processes
post-boot — see crun#1098), so exec routes through a pluggable
KrunTransport instead. The
real transport is OpenSSH over a passt-forwarded TCP port (see
TcpSSHTransport);
a FakeKrunTransport
ships here so the skeleton and its callers are unit-testable without
standing up a real guest.
KrunRuntime(*, transport, podman=None)
¶
Container runtime that launches tasks inside KVM microVMs.
Composition, not inheritance: holds a
PodmanRuntime for every
lifecycle verb (podman --runtime krun is just podman driving a
different OCI runtime) and a
KrunTransport for the
one verb that can't go through podman — exec.
The transport is required: there is no sensible default beyond a
real SSH-over-passt-TCP implementation, and the fake exists explicitly
for tests. Production callers wire the real transport at the
ContainerRuntime selection point
in the orchestrator.
Source code in src/terok_sandbox/runtime/krun.py
container(name)
¶
Return a KrunContainer
handle wrapping the podman container — same lifecycle, krun-aware
login_command.
Return type stays the Container
Protocol rather than the narrower concrete class: mypy treats
Protocol method return types as invariant, so a narrower
annotation breaks structural ContainerRuntime matching for
downstream consumers (terok's _runtime: ContainerRuntime
assignment was the loud failure). The runtime value is
genuinely a KrunContainer — callers needing the concrete
type cast at the call site.
Source code in src/terok_sandbox/runtime/krun.py
containers_with_prefix(prefix)
¶
Same prefix lookup as podman; rewrap each handle as a
KrunContainer so its
login_command routes through the TCP-SSH transport.
Same Protocol-invariance rationale as
container
for the wider declared return type.
Source code in src/terok_sandbox/runtime/krun.py
image(ref)
¶
images(*, dangling_only=False)
¶
exec(container, cmd, *, timeout=None)
¶
Route to the transport — typically SSH-over-passt-TCP.
Source code in src/terok_sandbox/runtime/krun.py
exec_stdio(container, cmd, *, stdin, stdout, stderr=None, env=None, timeout=None)
¶
Route stdio-bridged exec to the transport.
Source code in src/terok_sandbox/runtime/krun.py
force_remove(containers)
¶
KrunTransport
¶
Bases: Protocol
How KrunRuntime reaches into a
running microVM to run commands.
The exec divergence is forced by libkrun: a microVM is sealed after boot and cannot accept injected processes. The real implementation speaks SSH to a sshd inside the guest, reachable through a per-task host TCP port that podman's passt has forwarded into the guest namespace; that is wire-protocol shaped, not in-tree code we want to invent.
Kept narrow on purpose — only the two operations
ContainerRuntime
needs to route through it. Lifecycle stays on the podman side.
exec(container, cmd, *, timeout=None)
¶
Run cmd inside the guest backed by container; return its outcome.
exec_stdio(container, cmd, *, stdin, stdout, stderr=None, env=None, timeout=None)
¶
Bridge byte streams to cmd inside the guest; return its exit code.
Source code in src/terok_sandbox/runtime/krun.py
login_command(container, *, command=())
¶
Return an argv for os.execvp to attach interactively.
Mirrors the protocol method on
Container.login_command
but routed through the transport so the krun runtime can hand the
operator an SSH invocation instead of podman exec.
Source code in src/terok_sandbox/runtime/krun.py
FakeKrunTransport()
¶
In-memory KrunTransport for tests.
Mirrors NullRuntime's
pre-register-then-replay shape so tests that already understand the
null backend pick this up by analogy. Records every call so tests
can assert dispatch without a real sshd listener.
Source code in src/terok_sandbox/runtime/krun.py
exec_calls = []
instance-attribute
¶
exec_stdio_calls = []
instance-attribute
¶
set_result(container_name, cmd, result)
¶
Pre-register the result exec
returns for exact cmd on container_name.
Source code in src/terok_sandbox/runtime/krun.py
exec(container, cmd, *, timeout=None)
¶
Return a pre-registered result, or empty success.
Source code in src/terok_sandbox/runtime/krun.py
exec_stdio(container, cmd, *, stdin, stdout, stderr=None, env=None, timeout=None)
¶
Record the call and return exit code 0 (no I/O is moved).
Source code in src/terok_sandbox/runtime/krun.py
login_command(container, *, command=())
¶
Return a placeholder argv ["fake-login", <name>, *command].
Tests assert on the shape; no real transport is contacted.
Source code in src/terok_sandbox/runtime/krun.py
KrunContainer(name, *, runtime, transport)
¶
Bases: PodmanContainer
Container handle for krun-managed microVMs.
Subclasses PodmanContainer
because podman --runtime krun honours every lifecycle verb
(state, start/stop, logs, inspect) — only login_command diverges,
since podman exec can't enter the guest. That single override
routes through the held KrunTransport
so the operator gets an SSH argv that actually reaches in.
Source code in src/terok_sandbox/runtime/krun.py
login_command(*, command=())
¶
Return the transport's interactive-attach argv for this container.