fix(template): clean snapshot chain on deploy --force; seal cloud-init; harden first-boot IP
deploy-linux --force reused the VM directory but left any prior snapshot chain in place, so vmware-vdiskmanager refused the Step 4 resize with 'disk is part of a snapshot chain'. Add _clean_force_artifacts to remove snapshot deltas (.vmdk), .vmsn, .vmsd and stale .lck before resize. prepare-linux Step 7d seals the image: drop the stale cloud-init netplan (leaving only the MAC-agnostic 99-ci-dhcp-allnics), regenerate networkd config, and disable cloud-init so it never re-runs on linked clones. deploy user-data sets package_update/upgrade: false so cloud-init does not hold the dpkg lock at first boot and delay open-vm-tools past the IP-detection poll; the step-7 IP timeout is raised 300s -> 600s as a safety net for slow first boots. Adds unit tests for _clean_force_artifacts (snapshot chain, lock dir, clean-dir no-op) and updates prepare-linux stubs for the seal step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1854,6 +1854,9 @@ def _stub_prepare(
|
||||
return 0, "", ""
|
||||
if "echo connected" in cmd:
|
||||
return 0, "connected", ""
|
||||
# Step 7d cloud-init seal verification.
|
||||
if "cloud-init.disabled" in cmd and "echo DISABLED" in cmd:
|
||||
return 0, "DISABLED\nNO50\n", ""
|
||||
# validation script
|
||||
return 0, val_output, ""
|
||||
|
||||
@@ -2063,6 +2066,8 @@ def test_prepare_linux_happy_path_skip_flags(
|
||||
return 0, "", ""
|
||||
if "echo connected" in cmd:
|
||||
return 0, "connected", ""
|
||||
if "cloud-init.disabled" in cmd and "echo DISABLED" in cmd:
|
||||
return 0, "DISABLED\nNO50\n", ""
|
||||
return 0, "UserSudo:OK\nSudoNoPass:OK\n", ""
|
||||
|
||||
def fake_pl_stream(client: object, cmd: str) -> int:
|
||||
@@ -2119,3 +2124,55 @@ def test_prepare_linux_existing_snapshot_deleted(
|
||||
cmds = [" ".join(c) for c in run_calls]
|
||||
assert any("deleteSnapshot" in c for c in cmds)
|
||||
assert any("snapshot" in c and "deleteSnapshot" not in c for c in cmds)
|
||||
|
||||
|
||||
# ── _clean_force_artifacts (deploy-linux --force snapshot-chain cleanup) ────────
|
||||
|
||||
|
||||
def test_clean_force_artifacts_removes_snapshot_chain(tmp_path: Path) -> None:
|
||||
"""Snapshot delta/.vmsn/.vmsd/.lck are removed; base disk + vmx kept."""
|
||||
(tmp_path / "LinuxBuild2404.vmdk").write_text("base")
|
||||
(tmp_path / "LinuxBuild2404.vmx").write_text("vmx")
|
||||
(tmp_path / "LinuxBuild2404-000001.vmdk").write_text("delta")
|
||||
(tmp_path / "LinuxBuild2404-000002.vmdk").write_text("delta2")
|
||||
(tmp_path / "LinuxBuild2404-Snapshot7.vmsn").write_text("snap")
|
||||
(tmp_path / "LinuxBuild2404.vmsd").write_text("snapdb")
|
||||
(tmp_path / "LinuxBuild2404.vmdk.lck").write_text("lock")
|
||||
|
||||
removed = tmpl_mod._clean_force_artifacts(tmp_path, "LinuxBuild2404")
|
||||
|
||||
assert set(removed) == {
|
||||
"LinuxBuild2404-000001.vmdk",
|
||||
"LinuxBuild2404-000002.vmdk",
|
||||
"LinuxBuild2404-Snapshot7.vmsn",
|
||||
"LinuxBuild2404.vmsd",
|
||||
"LinuxBuild2404.vmdk.lck",
|
||||
}
|
||||
# Base disk and vmx survive (Step 4/5 overwrite them).
|
||||
assert (tmp_path / "LinuxBuild2404.vmdk").is_file()
|
||||
assert (tmp_path / "LinuxBuild2404.vmx").is_file()
|
||||
# Chain artifacts gone.
|
||||
assert not (tmp_path / "LinuxBuild2404-000001.vmdk").exists()
|
||||
assert not (tmp_path / "LinuxBuild2404.vmsd").exists()
|
||||
|
||||
|
||||
def test_clean_force_artifacts_removes_lock_directory(tmp_path: Path) -> None:
|
||||
"""Lock entries may be directories (VMware writes .lck dirs)."""
|
||||
lck = tmp_path / "LinuxBuild2404.vmx.lck"
|
||||
lck.mkdir()
|
||||
(lck / "M12345.lck").write_text("host")
|
||||
|
||||
removed = tmpl_mod._clean_force_artifacts(tmp_path, "LinuxBuild2404")
|
||||
|
||||
assert removed == ["LinuxBuild2404.vmx.lck"]
|
||||
assert not lck.exists()
|
||||
|
||||
|
||||
def test_clean_force_artifacts_noop_on_clean_dir(tmp_path: Path) -> None:
|
||||
"""A clean directory yields no removals and leaves the base disk."""
|
||||
(tmp_path / "LinuxBuild2404.vmdk").write_text("base")
|
||||
|
||||
removed = tmpl_mod._clean_force_artifacts(tmp_path, "LinuxBuild2404")
|
||||
|
||||
assert removed == []
|
||||
assert (tmp_path / "LinuxBuild2404.vmdk").is_file()
|
||||
|
||||
Reference in New Issue
Block a user