Files
codex-app-server/cloud/chv/compat215.py
T
host df8c64bd64 feat(chv): 架构/可维护性/前端只读侧推进——生产实验分离、配置片段化、VM 只读展示
架构:WarmPool 从 cloud/chv/pool.py 移到 experimental_pool.py,
生产残留清理彻底分文件到 cloud/chv/orphans.py(facade 直接读
registry 文件清理,不构造池、不碰 prewarm/acquire/release);
cloud/chv 与 cloud/sandbox 不再导出 WarmPool,旧路径一律
ImportError(CHV 未合并、无生产用户,兼容保留已无保留理由);
worker 改走 orphans facade,不再持有 _warm_pool;#215 对齐从
接口形状推进到 REPLACEMENT_POINTS 替换清单(R1/R2 可机械替换、
R3 永不替换,#215 模块当前不存在由测试钉住)。

可维护性:build_chv_config 拆成 base/ssh/network/quota/disk/
timeout 六片段(组装只做 dict 合并,键冲突即报错;38 字段集
与取值不变,单项非法报错文案逐字一致);ADR-12 模块职责图
与禁 import 清单(AST 钉住);cloud/chv/ 公开 API 全量类型
标注、无 Any 逃逸,并修正三处旧标注错误;死代码扫一遍
(删实验池已无调用的 _quarantine 委托与未用 _LOGGER)。

前端(只读侧,不做控制按钮):chv.ts 新增纯逻辑谓词与文案
(执行器精确匹配、附件守卫、VM 状态文案、列表徽标);列表
行新增 VM 已报告死亡徽标;详情对全部 CHV 任务显示 VM 行
(已报告死亡/未报告死亡,不猜 live);WorkersSection 与成本
卡沿用已有数据,不新开池管理/成本页;服务端未新增第二个
生命周期字段(持久化事实只有三项,chv_vm_dead 已是完整派生),
只把派生抽成 _chv_vm_dead_from_row 并补 goal 回落形态测试。
2026-10-31 06:55:26 +00:00

115 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""#215(feat-arch-converge)接口对齐层,CHV 本地实现。
背景:#215 未合并,本基线里没有 cloud/timeouts.py、
cloud/gates.py、cloud/quota.py、cloud/sandbox_policy.py。
本模块绝不复制 #215 的文件,只把 CHV 真正能映射的
接口写成与 #215 相同的签名,#215 合并后替换为 import
即是机械的(见 docs/chv-architecture.md ADR-8)。
映射表(逐个核对过 #215 远程分支的真实函数,不是凭空编的):
- gates.resolve_inside(base, rel):目录门,CHV 快照/磁盘
路径白名单正好需要它——本模块实现同语义并已在
hardening.validate_snapshot_url 里使用,#215 合并后
改为 from cloud.gates import resolve_inside 即可。
- sandbox_policy.tmpfs_isolated(executor_kind, path):CHV
客机 /tmp 落在客机磁盘上,不是宿主 tmpfs,故对
cloud-hypervisor 一律返回 (False, ...)——fail-closed,
绝不宣称隔离。未知执行器同样 fail-closed。
- timeouts.resolve_module_timeout / quota.decide:无映射。
前者是审批/队列超时(None=不过期、0=不过期),CHV
的 api/ready 超时是秒数且 0 无效,语义不同,硬套会
改行为;后者是按月美元配额,CHV 的配额是 VM 数/磁盘
GB/快照数,单位不同。两者在本模块里 deliberately
不提供,测试钉住“CHV 不 import 它们”。
本模块只依赖标准库,是叶子模块,不 import cloud.sandbox。
合并后替换清单(REPLACEMENT_POINTS,本轨从“接口形状”
推进到可机械执行的清单;#215 未合并前一律不 import
cloud.gates / cloud.sandbox_policy / cloud.timeouts /
cloud.quota,测试钉住这些模块在本基线里不存在):
- R1 gates.resolve_inside:唯一生产调用方是
hardening._is_within(快照 URL 白名单)。合并后两步:
① hardening 改为 `from cloud.gates import resolve_inside`;
② 删本模块 resolve_inside。语义必须逐字一致,改完
重跑快照白名单测试(逃逸/符号链接/绝对路径三例)。
- R2 sandbox_policy.tmpfs_isolated:形状占位,当前无
生产调用方(只有测试)。合并后一步:删本模块
tmpfs_isolated;将来有调用方时直接 import #215 版,
不得再本地复刻。CHV 语义是“一律不隔离(fail-closed)”,
若 #215 版对 cloud-hypervisor 返回 True,替换即改行为,
必须先停下来核对,不得机械替换。
- R3 timeouts / quota:永不替换。#215 的 timeouts 是
审批/队列超时(None/0 = 不过期),quota 是按月美元
配额;CHV 的 api/ready 超时是秒数(0 无效)、配额是
VM 数/磁盘 GB/快照数,单位与语义都不同。清单里明写
“不替换”,防止合并时有人按名字硬套。
"""
import os
# 合并后替换清单:每项的 local/replacement/test 字段由测试
# 逐项核对(local 函数真实存在、#215 模块当前不存在、
# test 命名的测试类真实存在),清单本身不得漂移。
REPLACEMENT_POINTS = (
{
"id": "R1",
"upstream": "cloud.gates.resolve_inside",
"local": "cloud.chv.compat215.resolve_inside",
"caller": "cloud.chv.hardening._is_within",
"replacement": "hardening 改为 from cloud.gates import "
"resolve_inside,并删除本地 resolve_inside",
"test": "Compat215Test + 快照白名单测试",
},
{
"id": "R2",
"upstream": "cloud.sandbox_policy.tmpfs_isolated",
"local": "cloud.chv.compat215.tmpfs_isolated",
"caller": None,
"replacement": "删除本地 tmpfs_isolated;有调用方时"
"直接 import #215 版(先核对 CHV 一律 False 语义)",
"test": "Compat215Test.test_tmpfs_isolated_chv_and_unknown_"
"fail_closed",
},
{
"id": "R3",
"upstream": "cloud.timeouts / cloud.quota",
"local": None,
"caller": None,
"replacement": None,
"test": "Compat215Test.test_no_timeout_or_quota_map",
},
)
def resolve_inside(base: str, rel: str) -> str | None:
"""目录门:base 内的相对路径安全解析,越界回 None。
空串回 base 本身;绝对路径、.. 逃逸、符号链接逃逸、
commonpath 跨盘符 ValueError 一律 None。签名与 #215
的 gates.resolve_inside 一致,合并后可直接替换为 import。"""
if not rel:
return base
if os.path.isabs(rel):
return None
real_base = os.path.realpath(base)
target = os.path.realpath(os.path.join(real_base, rel))
try:
if os.path.commonpath([real_base, target]) != real_base:
return None
except ValueError:
return None
return target
def tmpfs_isolated(executor_kind: str, path: str) -> tuple[bool, str]:
"""某执行器下某路径是否走 tmpfs 隔离:(isolated, reason)。
cloud-hypervisor:客机 /tmp 落在客机磁盘上,不走宿主
tmpfs,一律 (False, ...);未知执行器 fail-closed 同样
False。签名与 #215 的 sandbox_policy.tmpfs_isolated 一致。"""
if executor_kind == "cloud-hypervisor":
return False, "CHV 客机 /tmp 落在客机磁盘上,不走宿主 tmpfs"
return False, "未知执行器,按不隔离处理(fail-closed 口径)"