Skip to content

convert: fix boot order for multi-OS Windows guests#149

Open
ssahani wants to merge 2 commits intolibguestfs:masterfrom
ssahani:RHEL-122817-fix-boot-order-multi-os-windows
Open

convert: fix boot order for multi-OS Windows guests#149
ssahani wants to merge 2 commits intolibguestfs:masterfrom
ssahani:RHEL-122817-fix-boot-order-multi-os-windows

Conversation

@ssahani
Copy link
Copy Markdown
Contributor

@ssahani ssahani commented Mar 27, 2026

Use inspect.i_root to determine the boot disk for non-Linux guests, so the correct disk gets boot order=1 in the output XML.

Fixes: https://redhat.atlassian.net/browse/RHEL-161193

@rwmjones
Copy link
Copy Markdown
Member

What testing has been done on this patch?

@ssahani
Copy link
Copy Markdown
Contributor Author

ssahani commented Mar 29, 2026

What testing has been done on this patch?

It's hard to prepare a disk like this. I wrote a test case.

cd tests && srcdir=. LD_LIBRARY_PATH=/usr/local/lib ../run ./test-windows-multi-disk-boot-order.sh

@rwmjones
Copy link
Copy Markdown
Member

Since this is about Windows booting, a phony Windows test isn't really testing anything.

@ssahani
Copy link
Copy Markdown
Contributor Author

ssahani commented Mar 30, 2026

Since this is about Windows booting, a phony Windows test isn't really testing anything.

Yes Need to setup real env.

@ssahani
Copy link
Copy Markdown
Contributor Author

ssahani commented Apr 2, 2026

Test scenario creation:

Disk 1 — Blank data disk (blank-data.qcow2):

We just created an empty 10G qcow2 image with no partitions, no filesystem, nothing on it:

qemu-img create -f qcow2 /var/lib/libvirt/images/blank-data.qcow2 10G

It's only 196 KiB on disk since it's completely empty. The whole point of this disk is to sit as the first disk (sda) so the Windows disk gets pushed to sdb, which
is what triggers the bug.

Disk 2 — Windows 11 OS disk (win11-boot-test.qcow2):

This is a real Windows 11 installation from a working KVM guest. We installed Windows 11 in a VM normally and then copied the resulting disk image to
/var/lib/libvirt/images/win11-boot-test.qcow2. It's 15G with the standard Windows partition layout — EFI system partition on sda1, Microsoft reserved on sda2, the
actual Windows OS (C: drive) on sda3, and recovery partition on sda4.

Putting them together:

We defined a libvirt guest windows-multi-disk-test with both disks attached — blank-data as vda (first disk) and win11-boot-test as vdb (second disk). This way when
virt-v2v inspects the guest it sees Windows on /dev/sdb3, which is exactly the same situation as the original bug report where the user has multiple Windows OS
disks and selects the second one with --root /dev/sdb2.

virt-v2v via ./run to convert the guest, explicitly selecting the Windows root on the second disk:

  sudo LD_LIBRARY_PATH=/usr/local/lib VIRT_TOOLS_DATA_DIR=/usr/share/virt-tools \
    ./run virt-v2v \
    -i disk /var/lib/libvirt/images/blank-data.qcow2 \
           /var/lib/libvirt/images/win11-boot-test.qcow2 \
    -o local -os /tmp/v2v-multi-disk-test \
    --root /dev/sdb3 -v

Debug log confirms the fix is active:
get_target_boot_device: root /dev/sdb3 is on device /dev/sdb
target boot device: 1
The new code path in get_target_boot_device correctly used inspect.i_root (/dev/sdb3) to identify /dev/sdb as the boot device (index 1). Output XML has correct boot order:

Previously, get_target_boot_device in convert/convert.ml returned None immediately for all non-Linux guests, assuming Windows always boots from the first disk. The
fix adds a code path for non-Linux guests that:

Takes inspect.i_root (the user-selected root, e.g. /dev/sdb3)

Calls g#part_to_dev to get the parent disk (/dev/sdb)

Calls g#device_index to get the disk index (1)

Returns that index so the correct disk gets boot order='1'

