已合并
feat(e2b): add sandbox compatibility and golden snapshots #63
feat(e2b): add sandbox compatibility and golden snapshots #63
已合并
songminhui创建于 15 天前
共 231 个文件变更+25223-1017
M.buildkite/README.md+12-0文件内容审核中,请稍后刷新重试
M.buildkite/build-arm-package.sh+5-0文件内容审核中,请稍后刷新重试
M.buildkite/build-component.sh+10-3文件内容审核中,请稍后刷新重试
@@ -36,6 +36,9 @@ PYTHONPATH="$PWD/build${PYTHONPATH:+:$PYTHONPATH}" \
36echo "--- :test_tube: Release tooling tests"36echo "--- :test_tube: Release tooling tests"
37python3 -u -m unittest discover -s build/release/tests -v \37python3 -u -m unittest discover -s build/release/tests -v \
38 2>&1 | tee out/buildkite/logs/release-tests.log38 2>&1 | tee out/buildkite/logs/release-tests.log
39+echo "--- :test_tube: E2B tooling tests"
40+python3 -u -m unittest discover -s build/e2b -p 'test_*.py' -v \
41+ 2>&1 | tee out/buildkite/logs/e2b-tooling-tests.log
39echo "--- :rust: Rust guideline gate"42echo "--- :rust: Rust guideline gate"
40ADX_WITH_AFS="$ADX_WITH_AFS" ADX_AFS_ALL_FEATURES="$ADX_AFS_ALL_FEATURES" \43ADX_WITH_AFS="$ADX_WITH_AFS" ADX_AFS_ALL_FEATURES="$ADX_AFS_ALL_FEATURES" \
41 make rust-check JOBS="${JOBS:-4}" \44 make rust-check JOBS="${JOBS:-4}" \
MCargo.lock+2-0文件内容审核中,请稍后刷新重试
MREADME.md+2-0文件内容审核中,请稍后刷新重试
@@ -224,3 +224,5 @@ SDK 发布名为 `adx-environment`,Python 导入名为 `adx_environment`,CLI
224## 许可证224## 许可证
225 225 
226Agent DX 使用 [Apache License 2.0](LICENSE)。226Agent DX 使用 [Apache License 2.0](LICENSE)。
227+ 
228+实验性的 [E2B 兼容入口](docs/deployment/e2b-compatibility.md) 可显式启用管理协议适配、固定 envd、凭据路由和绝对运行期限;部署、支持范围与验证入口见该能力文档。
Mafs/src/meta/dfs/gc.rs+3-3文件内容审核中,请稍后刷新重试
Mafs/src/meta/dfs/gc_fence_tests.rs+1-6文件内容审核中,请稍后刷新重试
@@ -2,8 +2,6 @@
2 2 
3Agent 层使用 Rust,产品 API 嵌入统一 Gateway。Activator 可独立部署,也可与 API Server 和 Ingress 共进程;多个副本使用相同产品状态命名空间。3Agent 层使用 Rust,产品 API 嵌入统一 Gateway。Activator 可独立部署,也可与 API Server 和 Ingress 共进程;多个副本使用相同产品状态命名空间。
4 4 
5-面向开发与交付的讲解见 [Agent 统一能力与 Jiuwen 交付场景串讲](../docs/development/agent-jiuwen-walkthrough.zh.md),通过单机、多机和场景部署视图,先讲通用模型、激活与访问,再讲 digital-mate App 场景的账号、模型和共享工作区部署。
6- 
7| 目录 | 职责 |5| 目录 | 职责 |
8| --- | --- |6| --- | --- |
9| `crates/core` | 产品类型、协议、Environment 能力边界及通用校验 |7| `crates/core` | 产品类型、协议、Environment 能力边界及通用校验 |
Abuild/config/examples/e2b-runc-oci-spec.json+117-0文件内容审核中,请稍后刷新重试
Abuild/e2b/build_envd.py+93-0文件内容审核中,请稍后刷新重试
Abuild/e2b/checkpoint.py+583-0文件内容审核中,请稍后刷新重试
Abuild/e2b/smoke.py+291-0文件内容审核中,请稍后刷新重试
Abuild/e2b/test_build_envd.py+72-0文件内容审核中,请稍后刷新重试
Abuild/e2b/test_checkpoint.py+56-0文件内容审核中,请稍后刷新重试
Mbuild/e2e/firecracker/README.md+3-1文件内容审核中,请稍后刷新重试
Mbuild/e2e/tests/test_backend_cache.py+0-6文件内容审核中,请稍后刷新重试
Mbuild/e2e/tests/test_backend_obs.py+2-16文件内容审核中,请稍后刷新重试
@@ -1,5 +1,6 @@
1import importlib.util1import importlib.util
2import os2import os
3+import shutil
3import subprocess4import subprocess
4import tempfile5import tempfile
5import unittest6import unittest
@@ -8,9 +9,48 @@ from pathlib import Path
8import yaml9import yaml
9 10 
10ROOT = Path(__file__).resolve().parents[3]11ROOT = Path(__file__).resolve().parents[3]
12+BASH = shutil.which("bash")
11 13 
12 14 
13class IndependentPipelineTests(unittest.TestCase):15class IndependentPipelineTests(unittest.TestCase):
16+ def test_arm_execd_maps_optional_host_source_into_linux_container(self):
17+ with tempfile.TemporaryDirectory() as directory:
18+ root = Path(directory)
19+ shell_env = root / "shell-env"
20+ shell_env.write_text(
21+ 'uname() { echo arm64; }\n'
22+ 'git() { if [[ $1 == rev-parse ]]; then echo fixture-commit; fi; }\n'
23+ 'docker() { if [[ $1 == run ]]; then printf "%s\\n" "$@" > "$DOCKER_ARGS"; fi; }\n'
24+ )
25+ image = root / "build/images/build-environment-arm64.json"
26+ image.parent.mkdir(parents=True)
27+ image.write_text('{"ci_image":"fixture@sha256:abc"}')
28+ source = root / "source with spaces"
29+ source.mkdir()
30+ arguments = root / "docker-args"
31+ env = {key: value for key, value in os.environ.items() if not key.startswith(("ADX_", "BUILDKITE_"))}
32+ env.update(BASH_ENV=str(shell_env), BUILDKITE_COMMIT="fixture-commit",
33+ BUILDKITE_BUILD_ID="fixture-build", DOCKER_ARGS=str(arguments))
34+ for override in (None, source, root / "missing"):
35+ with self.subTest(override=override):
36+ arguments.unlink(missing_ok=True)
37+ child_env = dict(env)
38+ if override is not None:
39+ child_env["ADX_ENVD_SOURCE"] = str(override)
40+ result = subprocess.run([BASH, str(ROOT / ".buildkite/build-arm-package.sh"), "build", "execd"],
41+ cwd=root, env=child_env, capture_output=True, text=True)
42+ if override is not None and not override.exists():
43+ self.assertNotEqual(result.returncode, 0)
44+ self.assertFalse(arguments.exists())
45+ continue
46+ self.assertEqual(result.returncode, 0, result.stderr)
47+ args = arguments.read_text().splitlines()
48+ if override is None:
49+ self.assertFalse(any("ADX_ENVD_SOURCE=" in arg for arg in args))
50+ else:
51+ self.assertIn(str(source.resolve()) + ":/mnt/adx-envd-source:ro", args)
52+ self.assertIn("ADX_ENVD_SOURCE=/mnt/adx-envd-source", args)
53+ 
14 def test_product_pipelines_have_separate_configs_and_steps(self):54 def test_product_pipelines_have_separate_configs_and_steps(self):
15 package = (ROOT / ".buildkite/pipeline-package.yml").read_text()55 package = (ROOT / ".buildkite/pipeline-package.yml").read_text()
16 sdk = (ROOT / ".buildkite/pipeline-sdk.yml").read_text()56 sdk = (ROOT / ".buildkite/pipeline-sdk.yml").read_text()
@@ -150,7 +190,7 @@ class IndependentPipelineTests(unittest.TestCase):
150 if mode is not None:190 if mode is not None:
151 child_env["ADX_WITH_AFS"] = mode191 child_env["ADX_WITH_AFS"] = mode
152 result = subprocess.run(192 result = subprocess.run(
153- ["bash", str(ROOT / ".buildkite/package-e2e.sh")],193+ [BASH, str(ROOT / ".buildkite/package-e2e.sh")],
154 cwd=root,194 cwd=root,
155 env=child_env,195 env=child_env,
156 capture_output=True,196 capture_output=True,
Mbuild/e2e/tests/test_firecracker_driver.py+99-24文件内容审核中,请稍后刷新重试
Mbuild/e2e/tests/test_pipeline_contracts.py+51-24文件内容审核中,请稍后刷新重试
Mbuild/e2e/tests/test_release_handoff.py+3-1文件内容审核中,请稍后刷新重试
@@ -55,7 +55,13 @@ if [[ "$host" == *-linux-gnu ]]; then
55 echo "--- :package: Static EXECD and local EROFS runtime"55 echo "--- :package: Static EXECD and local EROFS runtime"
56 cargo build --locked --release --target "$musl_target" -j "$JOBS" -p adx-execd --bin adx-execd56 cargo build --locked --release --target "$musl_target" -j "$JOBS" -p adx-execd --bin adx-execd
57 cp "$CARGO_TARGET_DIR/$musl_target/release/adx-execd" "$stage/adx-execd"57 cp "$CARGO_TARGET_DIR/$musl_target/release/adx-execd" "$stage/adx-execd"
58- "$PYTHON" build/runtime/rootfs.py --binary "$stage/adx-execd" --output "$stage/adx-runtime-rootfs.img"58+ rootfs_args=(--binary "$stage/adx-execd" --output "$stage/adx-runtime-rootfs.img")
59+ if [[ -n "${ADX_ENVD_SOURCE:-}" ]]; then
60+ echo "--- :package: Build optional pinned envd"
61+ "$PYTHON" build/e2b/build_envd.py --source "$ADX_ENVD_SOURCE" --output "$stage/envd" --jobs "$JOBS"
62+ rootfs_args+=(--envd-binary "$stage/envd/envd")
63+ fi
64+ "$PYTHON" build/runtime/rootfs.py "${rootfs_args[@]}"
59fi65fi
60echo "--- :python: Build Environment SDK wheel"66echo "--- :python: Build Environment SDK wheel"
61PYTHON="$PYTHON" bash platform/sdk/environment/python/build.sh "$stage/sdk"67PYTHON="$PYTHON" bash platform/sdk/environment/python/build.sh "$stage/sdk"
@@ -31,6 +31,17 @@ REQUIRED_FILES = {
31 "execd": {"adx-execd", "adx-runtime-rootfs.img"},31 "execd": {"adx-execd", "adx-runtime-rootfs.img"},
32 "afs": {"afs-meta", "afs-node"},32 "afs": {"afs-meta", "afs-node"},
33}33}
34+OPTIONAL_FILE_SETS = {
35+ "execd": {"envd-LICENSE", "envd-manifest.json"},
36+}
37+ 
38+ 
39+def valid_files(component, files):
40+ required = REQUIRED_FILES[component]
41+ optional = OPTIONAL_FILE_SETS.get(component, set())
42+ return required.issubset(files) and files.issubset(required | optional) and (
43+ not (files & optional) or optional.issubset(files)
44+ )
34 45 
35 46 
36def sha256(path):47def sha256(path):
@@ -66,7 +77,7 @@ def create_manifest(component, directory, commit, target):
66 _identity(commit, target)77 _identity(commit, target)
67 directory = Path(directory)78 directory = Path(directory)
68 files = _regular_files(directory)79 files = _regular_files(directory)
69- if set(files) != REQUIRED_FILES[component]:80+ if not valid_files(component, set(files)):
70 raise ValueError("component artifact file set is incomplete or unexpected")81 raise ValueError("component artifact file set is incomplete or unexpected")
71 manifest = {82 manifest = {
72 "schema_version": 1,83 "schema_version": 1,
@@ -94,7 +105,7 @@ def verify_manifest(directory, component=None, commit=None, target=None):
94 raise ValueError("component commit mismatch")105 raise ValueError("component commit mismatch")
95 if target is not None and manifest["target"] != target:106 if target is not None and manifest["target"] != target:
96 raise ValueError("component target mismatch")107 raise ValueError("component target mismatch")
97- if set(manifest.get("files", {})) != REQUIRED_FILES[manifest["component"]]:108+ if not valid_files(manifest["component"], set(manifest.get("files", {}))):
98 raise ValueError("component artifact file set is incomplete or unexpected")109 raise ValueError("component artifact file set is incomplete or unexpected")
99 if manifest.get("files") != _regular_files(directory):110 if manifest.get("files") != _regular_files(directory):
100 raise ValueError("component artifact integrity check failed")111 raise ValueError("component artifact integrity check failed")
@@ -193,7 +204,7 @@ def verify_build_manifest(
193 if set(manifest.get("components", {})) != expected_components:204 if set(manifest.get("components", {})) != expected_components:
194 raise ValueError("build manifest component set is incomplete")205 raise ValueError("build manifest component set is incomplete")
195 for name, record in manifest["components"].items():206 for name, record in manifest["components"].items():
196- if set(record.get("files", {})) != REQUIRED_FILES[name]:207+ if not valid_files(name, set(record.get("files", {}))):
197 raise ValueError(f"{name} component file set is incomplete")208 raise ValueError(f"{name} component file set is incomplete")
198 digest = record.get("manifest_sha256", "")209 digest = record.get("manifest_sha256", "")
199 if len(digest) != 64 or any(character not in "0123456789abcdef" for character in digest):210 if len(digest) != 64 or any(character not in "0123456789abcdef" for character in digest):
Mbuild/release/package.py+28-2文件内容审核中,请稍后刷新重试
@@ -26,6 +26,10 @@ AFS_REQUIRED_FILES = {
26 "third_party/afs-source/LICENSE",26 "third_party/afs-source/LICENSE",
27 "third_party/afs-source/NOTICE",27 "third_party/afs-source/NOTICE",
28}28}
29+ENVD_PROVENANCE_FILES = {
30+ "runtime/envd/manifest.json",
31+ "runtime/envd/LICENSE",
32+}
29 33 
30 34 
31def sha256(path: Path) -> str:35def sha256(path: Path) -> str:
@@ -57,6 +61,9 @@ def verify(directory: Path, *, enforce_host_architecture: bool = False) -> dict:
57 target = manifest.get("target", "")61 target = manifest.get("target", "")
58 if manifest.get("profile") == "release" and "linux" in target:62 if manifest.get("profile") == "release" and "linux" in target:
59 required.add("runtime/adx-runtime-rootfs.img")63 required.add("runtime/adx-runtime-rootfs.img")
64+ envd_artifacts = expected & ENVD_PROVENANCE_FILES
65+ if envd_artifacts and envd_artifacts != ENVD_PROVENANCE_FILES:
66+ raise ValueError("incomplete envd provenance")
60 afs_artifacts = {f"bin/{binary}" for binary in AFS_BINARIES} & expected67 afs_artifacts = {f"bin/{binary}" for binary in AFS_BINARIES} & expected
61 afs_artifacts.update(path for path in expected if path.startswith("etc/examples/afs/"))68 afs_artifacts.update(path for path in expected if path.startswith("etc/examples/afs/"))
62 afs_artifacts.update(path for path in expected if path.startswith("third_party/afs-source/"))69 afs_artifacts.update(path for path in expected if path.startswith("third_party/afs-source/"))
@@ -38,6 +38,25 @@ class ComponentManifestTests(unittest.TestCase):
38 with self.assertRaises(ValueError):38 with self.assertRaises(ValueError):
39 component.create_manifest("gateway", root, "a" * 40, "x86_64-unknown-linux-gnu")39 component.create_manifest("gateway", root, "a" * 40, "x86_64-unknown-linux-gnu")
40 40 
41+ def test_execd_component_accepts_complete_optional_envd_provenance(self):
42+ with tempfile.TemporaryDirectory() as temporary:
43+ root = Path(temporary)
44+ for filename in component.REQUIRED_FILES["execd"]:
45+ (root / filename).write_text(filename)
46+ for filename in component.OPTIONAL_FILE_SETS["execd"]:
47+ (root / filename).write_text(filename)
48+ manifest = component.create_manifest(
49+ "execd", root, "a" * 40, "x86_64-unknown-linux-gnu"
50+ )
51+ self.assertEqual(
52+ set(manifest["files"]),
53+ component.REQUIRED_FILES["execd"] | component.OPTIONAL_FILE_SETS["execd"],
54+ )
55+ component.verify_manifest(root)
56+ (root / "envd-LICENSE").unlink()
57+ with self.assertRaises(ValueError):
58+ component.verify_manifest(root)
59+ 
41 @staticmethod60 @staticmethod
42 def write_component(root, name):61 def write_component(root, name):
43 directory = root / name62 directory = root / name
Mbuild/release/tests/test_package.py+52-0文件内容审核中,请稍后刷新重试
Mbuild/runtime/rootfs.py+71-7文件内容审核中,请稍后刷新重试
Mdocs/architecture/repository-layout.html+21-13文件内容可能有违规信息
Mdocs/architecture/repository-layout.md+19-3文件内容可能有违规信息
@@ -0,0 +1,261 @@
1+# E2B 兼容(实验版)
2+ 
3+ADX 在原生 Environment 生命周期上提供 E2B SDK 兼容入口。控制面适配管理协议,数据面经 Ingress/Relay 到 guest envd;Coordinator 负责调度,owner adxlet 负责运行计时和生命周期,Execd 管理固定上游 envd。本文说明部署配置、接口合同、能力边界和验证方法。
4+ 
5+## 支持范围
6+ 
7+| 能力 | 当前合同 |
8+| --- | --- |
9+| 创建 | `POST /sandboxes`、`POST /v2/sandboxes` 共用处理;解析平台模板的 Ready build 或本租户 E2B snapshot,等待配置服务就绪 |
10+| 查询与列表 | `GET /sandboxes/{id}` 返回状态、时间及凭据;`GET /v2/sandboxes` 支持 state/metadata/limit/nextToken,返回原始数组和 `X-Next-Token`;旧根路径 GET 列表未接入 |
11+| 模板 alias | 裸 alias 查询本租户已注册名称,返回实际 templateID;仅 default selector 解析 latest-success,custom tag 明确拒绝。平台只保存 current 与 latest-success |
12+| 删除与续期 | `DELETE /sandboxes/{id}` 复用原生删除;`POST /sandboxes/{id}/timeout` 设置从当前时刻计算的期限,0 表示立即到期 |
13+| Connect | `POST /v2/sandboxes/{id}/connect` 对运行态续期,对暂停态恢复;timeout 默认 300 秒,可取 1~86400 秒 |
14+| Pause/Snapshot | `POST /sandboxes/{id}/pause`、`POST /sandboxes/{id}/snapshots` 支持内存模式;memory 省略或 true,false 明确拒绝;实际能力取决于 backend/checkpoint storage |
15+| Snapshot 查询/删除 | `GET /snapshots` 查询 Regular;`DELETE /templates/{id}` 先解析平台模板并逻辑删除绑定,有引用时拒绝;普通运行态 snapshot ID 保留原生删除路径 |
16+| 数据面 | commands、files、PTY 和应用端口经共享网关转发;网关鉴权模式增加 SDK 签名文件 URL,见下文配置与限制 |
17+| Key 管理 | `POST/GET /api-keys`、`DELETE /api-keys/{uuid}` 复用原生凭据服务,具体认证差异见下文 |
18+| 出站网络 | 创建和 `PUT /sandboxes/{id}/network` 支持 IPv4/CIDR 策略;真实效果依赖可执行 ACL 的后端 |
19+ 
20+E2B 错误使用原始 JSON `{code, message, error_code?}`,不使用 ADX data envelope。不支持能力返回明确错误;例如检查点后端不支持时为 400 / `capability_not_supported`,不按错误文本推断。
21+ 
22+模板准备仅接入 fromImage;RUN/COPY/fromTemplate/startCmd/readyCmd、私有镜像凭据、完整日志和缓存优化暂不支持,启动前明确返回 capability_not_supported。Code Interpreter、完整 Desktop/computer-use、IAM/卷/MCP、自动恢复、磁盘暂停及高级网络未接入。实验版不声明完整 E2B API/生态兼容。
23+ 
24+## 构建与配置
25+ 
26+1. Buildkite 的两种架构 Execd 组件默认在 Linux 构建器内拉取 `third_party/e2b/source.json` 固定的 infra revision,校验源码摘要后编译 envd;失败即中止构建。可用 `ADX_ENVD_SOURCE` 指定同一固定版本的干净 checkout;ARM 封装会将宿主目录只读挂入容器并转换路径。独立 `build/release/build.sh` 仍需设置此变量才编译 envd。rootfs 包含固定 envd、bash/动态库和默认 user;发布包保存 envd LICENSE、manifest 和摘要。
27+2. sandboxd 使用 [固定上游 revision](../../third_party/sandboxd/source.json)。当前 AMD64 后端二进制包要求 glibc ≥ 2.34;Firecracker 的递归 virtiofs 挂载保护依赖 `mount_setattr`(Linux 5.12+ 或具有相应回移的内核),仅存在 `/dev/kvm` 不足以证明宿主可用。[后端构建器](../../build/e2e/build_backend.py) 校验来源和工件摘要;Firecracker host/initrd 与 backend 使用配套的同源工件,详见 [kit 说明](../../build/e2e/firecracker/README.md)。不承诺不匹配的工件和快照之间兼容。
28+3. 使用 fromImage 在本租户登记名称并准备 Golden Snapshot;已有快照可直接按 snapshotId 创建。E2B 配置不保存第二份模板目录,也不依赖 Agent Template、Activator 或 ADX_AGENT_CONFIG。准备流程复用 Coordinator 与现有 worker,需要支持真实 Snapshot 的运行后端。
29+4. API Server 与 worker 配置相同可信 RuntimeProfile,worker 标签匹配 requiredNodeLabels。标签不安装 profile;当前每个 worker deployment 只有一个 profile。
30+ 
31+API Server `config` 示例使用支持内存 Snapshot 的 Firecracker 后端(替换域名、路径、实际 Relay 来源和工件摘要):
32+ 
33+```json
34+{
35+ "runtime_profile": {
36+ "rootfs": {"runtime_class": "firecracker", "type": "local", "path": "/opt/adx/e2b-v1/runtime/adx-runtime-rootfs.img", "readonly": false},
37+ "bootstrap": {"type": "erofs", "root": "/opt/adx/e2b-v1/runtime/adx-runtime-rootfs.img", "target": "/__adx", "entrypoint": ["/__adx/usr/local/bin/adx-execd"]},
38+ "env": {"ADX_ENVD_PATH": "/__adx/usr/local/bin/envd", "ADX_ENVD_SHA256": "REPLACE_WITH_BUILT_ENVD_SHA256", "ADX_ENVD_DEFAULT_USER": "user", "ADX_ENVD_DEFAULT_WORKDIR": "/home/user"}
39+ },
40+ "e2b": {
41+ "domain": "sandbox.example.com",
42+ "envdVersion": "0.9.0",
43+ "envdIngressSources": ["10.42.0.1"],
44+ "requiredNodeLabels": {"adx.runtime.profile": "e2b-v1"}
45+ }
46+}
47+```
48+ 
49+OCI 镜像提供用户 rootfs,可信 bootstrap 只读挂到 `/__adx`。fromImage 直接复用原生后端的镜像解析、拉取、缓存和 Env 继承,不在 Coordinator 另建 registry 客户端;需要固定镜像内容时传入 `@sha256:...` 引用,可变 tag 的重新解析沿用原生 ADX 行为。不执行 ENTRYPOINT/CMD,也不自动继承 OCI USER/WORKDIR。默认用户和目录来自可信 envd profile(user、/home/user);缺用户时 Execd 使用镜像 useradd 创建。镜像须提供 bash、envd 动态依赖以及已有用户或 useradd。快照中的资源、执行配置及服务配置随产物固定。envVars 允许覆盖普通变量,不能覆盖 `ADX_`/`EXECD_` 控制键。Firecracker 使用对应 runtime class;网关鉴权模式由 Execd 追加 `--isnotfc`,跳过 envd 的 MMDS 集成,保留 VM 隔离和 cgroup。
50+ 
51+容器部署时,将 sandboxd 状态目录放在支持 OverlayFS upper/work 的独立状态卷上,例如 ext4;容器镜像自身的 overlay 层不能作为该路径的 upperdir。状态卷可挂载到短路径,再配置 `rootDir`、`storeDir` 等目录,为 runsc 动态生成的 Unix socket 路径预留长度。
52+ 
53+envd 容器 worker 使用包内 [OCI 基线](../../build/config/examples/e2b-runc-oci-spec.json):在固定默认基线上增加 `CAP_SETUID`、`CAP_SETGID`、`CAP_CHOWN`、`CAP_DAC_OVERRIDE`、`CAP_FOWNER`,供用户切换、文件归属和 root chmod user 上传文件;`oomScoreAdj=0` 允许 envd 将命令分数调整为 100,不增加 `CAP_SYS_RESOURCE`。原生 worker 保留原基线;当前 E2B 网关鉴权入口仅接受 runsc、firecracker 和 firecracker-pvm,不支持 runc。
54+ 
55+```toml
56+[plugin.runtime.basic_spec]
57+runc = "/opt/adx/current/etc/examples/e2b-runc-oci-spec.json"
58+# runsc worker 使用相同基线:
59+# runsc = "/opt/adx/current/etc/examples/e2b-runc-oci-spec.json"
60+```
61+ 
62+核查实际 OCI bundle 采用该配置;sandboxd 旧加载器读取失败会回退默认值。修改基线后,在无活动沙箱的隔离 worker 重启 sandboxd、创建新沙箱,旧容器不会自动取得权限。sticky `/tmp` 的 user 文件覆盖可能受 Linux protected_regular 限制,优先使用 `/home/user` 或非 sticky 子目录。
63+ 
64+Ingress 设置 `ADX_DATA_PLANE_INGRESS_E2B_ENABLED=true`、`ADX_DATA_PLANE_INGRESS_PORT_HOST_DOMAIN=sandbox.example.com`,配置正式 HTTPS 证书、源地址 ACL、API Server 和 Relay 目标 CIDR;独立/内嵌模式共用入口实现。升级配套使用同版 Coordinator、adxlet、API Server、Ingress 和对应工件,所有相关节点升级完成后再开启 E2B;旧节点不识别新增的 envd/run_policy 字段,不能承担该配置的执行。
65+ 
66+从 master `54efe5a` 存量前向升级的删除回执合同为:保留原有 600 秒有效期,旧回执仅允许 Environment ID、generation 和完整结果摘要相同、且未提交新增 cleanup artifacts 的删除重放;空 artifact scope 不改变旧结果的序列化字节。升级验收须覆盖旧格式 Redis/节点 journal、双版本进程切换、存量实例访问和生命周期,以及 AKernel 集成,不能以数据 fixture 回归代替完整升级验收。此前未发布 PR 的中间 schema 不提供迁移;新增 E2B 能力不得在旧节点混部期间启用。
67+ 
68+上述存量前向升级先更新 Coordinator,再更新 API Server 和 Ingress;旧 owner 在此阶段继续处理既有原生实例,新增 E2B 能力仍须等待相关节点全部升级后开启。控制面切换期间的请求和长连接可用性取决于副本及切换部署,不能由 guest 持续运行推导为入口零中断。
69+ 
70+节点或后端的计划升级先停止新分配,对需要保留的 Running 实例执行 Pause,确认权威 Paused 状态、恢复点可用、待补交结果已确认及活动 Runtime 已停止;其余实例迁移或删除,完成排空后再退出和升级。adxlet 收到 SIGTERM 会执行 planned unregister,使旧 owner 会话失效,不适用 crash 后未过期会话的进程接管条件。新节点注册并完成对账后,通过 Connect 恢复原 Paused 身份,必要时沿原生恢复调度重新分配。恢复节点须提供与原 Spec 一致的受信任 profile/bootstrap,并保留仍被引用的检查点和旧工件;停止控制面使 unregister 失败不属于计划滚动升级流程。
71+ 
72+回退 master 也需要单独验证:新 Snapshot 写入的 kind/created_at_unix_ms 字段会被旧版的严格反序列化拒绝。升级前验证备份与恢复方案;出现问题时按已验证的恢复流程或前向修复处理,不直接回退二进制并假定持久化数据兼容。
73+ 
74+## Python SDK 用法
75+ 
76+使用原版 `e2b==2.52.0`,在进程环境设置 ADX 的 `E2B_API_URL`、`E2B_SANDBOX_URL` 和本租户 API Key。SDK 不要求 Key 必须使用 `e2b_` 前缀;使用 ADX 正式发放的凭据。`template_id` 为本租户已 Ready 的模板 ID,其他服务的模板 ID 不会自动导入 ADX。
77+ 
78+```python
79+from e2b import Sandbox, SandboxQuery, SandboxState
80+ 
81+sandbox = Sandbox.create(template_id)
82+try:
83+ running = Sandbox.list(limit=20, query=SandboxQuery(state=[SandboxState.RUNNING]))
84+ print(running.next_items())
85+ print(sandbox.commands.run("echo hello world").stdout, end="")
86+ sandbox.beta_pause() # SDK 2.52.0 中为 pause() 的兼容别名。
87+finally:
88+ sandbox.kill()
89+```
90+ 
91+两个 URL 可使用同一入口。固定 `E2B_SANDBOX_URL` 时 SDK 通过 `E2b-Sandbox-Id`、`E2b-Sandbox-Port` 和访问凭据路由 envd。若入口为 `https://sandbox.example.com/agentenv`,部署层反向代理必须对管理及数据面请求统一剥离 `/agentenv` 后转发到 ADX 根路径,同时保留路由头、WebSocket 和流式响应;直连根路径不需要改写。ADX 不增加 E2B 专用前缀分派。
92+ 
93+SDK 2.52.0 生成独立文件签名 URL 时使用根路径 `/files`,会丢弃固定入口中的路径前缀,也不会在 URL 中加入沙箱路由头。因此上述固定入口适用于普通命令、文件和 PTY 调用;直接使用 SDK 生成的独立签名 URL,需要标准的逐沙箱 Host/DNS 地址与对应 TLS 配置。不能仅凭固定入口的普通文件读写通过,就认定独立签名 URL 可用。
94+ 
95+## 镜像准备与 Golden Snapshot
96+ 
97+实验模板入口采用下述固定协议;功能互通不代表完整 E2B 兼容,恢复后的时钟和网络行为仍需按部署后端单独验收。
98+ 
99+```text
100+SDK 注册名称 → 平台登记 preparation → SDK 提交 fromImage
101+ → Coordinator 复用原生创建 → sandboxd 拉镜像并继承 Env → seed 配置服务 Ready
102+ → 原生 Snapshot(kind=golden) → 删除 seed → Ready
103+Sandbox.create(templateID[:tag]) → Ready snapshotId → 原生从快照创建
104+```
105+ 
106+`POST /v3/templates` 返回稳定名称绑定的 templateID 和新的 buildID;同名仅保存 current preparation 与 latest-success 指针,current 尚未终态或清理未完成时返回 busy,串行准备;`POST /v2/templates/{templateID}/builds/{buildID}` 仅启动 waiting 构建,重复启动返回参数错误。状态使用 `GET /templates/{templateID}/builds/{buildID}/status` 查询。SDK 可使用 `Template().from_image("python:3.11")` 与 `Template.build(..., name="base")`;镜像须符合后端架构和依赖要求。仅接入公开 OCI registry 的匿名拉取。
107+ 
108+只接受省略 tags、空 tags 或 default;custom tag 明确返回 capability_not_supported。名称/templateID 的创建解析只选择 latest-success;新准备失败不遮住该结果。不保存任意 build 历史:仅 current 和 latest-success 可查询,更早的 buildID 返回 404。`GET /v2/templates` 明确不支持,不提供家族目录分页或兼容占位;Golden 使用原生 Snapshot 列表。
109+ 
110+平台 Snapshot 增加 `kind=regular/golden` 和 `createdAt`。原生 `GET /api/environment/v1/snapshots?kind=golden` 列出本租户 Ready Golden,通过同一个 snapshotId 创建入口使用;Regular 克隆不变。公共目录解绑可由调用方显式要求无使用者;E2B 删除入口启用此限制。模板逻辑删除不自动删除独立 Golden,也不保证取消正在执行的构建;快照实体继续使用原生删除和 GC。
111+ 
112+公共 RPC 返回真实准备阶段、资源、ID 和快照可用性;E2B waiting/building/ready/error 只在适配层转换。E2B 冒号后缀仅接受 default,buildID 用于 current/latest-success 状态查询,固定产物可直接使用 snapshotID。
113+ 
114+准备状态、输入和确定的 seed/operation/snapshot 身份持久化在平台。Coordinator 接管已登记任务并清理失败 seed;结果未知先查询既有操作,不换 ID 重拍。恢复扫描跳过正在执行的 build,并使用原生恢复同样的有界并发;不新增任务引擎。终态且清理完成后释放完整执行规格,Ready 摘要从原生 Snapshot 读取;删除目录的全部待办完成后按 epoch/CAS 回收墓碑,不删除独立 Golden。组件重启可重试已知阶段,不承诺任意构建断点精确恢复。缺少镜像 useradd 或 bash/动态依赖时明确失败,不提供完整上游 sudo 环境。
115+ 
116+## 请求路径与鉴权
117+ 
118+```mermaid
119+flowchart LR
120+ SDK[E2B SDK] -->|管理 HTTPS / X-API-Key| I[Ingress]
121+ I --> A[API Server E2B adapter]
122+ A -->|登记 / 启动 fromImage 构建| C[Coordinator / Redis]
123+ C -->|准备镜像 / seed / 拍快照| G[平台 Golden Snapshot]
124+ A -->|templateID 解析为 snapshotID / 创建| C
125+ C --> N[adxlet]
126+ N --> S[sandboxd]
127+ S --> X[guest Execd]
128+ X --> E[envd :49983]
129+ SDK -->|commands / files / PTY / 应用| I
130+ I -->|路由与授权| R[Relay]
131+ R --> E
132+ R --> APP[guest 应用端口]
133+```
134+ 
135+管理请求实时验证 `X-API-Key`,不复用 API Server 成功认证缓存。创建/恢复须等待 Execd、envd `/init`、实际版本和鉴权探测完成才发布路由;版本取 `/init` 的 `X-Envd-Version`,不是 `/health`。E2B 运行期持续检查 envd,退出/探测失败触发 Failed、路由撤销和清理。
136+ 
137+仅启用 E2B 时解析数据面 `<port>-<sandboxID>.<domain>` 或 `E2b-Sandbox-Id`/`E2b-Sandbox-Port`,两者同时提供须一致。Host 同时满足原生 `<environmentID>-<port>` 格式时默认选原生目标,仍执行该目标已发布的策略;原生失败不会回退到 E2B。数字后缀 sandbox ID 导致格式重叠时,选择 E2B 目标须同时提供与 E2B Host 一致的两个转发头。SDK 使用 `X-Access-Token`,网关鉴权模式校验后剥离;私有应用使用 `E2b-Traffic-Access-Token`;`/init`、Execd 50090 及控制端口不对 E2B 数据面开放。每次创建/clone 生成独立 envd 和 traffic 凭据。
138+ 
139+策略跟随目标路由:启用 E2B 策略的沙箱通过 E2B 地址、原生地址和统一端口路径执行同一授权及凭据清理,拒绝无法检查内部 HTTP 路径的通用 CONNECT/L4 隧道。原生 `/direct/{id}/...` 仍要求原生认证及同租户;普通原生路由保持公开端口匿名、私有端口使用原生平台 Token 的合同。Gateway 只校验凭据、服务就绪和当前执行身份;暂停、删除或迁移通过既有路由撤销结束转发。运行期限由 owner 节点计时,路由不携带运行 deadline/控制版本,Gateway 不按绝对时间准入或为流设置 expiry guard。
140+ 
141+## 网关鉴权
142+ 
143+启用 E2B 兼容入口即使用 Gateway 鉴权,无独立 `gatewayEnvdAuth` 开关。旧配置中的该字段会因未知字段校验在启动时拒绝,升级时必须移除;不提供 legacy alias。原生 envd 服务配置仍可显式使用 guest-token 模式。该入口须使用 ACL 后端和当前鉴权模式产生的快照。配置片段如下,地址须替换为实际观测且验证过的同节点 Relay 来源,通常为 sandbox bridge IP:
144+ 
145+```json
146+{
147+ "e2b": {
148+ "envdIngressSources": ["10.42.0.1"]
149+ }
150+}
151+```
152+ 
153+上述片段合并进前面的 e2b 配置;runtime profile 选择 runsc 或 Firecracker,并在 sandboxd 开启 `enable_network_acl`。runc 不支持该 ACL,不能启用无 token 模式。API Server 不接受空来源、通配来源、CIDR、未指定或组播地址;不要将 guest 可借 SNAT 取得的出口 IP 当作可信 Relay 来源。必须在真实部署验证 Relay 实际源 IP、同节点及跨节点 guest 流量,配置语法通过不构成隔离验收。
154+ 
155+构造与最终校验共用 `adx_core::envd` 的端口、优先级和规则匹配小函数;原生 create、clone、update、start 仍分别执行必要校验。平台为 guest envd TCP 49983 添加优先级 `UINT32_MAX-2` 的入站拒绝,再以 `UINT32_MAX-1` 允许精确可信来源。其余应用端口保留原策略;不能将 49983 声明为公开端口或 tunnel HTTP 端口。动态 E2B 出站更新保留入站保护;原生网络策略替换若缺失或覆盖保护规则,节点在调用 backend 前拒绝。节点按公共 protected_ingress 执行校验;具体 envd 配置由服务边界校验。普通 L4/CONNECT 转发拒绝 private_service_ports,仅经协议策略授权的 HTTP 路径可访问。backend 在 ACL 不可用时拒绝 Start;检查点与恢复复用其网络生命周期。启用前须同步升级 API Server、Coordinator、Ingress/Relay、adxlet 和 Execd,不能用旧网关验证新模式的端口保护。
156+ 
157+```text
158+SDK token / 文件签名 → TLS Ingress:路由、执行身份、凭据及控制路径检查
159+ → 剥离 SDK token 和已验证的文件签名
160+ → Relay → envd(不设置 token)
161+其他 guest / 外部直连 → backend 入站 ACL → 拒绝 envd 端口
162+同 guest 程序 → envd → 允许(接受的权限降级)
163+```
164+ 
165+SDK token 和 traffic token 继续逐沙箱独立生成、持久化及返回。Execd 通过受控 `ADX_ENVD_GATEWAY_AUTH=true` 识别新模式,省略 `/init.accessToken`,保留 freeze、unfreeze、恢复 init 与联合就绪。`EnvironmentSpec.envd.gateway_auth` 和可信来源随实例/快照保存;旧快照携带的 envd token 不能假设已消失,API 明确拒绝旧模式快照克隆(409),Execd 拒绝恢复时切换鉴权模式。
166+ 
167+签名仅授权 `/files` 的 GET 下载或 POST 上传。网关从仅允许 Ingress 身份订阅的 Coordinator RouteService 获取 SDK 原 token 作为签名材料,校验与路由 token 哈希一致;Debug 隐藏原文。使用上游 v1 的 SHA-256 拼接和标准无 padding Base64,绑定文件 path、read/write、username 和可选到期秒数;重复参数、过期、篡改、其他沙箱 key 和操作不匹配均拒绝。携带错误的 SDK header 不会回退到签名。无到期参数沿 SDK 合同允许,但仍受签名自身到期校验和沙箱路由撤销约束;它不是一次性 URL。旧模式不新增签名 URL 能力。
168+ 
169+接受的降级仅说明平台不依靠 envd token 限制同 guest 的进程:它们可能调用 root 文件/命令能力以及 init/freeze 等控制接口。guest 所有者发布的应用若主动转发本地 envd,相当于其应用对外委托这项能力;平台无法一边允许该内部调用,一边阻止所有自建代理。跨沙箱直连不属于这一豁免,必须由入站隔离证明。代码/组件测试不能代替部署隔离和真实 checkpoint/restore/clone 验收。
170+ 
171+## Metadata、期限与检查点
172+ 
173+E2B metadata 直接映射到原生 `EnvironmentSpec.scheduling.labels`,不另设 metadata 模型、持久字段或创建/发布副本。它对原生调度选择可见,随 Snapshot 执行规格继承;创建请求的 metadata 覆盖继承 labels 的同名项。详情和列表从 labels 投影 metadata,多键筛选转为原生 LabelSelector 的 match_labels。创建、claim、local-first 和请求重放沿用原生 spec/operation/winner 规则,不保留 metadata 专属冲突规则,也不写入 guest env。
174+ 
175+E2B 入口保留最多 128 项、键 256 bytes、值 4096 bytes、总计 64KiB 的响应大小约束;内部执行继续使用原生 labels 校验。列表复用 `EnvironmentDirectory::page`,tenant、E2B 范围、state 和 labels 在分页前过滤,目录未同步时明确失败。每页 1~100、响应约 1MiB,游标绑定 tenant/范围/state/selector。时间字段按页通过公共 `BatchGetEnvironmentControl` 批量查询,列表专用 summary 直接投影所需字段;不逐条查询 control,不构造含 token 的详情后再删除凭据。实时目录分页不保证历史快照一致性。
176+ 
177+可选 `EnvironmentSpec.run_policy` 保存默认运行时长与 Pause/Delete 动作;当前 E2B 入口填写它,原生公共 HTTP 暂不开放,未配置的原生实例无额外期限。当前 owner adxlet 在首次 Running 或恢复接管时建立单调时钟 timer。进程 crash 后,仅在旧会话未过期且未退役、相同节点 ID 与 RPC/Relay 地址通过原生身份校验并成功接管现存 Runtime 时,才按 Spec 默认时长重建 timer;先前的动态续期不跨进程保存。SIGTERM 计划退役不适用该接管条件,节点计划升级须先 Pause 或排空。频繁更新不持久化绝对 deadline。Connect 只延长至 `max(当前截止, now + timeout)`;setTimeout 替换为 `now + timeout`,0 表示立即到期,均由 owner 接受后返回。owner 串行处理续期和到期,执行前复核 runtime、assignment generation 与 timer 更新序号;到期进入既有 Pause/Delete,失败保留重试。Coordinator 不保存动态 control、续期 CAS 或到期扫描/claim。
178+ 
179+显式 Pause 停止当前 timer;Resume 开始新周期。E2B Connect 对暂停态先复用原生 EnsureRunning 恢复(包括可接管的离线 owner),再为本轮运行设置请求时长;运行态 Connect 仍只延长期限。Paused Connect 的请求时长随原生恢复意图保留,并传到最终 owner,在首次建立该运行期 timer 前消费;原 owner 不可用、替代调度及后台重试沿用同一恢复意图,RPC 等待预算不作为运行时长。合并到既有恢复意图的请求不改写其初始时长,恢复后的 Connect 续期只延长、不缩短,避免重试重置 timer;Spec 默认时长不变。暂停态独立更新的 nextDuration 只在下一次运行消费一次,不跨节点进程重启保存;Snapshot 临时暂停/源恢复保留原 deadline,capture 耗时计入本轮运行。普通 Running 重报不续期。`startedAt` 复用原生 CreationSummary 的首次成功 Running 时间,Pause/Resume 后保持;运行态 `endAt` 是 owner 剩余单调时长映射到当前墙钟的估计值。Paused `endAt` 来自 RestorePoint 的真实保留期限,Forever 映射为 `9999-12-31T23:59:59Z`。
180+ 
181+模板 snapshotId、实际规格、profile 和 pause policy 在创建时固定,alias 改动只影响后续创建;Pause/Connect/clone 不回查当前 alias,恢复所需旧 profile/工件不可用则失败。暂停保留期复用原生策略,缺省 90000 秒,可配置 Forever/Shared,与原装 E2B 的无限保留存在差异。`autoPause:true` 的 autoPauseMemory 缺省为内存模式,显式 false 拒绝。secure 省略/null/true 沿用 envd 鉴权;false 为 400 / `capability_not_supported`,错类型/未知字段为 400。
182+ 
183+Execd 使用上游 envd 原有 `/freeze`、`/unfreeze`、`/init`,不修改 envd。`ADX_ENVD_FREEZE_ON_CHECKPOINT` 默认 true,由可信 profile 注入,可设 false。freeze 总限时 2 秒,保持 best-effort:204/no-op/部分冻结/超时不算完整冻结证明,但记录发送尝试以便回滚。重复同一 operation 复用结果,新 operation 重新准备;调用方断连不取消已接受的协作。`--no-cgroups` 不证明用户进程冻结。
184+ 
185+未开始 capture 的回滚,或已确认源继续运行的 checkpoint,须 `/unfreeze` 成功才报告 Running,失败为 Failed;已停止的源不额外解冻。未知 handoff 结果不授权重捕获或盲目解冻。恢复走 `/init`,保留 envd 进程/命令表,失败不发布路由。网关模式中的 envd 无 token,克隆只换发网关凭据,Execd 恢复 `/init` 不配置 accessToken;旧模式快照不能作为网关模式的克隆源,恢复也拒绝改变已有 auth mode。
186+ 
187+host/initrd/快照须与固定 sandboxd revision 和工件摘要配套。宿主不支持 Direct I/O 对齐时,可在空 worker 验证后使用固定 sandboxd 的 `writable_io_engine="Sync"`。
188+ 
189+## 后端已知限制
190+ 
191+恢复校时和 TAP 恢复隔离属于 sandboxd Firecracker 后端的公共限制,当前 ADX 不提供额外修复。原生 ADX 与 E2B 使用同一后端时均可能受影响:
192+ 
193+| 问题 | 影响与验收边界 |
194+| --- | --- |
195+| 恢复后 guest 时钟偏差 | 恢复后 guest 时钟可能落后于宿主,影响用户程序的绝对时间、定时器或凭据判断。部署时检查 Pause/Connect 与 clone 的时间行为 |
196+| clone 恢复时的网络干扰 | clone 恢复窗口中,源 MAC 可能被学习到 clone TAP,导致源流量转错、连接失败或 Relay 504。该限制由 sandboxd 的恢复网络流程处理,不能据此判定所有 504 的原因 |
197+| 跨运行时复用 TAP | 当前 backend 的 runsc 接管路径未显式复位 Firecracker 可设置的 offload 状态。单 backend 混合这两类运行时的连接行为需单独验收;不能把单运行时结果外推为混布通过。`interface_cache_size=0` 会关闭正常 ACL 所依赖的接口管理,不能作为禁用复用的替代 |
198+ 
199+这些问题不改变 E2B 接口适配范围,但会影响实际 Pause/Connect、Snapshot/clone 的正确性或可用性。保留时钟、源沙箱与 clone 独立访问的验收检查,按实际结果记录;不通过提高 Relay 超时、跳过检查或在 ADX 增加绕行逻辑宣称通过。
200+ 
201+## API Key 与网络
202+ 
203+Key 管理采用 ADX 管理员认证:`X-Admin-Token` 或 `Authorization: Bearer <ADX administrator key>` 二选一,`X-Team-ID` 须等于管理员 tenant,普通 X-API-Key 不授予管理权限。这与原装 AuthProvider JWT 是明确差异,不支持跨团队管理或重命名(PATCH 为 501)。
204+ 
205+POST 只接收 `{ "name": "ci-key" }`,name 非空、最多 256 个非控制字符;同名允许,创建不幂等。201 一次性返回 `key`,列表只返回 UUID id、RFC3339 createdAt 和真实 mask,createdBy/lastUsed 为 null,成功响应 no-store。新密钥统一复用 `adx_` 加 64 个小写 hex,SDK 将其作为不透明凭据;内部不再区分 E2B KeyFormat。历史 `e2b_` 密钥仍可认证、查询和撤销,不替换前缀转换旧密钥。DELETE 为 204,缺失/已撤销/其它 tenant 为 404;tenant/UUID 校验与撤销原子执行。
206+ 
207+撤销在下一次 E2B 管理请求实时生效,不删除沙箱,不广播断开已有连接,不撤销独立 envd/traffic token;原生入口及 Ingress 认证缓存仍按其原有合同工作。
208+ 
209+真实 ACL 要求专用 worker 开启 `[plugin.network] enable_network_acl = true`。固定 sandboxd 拒绝 runc 非空网络策略和动态更新,runsc systrap 可执行 ACL 且不需要 KVM;Firecracker 另需 KVM。核查 iptables/ip6tables/ipset、bridge netfilter、conntrack 及权限,backend、bridge/TAP、ACL hooks 和报文处于同一可管理网络命名空间。hostNetwork 不是唯一部署方式;bpfnat 另需 Linux 5.17+/TC eBPF/可写 bpffs,完整条件见固定 sandboxd 的 `doc/network-acl.md`。
210+ 
211+创建与更新共用 IPv4/CIDR 转换:创建时未提供覆盖字段才继承快照出站策略;显式 `allow_internet_access:true` 或空 `allowOut`/`denyOut` 会应用允许/清空覆盖,同时保留受保护 ingress。allow 优先级 200、deny 100,默认允许;`allow_internet_access:false` 默认拒绝,`network:{}` 保留模板 allowPublicTraffic。域名、通配符、IPv6、egressProxy/rules/maskRequestHost/httpsPorts 明确拒绝。更新是出站配置替换,`{}` 清除旧出站规则并恢复默认允许,保留原生入站、DNS 及 stateful/stateless mode,Both 只保留 Ingress 投影;不接受动态 allowPublicTraffic。仅 Running 可更新,沿同一权威 revision 调用节点,竞争为 409,执行失败不返回 204。
212+ 
213+链路为 Ingress→API Server→EnvironmentService→adxlet→sandboxd,不调用 envd。保留平台控制流量例外,已有连接行为继承 backend;HTTP 204 或单元测试不是实际阻断报文的证明。
214+ 
215+## Harbor 预置模板接入
216+ 
217+Harbor 0.25.0 使用锁定的 E2B SDK 2.25.0。将任务依赖预装入 OCI 镜像,通过 fromImage 准备 Golden Snapshot,并登记任务实际使用的精确 alias。使用管理员签发的普通 ADX key、官方 SDK 地址与 CA 配置,运行 `--env e2b --no-force-build`。未知 alias 不回退 base。
218+ 
219+仅支持 fromImage 准备,非空构建步骤明确拒绝。保持任务原有网络要求,PUBLIC 使用默认网络策略;NO_NETWORK/IPv4 依赖支持 ACL 的后端,域名/通配符仍不支持。验证时保留 Harbor/SDK 的正常协议、secure 参数、路由和 alias,使用正式发钥接口;通过真实 provider/Oracle 检查任务执行结果和文件权限。
220+ 
221+## 验证入口
222+ 
223+在独立测试部署运行,通过 HTTPS 与已安装 SDK 验证业务行为,完成后核查测试实例、backend 和制品释放。基础驱动固定 SDK 2.52.0、envd 0.9.0;Harbor 验收单独锁定 SDK 2.25.0,不能用新版替代。不要开 debug 直连本地 envd;无通配 DNS 时显式配置 sandbox_url。
224+ 
225+最小 SDK 调用(使用部署 CA 的标准 SSL_CERT_FILE 配置):
226+ 
227+```python
228+import os
229+from e2b import Sandbox
230+ 
231+sandbox = Sandbox.create("base", api_key=os.environ["E2B_API_KEY"],
232+ api_url="https://adx.example.com", sandbox_url="https://adx.example.com",
233+ timeout=60)
234+try:
235+ assert sandbox.commands.run("printf ready").stdout == "ready"
236+finally:
237+ sandbox.kill()
238+```
239+ 
240+| 入口 | 检查内容 |
241+| --- | --- |
242+| [smoke.py](../../build/e2b/smoke.py) | 管理、命令/文件/PTY、端口、metadata、鉴权、期限/续期、envd 故障撤路由,以及 user 上传→root chmod→直接执行 |
243+| [checkpoint.py](../../build/e2b/checkpoint.py) | Pause→Connect 内存/进程连续性、时钟、snapshot 源继续运行、双 clone 独立运行/文件与凭据隔离、断连 snapshot、测试资源清理;可分阶段执行 |
244+| 组件测试 | Gateway 真实 envd、Execd init、Coordinator Redis/RPC 等;不代表真实 VM/集群验收 |
245+ 
246+```sh
247+ADX_TEST_ENVD_BIN=/absolute/path/to/envd ADX_TEST_E2B_PYTHON=/absolute/path/to/python \
248+cargo test -p data-plane-gateway --test e2b_envd -- --ignored --nocapture --test-threads=1
249+ADX_TEST_ENVD_BIN=/absolute/path/to/envd \
250+cargo test -p adx-execd real_envd_initialization -- --ignored
251+ADX_TEST_REDIS_SERVER=/absolute/path/to/redis-server \
252+cargo test -p adx-coordinator --test storage e2b_ -- --ignored
253+```
254+ 
255+Pod 内直接运行 envd 组件测试,若继承 oom_score_adj 高于 100,测试容器需 `CAP_SYS_RESOURCE`;这不是给生产 guest 增加该权限。传入测试 CA 和两个独立租户 key 文件,凭据/token 不写入结果。
256+ 
257+## 删除后的制品责任
258+ 
259+已登记共享 checkpoint/capture 继续由原生 registry、Snapshot 引用、execution holds 和 GC 管理,不重复加入 cleanup outbox。本地或确实未登记制品在 Deleted 退役时原子保存最小 pending payload,逐项幂等清理并收到完整 ACK 后 HDEL;部分清理、ACK 丢失或组件重启保留待办,本地节点永久丢失也不因 TTL 自动确认成功。
260+ 
261+删除重试沿用 600 秒 DeletedReceipt,增加规范化 cleanup payload 摘要;完成后不保留独立永久 cleanup/artifact fence。journal 遇 NotFound/Conflict 时须读取 fresh assignment,确认旧归属已撤销才丢弃旧条目,不把丢弃当作原提交成功。正常 Snapshot 发布在同一 CAS 比较源记录,防止 source 已退役后的迟到发布;制品 UUID 不复用,scope 继续阻止 alias 改指 bucket/prefix 后删错物理目标。
Mdocs/testing/control-rpc.md+2-1文件内容审核中,请稍后刷新重试
Mdocs/testing/coordinator-storage.md+1-1文件内容审核中,请稍后刷新重试
Mdocs/testing/environment-checkpoint.md+2-2文件内容审核中,请稍后刷新重试
Mdocs/testing/failed-environment-gc.md+20-4文件内容审核中,请稍后刷新重试
Mdocs/testing/snapshot-storage.md+3-1文件内容审核中,请稍后刷新重试
Mdocs/testing/system-reliability-gates.md+10-1文件内容审核中,请稍后刷新重试
@@ -54,12 +54,12 @@ base64 = "0.22"
54bytes = "1"54bytes = "1"
55percent-encoding = "2"55percent-encoding = "2"
56h2 = "0.4"56h2 = "0.4"
57-hyper-util = { version = "0.1", features = ["tokio", "client-legacy", "http1"] }57+hyper-util = { version = "0.1", features = ["tokio", "client-legacy", "server-auto"] }
58etcd-client = { version = "0.14", optional = true, features = ["tls"] }58etcd-client = { version = "0.14", optional = true, features = ["tls"] }
59futures-util = "0.3"59futures-util = "0.3"
60http = "1"60http = "1"
61http-body-util = "0.1"61http-body-util = "0.1"
62-hyper = { version = "1", features = ["client", "server", "http1"] }62+hyper = { version = "1", features = ["client", "server", "http1", "http2"] }
63ipnet = "2"63ipnet = "2"
64libc = "0.2"64libc = "0.2"
65prost = { version = "0.13", optional = true }65prost = { version = "0.13", optional = true }
@@ -84,6 +84,11 @@ route takes precedence over management and configured proxy paths. Unrelated
84Hosts retain the existing path routing. Deployments serving this form to84Hosts retain the existing path routing. Deployments serving this form to
85browsers need wildcard DNS and a TLS certificate covering the subdomains; the85browsers need wildcard DNS and a TLS certificate covering the subdomains; the
86Ingress still applies the same route publication and authentication checks.86Ingress still applies the same route publication and authentication checks.
87+When E2B routing is enabled, a Host valid in both the native `<instance-id>-<port>`
88+and E2B `<port>-<sandbox-id>` forms defaults to the native target. To select the
89+E2B target instead, supply both `E2b-Sandbox-Id` and `E2b-Sandbox-Port` matching
90+its E2B Host interpretation. The selected target retains its published access
91+policy; an unavailable or unauthorized native target does not fall back to E2B.
87Frontend is not a data-plane hop. Ingress removes credentials before opening Node92Frontend is not a data-plane hop. Ingress removes credentials before opening Node
88streams, so user API Keys never reach Node or the workload.93streams, so user API Keys never reach Node or the workload.
89 94 
Mgateway/apiserver/Cargo.toml+2-1文件内容审核中,请稍后刷新重试
Mgateway/apiserver/README.md+2-0文件内容审核中,请稍后刷新重试
Mgateway/apiserver/src/clients.rs+118-15文件内容审核中,请稍后刷新重试
Mgateway/apiserver/src/config.rs+7-0文件内容审核中,请稍后刷新重试
Mgateway/apiserver/src/contract.rs+5-0文件内容审核中,请稍后刷新重试
Agateway/apiserver/src/e2b/config.rs+168-0文件内容审核中,请稍后刷新重试
Agateway/apiserver/src/e2b/dto.rs+636-0文件内容审核中,请稍后刷新重试
Agateway/apiserver/src/e2b/http.rs+1206-0文件内容审核中,请稍后刷新重试
Agateway/apiserver/src/e2b/mod.rs+15-0文件内容审核中,请稍后刷新重试
Agateway/apiserver/src/e2b/network.rs+495-0文件内容审核中,请稍后刷新重试
Agateway/apiserver/src/e2b/template_api.rs+461-0文件内容审核中,请稍后刷新重试
Agateway/apiserver/src/e2b/templates.rs+133-0文件内容审核中,请稍后刷新重试
Mgateway/apiserver/src/environment_directory.rs+3-0文件内容审核中,请稍后刷新重试
Mgateway/apiserver/src/environment_service.rs+26-0文件内容审核中,请稍后刷新重试
Mgateway/apiserver/src/http.rs+82-9文件内容审核中,请稍后刷新重试
Mgateway/apiserver/src/lib.rs+1-0文件内容审核中,请稍后刷新重试
Mgateway/apiserver/src/operations.rs+233-57文件内容审核中,请稍后刷新重试
Mgateway/apiserver/tests/contract.rs+10-0文件内容审核中,请稍后刷新重试
Mgateway/apiserver/tests/create_replay.rs+1489-27文件内容审核中,请稍后刷新重试
Agateway/apiserver/tests/e2b_keys.rs+344-0文件内容审核中,请稍后刷新重试
Agateway/apiserver/tests/e2b_network.rs+599-0文件内容审核中,请稍后刷新重试
Mgateway/apiserver/tests/environment_file_directory.rs+1-0文件内容审核中,请稍后刷新重试
Mgateway/apiserver/tests/reload.rs+8-0文件内容审核中,请稍后刷新重试
Agateway/apiserver/tests/support/e2b_create_errors.rs+120-0文件内容审核中,请稍后刷新重试
Mgateway/src/common/route.rs+6-0文件内容审核中,请稍后刷新重试
Mgateway/src/ingress/agent_api_tests.rs+36-0文件内容审核中,请稍后刷新重试
Mgateway/src/ingress/coordinator_routes.rs+216-3文件内容审核中,请稍后刷新重试
Agateway/src/ingress/e2b_route.rs+548-0文件内容审核中,请稍后刷新重试
Agateway/src/ingress/e2b_signing.rs+143-0文件内容审核中,请稍后刷新重试
Mgateway/src/ingress/mod.rs+2-0文件内容审核中,请稍后刷新重试
Mgateway/src/ingress/resolver.rs+45-0文件内容审核中,请稍后刷新重试
Mgateway/src/ingress/server.rs+370-16文件内容审核中,请稍后刷新重试
Agateway/src/ingress/server/access_policy_tests.rs+687-0文件内容审核中,请稍后刷新重试
Mgateway/src/ingress/server/processing_tests.rs+4-0文件内容审核中,请稍后刷新重试
Mgateway/src/ingress/server/route_recovery_tests.rs+8-0文件内容审核中,请稍后刷新重试
Mgateway/src/ingress/service.rs+8-1文件内容审核中,请稍后刷新重试
Mgateway/src/node/server.rs+20-1文件内容审核中,请稍后刷新重试
Mgateway/tests/coordinator_routes.rs+2-0文件内容审核中,请稍后刷新重试
Agateway/tests/e2b_envd.rs+388-0文件内容审核中,请稍后刷新重试
Mgateway/tests/mock_e2e.rs+4-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/bin/adxlet.rs+6-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/checkpoint.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/control_stream.rs+41-1文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/controller.rs+176-15文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/controller/lifecycle.rs+29-8文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/controller/monitor.rs+12-2文件内容审核中,请稍后刷新重试
Aplatform/adxlet/src/controller/run_timer.rs+305-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/controller/snapshots.rs+8-10文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/jiuwenbox/mod.rs+5-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/journal.rs+72-18文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/lib.rs+69-1文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/readiness.rs+33-4文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/reconciliation.rs+45-2文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/reconciliation/periodic.rs+2-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/reconciliation/periodic_tests.rs+32-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/rpc.rs+266-22文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/runtime_control.rs+12-3文件内容审核中,请稍后刷新重试
Mplatform/adxlet/src/sandboxd.rs+181-3文件内容审核中,请稍后刷新重试
Aplatform/adxlet/tests/checkpoint_cleanup.rs+286-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/checkpoint_lru.rs+11-4文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/common/authority.rs+18-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/deletion_retention.rs+301-6文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/journal.rs+196-1文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/lifecycle.rs+273-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/lifecycle_events.rs+1-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/object_checkpoint.rs+155-154文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/pause_resume.rs+402-13文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/readiness.rs+130-1文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/reconciliation.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/reconciliation/isolation.rs+2-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/reconciliation/late_restore.rs+1-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/routes.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/adxlet/tests/sandboxd_rpc.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/api/http/error-contract.md+2-0文件内容审核中,请稍后刷新重试
Mplatform/api/proto/README.md+11-0文件内容审核中,请稍后刷新重试
Mplatform/api/proto/credentials.proto+19-2文件内容审核中,请稍后刷新重试
Mplatform/api/proto/environment.proto+77-4文件内容审核中,请稍后刷新重试
Mplatform/api/proto/environment_types.proto+42-1文件内容审核中,请稍后刷新重试
Mplatform/api/proto/routes.proto+15-0文件内容审核中,请稍后刷新重试
Mplatform/api/proto/snapshot.proto+12-3文件内容审核中,请稍后刷新重试
Aplatform/api/proto/snapshot_preparation.proto+70-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/examples/compare.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/examples/mixed_load.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/examples/stale_session_probe.rs+1-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/auth.rs+161-9文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/bin/adx-coordinator.rs+137-19文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/lib.rs+51-1文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/routes.rs+97-3文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/rpc.rs+143-58文件内容审核中,请稍后刷新重试
Aplatform/coordinator/src/rpc/checkpoint_cleanup.rs+148-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/rpc/cloning.rs+114-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/rpc/collection.rs+11-1文件内容审核中,请稍后刷新重试
Aplatform/coordinator/src/rpc/environment_control.rs+303-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/rpc/recovery.rs+40-31文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/rpc/resume.rs+58-46文件内容审核中,请稍后刷新重试
Aplatform/coordinator/src/rpc/snapshot_preparation.rs+1418-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/rpc/snapshots.rs+39-15文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/storage.rs+222-31文件内容审核中,请稍后刷新重试
Aplatform/coordinator/src/storage/checkpoint_cleanup.rs+171-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/storage/collection.rs+5-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/storage/credentials.rs+32-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/storage/failure.rs+1-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/storage/node_retirement.rs+5-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/storage/publication.rs+23-2文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/storage/resume.rs+18-0文件内容审核中,请稍后刷新重试
Aplatform/coordinator/src/storage/snapshot_preparation.rs+409-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/src/storage/snapshots.rs+78-11文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/benchmark.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/constraints.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/fairness.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/observability.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/on_demand.rs+192-5文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/optimization.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/optimization_safety.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/plugins.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/recovery.rs+5-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/retry.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/rpc.rs+721-39文件内容审核中,请稍后刷新重试
Aplatform/coordinator/tests/rpc/environment_control.rs+183-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/rpc/local_first.rs+159-1文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/rpc/network.rs+4-0文件内容审核中,请稍后刷新重试
Aplatform/coordinator/tests/rpc/snapshot_preparation.rs+268-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/rpc/volumes.rs+2-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/scheduling.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/snapshots.rs+16-1文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/storage.rs+191-1文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/storage/artifact_lifecycle.rs+71-0文件内容审核中,请稍后刷新重试
Aplatform/coordinator/tests/storage/checkpoint_cleanup.rs+407-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/storage/claims.rs+22-0文件内容审核中,请稍后刷新重试
Aplatform/coordinator/tests/storage/master_upgrade.rs+161-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/storage/node_retirement.rs+72-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/storage/observability.rs+1-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/storage/publication.rs+43-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/storage/publication_regressions.rs+26-0文件内容审核中,请稍后刷新重试
Aplatform/coordinator/tests/storage/snapshot_preparation.rs+453-0文件内容审核中,请稍后刷新重试
Mplatform/coordinator/tests/volumes.rs+25-0文件内容审核中,请稍后刷新重试
Mplatform/crates/checkpoint-storage/src/filesystem.rs+2-0文件内容审核中,请稍后刷新重试
Mplatform/crates/checkpoint-storage/src/lib.rs+53-1文件内容审核中,请稍后刷新重试
Mplatform/crates/checkpoint-storage/src/object.rs+19-0文件内容审核中,请稍后刷新重试
Mplatform/crates/checkpoint-storage/src/object/cache.rs+2-0文件内容审核中,请稍后刷新重试
Mplatform/crates/checkpoint-storage/src/reclaim.rs+35-3文件内容审核中,请稍后刷新重试
Mplatform/crates/core/Cargo.toml+2-3文件内容审核中,请稍后刷新重试
Mplatform/crates/core/src/checkpoint.rs+54-0文件内容审核中,请稍后刷新重试
Aplatform/crates/core/src/envd.rs+306-0文件内容审核中,请稍后刷新重试
Aplatform/crates/core/src/environment_control.rs+98-0文件内容审核中,请稍后刷新重试
Mplatform/crates/core/src/execution.rs+121-0文件内容审核中,请稍后刷新重试
Mplatform/crates/core/src/lib.rs+58-1文件内容审核中,请稍后刷新重试
Mplatform/crates/core/src/runtime.rs+84-0文件内容审核中,请稍后刷新重试
Aplatform/crates/core/src/snapshot_preparation.rs+196-0文件内容审核中,请稍后刷新重试
Mplatform/crates/core/src/snapshots.rs+60-17文件内容审核中,请稍后刷新重试
Mplatform/crates/core/src/volumes.rs+15-0文件内容审核中,请稍后刷新重试
Aplatform/crates/core/tests/checkpoint_serde.rs+20-0文件内容审核中,请稍后刷新重试
Mplatform/crates/core/tests/environment_runtime.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/crates/core/tests/snapshot_busy.rs+76-0文件内容审核中,请稍后刷新重试
Mplatform/crates/protocol/build.rs+4-0文件内容审核中,请稍后刷新重试
Aplatform/crates/protocol/src/checkpoint_cleanup.rs+34-0文件内容审核中,请稍后刷新重试
Aplatform/crates/protocol/src/envd.rs+52-0文件内容审核中,请稍后刷新重试
Aplatform/crates/protocol/src/environment_control.rs+131-0文件内容审核中,请稍后刷新重试
Mplatform/crates/protocol/src/execution.rs+20-0文件内容审核中,请稍后刷新重试
Mplatform/crates/protocol/src/lib.rs+115-9文件内容审核中,请稍后刷新重试
Mplatform/crates/protocol/src/snapshots.rs+25-1文件内容审核中,请稍后刷新重试
Mplatform/crates/protocol/tests/snapshots.rs+34-4文件内容审核中,请稍后刷新重试
Mplatform/crates/scheduling/tests/framework.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/crates/scheduling/tests/placement_groups.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/crates/scheduling/tests/snapshot.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/runtime/execd/src/runtime/control.rs+254-108文件内容审核中,请稍后刷新重试
Mplatform/runtime/execd/src/runtime/control_stream.rs+1-1文件内容审核中,请稍后刷新重试
Mplatform/runtime/execd/src/runtime/entrypoint.rs+3-1文件内容审核中,请稍后刷新重试
Aplatform/runtime/execd/src/runtime/envd.rs+1109-0文件内容审核中,请稍后刷新重试
Mplatform/runtime/execd/src/runtime/httpserver.rs+9-5文件内容审核中,请稍后刷新重试
Mplatform/runtime/execd/src/runtime/mod.rs+198-46文件内容审核中,请稍后刷新重试
Mplatform/runtime/execd/tests/control.rs+348-1文件内容审核中,请稍后刷新重试
Mplatform/runtime/execd/tests/control_http.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/runtime/execd/tests/control_stream/process.rs+3-0文件内容审核中,请稍后刷新重试
Mplatform/runtime/execd/tests/workload_probes.rs+3-0文件内容审核中,请稍后刷新重试