Skip to content

ci: restructure test infrastructure and add kernel failure tests#185

Draft
pcdubs wants to merge 18 commits into
fedora-iot:mainfrom
pcdubs:kernel-failure-tests
Draft

ci: restructure test infrastructure and add kernel failure tests#185
pcdubs wants to merge 18 commits into
fedora-iot:mainfrom
pcdubs:kernel-failure-tests

Conversation

@pcdubs

@pcdubs pcdubs commented Jun 17, 2026

Copy link
Copy Markdown
Member

Summary

  • Add kernel failure recovery test using BLS entry corruption
  • Add Fedora IoT raw image testing with pre-built disk images
  • Add cross-compiled aarch64/x86_64 test binaries
  • Replace virt-customize with kpartx-based SSH key injection for aarch64 support
  • Add VM console logging and diagnostics for SSH failures
  • Pass PR_NUMBER to all testing-farm CI jobs (for follow-up Copr integration)
  • Fix Packit release_suffix so PR builds have unique NVR

Comment thread tests/greenboot-bootc.yaml Fixed
- name: delay 300 seconds for GRUB fallback boot attempts
pause:
seconds: 300
delegate_to: 127.0.0.1

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces GRUB-level kernel fallback protection to Greenboot by tracking the expected next deployment ID and comparing it against the booted deployment ID. It adds fallback detection, updates rollback handling to support forced rollbacks that bypass the boot counter, and integrates these changes into the health check flow and systemd services. Additionally, comprehensive integration tests simulating kernel failures were added. The reviewer suggested simplifying get_grub_bool_var by reusing get_grub_str_var to eliminate duplicate command execution and parsing logic.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/lib/grub.rs
Comment on lines +139 to 161
fn get_grub_bool_var(key: &str, grub_path: &str) -> Result<bool> {
let grub_vars = Command::new("grub2-editenv")
.arg(grub_path)
.arg("list")
.output()
.context("Unable to list grubenv variables")?;
.context(format!("Unable to list grubenv variables for key: {key}"))?;

if !grub_vars.status.success() {
bail!(
"grub2-editenv failed to list variables: {}",
String::from_utf8_lossy(&grub_vars.stderr)
);
}

let prefix = format!("{key}=");
let output = String::from_utf8_lossy(&grub_vars.stdout);
for line in output.lines() {
if line.starts_with("greenboot_rollback_trigger=") {
let value = line.split('=').nth(1).unwrap_or("0");
if let Some(value) = line.strip_prefix(&prefix) {
return Ok(value == "1");
}
}
Ok(false) // Not set means false
Ok(false)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The helper function get_grub_bool_var duplicates the command execution, error handling, and output parsing logic of get_grub_str_var. We can simplify get_grub_bool_var by reusing get_grub_str_var and checking if the returned string is "1".

fn get_grub_bool_var(key: &str, grub_path: &str) -> Result<bool> {
    Ok(get_grub_str_var(key, grub_path)?.map_or(false, |val| val == "1"))
}

@pcdubs
pcdubs force-pushed the kernel-failure-tests branch 6 times, most recently from 77a7c10 to 9873615 Compare June 23, 2026 18:00
Comment thread tests/greenboot-ostree.sh Dismissed
say-paul and others added 12 commits June 24, 2026 14:33
Set fallback=1 alongside greenboot_rollback_trigger when an OS update
is detected, enabling GRUB to boot the previous deployment if the new
kernel panics. Disarm fallback at the start of healthcheck since
reaching systemd means the kernel booted successfully.

Closes: fedora-iot#180
Co-authored-by: Cursor <cursoragent@cursor.com>
DRY up get_fallback_at and get_rollback_trigger_at into a shared
get_grub_bool_var helper. Fix unset_grub_var context message that was
hardcoded to "boot_counter" for all keys.

Co-authored-by: Cursor <cursoragent@cursor.com>
Change greenboot-set-rollback-trigger.service to run when bootc update
or rpm-ostree upgrade stages a deployment, instead of at next boot.

The service is now RequiredBy=ostree-finalize-staged.service and ordered
Before= it, matching the pattern used by the original bash greenboot's
greenboot-grub2-set-counter.service. This means the rollback trigger
and fallback grub variables are set immediately when an update is
staged, not deferred to the next boot.

Removed: ConditionNeedsUpdate, boot-time ordering (sysinit.target,
systemd-update-done.service), WantedBy boot targets.
Added: ConditionPathExists=/run/ostree-booted, RequiresMountsFor=/boot,
PrivateMounts=yes, RemainAfterExit=yes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Healthcheck no longer directly triggers boot-complete.target. Instead:
healthcheck passes -> OnSuccess activates greenboot-success.target ->
success target Requires=boot-complete.target.

This ensures boot-complete.target is only reached through the greenboot
success chain, and greenboot-success.target has no [Install] section.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ack detection

Replace the boolean `greenboot_rollback_trigger` GRUB variable with
`greenboot_next_deployment_id`, which stores the staged deployment's
ID (imageDigest for bootc, checksum for rpm-ostree). This serves a
dual purpose: it acts as the rollback trigger and enables GRUB-level
kernel fallback detection by comparing the stored ID against the
actually booted deployment.

Key changes:
- grub.rs: replace set/get/unset_rollback_trigger with
  set/get/unset_next_deployment_id using new string-valued GRUB
  variable helpers (set_grub_str_var, get_grub_str_var)
- handler.rs: add get_booted_deployment_id and get_staged_deployment_id
  to query deployment IDs from bootc or rpm-ostree; add force flag to
  handle_rollback to bypass boot_counter checks when making a GRUB
  fallback permanent
- main.rs: add detect_grub_fallback() which compares stored vs booted
  deployment ID; on mismatch, make fallback permanent via forced
  rollback and clear next_deployment_id to prevent rollback loops;
  SetRollbackTrigger now queries the staged deployment ID and sets
  both next_deployment_id and fallback independently

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactored bootstate having 3 states NormalBoot,grub fallback and
greenboot fallback.
Refactored Rollback having 2 states, normal and forced

Signed-off-by: Sayan Paul <paul.sayan@gmail.com>
Signed-off-by: Sayan Paul <paul.sayan@gmail.com>
it runs after ostree-finalize-staged service to ensure that the rollback protection is enabled befor next reboot happens

Signed-off-by: Sayan Paul <paul.sayan@gmail.com>
removed greenboot-success.target as it only activates boot-complete.target

helthcheck service now  directly summons boot-complete.target thus removing the cyclic dependencies.

added rpm-ostreed as dependency to set-rollback.service to fix null next deployment ID in rpm-ostree deployment

Signed-off-by: Sayan Paul <paul.sayan@gmail.com>
Signed-off-by: Sayan Paul <paul.sayan@gmail.com>
Stage a deployment, corrupt the higher-version BLS entry kernel path
to trigger GRUB fallback, then validate greenboot detects the fallback
and recovers cleanly.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Whalen <pwhalen@fedoraproject.org>
The Makefile uses git archive to create source tarballs, but git
was not listed as a dependency in any of the test scripts.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Whalen <pwhalen@fedoraproject.org>
@pcdubs
pcdubs force-pushed the kernel-failure-tests branch 2 times, most recently from e2ef305 to 2a4afc9 Compare June 24, 2026 19:43
Comment thread tests/greenboot-fedora-iot-raw.sh Dismissed
@pcdubs
pcdubs force-pushed the kernel-failure-tests branch from 2a4afc9 to 1b913cc Compare June 24, 2026 20:22
Paul Whalen added 3 commits June 25, 2026 14:24
The empty release_suffix caused PR COPR builds to have the same
NVR as released packages, making them uninstallable as overrides.
Packit's default behavior appends PR number and commit hash for
PR builds while keeping clean releases for downstream proposals.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Whalen <pwhalen@fedoraproject.org>
All test scripts were blind when SSH connectivity failed — no way to
determine if the VM booted, got a DHCP lease, or hit a kernel panic.

- Replace --nographics with --graphics none --serial file,path= to
  capture serial console output to a log file
- Dump VM state, DHCP leases, and console output on SSH failure
- Add missing check_result after SSH loop in ostree test
- Add update_release: true to packit copr_build so PR builds get
  unique NVRs with commit hash and PR number

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Whalen <pwhalen@fedoraproject.org>
Use pre-built daily Fedora IoT raw images from kojipkgs instead of
building ostree commits with osbuild-composer. Greenboot is installed
from Packit Copr PR builds via rpm-ostree override replace.

- Add greenboot-fedora-iot-raw.sh test script
- Add /fedora-iot-raw TMT plan and test dispatcher routing
- Add fedora-44-ostree and fedora-45-ostree CI jobs
- Add fedora-44 and centos-stream-9 Packit Copr build targets
- Pass PR_NUMBER to Testing Farm for Copr repo lookup

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Whalen <pwhalen@fedoraproject.org>
@pcdubs
pcdubs force-pushed the kernel-failure-tests branch from 1b913cc to b7b0108 Compare June 25, 2026 18:24
Replace arch-less x86_64 test binaries with arch-suffixed variants
(passing_binary.x86_64, passing_binary.aarch64, etc.) and update all
test scripts to select the correct binary based on $(uname -m). Also
replace hardcoded x86_64 paths in BOOT_LOCATION URLs and RPM copy
commands with ${ARCH}.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Whalen <pwhalen@fedoraproject.org>
@pcdubs
pcdubs force-pushed the kernel-failure-tests branch 2 times, most recently from faa132f to 1c682f9 Compare June 26, 2026 17:21
virt-customize fails on aarch64 because libguestfs cannot inspect
the IoT image partition layout. Use an Ignition config passed via
QEMU fw_cfg instead, which works on both x86_64 and aarch64 without
image modification.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Whalen <pwhalen@fedoraproject.org>
@pcdubs
pcdubs force-pushed the kernel-failure-tests branch from 1c682f9 to 86ed1ee Compare June 26, 2026 17:27
@say-paul
say-paul requested a review from mcattamoredhat July 6, 2026 14:08
Add PR_NUMBER variable to all CI workflow jobs so test scripts can
install greenboot from Packit Copr PR builds in a follow-up change.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Whalen <pwhalen@fedoraproject.org>
@pcdubs
pcdubs force-pushed the kernel-failure-tests branch from 3081298 to 2218aec Compare July 6, 2026 15:07
@pcdubs pcdubs changed the title Kernel failure tests ci: restructure test infrastructure and add kernel failure tests Jul 6, 2026
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.

3 participants