Skip to content

meta: a pod annotation requests a live snapshot push, and its status answers it - #38

Merged
CMGS merged 2 commits into
mainfrom
tonic/snapshot-request
Oct 12, 2026
Merged

CMGS merged 2 commits into
mainfrom
tonic/snapshot-request

Conversation

@tonicmuroq

@tonicmuroq tonicmuroq commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

What

  • meta.AnnotationSnapshotRequest = vm.cocoonstack.io/snapshot: a registry-relative repo[:tag] (tag defaults to latest) that asks vk-cocoon to push a live snapshot of the pod's running VM there.
  • meta.AnnotationSnapshotStatus = vm.cocoonstack.io/snapshot-status: vk-cocoon's answer, a JSON meta.SnapshotStatus {ref, state, message} with state pushed or failed. ref echoes the request, so a caller waits for a status carrying its own ref and can tell it from an older answer.
  • meta.ReadSnapshotStatus(pod), SnapshotStatus.Annotations(): the typed reader and the merge-patch map; a missing or malformed status reads as the zero status, which no ref matches.
  • A ref is answered once, pushed or failed, so every push, a retry included, uses a new tag.
  • snapshot.PushOptions.LocalName: the local snapshot to export when it differs from the registry repo (Name); empty falls back to Name, so existing callers are unchanged. vk-cocoon saves a requested snapshot as snap-<vm> and pushes it to the caller's repo.
  • docs/meta.md: both keys in the vm.cocoonstack.io/ row and one paragraph in the snapshot contract.

Why

The developer API lets a user snapshot their machine and later create or reset a machine from it. Today vk-cocoon pushes only on its own schedule: the hibernate push (CH+Windows drops the NIC first, so it cannot serve as a clone source) and the delete-time latest push (the VM is gone afterwards). There is no way to ask for a push of a VM that keeps running. cocoon snapshot save already pauses only for the save and resumes, and keeps the NICs, which clone hot-swaps for fresh ones, so the result is a clone source like the base snapshots. The request goes straight on the pod rather than through the CocoonSet: it touches one VM and creates or deletes no pods, so the operator has nothing to coordinate.

Consumer

vk-cocoon PR to follow, pinned to this branch's commit until this merges.

Gates

make fmt-check clean, go test -race ./... green (GOWORK=off). make lint could not run locally (golangci-lint v2.13.2 cannot read Go 1.27.2 export data); leaving it to CI.

@tonicmuroq
tonicmuroq force-pushed the tonic/snapshot-request branch 2 times, most recently from 8fa691d to 4ca2b76 Compare October 11, 2026 14:54
tonicmuroq added a commit to cocoonstack/vk-cocoon that referenced this pull request Oct 11, 2026
…e running VM

vm.cocoonstack.io/snapshot names a registry-relative repo[:tag]. UpdatePod
saves the running VM as snap-<vm> (never the VM-named warm-wake cache), pushes
it there, drops the local copy, and answers in vm.cocoonstack.io/snapshot-status
with the ref echoed and pushed or failed. The save pauses the VM only for its
duration and keeps the NICs, so the result is a clone source. A VM that is not
running or is hibernating fails the request instead of serving it later; a
pending hibernate still runs afterwards.

Each ref is answered once per pod incarnation: the answer is kept in memory, so
a stale informer copy or a failed status patch re-patches the status without a
second save. The request is read before the pod is tracked, since tracked pods'
annotations are written under p.mu.

The delete-time latest push and the requested push share saveAndPush.
cocoon-common is pinned to cocoonstack/cocoon-common#38 until it merges.
@tonicmuroq
tonicmuroq force-pushed the tonic/snapshot-request branch from 4ca2b76 to 9d4a96c Compare October 11, 2026 15:00
tonicmuroq added a commit to cocoonstack/vk-cocoon that referenced this pull request Oct 11, 2026
…e running VM

vm.cocoonstack.io/snapshot names a registry-relative repo[:tag]. While the VM
runs and no hibernate is asked for, UpdatePod saves it as snap-<vm> (never the
VM-named warm-wake cache), pushes it there, drops the local copy, and answers in
vm.cocoonstack.io/snapshot-status with the ref echoed and pushed or failed. The
save pauses the VM only for its duration and keeps the NICs, so the result is a
clone source. The pending ref is read before the pod is tracked, like the
hibernate intent.

The delete-time latest push and the requested push share saveAndPush.
cocoon-common is pinned to cocoonstack/cocoon-common#38 until it merges.
…answers it

