opstate,daemon: list in-flight operations via daemon.operations.list

Prerequisite for `banger update`'s preflight, which refuses to swap
binaries while anything is in flight. Today's opstate.Registry
exposes Insert/Get/Prune but no iteration; without a snapshot
accessor the update flow can't tell whether a vm.create is
mid-prepare-work-disk.

  * opstate.Registry.List(): returns a freshly-allocated snapshot
    of every entry. Mutating the slice doesn't poison the
    registry. Pinned by tests covering the snapshot semantics
    and the empty case.
  * api.OperationSummary / OperationsListResult: a public-shape
    record per op. Today the Kind is always "vm.create" — the
    field exists so future async kinds (image.pull, kernel.pull)
    plug in without an API change.
  * Daemon.ListOperations + daemon.operations.list RPC:
    walks vmService.createOps and emits OperationSummary entries.
    Done ops are included in the snapshot; the update preflight
    filters by Done itself.
  * dispatch_test's documented-methods list updated.

No behaviour change for existing flows; this is a read-only
addition.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Thales Maciel 2026-04-28 18:14:57 -03:00
parent 775525b592
commit 3c0af3a2de
No known key found for this signature in database
GPG key ID: 33112E6833C34679
6 changed files with 117 additions and 2 deletions

View file

@ -50,8 +50,9 @@ func noParamHandler[R any](call func(ctx context.Context, d *Daemon) (R, error))
// live below the map; they need pre-service validation or raw result
// encoding that the generic wrapper can't express.
var rpcHandlers = map[string]handler{
"ping": pingHandler,
"shutdown": shutdownHandler,
"ping": pingHandler,
"shutdown": shutdownHandler,
"daemon.operations.list": noParamHandler(daemonOperationsListDispatch),
"vm.create": paramHandler(vmCreateDispatch),
"vm.create.begin": paramHandler(vmCreateBeginDispatch),
@ -214,6 +215,10 @@ func imageCachePruneDispatch(ctx context.Context, d *Daemon, p api.ImageCachePru
return d.img.PruneOCICache(ctx, p)
}
func daemonOperationsListDispatch(ctx context.Context, d *Daemon) (api.OperationsListResult, error) {
return d.ListOperations(ctx)
}
func kernelListDispatch(ctx context.Context, d *Daemon) (api.KernelListResult, error) {
return d.img.KernelList(ctx)
}