fix(chv-hybrid): p2 热插盘 body 补 image_type + 非 2xx 记 CHV 原话
ci / test (push) Failing after 48m54s

- attach_tenant_data_disk:PUT /vm.add-disk body 由 {"path"} 改为
  {"path", "image_type"}(复用 _disk_image_type,与 create 时盘
  同款;租户数据盘 raw → Raw)。CHV v54 已移除盘格式自动探测,
  只发 path 时真机回 400(p2 复测);证据:v54 release notes
  “autodetection removed”、ch-remote v54.0 add-disk --help 含
  image_type=<raw,qcow2,...>、本仓 _vm_config_disks 的 vm.boot
  400 "Image type required for disk" 真机实测(2026-11-07)。
- 非 2xx 时 body 原样记入 data_disk_attach_failed 审计事件与
  ChvFailure detail(新增 _api_error_body_text,截断上限 500
  字符:CHV 400 体通常一行 JSON <200 字符,500 足够装完整原话;
  超长截断并标 "…(已截断)",保审计与异常串有界);同类问题一并
  修 _create_vm(vm_create_failed 带 body)。fail-closed 语义
  不变(失败仍销毁/回落,不把未挂盘的 VM 当已绑定)。
- 单测:attach 成功断言 image_type=Raw;新增 400 body 记录用例
  与超长截断用例;vm.create 失败 body 用例。
- 真机探针:chv-multi-host/probe-add-disk.py(px2,旧形状 A/B +
  产品函数成功路径 + 两条 400 记录路径,待复测代理跑)。

全量:Ran 4678,OK (skipped=14),0 失败/错误。
This commit is contained in:
host committed 2026-11-09 06:12:21 +00:00
1 parent 6c03ac9b0f
commit 0dc8328ecc
3 files changed
+101 -8

No files matched your search

+47
View File
@@ -489,6 +489,9 @@ class DataDiskAttachTest(HybridACase):
(m, p, pl) for m, p, pl in self.api_calls
if p == "/vm.add-disk")
self.assertEqual(payload["path"], out["data_disk"])
# CHV v54 已移除盘格式自动探测:热插盘 body 须与 create
# 时盘同款带 image_type(租户数据盘是 raw 稀疏盘 → Raw)。
self.assertEqual(payload["image_type"], "Raw")
# 客内挂载脚本被调过(chv-data-mount)。
self.assertTrue(any(
"/usr/local/bin/chv-data-mount" in call
@@ -496,6 +499,50 @@ class DataDiskAttachTest(HybridACase):
self.assertEqual(
read_vm_tenant(self.state_dir, "chv-pool-0"), "tenant-a")
def test_attach_failure_records_chv_body(self):
# p2 修复:非 2xx 时 CHV 的原话(body)须进异常 detail
# 与审计事件,不再丢弃;失败仍 fail-closed(不挂载、不
# 写归属标记)。
def api(socket_path, method, path, payload=None):
self.api_calls.append((method, path, payload))
if path == "/vm.add-disk":
return (400, {"error": "Image type required for disk"})
return (200, {})
ex = self.make_exec(api_client=api)
with self.assertRaises(ChvFailure) as ctx:
ex.attach_tenant_data_disk(
self._task(project="tenant-a"), "chv-pool-0")
self.assertEqual(ctx.exception.kind, "data_disk_attach_failed")
self.assertIn("Image type required for disk", str(ctx.exception))
self.assertIn("status=400", str(ctx.exception))
details = self._event_details("data_disk_attach_failed")
self.assertEqual(len(details), 1)
self.assertIn("Image type required for disk", details[0])
self.assertIn("status=400", details[0])
# 挂载脚本没跑、归属标记没写。
self.assertFalse(any(
"/usr/local/bin/chv-data-mount" in call
for call in self.calls if call and call[0] == "ssh"))
self.assertIsNone(read_vm_tenant(self.state_dir, "chv-pool-0"))
def test_attach_failure_truncates_long_body(self):
# 超 500 字符的 body 只记前 500 字符并标明,不把整段
# 塞进审计与异常。
def api(socket_path, method, path, payload=None):
self.api_calls.append((method, path, payload))
if path == "/vm.add-disk":
return (400, {"error": "E" * 600})
return (200, {})
ex = self.make_exec(api_client=api)
with self.assertRaises(ChvFailure) as ctx:
ex.attach_tenant_data_disk(
self._task(project="tenant-a"), "chv-pool-0")
self.assertIn("…(已截断)", str(ctx.exception))
self.assertNotIn("E" * 600, str(ctx.exception))
details = self._event_details("data_disk_attach_failed")
self.assertEqual(len(details), 1)
self.assertIn("…(已截断)", details[0])
def test_dispatch_pool_hit_binds_tenant_disk_and_destroys_vm(self):
ex = self.make_exec()
ex.prewarm_clean_pool(slot=0)