feat: CHV 审核修复(P0+P1,堆叠于 #230)

P0:seed 磁盘 CIDATA ISO 挂进 VmConfig 第二块只读盘;
restore provisioned 下复用钉死 known_hosts、缺失 fail-fast
绝不 keyscan;preflight 拦截 CHV_DISK_MODE=reuse(显式
实验二次确认 + 审计放行);SSH 目标选客机 IP 方案(显式
host > net 静态 ip > 显式转发宣称回环,三者皆无 fail-fast)。
P1:网关 extra_env 经 SSH env 前缀注入、worker 守卫收窄到
Local/CHV;取消/清理/看门狗接 CHV 通用路径;WarmPool
acquire 内 resume;容量门持久化计数;磁盘配额总量+余量
与已存在磁盘校验重拷;API 按 Content-Length 验完整性;
快照 file:// 验落盘再 shutdown;execute 死端口归类
vm_not_running。
P2 全部排除未做(用户范围收窄令,留待以后一轨)。
测试:原 84 + 新增 29 = 113 项,mock,无真 VM。
This commit is contained in:
host committed 2026-10-31 01:54:13 +00:00
1 parent 22b83f118a
commit 9771ed9e8c
13 files changed
+1231 -128

No files matched your search

+32 -18
View File
@@ -34,34 +34,48 @@ def known_hosts_path(state_dir, vm_name):
def build_ssh_command(ssh_port, ssh_key, ssh_user, egress_proxy,
known_hosts_file, inner_cmd):
known_hosts_file, inner_cmd, ssh_host="127.0.0.1",
extra_env=None):
"""构造 SSH 命令:ssh -p <端口> -i <key 文件> + 钉死选项
+ user@127.0.0.1 + 客内命令。
+ user@<ssh_host> + 客内命令。
与 #216 的区别只有 host key 选项:StrictHostKeyChecking=yes
+ UserKnownHostsFile=<每 VM 文件>,不再是 no + /dev/null。
BatchMode=yes 不变(绝不交互问 host key / 口令)。
feat-chv-fix(P0-4):ssh_host 不再在传输层写死回环,
由执行器解析传入(显式 CHV_SSH_HOST / net 客机 IP /
显式转发宣称下的回环);本函数缺省回环仅为旧调用点
兼容,执行器路径绝不依赖该缺省。
extra_env(feat-chv-fix,P1-1 网关注入):经同一 env
前缀进客机环境(与 egress 代理前缀同款机制),不进
镜像/代码/prompt;值本身只出现在宿主侧 ssh argv(与
worker 同一信任边界),执行器绝不把完整命令记入日志。
egress_proxy 已设时客内命令前加 env 前缀(代理地址本身
不是密钥;客机出口只走该白名单代理)。"""
inner = list(inner_cmd)
env_assignments = []
if extra_env:
for key in sorted(extra_env):
env_assignments.append("%s=%s" % (key, extra_env[key]))
if egress_proxy:
inner = ["env",
"HTTPS_PROXY=%s" % egress_proxy,
"HTTP_PROXY=%s" % egress_proxy,
"NO_PROXY=localhost,127.0.0.1"] + inner
env_assignments += [
"HTTPS_PROXY=%s" % egress_proxy,
"HTTP_PROXY=%s" % egress_proxy,
"NO_PROXY=localhost,127.0.0.1"]
if env_assignments:
inner = ["env"] + env_assignments + inner
return ["ssh", "-p", str(ssh_port),
"-i", ssh_key,
"-o", "StrictHostKeyChecking=yes",
"-o", "UserKnownHostsFile=%s" % known_hosts_file,
"-o", "BatchMode=yes",
"%s@127.0.0.1" % ssh_user] + inner
"%s@%s" % (ssh_user, ssh_host)] + inner
def parse_keyscan_output(text):
"""从 ssh-keyscan 的 stdout 里挑出本机回环端口的 host key
行:形如 "[127.0.0.1]:<port> ssh-ed25519 AAAA..."(-p 时
的标准写法)或 "127.0.0.1 ssh-rsa AAAA..."。其它主机行、
注释行、空行一律丢掉,绝不把陌生主机的 key 写进文件。"""
def parse_keyscan_output(text, host="127.0.0.1"):
"""从 ssh-keyscan 的 stdout 里挑出目标主机的 host key
行:形如 "[<host>]:<port> ssh-ed25519 AAAA..."(-p 时
的标准写法)或 "<host> ssh-rsa AAAA..."。其它主机行、
注释行、空行一律丢掉,绝不把陌生主机的 key 写进文件。
host 缺省回环仅为旧调用点兼容;客机 IP 方案下应传
解析出的客机 IP。"""
kept = []
for line in (text or "").splitlines():
line = line.strip()
@@ -70,9 +84,9 @@ def parse_keyscan_output(text):
parts = line.split()
if len(parts) < 3:
continue
host, keytype = parts[0], parts[1]
if host != "127.0.0.1" \
and not host.startswith("[127.0.0.1]:"):
line_host, keytype = parts[0], parts[1]
if line_host != host \
and not line_host.startswith("[%s]:" % host):
continue
if not keytype.startswith("ssh-"):
continue