From 365ef1fab58adc0ab6b5db0f224ab60569f2550d Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 25 Sep 2025 14:26:43 +0200 Subject: [PATCH 1/3] component: Make update metadata generation to be optional Currently, the `bootupctl backend generate-update-metadata` command tries to generate an update layout for each component, and it bails out if one of the components can't be installed. There are systems in which some of the bootupd components are not needed (e.g.: x86_64 EFI-only systems). But if one of the requirements for one of the components is not meet (e.g.: grub2-install is missing for BIOS), this will lead to a fatal error instead of just skipping the component that is not supported. To prevent this, let's make the update layout generation to be optional. Signed-off-by: Javier Martinez Canillas --- src/bios.rs | 4 ++-- src/bootupd.rs | 18 ++++++++++++------ src/component.rs | 2 +- src/efi.rs | 4 ++-- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/bios.rs b/src/bios.rs index b4eaca5d..84387639 100644 --- a/src/bios.rs +++ b/src/bios.rs @@ -127,7 +127,7 @@ impl Component for Bios { }) } - fn generate_update_metadata(&self, sysroot_path: &str) -> Result { + fn generate_update_metadata(&self, sysroot_path: &str) -> Result> { let grub_install = Path::new(sysroot_path).join(GRUB_BIN); if !grub_install.exists() { bail!("Failed to find {:?}", grub_install); @@ -136,7 +136,7 @@ impl Component for Bios { // Query the rpm database and list the package and build times for /usr/sbin/grub2-install let meta = packagesystem::query_files(sysroot_path, [&grub_install])?; write_update_metadata(sysroot_path, self, &meta)?; - Ok(meta) + Ok(Some(meta)) } fn query_adopt(&self, devices: &Option>) -> Result> { diff --git a/src/bootupd.rs b/src/bootupd.rs index 4dc10c3e..4e3799be 100644 --- a/src/bootupd.rs +++ b/src/bootupd.rs @@ -199,12 +199,18 @@ pub(crate) fn generate_update_metadata(sysroot_path: &str) -> Result<()> { std::fs::create_dir_all(&updates_dir) .with_context(|| format!("Failed to create updates dir {:?}", &updates_dir))?; for component in get_components().values() { - let v = component.generate_update_metadata(sysroot_path)?; - println!( - "Generated update layout for {}: {}", - component.name(), - v.version, - ); + if let Some(v) = component.generate_update_metadata(sysroot_path)? { + println!( + "Generated update layout for {}: {}", + component.name(), + v.version, + ); + } else { + println!( + "Generating update layout for {} was not possible, skipping.", + component.name(), + ); + } } Ok(()) diff --git a/src/component.rs b/src/component.rs index 8c3ec3cb..5e611590 100644 --- a/src/component.rs +++ b/src/component.rs @@ -62,7 +62,7 @@ pub(crate) trait Component { /// this is an `rpm-ostree compose tree` for example. For a dual-partition /// style updater, this would be run as part of a postprocessing step /// while the filesystem for the partition is mounted. - fn generate_update_metadata(&self, sysroot: &str) -> Result; + fn generate_update_metadata(&self, sysroot: &str) -> Result>; /// Used on the client to query for an update cached in the current booted OS. fn query_update(&self, sysroot: &openat::Dir) -> Result>; diff --git a/src/efi.rs b/src/efi.rs index 25d6ccd7..bc0fcc9c 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -460,7 +460,7 @@ impl Component for Efi { }) } - fn generate_update_metadata(&self, sysroot: &str) -> Result { + fn generate_update_metadata(&self, sysroot: &str) -> Result> { let sysroot_path = Utf8Path::new(sysroot); // copy EFI files to updates dir from usr/lib/efi @@ -533,7 +533,7 @@ impl Component for Efi { }; write_update_metadata(sysroot, self, &meta)?; - Ok(meta) + Ok(Some(meta)) } fn query_update(&self, sysroot: &openat::Dir) -> Result> { From 81edbae35cea7b968f974643cedfa8037c4d8898 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 25 Sep 2025 14:26:46 +0200 Subject: [PATCH 2/3] component: Skip installing components without update metadata Now that update metadata generation is optional for some components, skip installing the components that don't have an update metadata. --- src/bootupd.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bootupd.rs b/src/bootupd.rs index 4e3799be..34516ddf 100644 --- a/src/bootupd.rs +++ b/src/bootupd.rs @@ -93,6 +93,15 @@ pub(crate) fn install( continue; } + // skip components that don't have an update metadata + if component.query_update(&source_root_dir)?.is_none() { + println!( + "Skip installing component {} without update metadata", + component.name() + ); + continue; + } + let meta = component .install(&source_root, dest_root, device, update_firmware) .with_context(|| format!("installing component {}", component.name()))?; From f9de0fd24d14cac08b48e833cfab04b3a5a0179d Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 25 Sep 2025 14:26:49 +0200 Subject: [PATCH 3/3] bios: Don't bail out if `grub2-install` is not present Instead of making it a fatal error, just make the component to be skipped. This allows to generate the update metadata for other components, instead of failing due not being able to generate the metadata for BIOS component. --- src/bios.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bios.rs b/src/bios.rs index 84387639..f97258f9 100644 --- a/src/bios.rs +++ b/src/bios.rs @@ -130,7 +130,8 @@ impl Component for Bios { fn generate_update_metadata(&self, sysroot_path: &str) -> Result> { let grub_install = Path::new(sysroot_path).join(GRUB_BIN); if !grub_install.exists() { - bail!("Failed to find {:?}", grub_install); + println!("Failed to find {:?}", grub_install); + return Ok(None); } // Query the rpm database and list the package and build times for /usr/sbin/grub2-install