Skip to content

[Feature] Support CPU/memory/disk resource updates on sandbox restart #1099

Description

@zhangjaycee

Feature Category

  • Sandbox
  • Actions
  • Deployments
  • SDK & API
  • Envhub
  • CLI
  • Performance & Optimization
  • Documentation & Examples

Problem Statement

When a sandbox is restarted via POST /restart or sandbox.restart(), it always reuses the original resource configuration (CPU, memory, disk) from the initial start() call. Users have no way to adjust resources on restart — for example, using a smaller spec during development and scaling up for production runs, increasing memory after hitting OOM, or expanding disk after running out of space.

ROCK does not expose any resource update capability through the restart API.

Proposed Solution

Add optional cpus, memory, and disk parameters to the restart path (Admin API → SandboxManager → StateMachine → DockerDeployment), and let the SDK always carry the current resource values via get_status():

  1. Admin APIPOST /restart accepts optional cpus, memory, disk in the request body
  2. SandboxManager — builds resource_overrides dict from non-None params
  3. StateMachine — merges overrides into the spec snapshot, persists updated spec to DB
  4. DockerDeployment — calls docker update --cpus --memory --memory-swap before docker start
  5. SDKrestart() takes no resource parameters; always calls get_status(include_all_states=True) to fetch current cpus/memory/disk and forwards them to the restart endpoint

Detailed Feature Description

Admin API

POST /restart
{
    "sandbox_id": "abc123",
    "cpus": 4,           // optional, omit to keep current
    "memory": "16g",     // optional, omit to keep current
    "disk": "50g"        // optional, omit to keep current
}

When resource params are provided, the server merges them into the DockerDeploymentConfig spec snapshot, persists the updated spec to the database, and applies the changes before docker start.

SDK Layer

Sandbox.restart() does not accept resource parameters directly. Instead it always fetches the current configuration from the server:

async def restart(self):
    status = await self.get_status(include_all_states=True)
    data = {
        "sandbox_id": self.sandbox_id,
        "cpus": status.cpus,
        "memory": status.memory,
        "disk": status.disk,
    }
    response = await HttpUtils.post(url, headers, data)

Design rationale: SandboxConfig has default values for cpus (2) and memory ("8g"), making it impossible to distinguish user-explicit values from defaults at the SDK layer. Forcing get_status() ensures the restart request always carries the actual server-side resource values, not stale or default config values. Users who need to change resources should use the Admin API directly.

Resource Update

Before docker start, the deployment layer applies resource changes:

  • cpus / memory: docker update --cpus --memory --memory-swap on the stopped container
  • disk: update XFS project quota for the log directory; rootfs quota via --storage-opt is set at docker run time and persisted in the spec snapshot for future container recreation

Spec Snapshot Persistence

When resource overrides are provided, the state machine:

  1. Merges overrides into DockerDeploymentConfig built from the DB spec snapshot
  2. Persists the updated spec to the database via meta_store.update()
  3. Updates flat fields (cpus, memory, disk) in SandboxInfo for get_status() consistency

This ensures that subsequent get_status() calls and future restarts reflect the most recently applied resources.

Call Chain

SDK  Sandbox.restart()
  → get_status(include_all_states=True)  # fetch current cpus/memory/disk
  → POST /restart {sandbox_id, cpus, memory, disk}
    → SandboxManager.restart_async(sandbox_id, cpus, memory, disk)
      → StateMachine.on_restart(resource_overrides={cpus, memory, disk})
        → merge overrides into DockerDeploymentConfig
        → meta_store.update()  # persist updated spec + flat fields
        → Operator.restart(config, host_ip)
          → Actor.restart()
            → DockerDeployment.restart()
              → docker update --cpus --memory
              → update log dir XFS quota (if disk changed)
              → docker start

Test Plan

Unit tests covering resource override behavior:

  • test_cpu_override_merges_into_config — cpus override applied to restart config passed to operator
  • test_memory_override_merges_into_config — memory override applied to restart config
  • test_disk_override_merges_into_config — disk override applied to restart config
  • test_no_overrides_uses_original_spec — without overrides, original spec values are preserved
  • test_overrides_update_spec_snapshot_in_meta_store — updated spec (cpus/memory/disk) persisted to DB via meta_store.update(), flat fields updated in SandboxInfo

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions