# How the Rollback Feature Restores Sandbox State to Any Previous Checkpoint in CubeSandbox

> Discover how CubeSandbox's rollback feature restores sandbox state instantly. Clone checkpoints and atomically swap to a previous VM state with ease. Learn more now.

- Repository: [Tencent Cloud/CubeSandbox](https://github.com/TencentCloud/CubeSandbox)
- Tags: internals
- Published: 2026-07-11

---

**The rollback feature recreates a sandbox exactly as it existed at a specific snapshot moment by cloning the checkpointed root‑FS into a new copy‑on‑write (COW) generation and atomically swapping the running VM to that restored state.**

The **rollback** capability in **TencentCloud/CubeSandbox** enables instant restoration of sandbox state using the **cubecow** storage backend. This process operates entirely in‑process without external commands, leveraging COW volumes to preserve the original snapshot while creating a new writable root‑FS for the resumed workload.

## Understanding the Rollback Architecture

The rollback mechanism relies on the **cubecow copy‑on‑write (COW) storage backend** to manage disk state efficiently. When a checkpoint is created, the system captures both the **root‑FS volume** (disk state) and **memory volume** (RAM contents). During rollback, the system derives a new root‑FS generation from the snapshot while reusing the memory volume, then instructs the containerd shim to destroy the current VM and resume a new one using the restored configuration.

## Step‑by‑Step Rollback Execution Flow

### API Entry and Request Validation

Clients initiate rollback via the `RollbackSandbox` endpoint, accessible through the Go SDK or `cubecli` command. The request requires `sandbox_id`, `snapshot_id`, and a `new_gen` value exceeding the current generation.

In [`Cubelet/services/cubebox/rollback.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/services/cubebox/rollback.go), the `validateRollbackSandboxRequest` function verifies that the storage backend supports COW operations (`storage.IsCowBackend`). If validation fails, the service returns a structured error before any state changes occur.

### Sandbox Locking and State Verification

Before proceeding, the system acquires a per‑sandbox lock via `s.updateSandboxLocks.Lock` to prevent concurrent modifications. The cubebox manager retrieves the live cubebox object and confirms the sandbox is running (not terminated), ensuring rollback only targets active instances.

### Resolving Target Volumes

The `resolveRollbackTargets` function (lines 31‑55 in [`rollback.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/rollback.go)) determines the sources for restoration:

- **Explicit overrides** – Uses master‑supplied `rootfs_vol`, `memory_vol`, or `meta_dir` parameters if provided.
- **Catalog lookup** – Calls `storage.GetLocalSnapshot` to retrieve the root‑FS and memory volume names associated with the requested snapshot ID.

### Snapshot Object Resolution

`storage.ResolveSnapshotForRollback` (defined in [`Cubelet/storage/cubecow_snapshot_artifacts.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/storage/cubecow_snapshot_artifacts.go)) obtains **CowSnapshotObject** handles for both root‑FS and memory volumes. This function supports the optional `memory_kind` parameter to distinguish between snapshot and volume types, enabling incremental memory snapshot restoration.

### Creating the New Root‑FS Generation

`RollbackDeriveNewGen` (in [`cubecow_snapshot_artifacts.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/cubecow_snapshot_artifacts.go)) interacts with the **CowVolumeManager** to clone the snapshot’s root‑FS into a fresh COW volume. This new volume carries the requested generation number and optional size constraints, becoming the restored root‑FS without modifying the original snapshot data.

### Configuring the Shim Restore

`buildRollbackRestoreConfig` constructs a JSON payload that guides the containerd shim through VM reconstruction:

- `SourceURL` – File path to the snapshot’s meta directory.
- `MemoryVolURL` – Device path of the memory volume.
- `Disks` – Updated disk specifications where `rollbackDisksFromSnapshotSpec` replaces the old root‑FS entry with the new generation’s device path.

### Executing the Atomic VM Swap

Before contacting the shim, `setSandboxRollingBack` sets an in‑memory flag on every container to signal that background scanners (such as DeadGC heartbeat monitors) should skip this sandbox, preventing race conditions during the swap.

`updateShimForRollback` transmits the restore configuration via containerd annotations:

```go
task.Update(ctx, containerd.WithAnnotations(map[string]string{
    shimUpdateActionAnnotation:          shimUpdateRollbackAction,
    shimUpdateRollbackRestoreAnnotation: restoreConfig,
}))

```

The shim internally executes **`delete_vm`** to remove the old VM, then **`resume_vm_with_config`** to start a new VM from the supplied root‑FS and memory volumes.

### Post‑Rollback Cleanup and Persistence

