From fe7250870e7297f2bc0ff5f14cc083a356e8b038 Mon Sep 17 00:00:00 2001 From: Guofang Date: Mon, 2 Nov 2026 11:19:48 +0800 Subject: [PATCH] Attach the cloud-init seed ISO only when the VM disk is created cloud-init reads the seed on the first boot only, so the Linux launchers now mount it just for the run that creates the overlay disk. The seed drive moves from the config files to the launcher arguments. Co-Authored-By: Claude Sonnet 5.5 --- qemu/debian13/config.ini | 11 ----------- qemu/fedora44/config.ini | 11 ----------- qemu/ubuntu2604/config.ini | 11 ----------- run-almalinux10.py | 14 ++++++++++---- run-debian13.py | 13 ++++++++++--- run-fedora44.py | 13 ++++++++++--- run-ubuntu2604.py | 13 ++++++++++--- 7 files changed, 40 insertions(+), 46 deletions(-) diff --git a/qemu/debian13/config.ini b/qemu/debian13/config.ini index 06c4301..5d364dc 100644 --- a/qemu/debian13/config.ini +++ b/qemu/debian13/config.ini @@ -39,17 +39,6 @@ driver = "virtio-blk-pci" drive = "disk0" -# cloud-init seed ISO. -[drive "seed0"] - if = "none" - format = "raw" - readonly = "on" - file = "${seed_image}" - -[device "seed0-dev"] - driver = "virtio-blk-pci" - drive = "seed0" - # The NIC is attached to the user-mode network "net0", which the launcher # defines with -netdev from qemu/debian13/forwards.conf because a config file # section cannot hold more than one hostfwd. diff --git a/qemu/fedora44/config.ini b/qemu/fedora44/config.ini index 9226d38..991f5ee 100644 --- a/qemu/fedora44/config.ini +++ b/qemu/fedora44/config.ini @@ -39,17 +39,6 @@ driver = "virtio-blk-pci" drive = "disk0" -# cloud-init seed ISO. -[drive "seed0"] - if = "none" - format = "raw" - readonly = "on" - file = "${seed_image}" - -[device "seed0-dev"] - driver = "virtio-blk-pci" - drive = "seed0" - # The NIC is attached to the user-mode network "net0", which the launcher # defines with -netdev from qemu/fedora44/forwards.conf because a config file # section cannot hold more than one hostfwd. diff --git a/qemu/ubuntu2604/config.ini b/qemu/ubuntu2604/config.ini index d033c75..af68ccb 100644 --- a/qemu/ubuntu2604/config.ini +++ b/qemu/ubuntu2604/config.ini @@ -39,17 +39,6 @@ driver = "virtio-blk-pci" drive = "disk0" -# cloud-init seed ISO. -[drive "seed0"] - if = "none" - format = "raw" - readonly = "on" - file = "${seed_image}" - -[device "seed0-dev"] - driver = "virtio-blk-pci" - drive = "seed0" - # The NIC is attached to the user-mode network "net0", which the launcher # defines with -netdev from qemu/ubuntu2604/forwards.conf because a config file # section cannot hold more than one hostfwd. diff --git a/run-almalinux10.py b/run-almalinux10.py index c157f30..2344497 100755 --- a/run-almalinux10.py +++ b/run-almalinux10.py @@ -208,7 +208,8 @@ for firmware_file in (uefi_code, uefi_vars_template): if not firmware_file.is_file(): die(f"required UEFI firmware was not found: {firmware_file}") -if not seed_image.is_file(): +creating = not disk_image.is_file() +if creating and not seed_image.is_file(): seed_builder = script_dir / "seediso" / "almalinux10" / "build-seed.sh" if not is_executable(seed_builder): die(f"seed image is missing and builder is unavailable: {seed_builder}") @@ -240,7 +241,7 @@ if pid_file.is_file(): die(f"the AlmaLinux virtual machine is already running (PID {old_pid}).") pid_file.unlink(missing_ok=True) -if not disk_image.is_file(): +if creating: run(["qemu-img", "create", "-q", "-f", "qcow2", "-F", "qcow2", "-b", str(base_image), str(disk_image), disk_size]) print(f"Created writable disk overlay: {disk_image}") @@ -261,12 +262,17 @@ qemu_args = [ "-drive", f"if=pflash,format=raw,file={uefi_vars}", "-drive", f"file={disk_image},if=none,id=disk0,format=qcow2", "-device", "virtio-blk-pci,drive=disk0", - "-drive", f"file={seed_image},if=none,id=seed0,format=raw,readonly=on", - "-device", "virtio-blk-pci,drive=seed0", "-netdev", vmforwards.netdev_argument(forwards), "-device", "virtio-net-pci,netdev=net0", ] +if creating: + # cloud-init reads the seed ISO on the first boot only (the users, keys, + # network and packages it sets up stay on the disk), so it is attached only + # when the disk is created. + qemu_args += ["-drive", f"file={seed_image},if=none,id=seed0,format=raw,readonly=on", + "-device", "virtio-blk-pci,drive=seed0"] + if machine_type == "virt": # Unlike q35, the "virt" machine has no default GPU or USB input devices. qemu_args += [ diff --git a/run-debian13.py b/run-debian13.py index 934e87f..e3290d5 100755 --- a/run-debian13.py +++ b/run-debian13.py @@ -208,7 +208,8 @@ for firmware_file in (uefi_code, uefi_vars_template): if not firmware_file.is_file(): die(f"required UEFI firmware was not found: {firmware_file}") -if not seed_image.is_file(): +creating = not disk_image.is_file() +if creating and not seed_image.is_file(): seed_builder = script_dir / "seediso" / "debian13" / "build-seed.sh" if not is_executable(seed_builder): die(f"seed image is missing and builder is unavailable: {seed_builder}") @@ -240,7 +241,7 @@ if pid_file.is_file(): die(f"the virtual machine is already running (PID {old_pid}).") pid_file.unlink(missing_ok=True) -if not disk_image.is_file(): +if creating: run(["qemu-img", "create", "-q", "-f", "qcow2", "-F", "qcow2", "-b", str(base_image), str(disk_image), disk_size]) print(f"Created writable disk overlay: {disk_image}") @@ -254,7 +255,6 @@ config_values = { "uefi_code": uefi_code_flash, "uefi_vars": uefi_vars, "disk_image": disk_image, - "seed_image": seed_image, } for key, value in config_values.items(): # QEMU's config file parser has no escape syntax for quoted values. @@ -285,6 +285,13 @@ qemu_args = [ "-display", display_backend, ] +if creating: + # cloud-init reads the seed ISO on the first boot only (the users, keys, + # network and packages it sets up stay on the disk), so it is attached only + # when the disk is created. + qemu_args += ["-drive", f"file={seed_image},if=none,id=seed0,format=raw,readonly=on", + "-device", "virtio-blk-pci,drive=seed0"] + print(f"Starting {host_arch} VM from {qemu_config_template} " f"and {qemu_platform_config}.", flush=True) vmforwards.print_forwards(forwards) diff --git a/run-fedora44.py b/run-fedora44.py index 6d6ac13..c31d467 100755 --- a/run-fedora44.py +++ b/run-fedora44.py @@ -210,7 +210,8 @@ for firmware_file in (uefi_code, uefi_vars_template): if not firmware_file.is_file(): die(f"required UEFI firmware was not found: {firmware_file}") -if not seed_image.is_file(): +creating = not disk_image.is_file() +if creating and not seed_image.is_file(): seed_builder = script_dir / "seediso" / "fedora44" / "build-seed.sh" if not is_executable(seed_builder): die(f"seed image is missing and builder is unavailable: {seed_builder}") @@ -242,7 +243,7 @@ if pid_file.is_file(): die(f"the Fedora virtual machine is already running (PID {old_pid}).") pid_file.unlink(missing_ok=True) -if not disk_image.is_file(): +if creating: run(["qemu-img", "create", "-q", "-f", "qcow2", "-F", "qcow2", "-b", str(base_image), str(disk_image), disk_size]) print(f"Created writable disk overlay: {disk_image}") @@ -256,7 +257,6 @@ config_values = { "uefi_code": uefi_code_flash, "uefi_vars": uefi_vars, "disk_image": disk_image, - "seed_image": seed_image, } for key, value in config_values.items(): # QEMU's config file parser has no escape syntax for quoted values. @@ -287,6 +287,13 @@ qemu_args = [ "-display", display_backend, ] +if creating: + # cloud-init reads the seed ISO on the first boot only (the users, keys, + # network and packages it sets up stay on the disk), so it is attached only + # when the disk is created. + qemu_args += ["-drive", f"file={seed_image},if=none,id=seed0,format=raw,readonly=on", + "-device", "virtio-blk-pci,drive=seed0"] + print(f"Starting Fedora 44 ({host_arch}) from {qemu_config_template} " f"and {qemu_platform_config}.", flush=True) vmforwards.print_forwards(forwards) diff --git a/run-ubuntu2604.py b/run-ubuntu2604.py index ec034be..249689c 100755 --- a/run-ubuntu2604.py +++ b/run-ubuntu2604.py @@ -210,7 +210,8 @@ for firmware_file in (uefi_code, uefi_vars_template): if not firmware_file.is_file(): die(f"required UEFI firmware was not found: {firmware_file}") -if not seed_image.is_file(): +creating = not disk_image.is_file() +if creating and not seed_image.is_file(): seed_builder = script_dir / "seediso" / "ubuntu2604" / "build-seed.sh" if not is_executable(seed_builder): die(f"seed image is missing and builder is unavailable: {seed_builder}") @@ -242,7 +243,7 @@ if pid_file.is_file(): die(f"the Ubuntu virtual machine is already running (PID {old_pid}).") pid_file.unlink(missing_ok=True) -if not disk_image.is_file(): +if creating: run(["qemu-img", "create", "-q", "-f", "qcow2", "-F", "qcow2", "-b", str(base_image), str(disk_image), disk_size]) print(f"Created writable disk overlay: {disk_image}") @@ -256,7 +257,6 @@ config_values = { "uefi_code": uefi_code_flash, "uefi_vars": uefi_vars, "disk_image": disk_image, - "seed_image": seed_image, } for key, value in config_values.items(): # QEMU's config file parser has no escape syntax for quoted values. @@ -287,6 +287,13 @@ qemu_args = [ "-display", display_backend, ] +if creating: + # cloud-init reads the seed ISO on the first boot only (the users, keys, + # network and packages it sets up stay on the disk), so it is attached only + # when the disk is created. + qemu_args += ["-drive", f"file={seed_image},if=none,id=seed0,format=raw,readonly=on", + "-device", "virtio-blk-pci,drive=seed0"] + print(f"Starting Ubuntu 26.04 ({host_arch}) from {qemu_config_template} " f"and {qemu_platform_config}.", flush=True) vmforwards.print_forwards(forwards)