Skip to content

Add LCOW live migration source and destination APIs - #2803

Merged
rawahars merged 3 commits into
microsoft:mainfrom
rawahars:lm_service
Jul 27, 2026
Merged

Add LCOW live migration source and destination APIs#2803
rawahars merged 3 commits into
microsoft:mainfrom
rawahars:lm_service

Conversation

@rawahars

@rawahars rawahars commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

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.

@rawahars
rawahars requested a review from a team as a code owner July 2, 2026 05:30
@rawahars
rawahars force-pushed the lm_service branch 2 times, most recently from 4a16358 to 68e2037 Compare July 2, 2026 06:41

@marma-dev marma-dev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread internal/controller/migration/controller.go Outdated
Comment thread internal/controller/migration/controller_destination.go Outdated
Comment thread internal/controller/migration/socket.go
// 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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@rawahars

rawahars commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto the mainline. No code changes from the last review were made.

@rawahars

Copy link
Copy Markdown
Contributor Author

Rebased onto the mainline. No code changes from the last review were made.

@rawahars

Copy link
Copy Markdown
Contributor Author

@marma-dev @jiechen0826 All your review suggestions have been incorporated in 166ff74. Please take a look now.

rawahars added 2 commits July 27, 2026 12:11
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>
@rawahars

Copy link
Copy Markdown
Contributor Author

Rebased onto the mainline

@marma-dev
marma-dev requested a review from Copilot July 27, 2026 09:59

@marma-dev marma-dev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/migration controller 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.

Comment thread internal/hcs/v2/migration.go
Comment thread internal/controller/migration/controller.go
Comment thread internal/controller/migration/controller_source.go
Comment thread cmd/containerd-shim-lcow-v2/service/service_task_internal.go
Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
@rawahars
rawahars merged commit 7670554 into microsoft:main Jul 27, 2026
20 checks passed
@rawahars
rawahars deleted the lm_service branch July 27, 2026 16:45
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.

4 participants