feat(operator): add OpenSandboxOperator lifecycle backend (Phase 1)#1203
Merged
Conversation
Phase 0 deliverables for adding OpenSandboxOperator as a Rock backend (方案 B: delegate lifecycle + exec/file ops to OpenSandbox via its Python SDK). refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds OpenSandboxConfig dataclass (endpoint/api_key/protocol/runtime/ namespace/use_server_proxy/default_timeout), wires it into RockConfig and RockConfig.from_env yaml parsing. Enables runtime.operator_type=opensandbox. refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements 方案 B Phase 1 (lifecycle seam) for using OpenSandbox as a Rock backend via its Python SDK: - OpenSandboxClient: async facade over opensandbox.Sandbox with lazy SDK import (optional 'opensandbox' extra) and exception translation. - OpenSandboxOperator(AbstractOperator): submit->create, stop->pause, restart->resume, delete->kill; state mapping and docker->k8s memory/cpu normalization; stores backend + opensandbox_id in extended_params. - OperatorFactory: dispatch operator_type=opensandbox; OperatorContext gains opensandbox_config; admin main wires rock_config.opensandbox. - pyproject: opensandbox optional extra. Verified client calls against the installed opensandbox==0.1.13 SDK signatures. refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The opensandbox backend delegates the full sandbox lifecycle to an external OpenSandbox service, so admin no longer needs a local Ray cluster to boot with operator_type=opensandbox. Adds operator_requires_ray() and gates RayService.init() on it; GemManager already tolerates ray_service=None and the lifecycle path dispatches through the operator. ray/k8s behavior unchanged. refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Real end-to-end run against a live OpenSandbox server surfaced this: get_state connected with the default health check, so a *paused* sandbox failed the check and blocked ~ready_timeout, making get_status report the sandbox as gone (None) instead of STOPPED. get_state/pause/kill only need a handle, so connect() now passes skip_health_check=True. Verified e2e: paused sandbox now reads STOPPED. refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
zpzjzj
force-pushed
the
feat/opensandbox-operator
branch
from
July 6, 2026 06:19
df637e8 to
ba709d1
Compare
zhongwen666
reviewed
Jul 7, 2026
zhongwen666
reviewed
Jul 7, 2026
Per review: only the ray operator needs a local Ray cluster; k8s and opensandbox both delegate the sandbox lifecycle to an external orchestrator, so admin boots without Ray for them too. Replaces the ray-free allowlist with a direct operator_type == 'ray' check. refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per review: the opensandbox operator runs inside the admin service (deployed as the admin cluster), so the SDK belongs in the admin extra rather than a separate optional group. Drops the standalone opensandbox group and its 'all' entry. refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jwx0925
reviewed
Jul 8, 2026
Per review: server-proxy mode is not supported on all OpenSandbox deployments, and False matches the SDK default. Only affects the execd (command/file) route (Phase 2); the lifecycle path talks to the server directly regardless. Enable explicitly in yaml when the target deployment supports it. refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Shows where the opensandbox operator backend is configured on the admin side (endpoint/api_key/protocol/use_server_proxy/...), sibling to ray:/k8s:. These are admin deployment config, not Harbor job parameters. refs alibaba#1202 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two issues surfaced by an end-to-end run against a real (Aone Sandbox) server
that a lenient local server hid:
1. Passing timeout=None explicitly sent a null duration the server rejects
("Provided duration string (nulls) is invalid"). Omit the timeout kwarg when
unset so the SDK default (sandbox TTL) applies.
2. create() blocked on the SDK readiness health check (default 30s), which
times out on a cold image pull or when the caller can't directly reach the
sandbox. Pass skip_health_check=True so create() returns the id immediately —
matching Rock's async lifecycle (submit -> PENDING, get_status polls RUNNING)
and Harbor's own OpenSandbox environment.
refs alibaba#1202
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
zhongwen666
reviewed
Jul 10, 2026
zhongwen666
approved these changes
Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Phase 1 of adding OpenSandbox as a Rock backend (方案 B: delegate both sandbox lifecycle and command/file execution to OpenSandbox via its official Python SDK). This PR delivers the lifecycle seam only; the proxy-layer exec/file seam is a follow-up PR.
refs #1202
Changes
OpenSandboxConfig(rock/config.py) — endpoint / api_key / protocol / runtime / namespace / use_server_proxy / default_timeout; wired intoRockConfigandfrom_envyaml parsing. Enablesruntime.operator_type=opensandbox.OpenSandboxClient(rock/sandbox/operator/opensandbox/client.py) — async facade overopensandbox.Sandboxwith lazy SDK import (optionalopensandboxextra) and exception translation to Rock errors.OpenSandboxOperator(rock/sandbox/operator/opensandbox/operator.py) — implementsAbstractOperator:submit → Sandbox.create,stop → pause,restart → resume,delete → kill(semantics locked in Phase 0).8g→8Gi) and cpu normalization.backend+opensandbox_idinSandboxInfo.extended_params.OperatorFactory— dispatchoperator_type=opensandbox;OperatorContextgainsopensandbox_config;admin/main.pywiresrock_config.opensandbox.pyproject.toml—opensandboxoptional extra (opensandbox>=0.1.13).Testing
tests/unit/sandbox/operator/ + tests/unit/test_config.py: 187 passed, no regressions.ruff checkclean.opensandbox==0.1.13SDK signatures (Sandbox.create/connect/resume/pause/kill,ConnectionConfigfields,info.status.state,sandbox.id) — not just mocks.Known limitation (tracked for follow-up)
submitdoes not yet forward container env vars toSandbox.create(env=None); Rock's runtime-env injection for the OpenSandbox backend is deferred to the Phase 2 exec/file seam. Documented indocs/plans/opensandbox-sdk-contract.md§5.Follow-up
Phase 2 (proxy exec/file seam: extract
SandboxRuntimeBackend, addOpenSandboxBackend, route byextended_params["backend"]) will land in a separate PR.🤖 Generated with Claude Code