You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit e7940da
Browse filesBrowse the repository at this point in the historyBrowse files
fix(pause): preserve sandbox when snapshot fails, behind a flag
A pause whose snapshot failed after the guest was suspended (e.g. a
rootfs-diff fsync EIO, or a memfd ENOMEM under host memory/hugepage
pressure) destroyed the sandbox: Server.Pause armed an unconditional
deferred stop before snapshotting, so the error path tore down the
already-suspended VM, and the API had already removed the routing entry
and store record. The sandbox was left unrecoverable with no snapshot
(#3658).
Behind PauseRefusalRestoreFlag (off by default, so today's
destroy-on-failure behaviour is unchanged), keep the sandbox recoverable:
- sandbox: decouple the resume-on-error cleanup from WithMaintainSandbox
via a new WithResumeOnFailure() option. It arms the same resume-in-place
cleanup (health checks restarted, guest clock re-synced) that the
in-place checkpoint uses, but only on failure - a successful pause still
suspends and leaves the VM for the caller to stop.
- Server.Pause: pass resumeOnFailure when the flag is on, and arm the
deferred stop only after the snapshot succeeds. On snapshot error the
guest has been resumed in place, so re-register it in the live map
(MarkRunning) and return FailedPrecondition with a "sandbox preserved"
marker. ErrSandboxLost (the resume itself failed) falls through to the
destroy path and returns Internal unchanged.
- api: classify that FailedPrecondition+marker as ErrPausePreservedSandbox
(pause_instance.go) and map it in DeleteInstance to the existing
restoreRefusedPause path, restoring the store record and route instead
of removing them.
Tests: TestSnapshotInstance_PreservedSandboxIsClassified and
_PlainFailedPreconditionNotPreserved cover the API classification (a
plain FailedPrecondition is not misclassified). All three packages build;
the full internal/orchestrator suite passes.
End-to-end validation with the flag enabled against real Firecracker
(inject a snapshot fault, assert the sandbox survives and stays routable)
requires a KVM host and is a follow-up.
Addresses the pause half of #3658 (checkpoint half: #3666).
Signed-off-by: adababys <8872412+adababys@users.noreply.github.com>
// The node's snapshot failed but it resumed the sandbox in place instead of
123
+
// destroying it (e2b-dev/infra#3658). The orchestrator signals this with
124
+
// FailedPrecondition and a stable "sandbox preserved" marker in the message.
125
+
// Classify it so DeleteInstance restores the record + route rather than
126
+
// removing them, keeping the still-healthy sandbox usable.
127
+
ifst.Code() ==codes.FailedPrecondition&&strings.Contains(st.Message(), "sandbox preserved after snapshot failure") {
128
+
logger.L().Warn(ctx, "Pause snapshot failed but the node preserved the sandbox", logger.WithSandboxID(sbx.SandboxID), zap.String("node_message", st.Message()))
129
+
130
+
returnErrPausePreservedSandbox
131
+
}
132
+
121
133
returnfmt.Errorf("failed to pause sandbox '%s': %w", sbx.SandboxID, err)
0 commit comments