Skip to content

[live-migration] Renegotiate GCS version on restore and drop Plan9 from HCS Document - #2845

Open
rawahars wants to merge 3 commits into
mainfrom
harshrawat/minor-lm-fixes
Open

[live-migration] Renegotiate GCS version on restore and drop Plan9 from HCS Document#2845
rawahars wants to merge 3 commits into
mainfrom
harshrawat/minor-lm-fixes

Conversation

@rawahars

@rawahars rawahars commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

After a migration blackout the guest re-dials and resets its GCS protocol version, so version-gated RPCs (e.g. exec) failed on source resume. Renegotiate via connect() in ResumeOnConn before adopting the new connection.

  • GuestConnection.ResumeOnConn now takes a ctx and re-runs the version handshake after swapping the bridge transport.
  • Fix PrepareConnection idempotency to key only on the armed listener (gcListener) so the log/GCS listener can be re-armed on resume even when a GuestConnection already exists about to be discarded.
  • Clarify resume comments and error messages.

An empty Plan9 element makes HCS attach a file-sharing device that becomes part of the VM's saved device state and fails the save/restore path, breaking migration even when nothing is shared. Omit Plan9 for live-migratable sandboxes.

  • Gate the Plan9 device in BuildSandboxConfig on LiveMigrationSupportEnabled (nil when set, otherwise &Plan9{}).
  • Thread the migration-support flag through the kernel-arg builders instead of re-parsing the annotation.

After a migration blackout the guest re-dials and resets its GCS
protocol version, so version-gated RPCs (e.g. exec) failed on source resume.
Renegotiate via connect() in ResumeOnConn before adopting the new
connection.

- GuestConnection.ResumeOnConn now takes a ctx and re-runs the version
  handshake after swapping the bridge transport.
- Fix PrepareConnection idempotency to key only on the armed listener
  (gcListener) so the log/GCS listener can be re-armed on resume even
  when a GuestConnection already exists.
- Clarify resume comments and error messages.

Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
@rawahars
rawahars requested a review from a team as a code owner July 30, 2026 17:44
Comment thread internal/controller/vm/save_lcow.go Outdated
}

switch {
case rebuildBridge:

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.

Unrelated to this change, but it is harder to read this switch case. Can you re-write it as simple if-else block?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in the latest commit

rawahars added 2 commits July 31, 2026 16:04
Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
Signed-off-by: Harsh Rawat <harshrawat@microsoft.com>
@rawahars rawahars changed the title [live-migration] renegotiate GCS protocol version on LCOW resume [live-migration] Renegotiate GCS version on restore and drop Plan9 from HCS Document Jul 31, 2026
Comment on lines +247 to -253
func (gc *GuestConnection) ResumeOnConn(ctx context.Context, conn io.ReadWriteCloser) error {
if gc.brdg == nil {
// Not adopting conn; close it so the accepted socket does not leak.
_ = conn.Close()
return ErrBridgeClosed
}
return gc.brdg.ResumeOnConn(conn)

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.

connect's doc comment still says "It must not be called more than once"
Also just a question is there nothing that issues container RPCs while a source rollback resume is in progress/inflight ? I see container RPCs go sright to c.gc.brdg.RPC and never take the guest mutex, this function holding that lock doesn't cover the swap and negotiate landing

} else {
// Destination: reuse the connection already armed at start.
if err := c.guest.CreateConnection(ctx, false); err != nil {
return fmt.Errorf("resume guest connection: %w", 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.

Nit: both branches still wrap with "resume guest connection", so source and destination are indistinguishable in logs. You retitled the prepare message, worth splitting these too.

@shreyanshjain7174 shreyanshjain7174 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.

Nothing in CI exercises LM, so a unit test is the only thing that catches a regression here. guestconnection_test.go's simpleGcs already answers RPCNegotiateProtocol: set migrating, call ResumeOnConn with a second fake pipe, assert the second negotiate arrived. Worth adding?

@shreyanshjain7174

Copy link
Copy Markdown
Contributor

Everything else looks good!

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.

3 participants