Add LCOW live migration source and destination APIs - #2803
Conversation
4a16358 to
68e2037
Compare
marma-dev
left a comment
There was a problem hiding this comment.
Overall looks good, doc.go / state.go diagrams are excellent and match the code — nice 👍 .
I would like run.Transfer and service-owned maps comments addressed (or explained). Rest are nice to have.
| // Reattach each migrated pod's containers and processes on this host. | ||
| for podID, podCtrl := range c.podControllers { | ||
| if err := podCtrl.Resume(ctx, c.vmController, events, true /* isDestination */); err != nil { | ||
| return fmt.Errorf("resume pod %q from migration: %w", podID, err) |
There was a problem hiding this comment.
On the RESUME path, if one podCtrl.Resume fails partway through the loop, Finalize returns before setting StateFinalized, so the session stays in StateTransferCompleted with the VM already resumed and some pods live. Since finalizeSandboxInternal just propagates the error to the caller, what's the intended recovery here, is the caller expected to retry Finalize, or fall back to a STOP?
It seems like a retried RESUME would call vm.Resume again on an already-running VM, which vm.Resume rejects, so I wasn't sure how the partial-failure case is meant to unwind. I could be missing where that's handled upstream.
|
Rebased onto the mainline. No code changes from the last review were made. |
|
Rebased onto the mainline. No code changes from the last review were made. |
|
@marma-dev @jiechen0826 All your review suggestions have been incorporated in 166ff74. Please take a look now. |
Introduce an end-to-end live-migration workflow for LCOW sandboxes, letting a running sandbox be handed off from a source shim to a destination shim. - Add a migration Controller that sequences a single session through a source or destination lifecycle: the source prepares and exports an opaque sandbox snapshot (VM + per-pod state), while the destination imports it, patches each container onto its new IDs, builds the destination VM, transfers memory over a shared socket, and finalizes with a resume or stop. - Expose the migration gRPC/ttrpc surface on the LCOW shim service (PrepareAndExportSandbox, ImportSandbox, PrepareSandbox, TransferSandbox, FinalizeSandbox, Cancel, Cleanup, CreateDuplicateSocket, Notifications) and register it alongside the task and sandbox services. - Wire migration into the task lifecycle: route destination-side CreateTask for rehydrated containers into a patch path, and reject task mutations (state, delete, kill) while a session is in progress. - Add duplicated transport-socket adoption, a subscriber-based progress notification stream, and proto/HCS conversion helpers for migration options and events. Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
Give the live-migration session predictable, caller-facing behavior: - Cancellation & wind-down: a session can be aborted from any active state and always finalizes then cleans up back to idle, even after a failure or a partly-applied finalize. - Predictable retries: resource snapshots can be retaken and resumes are idempotent, while duplicate or out-of-order session calls are rejected instead of silently reapplied. - Typed errors: calls report invalid-argument, failed-precondition, or already-exists so callers can branch on them. Backed by unit tests and a documented state machine. Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
|
Rebased onto the mainline |
There was a problem hiding this comment.
Pull request overview
Introduce an end-to-end LCOW live migration workflow in the lcow-v2 shim by adding a migration session controller (source + destination lifecycles), wiring it into the shim service surface (ttrpc), and updating underlying controllers to support retry-safe save/import/patch/resume semantics and richer error classification.
Changes:
- Add an
internal/controller/migrationcontroller implementing a session state machine, duplicated-socket adoption, and subscriber-based progress notifications. - Extend VM/pod/container/process/network/device controller migration save/import/patch/resume flows (including idempotent retries) and wrap key failures with
containerd/errdefs. - Register and implement migration APIs in
cmd/containerd-shim-lcow-v2/service, including a destination CreateTask patch path for rehydrated containers.
Reviewed changes
Copilot reviewed 45 out of 47 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/migration/parse.go | Adds helpers to map HCS migration events/origin/results into wire notification fields. |
| pkg/migration/parse_test.go | Adds unit tests for migration proto parsing/mapping and blackout-exited details parsing. |
| internal/vm/vmmanager/migration.go | Adds UtilityVM.CancelLiveMigration wrapper. |
| internal/hcs/v2/migration.go | Adds System.CancelLiveMigration entry point (currently stubbed). |
| internal/controller/vm/vm.go | Ensures migrating flag cleared during VM termination to release bridge earlier. |
| internal/controller/vm/vm_migration.go | Broadens finalize state-acceptance and adds VM-level cancel API. |
| internal/controller/vm/save_lcow.go | Tightens migration state preconditions and wraps errors with errdefs; adds resume idempotency. |
| internal/controller/process/save.go | Makes Save retry-safe from StateSourceMigrating, adds resume idempotency, wraps errors with errdefs. |
| internal/controller/process/save_test.go | Updates/extends tests for new Save/Resume semantics and error wrapping. |
| internal/controller/pod/save_lcow.go | Makes Resume idempotent and improves error classification for Import/Patch. |
| internal/controller/pod/save_lcow_test.go | Updates tests for new Resume/Patch behavior and errdefs wrapping. |
| internal/controller/network/save.go | Makes Save retry-safe from StateSourceMigrating, adds resume/reset idempotency, wraps errors with errdefs. |
| internal/controller/network/save_test.go | Updates tests for new Save/Resume/Reset behavior and errdefs wrapping. |
| internal/controller/migration/types.go | Defines migration controller interfaces/options used by service + tests. |
| internal/controller/migration/state.go | Defines migration session state machine and stringification. |
| internal/controller/migration/socket.go | Implements duplicated transport socket adoption and validation. |
| internal/controller/migration/socket_test.go | Adds end-to-end tests for socket descriptor adoption and guards. |
| internal/controller/migration/notifications.go | Adds subscriber fan-out + replay notification stream over VM migration events. |
| internal/controller/migration/notifications_test.go | Adds tests for subscription lifecycle, replay, fan-out, and controller Subscribe integration. |
| internal/controller/migration/mocks/mock_lcow_migration.go | Adds gomock for migration controller’s VM interface. |
| internal/controller/migration/doc.go | Documents the migration controller lifecycle, failure/cancel paths, and notifications. |
| internal/controller/migration/controller.go | Implements core transfer/finalize/cancel/cleanup sequencing for a session. |
| internal/controller/migration/controller_source.go | Implements source-side prepare + export snapshot workflow. |
| internal/controller/migration/controller_source_test.go | Adds source-side unit tests. |
| internal/controller/migration/controller_destination.go | Implements destination import + per-container patch + prepare destination VM. |
| internal/controller/migration/controller_destination_test.go | Adds destination-side unit tests. |
| internal/controller/linuxcontainer/save.go | Makes container save retry-safe, adds resume idempotency, wraps errors with errdefs. |
| internal/controller/linuxcontainer/save_test.go | Updates tests for new save/resume semantics and error wrapping. |
| internal/controller/device/vpci/save.go | Makes VPCI Save a no-op when empty; wraps unsupported state with errdefs. |
| internal/controller/device/vpci/save_lcow_test.go | Updates VPCI Save tests to assert errdefs wrapping. |
| internal/controller/device/scsi/save.go | Wraps validation/precondition failures with errdefs; tightens import validation comments. |
| internal/controller/device/scsi/save_test.go | Updates SCSI tests for errdefs wrapping and new invalid-argument cases. |
| internal/controller/device/scsi/mount/save_lcow.go | Wraps mount save precondition failures with errdefs. |
| internal/controller/device/scsi/mount/save_lcow_test.go | Updates mount save tests for errdefs wrapping. |
| internal/controller/device/scsi/disk/save.go | Wraps disk save precondition failures with errdefs. |
| internal/controller/device/scsi/disk/save_test.go | Updates disk save tests for errdefs wrapping. |
| internal/controller/device/plan9/save.go | Makes Plan9 Save a no-op when empty; wraps unsupported state with errdefs. |
| internal/controller/device/plan9/save_test.go | Updates Plan9 Save tests to assert errdefs wrapping. |
| cmd/containerd-shim-lcow-v2/service/types.go | Extends service vmController interface to satisfy migration controller needs. |
| cmd/containerd-shim-lcow-v2/service/service.go | Instantiates migration controller and registers migration service; adds migration-in-progress guard. |
| cmd/containerd-shim-lcow-v2/service/service_task_internal.go | Routes migrated CreateTask into patch path and rejects task ops during migration. |
| cmd/containerd-shim-lcow-v2/service/service_task_internal_test.go | Updates task API tests to reflect migration/VM-running guard changes. |
| cmd/containerd-shim-lcow-v2/service/service_sandbox_internal_test.go | Updates service test construction to include migration controller. |
| cmd/containerd-shim-lcow-v2/service/service_migration.go | Adds instrumentation-layer migration service methods and registration plumbing. |
| cmd/containerd-shim-lcow-v2/service/service_migration_internal.go | Implements migration service business logic (prepare/export/import/prepare/transfer/finalize/notifications/cancel/cleanup). |
| cmd/containerd-shim-lcow-v2/service/mocks/mock_service.go | Updates mocks to include migration-related vmController methods. |
Files not reviewed (2)
- cmd/containerd-shim-lcow-v2/service/mocks/mock_service.go: Generated file
- internal/controller/migration/mocks/mock_lcow_migration.go: Generated file
Comments suppressed due to low confidence (1)
internal/controller/migration/controller.go:486
- Cleanup() resets c.socketReady to a new channel without closing the old one. If Transfer() previously started and is still blocked waiting on the old socketReady (e.g., canceled/failed before socket registration), that goroutine will keep waiting until timeout, causing a long-lived goroutine leak.
// Reset all session-scoped state so the controller can host a new session.
c.sessionID, c.sandboxID, c.origin = "", "", ""
c.vmController = nil
c.podControllers = nil
c.containerPodMapping = nil
c.pendingPatches = nil
c.socketReady = make(chan struct{})
c.state = StateIdle
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
Summary
Introduce an end-to-end live-migration workflow for LCOW sandboxes, letting a running sandbox be handed off from a source shim to a destination shim.
Add a migration Controller that sequences a single session through a source or destination lifecycle: the source prepares and exports an opaque sandbox snapshot (VM + per-pod state), while the destination imports it, patches each container onto its new IDs, builds the destination VM, transfers memory over a shared socket, and finalizes with a resume or stop.
Expose the migration gRPC/ttrpc surface on the LCOW shim service (PrepareAndExportSandbox, ImportSandbox, PrepareSandbox, TransferSandbox, FinalizeSandbox, Cancel, Cleanup, CreateDuplicateSocket, Notifications) and register it alongside the task and sandbox services.
Wire migration into the task lifecycle: route destination-side CreateTask for rehydrated containers into a patch path, and reject task mutations (state, delete, kill) while a session is in progress.
Add duplicated transport-socket adoption, a subscriber-based progress notification stream, and proto/HCS conversion helpers for migration options and events.
This PR needs #2790 to be merged.