Skip to content

Can't boot UEFI VM after migration - grub configuration problem - #160

Open
sparimi-rh wants to merge 1 commit into
libguestfs:masterfrom
sparimi-rh:rhel173538
Open

Can't boot UEFI VM after migration - grub configuration problem#160
sparimi-rh wants to merge 1 commit into
libguestfs:masterfrom
sparimi-rh:rhel173538

Conversation

@sparimi-rh

Copy link
Copy Markdown

UEFI boot mode based Linux VM, which reference /boot and /boot/efi partitions by device files (e.g. /dev/sdaX) in /etc/fstab, fail to boot post migration as virt-v2v re-writes the grub boot loader if it finds references to device files instead of disk UUIDs. The libguestfs appliance is configured to use BIOS boot mode. This causes the target VM's grub to be configured in BIOS boot mode. The target VM fails to boot in Qemu/KVM environment. The solution is to replace the BIOS boot mode specific grub commands which loads Linux kernel and init RAM disk, with UEFI boot mode specific commands. This is done only if source VM is in UEFI mode.

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

UEFI boot mode based Linux VM, which reference /boot and /boot/efi
partitions by device files (e.g. /dev/sdaX) in /etc/fstab, fail to
boot post migration as virt-v2v re-writes the grub boot loader if
it finds references to device files instead of disk UUIDs. The
libguestfs appliance is configured to use BIOS boot mode. This
causes the target VM's grub to be configured in BIOS boot mode.
The target VM fails to boot in Qemu/KVM environment. The solution
is to replace the BIOS boot mode specific grub commands which loads
Linux kernel and init RAM disk, with UEFI  boot mode specific
commands. This is done only if source VM is in UEFI mode.

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

Signed-off-by: Srihari Parimi <sparimi@redhat.com>
Comment thread convert/convert_linux.ml
if g#exists grub_cfg then (
try
ignore (g#sh (sprintf "sed -i 's/\\blinux16\\b/linuxefi/g;
s/\\binitrd16\\b/initrdefi/g' %s"

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.

We wouldn't normally want to run commands out of the guest like this. Augeas lets us programatically edit files in the guest which is considerably safer.

A bigger question that isn't answered is why do we need to change these linux16 commands? What is that doing exactly?

Also the commit message doesn't really explain anything, at least not in terms that I can understand. An example would go a long way.

@sparimi-rh sparimi-rh Jul 17, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Hi @rwmjones, Here is an explanation of what is happening and significance of linux16/initrd16 in failure case

  1. Guest VM is configured with EFI boot mode - Guest VM would have /sys/firmware/efi via sys FS mount
  2. Supermin appliance is configured in Legacy BIOS boot mode (NO /sys/firmware/efi)
  3. The /etc/fstab modified to use /dev/sdaX for mount points {/boot, /boot/efi}, instead of the normal mkfs created UUID reference. This was done in the source VM in the VMware
  4. supermin appliance conversion reads the /etc/fstab,
    • if it finds UUIDs, it does NOT invoke grub configuration change
    • if it finds /dev/sdaX instead, it decides that there is a need to re-write the grub configuration. These device files need to be replaced with virtio block storage files.
  5. For regenerating the Grub configuration,
  6. Guest VM's (storage mounted) grub configuration scripts (RHEL 7.9 /etc/grub.d/10_linux) are used
  7. Supermin's Legacy boot mode becomes and input - this ends up generating linux16, initrd16 - even though the Guest VM is EFI based.
  8. When the system boots, UEFI firmware fails to recognize the {linux16, initrd16}

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.

  1. The /etc/fstab modified to use /dev/sdaX for mount points {/boot, /boot/efi}, instead of the normal mkfs created UUID reference. This was done in the source VM in the VMware

Was this change made after the VM was created (and if so, why?)

As an aside we should really be rewriting any /dev/sdX references in /etc/fstab as UUIDs, at least for all modern Linuxes that support it. We've had other issues with leaving device references there in the past that would be solved if they were UUIDs.

I don't understand points 5-8 TBH.

Probably best to really go right back to basics and simplify everything. What does linux16 etc mean? What do the bootloader files look like before conversion? What commands are run now and what do they do? Why is what they are doing now wrong? What should we be doing instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Was this change made after the VM was created (and if so, why?)

Yes this change was made after the VM was created (source VM in VMware) to reproduce the problem described in the Jira issue.

As an aside we should really be rewriting any /dev/sdX references in /etc/fstab as UUIDs, at least for all modern Linuxes that support it. We've had other issues with leaving device references there in the past that would be solved if they were UUIDs.

The first idea that occurred to me was replace the /dev/sdX references with UUID. But this idea of replacing GRUB strings (linux16, initrd16) with (linuxefi, initrdefi) came from problem description in the Jira. Now as you say - it is better t o use UUIDs for future proofing. I will work upon that

Probably best to really go right back to basics and simplify everything. What does linux16 etc mean? What do the bootloader files look like before conversion? What commands are run now and what do they do? Why is what they are doing now wrong? What should we be doing instead?

Let me get back on this

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.

I really think using UUIDs is going to be better, assuming that this would fix the problem as well.

Using /dev/ devices in /etc/fstab isn't stable since this change was made to Linux: https://bugzilla.redhat.com/show_bug.cgi?id=1804207#c0 This change to Linux (probably) doesn't affect RHEL 7 specifically, but it does affect later versions, and using UUIDs has been suggested as the solution for other problems in the past.

@sparimi-rh sparimi-rh Jul 22, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@rwmjones, Here are the answers to the questions - for sake of readability, I split your questions into multiple lines

What does linux16 etc mean?

  • linux16, initrd16 seems to be specific to RHEL7 and may be older versions. Generated by RHEL7 /etc/grub/10_linux configuration script if it DOES NOT detect the system to be configured in UEFI boot mode (Absence of /sys/firmware/efi)
  • It is supported on Legacy BIOS systems and these strings are GRUB commands triggering a specific HW boot protocol

What do the bootloader files look like before conversion?

  • Relevant Snippet of bootloader file /boot/efi/EFI/redhat/grub.cfg in the Source VM. It shows use linuxefi, initrdefi which get generated for systems which are in UEFI bootmode. Point to the kernel and initramfs to load
### BEGIN /etc/grub.d/10_linux ###
menuentry 'Red Hat Enterprise Linux Server (3.10.0-1160.el7.x86_64) 7.9 (Maipo)' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.el7.x86_64-advanced-6a608d01-5254-46e5-85ff-d71679eac669' {
        load_video
...
...
        linuxefi /vmlinuz-3.10.0-1160.el7.x86_64 root=/dev/mapper/rhel-root ro crashkernel=auto rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet
        initrdefi /initramfs-3.10.0-1160.el7.x86_64.img
}

  • Post conversion too, the GRUB configuration file MUST have the same. However,in RHEL 7 case, linux16, initrd16 are generated because the Guest VM's (RHEL 7) GRUB config script /etc/grub.d/10_linux is running inside libguestfs appliance that is based on Legacy BIOS.