vm.cocoonstack.io/snapshot names a registry-relative repo[:tag]; vk-cocoon
saves the pod's running VM, which pauses only for the save and keeps its NICs
so the result can serve as a clone source, and pushes it there.
vm.cocoonstack.io/snapshot-status answers it with a JSON SnapshotStatus whose
ref echoes the request, so a caller can tell its answer from an older one; a
missing or malformed status reads as unanswered.

snapshot.PushOptions.LocalName names the local snapshot to export when it
differs from the registry repo; it defaults to Name, so existing pushes are
unchanged.
@tonicmuroq
tonicmuroq force-pushed the tonic/snapshot-request branch from 9d4a96c to 40b0dbf Compare October 11, 2026 15:10
tonicmuroq added a commit to cocoonstack/vk-cocoon that referenced this pull request Oct 11, 2026
…e running VM

vm.cocoonstack.io/snapshot names a registry-relative repo[:tag]. While the VM
runs and no hibernate is asked for, UpdatePod saves it as snap-<vm> (never the
VM-named warm-wake cache), pushes it there, drops the local copy, and answers in
vm.cocoonstack.io/snapshot-status with the ref echoed and pushed or failed. The
save pauses the VM only for its duration and keeps the NICs, so the result is a
clone source. The pending ref is read before the pod is tracked, like the
hibernate intent.

PushSnapshot now exports its vmName argument as the local snapshot
(PushOptions.LocalName) instead of the repo; the hibernate and latest pushes
pass the same name for both, so they are unchanged. The delete-time latest push
and the requested push share saveAndPush.

cocoon-common is pinned to cocoonstack/cocoon-common#38 until it merges.
tonicmuroq added a commit to cocoonstack/vk-cocoon that referenced this pull request Oct 12, 2026
…e running VM

vm.cocoonstack.io/snapshot names a registry-relative repo[:tag]. While the VM
runs and no hibernate is asked for, UpdatePod saves it as snap-<vm> (never the
VM-named warm-wake cache), pushes it there, drops the local copy, and answers in
vm.cocoonstack.io/snapshot-status with the ref echoed and pushed or failed. The
save pauses the VM only for its duration and keeps the NICs, so the result is a
clone source. The pending ref is read before the pod is tracked, like the
hibernate intent.

PushSnapshot now exports its vmName argument as the local snapshot
(PushOptions.LocalName) instead of the repo; the hibernate and latest pushes
pass the same name for both, so they are unchanged. The delete-time latest push
and the requested push share saveAndPush.

cocoon-common is pinned to cocoonstack/cocoon-common#38 until it merges.
tonicmuroq added a commit to cocoonstack/vk-cocoon that referenced this pull request Oct 12, 2026
…e running VM

vm.cocoonstack.io/snapshot names a registry-relative repo[:tag]. While the VM
runs and no hibernate is asked for, UpdatePod saves it as snap-<vm> (never the
VM-named warm-wake cache), pushes it there, drops the local copy, and answers in
vm.cocoonstack.io/snapshot-status with the ref echoed and pushed or failed. The
save pauses the VM only for its duration and keeps the NICs, so the result is a
clone source. The pending ref is read before the pod is tracked, like the
hibernate intent.

PushSnapshot now exports its vmName argument as the local snapshot
(PushOptions.LocalName) instead of the repo; the hibernate and latest pushes
pass the same name for both, so they are unchanged. The delete-time latest push
and the requested push share saveAndPush.

cocoon-common is pinned to cocoonstack/cocoon-common#38 until it merges.
tonicmuroq added a commit to cocoonstack/vk-cocoon that referenced this pull request Oct 12, 2026
…e running VM

vm.cocoonstack.io/snapshot names a registry-relative repo[:tag]. While the VM
runs and no hibernate is asked for, UpdatePod saves it as snap-<vm> (never the
VM-named warm-wake cache), pushes it there, drops the local copy, and answers in
vm.cocoonstack.io/snapshot-status with the ref echoed and pushed or failed. The
save pauses the VM only for its duration and keeps the NICs, so the result is a
clone source. The pending ref is read before the pod is tracked, like the
hibernate intent.

PushSnapshot now exports its vmName argument as the local snapshot
(PushOptions.LocalName) instead of the repo; the hibernate and latest pushes
pass the same name for both, so they are unchanged. The delete-time latest push
and the requested push share saveAndPush.

cocoon-common is pinned to cocoonstack/cocoon-common#38 until it merges.
… tag per push

A ref is answered once, pushed or failed, so a repeated or retried push
under the same ref would read the old answer. The docs now say every push
uses a new tag. The reader drops its ok result: the only consumer compares
the ref, and a zero status already reads as unanswered.
@CMGS
CMGS merged commit ba211c8 into main Oct 12, 2026
2 checks passed
@CMGS
CMGS deleted the tonic/snapshot-request branch October 12, 2026 12:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants