integration: VM drill for dedicated data disks
All checks were successful
CI/CD / typecheck (pull_request) Successful in 49s
CI/CD / lint (pull_request) Successful in 1m11s
CI/CD / test (pull_request) Successful in 1m14s
CI/CD / build (pull_request) Successful in 1m24s
CI/CD / publish-rpm (pull_request) Has been skipped
CI/CD / publish-deb (pull_request) Has been skipped

One real-VM test mirroring thebeast's topology: OS disk + two data disks
addressed by /dev/disk/by-id/ (virtio serials standing in for NVMe
serials). Fresh k8s-worker v2 install must put labelled whole-disk xfs
on each data disk and drop the matching LVs; a flagless reprovision must
rediscover both by label and remount them unformatted -- proven by
marker files AND unchanged filesystem UUIDs.

Harness: createPxeVm grows dataDisks (extra virtio disks with fixed
serials, <=20 chars or the guest by-id link truncates), provisionVm
passes the by-id paths to /api/install, virtioById exported.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V6HNx6cyr4J4CiMGCy1wkF
This commit is contained in:
Michal
2026-10-14 22:20:56 +01:00
parent b26733015f
commit 16659236f2
3 changed files with 201 additions and 1 deletions

View File

@@ -47,6 +47,15 @@ export interface PxeVmConfig {
*/
decoyNics?: number;
decoyNetwork?: string;
/**
* Extra blank data disks, attached after the OS disk. Each gets a fixed
* virtio serial, so inside the guest it has a stable
* /dev/disk/by-id/virtio-<serial> path -- the moral equivalent of the
* nvme-..._<serial> links the dedicated-data-disk feature requires on real
* hardware. virtio-blk truncates serials at 20 characters, so keep them
* short or the by-id link quietly won't match.
*/
dataDisks?: { serial: string; sizeGb: number }[];
}
/** Create a blank UEFI VM that PXE boots from the network. */
@@ -60,6 +69,14 @@ export function createPxeVm(config: PxeVmConfig): void {
const diskPath = join(IMAGE_DIR, `${config.name}.qcow2`);
run(`qemu-img create -f qcow2 "${diskPath}" ${config.diskSize}G`);
const dataDiskArgs: string[] = [];
for (const dd of config.dataDisks ?? []) {
if (dd.serial.length > 20) throw new Error(`virtio serial '${dd.serial}' exceeds 20 chars -- the guest by-id link would be truncated`);
const p = join(IMAGE_DIR, `${config.name}-${dd.serial}.qcow2`);
run(`qemu-img create -f qcow2 "${p}" ${dd.sizeGb}G`);
dataDiskArgs.push(`--disk=path=${p},format=qcow2,bus=virtio,serial=${dd.serial}`);
}
// UEFI firmware paths (Fedora)
if (arch === "aarch64") {
const aavmf = "/usr/share/edk2/aarch64/QEMU_EFI.fd";
@@ -79,6 +96,7 @@ export function createPxeVm(config: PxeVmConfig): void {
`--memory=${config.memory}`,
`--vcpus=${config.vcpus}`,
`--disk=path=${diskPath},format=qcow2,bus=virtio`,
...dataDiskArgs,
// Decoys first so they enumerate ahead of the PXE NIC. They are up and
// carry a lease, but have no route to the bastion.
...Array.from({ length: config.decoyNics ?? 0 }, () =>