What commands are run now and what do they do?

  • virt-v2v runs grub2-mkconfig under the following conditions (source file convert/convert_linux.ml)
    • if contents of /etc/fstab entries which had a change from /dev/sd* to corresponding Virtio storage devices /dev/vd*.
    • if GRUB_CMDLINE_LINUX has "resume=" (device or part used for hibernation) was modified.
    • /etc/crypttab - replaces occurrence of /dev/sd* with corresponding UUIDs. This was implemented for sles12sp5

Why is what they are doing now wrong?

  • Change the /dev/sd* to /dev/vd* have potential of causing disk access problems, invalid boot devices etc.
  • Replacement with UUIDs NOT being done in /etc/fstab. This can cause problems when the migrated VM boots.
  • GRUB_CMDLINE_LINUX may have root= having /dev/sd* device. So this can cause boot crash.

What should we be doing instead?

  • Replacement with UUIDs should also be carried out in /etc/fstab entries too
  • In /etc/default/grub, for GRUB_CMDLINE_LINUX, replace any occurrence of root=/dev/sd* with UUID
  • Finally if GRUB config was indeed executed, replace linux16, initrd16 with linuxefi, initrdefi

@rwmjones

Copy link
Copy Markdown
Member

I'm going to speak clearly now so you understand my position here.

I can only review what's in the upstream pull request, and currently it's the same as it always was. We can't run commands like sed from the guest, so the change is wrong.

This change will be run on 1000s of VMs per day, across hundreds of customers, on critical workloads of all kinds (some life safety critical) and it absolutely cannot mess up.

It must do the minimum thing possible that fixes the problem. As an example, if the file doesn't need to be changed (eg there are no linux16 directives) then it must not touch the file at all.

We don't have good QE still, for reasons outside our control, so everyone needs to clearly understand what the change does and why.

And I still do not understand this change because it hasn't been explained clearly to me. I can read code myself, I don't need someone to explain what code does. I need to know exactly why this is being done.

So, no.

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