merge(chv-hybrid): 合入 B 轨——租约 + 排队 + 升级提示 + 网关门
合入 feat-chv-hybrid-b (667a427)。executor.py 两处内容冲突按 hunk
解决,全部取 B 侧;合入时发现 merge 复制出第二个 suspend_after_task
定义(A 版截断体),已删除。
集成统一(A/B 语义冲突三处,设计 §4.1 的 state 模型为准):
- state 模型:A 的 flag 模型(resident: True + legacy state)与 B
的 state 模型(state ∈ resident-active/paused/hibernated/demoted)
统一为 state 模型;_mark_resident_record 标记常驻时同时置
resident-active,_ensure_resident_capacity 同时认 flag 与 state。
- 容量等待:A 的 bool 版 _wait_for_capacity 改名 _poll_capacity,
B 的 raise 版保留原名;_wait_for_resident_slot 豁免已有常驻登记
的租户(它已占一个槽位,再等等于把自己的槽位算成满——A 轨
test_resident_cap_blocks_new_resident 第二腿在合入时因此失败,
已修并通过)。
- 档位大小写:A 用小写 paid/heavy,B 用 Paid/Heavy;比较一律走
_norm_tier + HYBRID_RESIDENT_TIERS(resident_tier_eligible 与
promote_to_resident 两处),fail-closed 语义不变。
- 严格快照校验翻为默认开启(设计 §2.2):_snapshot_strict_tenant
默认 True,显式 CHV_SNAPSHOT_STRICT_TENANT=0 才关闭;旧恢复
测试的 fixture 已登记带匹配 tenant 的快照,A 轨 legacy 测试改
为显式 opt-out 覆盖。
生产接线:worker 只调 dispatch_task,dispatch_task_hybrid 在生产
路径上无调用方;dispatch_task 顶部加一道门,warm_pool_size>=1 时
走 dispatch_task_hybrid,==0 时保持旧冷启语义(不成环:hybrid 的
<=0 分支退化为 dispatch_task_persistent,后者 <=0 调回 dispatch_task)。
旧网关测试更新(B 的语义变更):test_worker_gateway_guard_allows_chv
前加常驻登记;新增 test_worker_gateway_guard_denies_pool_vm。
测试:test_chv_hybrid_a/b 64 项 + 受影响旧测试 16 项(Gateway、
RestoreNoFallback、RestoreSnapshotTest)全部通过;全量待跑。
This commit is contained in:
commit
99d9e5771b
5 files changed
+1659
-120
No files matched your search
@@ -21,7 +21,9 @@ from types import SimpleNamespace
|
||||
|
||||
try:
|
||||
from cloud.chv.api_client import _unix_socket_api
|
||||
from cloud.chv.disk import check_disk_quota, provision_task_disk
|
||||
from cloud.chv.disk import (check_disk_quota, provision_task_disk,
|
||||
record_snapshot)
|
||||
from cloud.chv.executor import write_persistent_vm
|
||||
from cloud.chv.hostkeys import build_seed_disk, seed_disk_path
|
||||
from cloud.chv.experimental_pool import WarmPool
|
||||
from cloud.sandbox import (
|
||||
@@ -32,7 +34,9 @@ try:
|
||||
except ImportError:
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
|
||||
from cloud.chv.api_client import _unix_socket_api
|
||||
from cloud.chv.disk import check_disk_quota, provision_task_disk
|
||||
from cloud.chv.disk import (check_disk_quota, provision_task_disk,
|
||||
record_snapshot)
|
||||
from cloud.chv.executor import write_persistent_vm
|
||||
from cloud.chv.hostkeys import build_seed_disk, seed_disk_path
|
||||
from cloud.chv.experimental_pool import WarmPool
|
||||
from cloud.sandbox import (
|
||||
@@ -227,8 +231,13 @@ class RestoreNoFallbackTest(ChvFixCase):
|
||||
# feat-chv-secfix(L2):恢复源须在白名单目录内,
|
||||
# 本测试的意图是“起 VMM 前失败”,用 state_dir 下路径。
|
||||
snap_url = "file://" + os.path.join(self.state_dir, "snap", "x")
|
||||
# 严格快照校验(设计 §2.2,默认开启):恢复须登记带
|
||||
# tenant_id 且与请求方一致;本测试意图是 known-hosts
|
||||
# 门,登记与请求方同租户 p1 后流程才走到该门。
|
||||
record_snapshot(self.state_dir, "chv-r1", snap_url, 20.0,
|
||||
tenant_id="p1")
|
||||
with self.assertRaises(ChvFailure) as ctx:
|
||||
ex.restore_vm({"id": "r1"}, snap_url)
|
||||
ex.restore_vm({"id": "r1", "project_id": "p1"}, snap_url)
|
||||
self.assertEqual(ctx.exception.kind, "host_key_not_pinned")
|
||||
self.assertEqual(launches, [])
|
||||
|
||||
@@ -304,6 +313,14 @@ class GatewayExtraEnvTest(ChvFixCase):
|
||||
db_path = os.path.join(self.dir, "control.db")
|
||||
init_db(db_path)
|
||||
ex = self.make_exec()
|
||||
# 混合模式网关分流(设计 §6):网关任务只接常驻 VM。
|
||||
# 本测试的租户 p1(project_id → tenant)须有常驻有效态
|
||||
# 登记 + Paid 档位,否则 _check_gateway_vm_class 以
|
||||
# gateway_pool_denied 拒绝;池 VM 拒绝腿见下一测试。
|
||||
write_persistent_vm(self.state_dir, "p1", {
|
||||
"vm": "chv-persist-p1", "tenant_id": "p1",
|
||||
"state": "resident-active", "tier": "Paid",
|
||||
"origin": "task", "gitea_synced": False})
|
||||
worker = Worker(db_path, "/fake/host.py", executor=ex,
|
||||
env={"XCM_API_KEY": "test-placeholder"})
|
||||
task = {"id": "gw1", "project_id": "p1", "prompt": "做目标",
|
||||
@@ -330,6 +347,19 @@ class GatewayExtraEnvTest(ChvFixCase):
|
||||
os.path.join(self.state_dir, "chv-gw1",
|
||||
"ssh_host_ed25519_key")))
|
||||
|
||||
def test_worker_gateway_guard_denies_pool_vm(self):
|
||||
# 混合模式网关分流(设计 §6):无常驻租约的网关任务
|
||||
# 走池即以 gateway_pool_denied 明确拒绝,不偷偷放行。
|
||||
ex = self.make_exec()
|
||||
task = {"id": "gw2", "project_id": "p1", "prompt": "做目标",
|
||||
"goal_mode": 1,
|
||||
"_gateway_provider": "sub2api",
|
||||
"_gateway_env": {"SUB2API_API_KEY": "gwkey",
|
||||
"SUB2API_BASE_URL": "http://gw/"}}
|
||||
with self.assertRaises(ChvFailure) as ctx:
|
||||
ex.dispatch_task(task)
|
||||
self.assertEqual(ctx.exception.kind, "gateway_pool_denied")
|
||||
|
||||
|
||||
# -- P1-2 取消/清理/看门狗 ----------------------------------------------
|
||||
class CancelCleanupTest(ChvFixCase):
|
||||
|
||||
Reference in new issue
Block a user