feat(chv-guest): seed 附加项供客机用户与静态网络(wake 路径前置)
wake_vm 在 WSL 台架上跑通需要客机身份与网络:镜像本身不建 用户、tap 无 DHCP,缺 users 块的 VM 登不进去、缺 network-config 的 VM 拿不到静态 IP。最小补法(复用 write_seed 机制): - hostkeys.write_seed 新增 user_data_extra(原样追加进 user-data,供 users: 块)与 network_config(写 seed network-config 文件,0600);附加项含 runcmd: 即 ValueError - config _seed_fragment:CHV_SEED_USER_DATA_EXTRA_FILE / CHV_SEED_NETWORK_CONFIG_FILE(只存路径) - executor._seed_extras 在 wake 起 VMM 前读入,缺失即 ChvFailure seed_extra_missing;provision_host_key 透传 - README §7 残留更新:guest-env 集成已做 - 测试:test_chv_gitea_sync 新增 5 项(写盘/禁 runcmd/ 配置映射/wake 带附加项/缺失 fail-closed)
This commit is contained in:
1 parent
e7f699c62b
commit
d7cc482ed5
5 files changed
+184
-11
No files matched your search
@@ -407,6 +407,82 @@ class WakeGuestEnvCase(unittest.TestCase):
|
||||
self.assertEqual(self.launches, [])
|
||||
|
||||
|
||||
# -- (4b) seed 附加项(users 块 + network-config)------------------------
|
||||
class SeedExtrasTest(unittest.TestCase):
|
||||
USERS_BLOCK = ("users:\n"
|
||||
" - name: chv\n"
|
||||
" sudo: ALL=(ALL) NOPASSWD:ALL\n"
|
||||
" shell: /bin/bash\n"
|
||||
" ssh_authorized_keys:\n"
|
||||
" - ssh-ed25519 AAAAfake chv-guest\n")
|
||||
NETCFG = ("version: 2\nethernets:\n ens4:\n"
|
||||
" addresses: [192.168.10.10/24]\n")
|
||||
|
||||
def test_write_seed_extras(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
seed_dir = os.path.join(tmp, "seed")
|
||||
write_seed(seed_dir, "vm1", "PRIV", "ssh-ed25519 AAAAx",
|
||||
user_data_extra=self.USERS_BLOCK,
|
||||
network_config=self.NETCFG)
|
||||
with open(os.path.join(seed_dir, "user-data")) as fh:
|
||||
content = fh.read()
|
||||
with open(os.path.join(seed_dir, "network-config")) as fh:
|
||||
net = fh.read()
|
||||
net_mode = oct(os.stat(
|
||||
os.path.join(seed_dir, "network-config")).st_mode
|
||||
& 0o777)
|
||||
parsed = yaml.safe_load(content)
|
||||
self.assertNotIn("runcmd", parsed)
|
||||
self.assertIn("users:", content)
|
||||
self.assertIn("ssh-ed25519 AAAAfake chv-guest", content)
|
||||
self.assertEqual(net, self.NETCFG)
|
||||
self.assertEqual(net_mode, "0o600")
|
||||
|
||||
def test_write_seed_extra_with_runcmd_rejected(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
with self.assertRaises(ValueError):
|
||||
write_seed(os.path.join(tmp, "seed"), "vm1",
|
||||
"PRIV", "ssh-ed25519 AAAAx",
|
||||
user_data_extra="runcmd:\n - echo hi\n")
|
||||
|
||||
def test_config_fragment_maps_seed_files(self):
|
||||
from cloud.chv.config import build_chv_config
|
||||
cfg = build_chv_config({}, {
|
||||
"CHV_SEED_USER_DATA_EXTRA_FILE": "/tmp/users.yaml",
|
||||
"CHV_SEED_NETWORK_CONFIG_FILE": "/tmp/net.yaml"})
|
||||
self.assertEqual(cfg.seed_user_data_extra_file, "/tmp/users.yaml")
|
||||
self.assertEqual(cfg.seed_network_config_file, "/tmp/net.yaml")
|
||||
self.assertIsNone(build_chv_config({}, {}).seed_user_data_extra_file)
|
||||
|
||||
|
||||
class WakeSeedExtrasCase(WakeGuestEnvCase):
|
||||
def test_wake_with_seed_extras(self):
|
||||
users_path = os.path.join(self.dir, "users.yaml")
|
||||
net_path = os.path.join(self.dir, "net.yaml")
|
||||
with open(users_path, "w") as fh:
|
||||
fh.write(SeedExtrasTest.USERS_BLOCK)
|
||||
with open(net_path, "w") as fh:
|
||||
fh.write(SeedExtrasTest.NETCFG)
|
||||
ex = self.make_exec(env_extra={
|
||||
"CHV_SEED_USER_DATA_EXTRA_FILE": users_path,
|
||||
"CHV_SEED_NETWORK_CONFIG_FILE": net_path})
|
||||
out = ex.wake_vm({"id": "extra1"})
|
||||
self.assertEqual(out["state"], "running")
|
||||
seed_dir = os.path.join(self.state_dir, "chv-extra1", "seed")
|
||||
with open(os.path.join(seed_dir, "user-data")) as fh:
|
||||
self.assertIn("ssh-ed25519 AAAAfake chv-guest", fh.read())
|
||||
with open(os.path.join(seed_dir, "network-config")) as fh:
|
||||
self.assertEqual(fh.read(), SeedExtrasTest.NETCFG)
|
||||
|
||||
def test_wake_missing_seed_extra_fails_closed(self):
|
||||
ex = self.make_exec(env_extra={
|
||||
"CHV_SEED_USER_DATA_EXTRA_FILE": "/nonexistent/users.yaml"})
|
||||
with self.assertRaises(ChvFailure) as ctx:
|
||||
ex.wake_vm({"id": "extra2"})
|
||||
self.assertEqual(ctx.exception.kind, "seed_extra_missing")
|
||||
self.assertEqual(self.launches, [])
|
||||
|
||||
|
||||
# -- (5) worker ---------------------------------------------------------
|
||||
class WorkerGiteaSyncTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in new issue
Block a user