This resolves the bug where multi-OS Windows guests couldn't boot into the selected OS after v2v conversion.


libvirt XML:
<?xml version='1.0' encoding='utf-8'?>
<domain type='kvm'>
 <!-- generated by virt-v2v 2.11.4 -->
 <name>blank-data</name>
 <metadata>
   <libosinfo:libosinfo xmlns:libosinfo='http://libosinfo.org/xmlns/libvirt/domain/1.0'>
     <libosinfo:os id='http://microsoft.com/win/11'/>
   </libosinfo:libosinfo>
 </metadata>
 <memory unit='KiB'>2097152</memory>
 <currentMemory unit='KiB'>2097152</currentMemory>
 <vcpu>1</vcpu>
 <cpu mode='host-model'/>
 <features>
   <acpi/>
   <apic/>
 </features>
 <os firmware='efi'>
   <firmware>
     <feature name='secure-boot' enabled='no'/>
   </firmware>
   <type arch='x86_64' machine='q35'>hvm</type>
 </os>
 <clock offset='localtime'/>
 <on_poweroff>destroy</on_poweroff>
 <on_reboot>restart</on_reboot>
 <on_crash>restart</on_crash>
 <devices>
   <disk type='file' device='disk'>
     <driver name='qemu' type='raw'/>
     <source file='/tmp/v2v-multi-disk-test/blank-data-sda'/>
     <target dev='sda' bus='sata'/>
     <boot order='2'/>
   </disk>
   <disk type='file' device='disk'>
     <driver name='qemu' type='raw'/>
     <source file='/tmp/v2v-multi-disk-test/blank-data-sdb'/>
     <target dev='sdb' bus='sata'/>
     <boot order='1'/>
   </disk>
   <interface type='network'>
     <source network='default'/>
     <model type='rtl8139'/>
   </interface>
   <video>
     <model type='vga' vram='16384' heads='1'/>
   </video>
   <graphics type='sdl'/>
   <memballoon model='none'/>
   <input type='tablet' bus='usb'/>
   <input type='mouse' bus='ps2'/>
   <console type='pty'/>
   <controller type='virtio-serial' model='virtio'/>
   <channel type='unix'>
     <target type='virtio' name='org.qemu.guest_agent.0'/>
   </channel>
 </devices>
</domain>

[  32.4] Finishing off
rm -rf -- '/tmp/v2vnbdkit.EfsqNG'

SRCDIR=$(srcdir) $(top_builddir)/run --test ./$< $@

# Make (dummy) multi-disk Windows images (for boot order testing).
windows-multi-disk-sda.img windows-multi-disk-sdb.img: make-windows-multi-disk-img.sh \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only works by accident (because of the .NOTPARALLEL directive in the Makefile). You have to use a stamp file to stop the command being run twice.

@rwmjones
Copy link
Copy Markdown
Member

rwmjones commented Apr 2, 2026

The bug reporter used two Windows instances rather than a blank disk, but fine I suppose.

Also please stop using LLMs, you'll not learn anything by using them.

The Resolves line should be Fixes and should refer to the original bug.

ssahani added 2 commits April 2, 2026 14:57
Use inspect.i_root to determine the boot disk for non-Linux guests,
so the correct disk gets boot order=1 in the output XML.

Fixes: https://redhat.atlassian.net/browse/RHEL-122817
Verify that when Windows is on the second disk, virt-v2v assigns
boot order 1 to the correct disk in the output XML.
@ssahani
Copy link
Copy Markdown
Contributor Author

ssahani commented Apr 2, 2026

The bug reporter used two Windows instances rather than a blank disk, but fine I suppose.

Also please stop using LLMs, you'll not learn anything by using them.

The Resolves line should be Fixes and should refer to the original bug.

It was hard to create this scenario. Shall update it

@ssahani ssahani force-pushed the RHEL-122817-fix-boot-order-multi-os-windows branch from 2c351f6 to 5ea8322 Compare April 2, 2026 13:34
@ssahani
Copy link
Copy Markdown
Contributor Author

ssahani commented Apr 2, 2026

Updated Thanks !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants