fix(chv): 生产级审核 P1-01~P1-10 修复(堆叠于 #270 之上)
This commit is contained in:
1 parent
8c8d62f70d
commit
971e054938
12 files changed
+1545
-120
No files matched your search
@@ -1,6 +1,6 @@
|
||||
# Cloud Hypervisor 执行器架构决策记录(ADR)
|
||||
|
||||
范围:cloud/chv/ 执行器链(#216 → #221 → #230 → #232 → #234 → #239 → #246 → #252 → #254 → 本轨 feat-chv-arch-maint-fe)。
|
||||
范围:cloud/chv/ 执行器链(#216 → #221 → #230 → #232 → #234 → #239 → #246 → #252 → #254 → feat-chv-arch-maint-fe → feat-chv-closeup → feat-chv-cover100 → 本轨 feat-chv-p1fix)。
|
||||
本文件只记录已落代码的决策,不记录未验证为已验证;真机、压测、动态安全
|
||||
仍见 docs/chv-production-readiness.md §11。
|
||||
|
||||
@@ -323,3 +323,35 @@
|
||||
缺 268 → 242);未覆盖大头仍是 executor 深层生命周期
|
||||
分支(需假 VMM 全链路)与 disk 配额分支,不靠删测试
|
||||
或改分母凑数。
|
||||
|
||||
## ADR-17 P1 修复轨语义收紧(feat-chv-p1fix,生产级审核 §5)
|
||||
|
||||
本轨只修审核报告 §5 的 P1 十项(P2 不动),决策均为
|
||||
“失败可见、猜测收紧、竞态加锁”,不放宽任何既有安全语义:
|
||||
|
||||
- 失败不算成功:孤儿清理失败项不进 cleaned、不清库、
|
||||
落盘保留失败项(P1-01);残留私钥删失败不进 cleaned、
|
||||
发审计并写脏标记(P1-03);单条超帽快照拒绝记录而不
|
||||
是悄悄保留(P1-06);快照失败与剪枝删失败均发审计
|
||||
(P1-08)。“尽力清理、不因单条失败卡住整批”的旧语义
|
||||
被修正为“尽力清理、失败项留痕可重试”——整批仍不卡,
|
||||
但失败不再被成功名单掩盖。
|
||||
- 损坏与非法不静默:registry 损坏与非法条目均发审计并
|
||||
计数(P1-02);非法条目落盘时丢弃(已审计,不再每次
|
||||
重启重复审计)。
|
||||
- 不猜目标:SSH 命令构造删除回环回落,失败即抛
|
||||
(P1-04);显式回环(CHV_SSH_HOST / CHV_SSH_FORWARD=1)
|
||||
仍可用,wake/wait 严格路径不受影响。
|
||||
- 竞态用文件锁:容量/net/磁盘 check→act 持
|
||||
`state_dir/chv-state.lock` 的 flock 全程(P1-05),
|
||||
拒绝“只加进程内锁就声称多 worker 已解决”的写法;
|
||||
串行 wake 是有意的代价,已运行 VM 的任务执行不持锁。
|
||||
- 非正配置在入口拦:CPU/内存/任务超时非正在构造层与
|
||||
preflight 层双重校验(P1-07);None 任务超时 = 不限
|
||||
的旧语义保留。
|
||||
- 覆盖口径诚实:行覆盖与分支覆盖分开报(P1-09);
|
||||
`__init__.py` 计入 coverage.py 分母(4 行);长函数
|
||||
50 行硬门禁靠提取维持,新增 helper 均有命名职责
|
||||
(`_snapshot_create`、`_tighten_snapshot_cap`、
|
||||
`_preflight_task_timeout_check`、`_emit_prune_events`、
|
||||
`_state_lock_ctx`),不是为凑行数而拆。
|
||||
@@ -580,6 +580,9 @@
|
||||
|
||||
### 14.1 本轨量化结果(实测,非上一轨回执转述)
|
||||
|
||||
(本节数字为 closeup 轨快照,历史数字保留不改;
|
||||
P1 修复轨后的最新数字见 §15,§14.1 不再是最新口径。)
|
||||
|
||||
- 后端:232 项 → 317 项(新增 `cloud/tests/test_chv_closeup.py`
|
||||
85 项),全过。命令(仓库根目录,cwd 须为根目录——
|
||||
在 `cloud/` 下跑会撞 `cloud/queue.py` 遮蔽 stdlib queue,
|
||||
@@ -761,6 +764,10 @@
|
||||
|
||||
### 14.7 本轨逐项评分(目标 10,无一项硬写 10)
|
||||
|
||||
(本节评分为 closeup 轨快照;P1 修复轨后的评分更新见
|
||||
§15.7,其中“80 行未覆”“317 项/36 项”扣分理由已过期,
|
||||
不再作为当前扣分依据。)
|
||||
|
||||
- 代码质量 9.8 → 9.8,未达 10:executor/worker_adapter
|
||||
覆盖到 100%,但 chv 仍有 80 行未覆(非 executor
|
||||
模块),且默认口径 mypy 余 2 错在作用域外。差:代码内。
|
||||
@@ -785,3 +792,194 @@
|
||||
UNSTABLE、未合并、未部署、真机 0 项。差:外部为主。
|
||||
- 动态安全 2.0 → 2.0,未达 10:本轨无任何动态验证,
|
||||
V-7 未跑。差:外部(KVM 宿主 + 审计结论)。
|
||||
## 15. P1 修复轨 feat-chv-p1fix(堆叠于 #270 之上)
|
||||
|
||||
本节是工程生产级审核(`~/workspace/chv-prod-audit/REPORT.md`,
|
||||
审核对象 #270,提交 `8c8d62f`)§5 的 P1-01~P1-10 修复轨。
|
||||
本轨只到 PR OPEN,不合并、不部署、不做合并试验(P0-01
|
||||
仍未做,见 §15.6);P2-01~P2-21 一律不动。
|
||||
|
||||
### 15.1 本轨量化结果(实测)
|
||||
|
||||
- 后端:362 项 → 389 项(新增 `cloud/tests/test_chv_p1fix.py`
|
||||
27 项),全过。命令(仓库根目录):
|
||||
`python3 -m unittest cloud.tests.test_chv_arch95
|
||||
cloud.tests.test_chv_arch95plus cloud.tests.test_chv_arch_maint_fe
|
||||
cloud.tests.test_chv_fix cloud.tests.test_chv_gaps
|
||||
cloud.tests.test_chv_optimize cloud.tests.test_chv_secfix
|
||||
cloud.tests.test_chv_to10 cloud.tests.test_cloud_hypervisor
|
||||
cloud.tests.test_chv_closeup cloud.tests.test_chv_cover100
|
||||
cloud.tests.test_chv_p1fix`
|
||||
- 覆盖率(同命令 + `coverage run --source=cloud/chv`,再
|
||||
`--append test_cloud_hypervisor`,`.coverage` 写 /tmp):
|
||||
行覆盖 100%(2097 行,缺 0);分支覆盖 99%
|
||||
(714 分支,28 处部分分支未全走——行 100% 不等于
|
||||
分支 100%,PR 描述按此口径写,不写裸“100%”)。
|
||||
`cloud/chv/__init__.py` 计入分母:4 行,100%(仅
|
||||
docstring + 3 个 re-export,coverage.py 口径;审核报告
|
||||
的 trace 口径把它排除在外,两口径差在此说明,不混用)。
|
||||
审核报告 P1-09 点名的 4 处三元 else 分支(str 形态
|
||||
pause/resume/snapshot + 非 dict spill task)已由
|
||||
`test_chv_p1fix.py` 的 BranchCover 测试覆盖。
|
||||
- mypy:silent 口径 `cloud/chv/` 0 错(不变);
|
||||
默认口径 `cloud/marker_tools.py` 仍 2 错(作用域外,
|
||||
本轨未改该文件)。
|
||||
- ruff:`--select F,E9,W,I` 口径 `cloud/chv/` +
|
||||
本轨新测试 0 错(不变;默认全规则基线不声称通过)。
|
||||
- 前端:Vitest 37 项不变(`chv.test.ts` 23 +
|
||||
`chv.closeup.test.ts` 14),本轨未改前端代码;三轮
|
||||
连跑 37/37/37,无抖动回归。
|
||||
- 全量:`python3 -m unittest discover -s cloud/tests`
|
||||
(仓库根目录)1819 项全过(skipped=8),392 秒;
|
||||
上一轨引用口径 1792 项的差额来自本轨新增 27 项。
|
||||
- 长函数:AST 扫描 `cloud/chv/`,>50 行函数 0 个
|
||||
(本轨新增的 snapshot_vm / record_snapshot /
|
||||
_preflight_numeric_checks 均经提取守住 50 行门禁,
|
||||
见 ADR-17)。
|
||||
- §13.1 的 main 头 `aebc6238` 与前端产物哈希
|
||||
`269820d1…f389` 仍是 to10 轨快照,本轨不更新它们:
|
||||
合并前必须按 §13.1 逐项重跑重核,绝不把旧快照写成
|
||||
新数字(审核报告 P1-10 的要求原样保留)。
|
||||
|
||||
### 15.2 P1 逐项修法(证据:文件与测试名)
|
||||
|
||||
- P1-01(orphans.py + experimental_pool.py):失败项不进
|
||||
cleaned、不触发清库;生产 reconcile 落盘只写回失败项
|
||||
原始条目并审计 `warm_pool_reconcile_failed`,下次可重试;
|
||||
实验池失败条目留在内存条目里(文件落盘语义属 P2-16,
|
||||
本轨不改)。同步改旧测试:`test_chv_arch_maint_fe.py`
|
||||
的 shutdown 失败用例与 `test_chv_cover100.py` 的
|
||||
`test_reconcile_shutdown_failure_still_cleans`(已改名
|
||||
`test_reconcile_shutdown_failure_not_cleaned`)——代码
|
||||
与测试同改,不存在“只改一侧”。
|
||||
新测试:`ReconcileP1FixTest.test_failure_not_cleaned_registry_retained_and_retryable`。
|
||||
- P1-02(orphans.py):registry 损坏发
|
||||
`warm_pool_registry_corrupt` 审计(quarantine 后仍审计,
|
||||
不静默返回空);非法条目发
|
||||
`warm_pool_registry_invalid_entries` 审计并计数,落盘
|
||||
时丢弃已审计条目(不再每次重启重复审计)。
|
||||
新测试:`test_corrupt_registry_audited_not_silent`、
|
||||
`test_invalid_entries_audited_and_counted`。
|
||||
- P1-03(executor.py `_clean_one_vm_secrets` /
|
||||
`cleanup_stale_secrets`):返回值由 2 元组改为
|
||||
(removed_priv, removed_seed, failed),删失败发
|
||||
`host_secret_residue_delete_failed` 审计并写脏标记
|
||||
(下次 provision 见标记即 `vm_dirty_refused` 拒起),
|
||||
删失败的 VM 不进 cleaned(即使部分删掉也不算已清理)。
|
||||
旧测试 `test_clean_one_vm_secrets_remove_failures` 已
|
||||
同步改 3 元组解包与 failed 断言。
|
||||
- P1-04(executor.py):删除 `build_ssh_command` 的回环
|
||||
回落(构造失败即抛 `ssh_target_undeclared`),不设
|
||||
dry-run 例外参数——干跑同样不许猜目标;同款回落
|
||||
`_write_provisioned_known_hosts` 一并删除(wake 路径
|
||||
在 provision 前已在 `_wake_prechecks` 里严格解析,
|
||||
不受影响;wait 路径的 `capture_host_key` 本来就
|
||||
解析失败返回 False,同样严格)。显式回环仍可用:
|
||||
`CHV_SSH_HOST=127.0.0.1` 或 `CHV_SSH_FORWARD=1`。
|
||||
旧测试 `test_build_ssh_command_fallback_and_secret_not_delivered`
|
||||
与 `test_write_provisioned_known_hosts_fallback` 已
|
||||
同步改为抛错断言。
|
||||
- P1-05(新增 `cloud/chv/locking.py` + executor.py):
|
||||
选文件锁方案(非单 worker 声明):`StateLock` =
|
||||
`flock`(`state_dir/chv-state.lock`,永不删除)+
|
||||
进程内 RLock 可重入(同一实例嵌套不自锁;多实例/
|
||||
多进程靠 flock 互斥)。持有范围:wake_vm 全程、
|
||||
restore_vm 全程、cleanup_stale_vms 全程、orphans
|
||||
reconcile 全程;`_purge_dead_registry` 改为锁内快照
|
||||
键列表、逐项锁内读/删,`_stop_dead_socket_vms` 的
|
||||
登记读持锁。串行 wake 是有意的代价(容量门只有
|
||||
“查完立即占位”才成立,提前释放会在 socket 未绑定
|
||||
前留出计数窗口);已运行 VM 的任务执行不持此锁。
|
||||
新测试:`StateLockP1FixTest`(线程互斥、跨进程互斥、
|
||||
purge 并发变更加锁)、`WakeSerializationP1FixTest`
|
||||
(两路并发 wake 实测串行化)。
|
||||
- P1-06(disk.py `record_snapshot`):单条快照本身大于
|
||||
总量帽时,在任何落盘/删旧动作之前直接拒绝
|
||||
(`snapshot_quota_exceeded`),不悄悄保留超大快照;
|
||||
大小未知(size 为 None,如远端目标)时无法判定,
|
||||
沿用旧口径。新测试:
|
||||
`SingleSnapshotCapP1FixTest`(拒绝无副作用:旧文件
|
||||
与旧登记均在)。
|
||||
- P1-07(config.py + executor.py preflight):构造层
|
||||
拒绝能解析出的 CPU/内存非正值与显式任务超时非正值
|
||||
(`CHV_CPU`/`CHV_MEM`/`CHV_TASK_TIMEOUT`);preflight
|
||||
再验属性事后改写(CPU 0/负、内存 0、任务超时 0/负
|
||||
一律 `config_invalid` 干净失败,不进 VmConfig)。
|
||||
`None` 任务超时 = 不限(旧语义保留);解析不出的
|
||||
格式仍留给 preflight(构造时机分工不变)。
|
||||
新测试:`PositiveConfigP1FixTest`。
|
||||
- P1-08(disk.py + executor.py `snapshot_vm`):剪枝
|
||||
事件外发(`prune_snapshots` / `check_snapshot_limits` /
|
||||
`record_snapshot` 均接受 `events` 列表:deleted /
|
||||
delete_failed / pruned_no_file);`snapshot_vm` 据此发
|
||||
`vm_snapshot_pruned` / `vm_snapshot_prune_failed`
|
||||
审计,失败路径(白名单/上限/ch-remote/落盘校验/
|
||||
登记拒绝)统一发 `vm_snapshot_failed` 审计再抛。
|
||||
新测试:`SnapshotAuditP1FixTest`。
|
||||
- P1-09:见 §15.1(行 100% / 分支 99% 分开写;
|
||||
`__init__.py` 计入分母说明;4 分支测试在
|
||||
`BranchCoverP1FixTest`)。
|
||||
- P1-10:本节即同步结果;§14.1/§14.7 已加“已被 §15
|
||||
取代”指针(历史数字保留不改);架构文档头范围与
|
||||
ADR-17 见 `docs/chv-architecture.md`;§13.1 快照数
|
||||
字按要求保留、合并前重跑(见 §15.1 末)。
|
||||
|
||||
### 15.3 安全语义未放宽清单
|
||||
|
||||
egress 默认 fail-closed、key seed 投递(provisioned 才
|
||||
投递、keyscan 下密钥 fail-closed)、磁盘删除(删失败
|
||||
审计 + 脏标记)、默认 provisioned、tap/mac/ip 校验、
|
||||
StrictHostKeyChecking 钉死、网关 loud fail 守卫——
|
||||
本轨一律未改动,只收紧(回落删除、失败可见性、
|
||||
check→act 加锁)。前端无改动,不存在绕后端白名单
|
||||
的新路径。
|
||||
|
||||
### 15.4 新增与改动文件
|
||||
|
||||
- 新增:`cloud/chv/locking.py`(StateLock)、
|
||||
`cloud/tests/test_chv_p1fix.py`(27 项)。
|
||||
- 改动:`cloud/chv/orphans.py`、`cloud/chv/disk.py`、
|
||||
`cloud/chv/executor.py`、`cloud/chv/experimental_pool.py`、
|
||||
`cloud/chv/config.py`;旧测试同步改:
|
||||
`cloud/tests/test_chv_arch_maint_fe.py`、
|
||||
`cloud/tests/test_chv_closeup.py`、
|
||||
`cloud/tests/test_chv_cover100.py`;
|
||||
文档:本节 + `docs/chv-architecture.md`(头范围 +
|
||||
ADR-17)。
|
||||
|
||||
### 15.5 逐项完成情况
|
||||
|
||||
P1-01~P1-10 全部修完(每项均有新测试或同步改的旧
|
||||
测试,见 §15.2;无“修不动”的项)。未修完的部分:
|
||||
无。但“修完”只等于代码层完成,不等于生产就绪,
|
||||
见 §15.6。
|
||||
|
||||
### 15.6 仍未验证项(原样保留,不冒充)
|
||||
|
||||
- 合并试验 P0-01 仍未做(本轨禁令):隔离演练区以
|
||||
当前远端 HEAD 为目标的三方合并 + 全量测试未跑,
|
||||
直接合入仍可能以链侧文件覆盖 main 新增功能。
|
||||
- CI 仍 UNSTABLE(账单秒级失败,本轨未改 CI 配置)。
|
||||
- KVM 宿主 provision、客机镜像真实构建与发布未做;
|
||||
真机验证 V-1~V-9 全部未跑。
|
||||
- 前端 live 点击验证未做;渲染测试未做。
|
||||
- 旧安全审计 No-Go 未复审、未推翻。
|
||||
|
||||
### 15.7 本轨逐项评分更新(目标 10,无一项硬写 10)
|
||||
|
||||
- 代码质量 9.8 → 9.8,未达 10:P1 语义缺陷已修,但
|
||||
分支覆盖 99% 未满、长函数门禁靠提取维持(边界脆弱)。
|
||||
差:代码内(小)。
|
||||
- 测试 9.8 → 9.9,未达 10:后端 389 项、前端 37 项
|
||||
全过,行覆盖 100% 恢复且口径诚实分开写;但真机
|
||||
用例 0 项已跑、分支 28 处部分。差:外部(真机)为主。
|
||||
- 文档 9.9 → 9.9,未达 10:§15 与 ADR-17 已同步,但
|
||||
§13.1 仍是旧快照、真机证据表仍空。差:外部。
|
||||
- 架构 9.7 → 9.7,未达 10:新增 flock 锁是并发语义
|
||||
收紧而非架构重构,ADR 取舍不变。差:外部。
|
||||
- 前端 9.6 → 9.6,未达 10:本轨未改前端。差:代码内
|
||||
(有意不做)+ 外部(live)。
|
||||
- 生产就绪 5.5 → 5.5,未达 10:P0-01 未做、CI 未绿、
|
||||
未合并、未部署、真机 0 项。差:外部为主。
|
||||
- 动态安全 2.0 → 2.0,未达 10:本轨无任何动态验证。
|
||||
差:外部。
|
||||
Reference in new issue
Block a user