If the shim call succeeds, the temporary new root‑FS volume is retained (`cleanupNewRootfs = false`). Otherwise, deferred cleanup removes it. `resetSandboxStatusAfterRollback` clears any stale termination markers set by concurrent code paths during the swap, trusting the shim’s authoritative state transition.

`PersistSandboxRootfsAfterRollback` writes the new root‑FS volume name, kind, generation, and device path into the sandbox’s backend file, making the restored state permanent for subsequent operations.

The old root‑FS volume is then deleted via `storage.DeleteCowObject` on a best‑effort basis. If deletion fails, the rollback remains successful but notes the deferred cleanup in the response.

## Implementing Rollback in Your Code

### Go SDK Example

```go
import "github.com/tencentcloud/CubeSandbox/sdk/go"

func rollbackExample() error {
    client, _ := sdk.NewClient(&sdk.Config{
        // endpoint & auth configuration
    })
    req := &sdk.RollbackSandboxRequest{
        SandboxID:  "sandbox-123",
        SnapshotID: "snap-2024-07-01",
        NewGen:     5, // must be > current generation
    }
    rsp, err := client.RollbackSandbox(req)
    if err != nil {
        return err
    }
    fmt.Printf("Rollback succeeded, new rootfs: %s (gen %d)\n",
        rsp.RootfsVol, rsp.NewGen)
    return nil
}

```

*Source:* [`sdk/go/snapshot.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/snapshot.go)

### Command‑Line Interface

```bash

# Production rollback via cubecli

cubecli sandboxes rollback \
  --sandbox-id sb1 \
  --snapshot-id snapA \
  --new-gen 3

# Debug rollback with explicit volume overrides

cubecli cubebox debug-rollback \
  --sandbox-id sb1 \
  --snapshot-id snapA \
  --rootfs-vol tpl-snap-rootfs \
  --memory-vol tpl-snap-memory \
  --meta-dir /var/lib/cube/snapshots/snapA \
  --new-gen 3

```

*Source:* [`Cubelet/cmd/cubecli/commands/cubebox/debug_rollback.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/cmd/cubecli/commands/cubebox/debug_rollback.go)

### Python SDK Example

```python
from cubesandbox import CubeSandboxClient

client = CubeSandboxClient(endpoint="http://localhost:8080")
resp = client.rollback_sandbox(
    sandbox_id="sandbox-01",
    snapshot_id="snap-2024-07-01",
    new_gen=4
)
print("New rootfs:", resp.rootfs_vol, "gen:", resp.new_gen)

```

## Summary

- **CubeSandbox** implements rollback through the **cubecow** storage backend, creating a new COW generation from the snapshot root‑FS while preserving the original checkpoint.
- The process acquires per‑sandbox locks and sets rolling‑back flags to prevent race conditions with background processes like DeadGC.
- `RollbackDeriveNewGen` clones the snapshot into a new writable volume, while `updateShimForRollback` atomically swaps the VM via containerd shim annotations.
- Post‑rollback, `PersistSandboxRootfsAfterRollback` updates persistent metadata, and the old root‑FS is cleaned up on a best‑effort basis.
- All operations occur in‑process without external command execution, ensuring consistent restoration to any previous checkpoint.

## Frequently Asked Questions

### What storage backend is required for rollback to function?

The rollback feature requires the **cubecow** copy‑on‑write storage backend. The `validateRollbackSandboxRequest` function in [`Cubelet/services/cubebox/rollback.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/Cubelet/services/cubebox/rollback.go) explicitly checks `storage.IsCowBackend` and rejects requests if the sandbox uses incompatible storage drivers.

### How does CubeSandbox prevent race conditions during rollback?

The system uses a per‑sandbox mutex (`s.updateSandboxLocks.Lock`) to block concurrent modifications. Additionally, `setSandboxRollingBack` marks containers with an in‑memory flag that instructs background scanners like DeadGC to skip the sandbox while the shim destroys the old VM and resumes the new one.

### What happens to the original root‑FS volume after a successful rollback?

The original root‑FS is deleted via `storage.DeleteCowObject` on a best‑effort basis after the new volume is persisted. If deletion fails due to locks or I/O errors, the rollback still succeeds but defers cleanup, exposing the old volume name in the response’s `old_rootfs_vol` field.

### Can rollback target a sandbox that is not currently running?

No. The `validateRollbackSandboxRequest` function checks that the sandbox is in a running state. Rollback to a checkpoint requires an active cubebox instance because the operation involves swapping the running VM via the containerd shim rather than creating a fresh instance from scratch.