Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions test/kickstart-templates/includes/main-prologue.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,66 @@ timezone UTC
text
reboot

# Work around bootupd 0.2.31 regression where "bootupctl backend install --auto"
# fails with "No update metadata for component BIOS/EFI found" in QEMU/KVM VMs.
# Make have_bootupd() return False so anaconda uses the legacy _move_grub_config()
# path for proper ostree boot configuration, then install GRUB to MBR/ESP in %post.
# The %pre runs before anaconda imports the rpm-ostree payload module.
%pre --log=/dev/console
UTIL_FILE=$(find /usr/lib*/python3*/site-packages/pyanaconda/modules/payloads/payload/rpm_ostree -name util.py 2>/dev/null | head -1)
if [ -n "${UTIL_FILE}" ] && grep -q 'def have_bootupd' "${UTIL_FILE}"; then
sed -i '/def have_bootupd/a\ return False' "${UTIL_FILE}"
find "$(dirname "${UTIL_FILE}")" -name '__pycache__' -type d -exec rm -rf {} + 2>/dev/null || true
fi
%end

%post --nochroot --log=/dev/console
# Install GRUB bootloader manually since bootupd was bypassed above.
BOOT_DISK=$(lsblk -ndo PKNAME "$(findmnt -no SOURCE /mnt/sysroot)" 2>/dev/null | head -1)
[ -z "${BOOT_DISK}" ] && BOOT_DISK=vda
if [ -d /sys/firmware/efi ]; then
# EFI: remove stale grub.cfg from ESP to avoid overlay resolution
# errors (BZ#1575957), then reinstall the EFI bootloader.
rm -f /mnt/sysroot/boot/efi/EFI/*/grub.cfg 2>/dev/null || true
EFI_TARGET=x86_64-efi
[ "$(uname -m)" = "aarch64" ] && EFI_TARGET=arm64-efi
grub2-install --target="${EFI_TARGET}" --efi-directory=/mnt/sysroot/boot/efi \
--boot-directory=/mnt/sysroot/boot --no-nvram "/dev/${BOOT_DISK}" 2>&1 || true
else
# BIOS: install GRUB stage1 to MBR.
grub2-install --target=i386-pc --boot-directory=/mnt/sysroot/boot "/dev/${BOOT_DISK}" 2>&1 || true
fi
# Generate grub.cfg with BLS support for ostree boot entries.
# Use the boot partition UUID for the search command since the
# partition may not have a filesystem label.
BOOT_UUID=$(lsblk -ndo UUID "$(findmnt -no SOURCE /mnt/sysroot/boot)" 2>/dev/null)
cat > /mnt/sysroot/boot/grub2/grub.cfg << GRUBEOF
set timeout=5
load_video
set gfx_payload=keep
insmod all_video
search --no-floppy --set=root --fs-uuid ${BOOT_UUID}

# Load grubenv for boot counter and saved entry support.
# The boot counter is used by greenboot to track failed boots and
# trigger automatic rollback to the previous ostree deployment.
load_env

if [ "\${boot_success}" != "1" ] && [ "\${boot_counter}" -gt 0 ]; then
set boot_counter=\$((\${boot_counter} - 1))
save_env boot_counter
fi

if [ "\${boot_success}" = "1" ] || [ "\${boot_counter}" -gt 0 ]; then
set default=0
else
set default=1
fi

blscfg
GRUBEOF
%end
Comment on lines +7 to +65

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

What is the pyanaconda rpm_ostree util.py have_bootupd() function signature and implementation in RHEL 9.8?

💡 Result:

In RHEL 9.8 (and consistent with recent versions of the Anaconda installer), the have_bootupd function is a utility designed to detect whether the bootupd utility is present and applicable for an OSTree-based installation [1][2]. Function Signature: The function signature is: def have_bootupd(sysroot) Implementation Details: The function is located in the pyanaconda/modules/payloads/payload/rpm_ostree/util.py module. While specific lines may vary slightly by patch level, the implementation typically checks for the existence of the bootupctl binary within the context of the target system root (sysroot) [1]. It is used by Anaconda, specifically within the rpm-ostree payload installation tasks, to determine whether to utilize bootupd for bootloader configuration (such as installing boot loader updates or writing UUIDs) or to fall back to traditional methods like moving GRUB configuration files [1][3][2]. For example, in the ConfigureBootloader task, the code performs the following check [1]: if have_bootupd(self._sysroot): self._install_bootupd else: self._move_grub_config This utility ensures that Anaconda can handle modern OSTree-based systems that require bootupd for distribution-independent bootloader updates [2][4].

Citations:


🏁 Script executed:

# Check the PR/commit context and objectives in the repository
git log --oneline --all test/kickstart-templates/includes/main-prologue.cfg | head -20

Repository: openshift/microshift

Length of output: 465


🏁 Script executed:

# Look for any PR description, issue references, or related discussions in the repo
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "*.rst" \) | xargs rg -l "bootloader.*leavebootorder|have_bootupd" 2>/dev/null | head -10

Repository: openshift/microshift

Length of output: 46


🏁 Script executed:

# Check if there's a specific pyanaconda version constraint or reference in the codebase
rg "pyanaconda|anaconda" -t cfg -t ini -t toml test/ | grep -i "version\|require" | head -20

Repository: openshift/microshift

Length of output: 92


🏁 Script executed:

# Inspect the actual kickstart file for more context around the patch
cat -n test/kickstart-templates/includes/main-prologue.cfg | head -30

Repository: openshift/microshift

Length of output: 1696


🏁 Script executed:

# Check commit message and full context for the file
git show bab7eb077 --stat

Repository: openshift/microshift

Length of output: 50378


🏁 Script executed:

# Look for any references to bootloader, leavebootorder, or related discussions
rg "bootloader|leavebootorder|have_bootupd" -i . --type sh --type py --type md 2>/dev/null | grep -v "node_modules\|\.git" | head -30

Repository: openshift/microshift

Length of output: 46


🏁 Script executed:

# Check if there are any issue/PR references in the repo directory
find . -name "*.md" -o -name "*.txt" | xargs cat 2>/dev/null | grep -i "bootloader\|leavebootorder" | head -10

Repository: openshift/microshift

Length of output: 46


Remove silent failure mode and improve robustness of the sed patch.

The monkey-patch approach works but lacks validation. If the pyanaconda file doesn't exist, the function definition differs, or the sed injection fails for any reason, the script exits silently and the installer fails later with a cryptic "No update metadata for component BIOS/EFI found" error instead of failing fast with clear diagnostics. Additionally, the sed pattern /def have_bootupd/ is unanchored and could inadvertently match text in comments or docstrings.

Recommend:

  1. Add explicit validation: check that the sed injection succeeded (e.g., verify the return statement exists in the file afterwards), and exit with a clear error message if it didn't.
  2. Use a more precise sed pattern (e.g., /^def have_bootupd\(/ or /^def have_bootupd(/) to reduce the risk of unintended matches.
  3. Consider adding a log message (to /dev/console since --log is already set) to report success or failure for debugging.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/kickstart-templates/includes/main-prologue.cfg` around lines 7 - 19, The
current sed monkey-patch in the %pre section lacks robustness and validation.
First, make the sed pattern more precise by anchoring it with `^` and matching
the opening parenthesis (e.g., use `/^def have_bootupd\(/` instead of `/def
have_bootupd/`) to avoid unintended matches in comments or docstrings. Second,
add explicit validation after the sed command completes to verify the return
statement was actually injected into the util.py file; if the injection fails,
echo a clear error message to `/dev/console` and exit with a non-zero status
rather than silently failing. Finally, add log messages to `/dev/console` to
report whether the patch succeeded or what went wrong, so debugging failures is
easier when the installer fails later.


# Partition the disk with hardware-specific boot and swap partitions, adding an
# LVM volume that contains a system root partition of the specified size.
# The remainder of the volume will be used by the CSI driver for storing data.
Expand Down