Install Windows 11 from a disk image with --install-from-img
Reading the installation files through QEMU's emulated USB CD-ROM runs at a few MB/s on macOS. --install-from-img FILE (or WIN11_VM_INSTALL_IMG) attaches an installation disk image built by vm-images/build-windows-install-disk.sh as an NVMe disk instead, which is read about 15 times faster. The image is attached with snapshot=on because NVMe cannot report write protection and Windows fails on a read-only volume. Add windows11-arm64-install-speed.md with the analysis and measurements. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
946771c6af
commit
1732ec39d0
3 files changed
+205
-7
No files matched your search
+39
-6
@@ -126,14 +126,15 @@ else:
|
||||
)
|
||||
daemonize = False
|
||||
install_from_iso = False
|
||||
install_img = Path(env("WIN11_VM_INSTALL_IMG")) if env("WIN11_VM_INSTALL_IMG") else None
|
||||
download_only = False
|
||||
extra_args = []
|
||||
|
||||
|
||||
def usage(stream=sys.stdout):
|
||||
stream.write(f"""\
|
||||
Usage: {Path(sys.argv[0]).name} [--daemon] [--download-only] [--install-from-iso] [--state-dir DIR]
|
||||
[--rdp-port PORT] [--ssh-port PORT] [-- QEMU_ARGUMENT ...]
|
||||
Usage: {Path(sys.argv[0]).name} [--daemon] [--download-only] [--install-from-iso | --install-from-img FILE]
|
||||
[--state-dir DIR] [--rdp-port PORT] [--ssh-port PORT] [-- QEMU_ARGUMENT ...]
|
||||
|
||||
If the system disk (DIR/disk.qcow2, see --state-dir) is missing, create it from
|
||||
the Windows 11 QCOW2 base image.
|
||||
@@ -141,7 +142,8 @@ The VM hardware (accelerator, memory, CPUs, drives, devices) is defined in
|
||||
qemu/windows11.ini, which is rendered to qemu.ini in the state directory and
|
||||
loaded with QEMU's -readconfig, followed by qemu/windows11-<os>-<arch>.ini (os is linux or darwin, arch is amd64 or arm64, chosen from the host system and
|
||||
architecture or VM_IMAGE_ARCH). Later QEMU arguments override them, e.g. -- -m 4G -smp 4.
|
||||
Use --install-from-iso to perform an automatic ISO installation instead.
|
||||
Use --install-from-iso to perform an automatic ISO installation instead, or
|
||||
--install-from-img to install from a disk image built from the ISO.
|
||||
If it exists, start Windows normally without attaching installation media.
|
||||
|
||||
Options:
|
||||
@@ -149,6 +151,12 @@ Options:
|
||||
--download-only Download the VirtIO tools ISO if it is missing, then exit
|
||||
(the Windows ISO and base QCOW2 are supplied manually)
|
||||
--install-from-iso Install from ISO when the system disk is missing
|
||||
--install-from-img FILE
|
||||
Install from a disk image made by
|
||||
vm-images/build-windows-install-disk.sh instead of the ISO
|
||||
(implies --install-from-iso). It is attached as an NVMe
|
||||
disk, much faster than the emulated USB CD-ROM, and is
|
||||
never modified (overrides WIN11_VM_INSTALL_IMG)
|
||||
--state-dir DIR Directory for the VM disk, seed ISO and runtime files
|
||||
(default: .vm/windows11; overrides WIN11_VM_STATE_DIR)
|
||||
--rdp-port PORT Host port forwarded to guest RDP (default: 3389;
|
||||
@@ -160,6 +168,7 @@ Options:
|
||||
Environment variables:
|
||||
WIN11_VM_BASE_IMAGE Windows 11 base QCOW2 image (default: beside shared images)
|
||||
WIN11_VM_INSTALL_ISO Windows 11 installation ISO used with --install-from-iso
|
||||
WIN11_VM_INSTALL_IMG Installation disk image used instead of the ISO
|
||||
WIN11_VM_TOOLS_ISO VirtIO Windows tools ISO (default: resolved by shared image helper)
|
||||
WIN11_VM_RDP_PORT Host RDP port (default: 3389)
|
||||
WIN11_VM_SSH_PORT Host SSH port (default: 2222)
|
||||
@@ -184,6 +193,12 @@ while args:
|
||||
download_only = True
|
||||
elif arg == "--install-from-iso":
|
||||
install_from_iso = True
|
||||
elif arg == "--install-from-img":
|
||||
if not args:
|
||||
die(f"{arg} requires a file argument.", 2)
|
||||
install_img = Path(args.pop(0))
|
||||
elif arg.startswith("--install-from-img="):
|
||||
install_img = Path(arg.split("=", 1)[1])
|
||||
elif arg == "--state-dir":
|
||||
if not args:
|
||||
die(f"{arg} requires a directory argument.", 2)
|
||||
@@ -213,6 +228,9 @@ while args:
|
||||
usage(sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
if install_img:
|
||||
install_from_iso = True
|
||||
|
||||
if download_only:
|
||||
# The VirtIO tools ISO is the only medium the launcher downloads itself.
|
||||
if env("WIN11_VM_TOOLS_ISO"):
|
||||
@@ -245,8 +263,10 @@ if not disk_image.is_file():
|
||||
installing_from_iso = install_from_iso
|
||||
image_downloader = find_image_downloader()
|
||||
if install_from_iso:
|
||||
install_iso = Path(env("WIN11_VM_INSTALL_ISO")
|
||||
or capture([str(image_downloader), "--print-path", "windows11", "--iso"]))
|
||||
# The installation disk image replaces the ISO, which is then not needed.
|
||||
install_iso = None if install_img else Path(
|
||||
env("WIN11_VM_INSTALL_ISO")
|
||||
or capture([str(image_downloader), "--print-path", "windows11", "--iso"]))
|
||||
uses_shared_tools_iso = False
|
||||
if env("WIN11_VM_TOOLS_ISO"):
|
||||
tools_iso = Path(env("WIN11_VM_TOOLS_ISO"))
|
||||
@@ -262,7 +282,11 @@ if shutil.which(qemu_binary) is None:
|
||||
if installing:
|
||||
if shutil.which("qemu-img") is None:
|
||||
die("qemu-img is not installed.")
|
||||
if installing_from_iso:
|
||||
if install_img:
|
||||
if not install_img.is_file():
|
||||
die(f"Windows 11 installation disk image was not found: {install_img}\n"
|
||||
"Build it with vm-images/build-windows-install-disk.sh ISO OUTPUT.img")
|
||||
elif installing_from_iso:
|
||||
if not install_iso.is_file():
|
||||
die(f"Windows 11 ISO was not found: {install_iso}")
|
||||
elif not base_image.is_file():
|
||||
@@ -375,6 +399,15 @@ if installing_from_iso:
|
||||
device = (f"ide-cd,drive={media_id},bus={ide_bus},bootindex={boot_index}"
|
||||
if host_arch == "amd64"
|
||||
else f"usb-storage,drive={media_id},bootindex={boot_index}")
|
||||
if media_id == "install_media" and install_img:
|
||||
# snapshot=on: NVMe cannot report write protection, and Windows
|
||||
# writes to the volume it mounts, so a read-only drive makes it fail.
|
||||
# The writes go to a temporary overlay and the image stays unchanged.
|
||||
qemu_args += [
|
||||
"-drive", f"file={install_img},if=none,id={media_id},format=raw,snapshot=on",
|
||||
"-device", f"nvme,drive={media_id},serial=installer,bootindex={boot_index}",
|
||||
]
|
||||
continue
|
||||
qemu_args += [
|
||||
"-drive", f"file={media_file},if=none,id={media_id},media=cdrom,readonly=on",
|
||||
"-device", device,
|
||||
|
||||
Reference in new issue
Block a user