package runtime import ( "context" "fmt" "strings" "git.cloudinit.dev/coreci/orca/internal/sshpush" ) // WasmRuntime implements Runtime for the "wasm" one_of. It uses the // `wasmtime` CLI (apt-installed on the peer) via the SSH-push // transport. It does NOT use the Go wasmtime binding // (github.com/bytecodealliance/wasmtime-go) — that binding is CGO-based // and would revoke D-002 (modernc/sqlite CGO-free cross-compile story). // See C01_WASMTIME_CGO_EVAL.md for the C-01 grill gate evaluation and // the auto-decision D-187. // // Lifecycle: // // - Prepare: `command -v wasmtime` (verify the CLI is installed) // - Start: `wasmtime run --dir /data ` // - Stop: `pkill -f wasmtime.*` // - Status: `pgrep -f wasmtime.*` // // The image is a .wasm file path on the peer. For v0.9 it is // pre-staged (downloaded out-of-band); the full OCI pull lands in v0.10. type WasmRuntime struct { transport *sshpush.Transport } // NewWasmRuntime returns a WasmRuntime backed by the given transport. func NewWasmRuntime(t *sshpush.Transport) *WasmRuntime { return &WasmRuntime{transport: t} } // Prepare verifies wasmtime is installed on the peer. func (w *WasmRuntime) Prepare(ctx context.Context, alloc *Alloc) error { if _, err := w.transport.Exec(ctx, alloc.Node, "command -v wasmtime"); err != nil { return fmt.Errorf("wasm: wasmtime not installed on peer: %w", err) } return nil } // Start runs `wasmtime run --dir /data ` on the peer. // The PID returned is a synthetic derived from the alloc ID hash. func (w *WasmRuntime) Start(ctx context.Context, alloc *Alloc) (int, error) { image, err := imageFor(alloc) if err != nil { return 0, err } cmdStr, _ := commandFor(alloc) // Tag the process so pkill/pgrep can find it by alloc ID. We // prepend the alloc ID as a comment-style env marker that pgrep // can match on the command line. cmd := fmt.Sprintf("ORCA_ALLOC_ID=%s wasmtime run --dir /data %q %s", alloc.ID, image, cmdStr) if _, err := w.transport.Exec(ctx, alloc.Node, cmd); err != nil { return 0, fmt.Errorf("wasm: start: %w", err) } return allocIDHash(alloc.ID), nil } // Stop kills the wasmtime process matching the alloc ID. func (w *WasmRuntime) Stop(ctx context.Context, alloc *Alloc) error { cmd := fmt.Sprintf("pkill -f %q", "wasmtime.*"+alloc.ID) if _, err := w.transport.Exec(ctx, alloc.Node, cmd); err != nil { return fmt.Errorf("wasm: stop: %w", err) } return nil } // Status reports whether the wasmtime process for the alloc is running. func (w *WasmRuntime) Status(ctx context.Context, alloc *Alloc) (State, error) { cmd := fmt.Sprintf("pgrep -f %q", "wasmtime.*"+alloc.ID) out, err := w.transport.Exec(ctx, alloc.Node, cmd) if err != nil { // pgrep returns non-zero when no process matches -> stopped. return StateStopped, nil } if strings.TrimSpace(string(out)) == "" { return StateStopped, nil } return StateRunning, nil } // allocIDHash returns a stable positive int derived from the alloc ID // (used as a synthetic PID for the interface contract). func allocIDHash(id string) int { var h uint32 for _, c := range id { h = h*31 + uint32(c) } pid := int(h % 99999) if pid <= 0 { pid = 1 } return pid }