diff --git a/.bootc.metadata b/.bootc.metadata index e848a85..d125842 100644 --- a/.bootc.metadata +++ b/.bootc.metadata @@ -1,2 +1,3 @@ 9ca5bceee40bd840b691c0a8024b2b6a916c36e7 SOURCES/bootc-1.8.0-vendor.tar.zstd b97adc7d411b192030dddea89366e2d6ebc5c7c2 SOURCES/bootc-1.8.0.tar.zstd +72cd838d60e13123e48e17bca3ef82329eab572c SOURCES/bootc-oraclelinux-configs.tar.gz diff --git a/.gitignore b/.gitignore index a539478..53819ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ SOURCES/bootc-1.8.0-vendor.tar.zstd SOURCES/bootc-1.8.0.tar.zstd +SOURCES/bootc-oraclelinux-configs.tar.gz diff --git a/SOURCES/0000-bootc-inistall-provision.patch b/SOURCES/0000-bootc-inistall-provision.patch index e250bdf..9b2e64f 100644 --- a/SOURCES/0000-bootc-inistall-provision.patch +++ b/SOURCES/0000-bootc-inistall-provision.patch @@ -1,8 +1,8 @@ diff --git i/tmt/tests/bootc-install-provision.sh w/tmt/tests/bootc-install-provision.sh -index c4c884b..29df30c 100755 +index ca8f82dc..94f7819f 100755 --- i/tmt/tests/bootc-install-provision.sh +++ w/tmt/tests/bootc-install-provision.sh -@@ -4,6 +4,8 @@ set -exuo pipefail +@@ -9,6 +9,8 @@ set -exuo pipefail BOOTC_TEMPDIR=$(mktemp -d) trap 'rm -rf -- "$BOOTC_TEMPDIR"' EXIT @@ -11,7 +11,7 @@ index c4c884b..29df30c 100755 # LBI only enabled for test-22-logically-bound-install LBI="${LBI:-disabled}" -@@ -16,6 +18,28 @@ case "$ID" in +@@ -21,6 +23,28 @@ case "$ID" in "fedora") TIER1_IMAGE_URL="${TIER1_IMAGE_URL:-quay.io/fedora/fedora-bootc:${VERSION_ID}}" ;; @@ -32,7 +32,7 @@ index c4c884b..29df30c 100755 + fi + + # use latest compose if specific compose is not accessible -+ RC=$(curl -skIw '%{http_code}' -o /dev/null "http://download.eng.bos.redhat.com/rhel-${VERSION_ID%%.*}/nightly/${BATCH_COMPOSE}RHEL-${VERSION_ID%%.*}/${CURRENT_COMPOSE_ID}/STATUS") ++ RC=$(curl -skIw '%{http_code}' -o /dev/null "http://download.devel.redhat.com/rhel-${VERSION_ID%%.*}/nightly/${BATCH_COMPOSE}RHEL-${VERSION_ID%%.*}/${CURRENT_COMPOSE_ID}/STATUS") + if [[ $RC != "200" ]]; then + CURRENT_COMPOSE_ID=latest-RHEL-${VERSION_ID%%} + fi @@ -40,7 +40,7 @@ index c4c884b..29df30c 100755 esac if [ "$TMT_REBOOT_COUNT" -eq 0 ]; then -@@ -93,6 +117,22 @@ COMMONEOF +@@ -98,7 +122,26 @@ COMMONEOF tee "$FEDORA_CI_CONTAINERFILE" > /dev/null << FEDORACIEOF FROM $TIER1_IMAGE_URL @@ -48,18 +48,22 @@ index c4c884b..29df30c 100755 +tee "/etc/yum.repos.d/rhel.repo" >/dev/null <"$CONTAINERFILE" < +Date: Fri, 23 Jan 2026 17:57:44 -0500 +Subject: [PATCH] install: Backport PR #1752 - add target_root_path for + RootSetup + +This is a backport of PR #1752 to v1.8.0, which enables bootc install +to-filesystem to work correctly on ostree OS systems (like FCOS). + +Changes backported: +- install: empty /boot & /boot/efi (preserving /boot/loader on ostree) +- install: add target_root_path for RootSetup +- install: remove empty directories under /boot after cleaning +- install: mount ESP in clean_boot_directories() + +Adaptation notes for v1.8.0: +The original commit 4 (mount ESP) depended on the composefs module +which does not exist in v1.8.0. This backport adapts it by: +- Adding ESP detection infrastructure to blockdev crate: + - ESP/ESP_ID_MBR constants + - find_partition_of_esp() and find_partition_of_type() methods + - parttype_matches() for case-insensitive UUID comparison +- Using path-based inspect_filesystem() instead of Dir-based + inspect_filesystem_of_dir() (which requires composefs) +- Implementing get_backing_device() locally in bootloader.rs + +Original PR: https://github.com/bootc-dev/bootc/pull/1752 + +Signed-off-by: Jose Marrero +Assisted-By: OpenCode (Claude Opus 4.5) +--- + crates/blockdev/src/blockdev.rs | 89 +++++++++++++++++++ + crates/lib/src/bootloader.rs | 53 ++++++++++++ + crates/lib/src/install.rs | 132 ++++++++++++++++++++++------- + crates/lib/src/install/baseline.rs | 1 + + 4 files changed, 243 insertions(+), 32 deletions(-) + +diff --git a/crates/blockdev/src/blockdev.rs b/crates/blockdev/src/blockdev.rs +index ceed18d9..4b18c248 100644 +--- a/crates/blockdev/src/blockdev.rs ++++ b/crates/blockdev/src/blockdev.rs +@@ -12,6 +12,11 @@ use serde::Deserialize; + + use bootc_utils::CommandRunExt; + ++/// ESP partition type UUID for GPT (EFI System Partition) ++pub const ESP: &str = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"; ++/// ESP partition type IDs for MBR (0x06 = FAT16, 0xEF = EFI System) ++pub const ESP_ID_MBR: &[u8] = &[0x06, 0xEF]; ++ + #[derive(Debug, Deserialize)] + struct DevicesOutput { + blockdevices: Vec, +@@ -117,6 +122,7 @@ pub struct Partition { + pub parttype: String, + pub uuid: Option, + pub name: Option, ++ pub bootable: Option, + } + + #[derive(Debug, Deserialize, PartialEq, Eq)] +@@ -161,6 +167,33 @@ impl PartitionTable { + .ok_or_else(|| anyhow::anyhow!("Missing partition for index {partno}"))?; + Ok(r) + } ++ ++ /// Find the partition with the given type UUID (case-insensitive). ++ /// ++ /// Partition type UUIDs are compared case-insensitively per the GPT specification, ++ /// as different tools may report them in different cases. ++ pub fn find_partition_of_type(&self, uuid: &str) -> Option<&Partition> { ++ self.partitions.iter().find(|p| p.parttype_matches(uuid)) ++ } ++ ++ /// Find the partition with bootable is 'true'. ++ #[allow(dead_code)] ++ pub fn find_partition_of_bootable(&self) -> Option<&Partition> { ++ self.partitions.iter().find(|p| p.is_bootable()) ++ } ++ ++ /// Find the ESP (EFI System Partition). ++ pub fn find_partition_of_esp(&self) -> Result> { ++ match &self.label { ++ PartitionType::Dos => Ok(self.partitions.iter().find(|b| { ++ u8::from_str_radix(&b.parttype, 16) ++ .map(|pt| ESP_ID_MBR.contains(&pt)) ++ .unwrap_or(false) ++ })), ++ PartitionType::Gpt => Ok(self.find_partition_of_type(ESP)), ++ _ => Err(anyhow::anyhow!("Unsupported partition table type")), ++ } ++ } + } + + impl Partition { +@@ -168,6 +201,17 @@ impl Partition { + pub fn path(&self) -> &Utf8Path { + self.node.as_str().into() + } ++ ++ /// Compare partition type UUID case-insensitively per the GPT specification, ++ /// as different tools may report them in different cases. ++ pub fn parttype_matches(&self, uuid: &str) -> bool { ++ self.parttype.eq_ignore_ascii_case(uuid) ++ } ++ ++ /// Check this partition's bootable property. ++ pub fn is_bootable(&self) -> bool { ++ self.bootable.unwrap_or(false) ++ } + } + + #[context("Listing partitions of {dev}")] +@@ -505,4 +549,49 @@ mod test { + ); + Ok(()) + } ++ ++ #[test] ++ fn test_find_partition_of_esp() -> Result<()> { ++ let fixture = indoc::indoc! { r#" ++ { ++ "partitiontable": { ++ "label": "gpt", ++ "id": "A67AA901-2C72-4818-B098-7F1CAC127279", ++ "device": "/dev/loop0", ++ "unit": "sectors", ++ "firstlba": 34, ++ "lastlba": 20971486, ++ "sectorsize": 512, ++ "partitions": [ ++ { ++ "node": "/dev/loop0p1", ++ "start": 2048, ++ "size": 8192, ++ "type": "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", ++ "uuid": "58A4C5F0-BD12-424C-B563-195AC65A25DD", ++ "name": "EFI System" ++ },{ ++ "node": "/dev/loop0p2", ++ "start": 10240, ++ "size": 20961247, ++ "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4", ++ "uuid": "F51ABB0D-DA16-4A21-83CB-37F4C805AAA0", ++ "name": "root" ++ } ++ ] ++ } ++ } ++ "# }; ++ let table: SfDiskOutput = serde_json::from_str(fixture).unwrap(); ++ ++ // Find ESP partition using case-insensitive UUID matching ++ let esp = table.partitiontable.find_partition_of_esp()?.unwrap(); ++ assert_eq!(esp.node, "/dev/loop0p1"); ++ ++ // Test parttype_matches is case-insensitive ++ assert!(esp.parttype_matches("c12a7328-f81f-11d2-ba4b-00a0c93ec93b")); ++ assert!(esp.parttype_matches("C12A7328-F81F-11D2-BA4B-00A0C93EC93B")); ++ ++ Ok(()) ++ } + } +diff --git a/crates/lib/src/bootloader.rs b/crates/lib/src/bootloader.rs +index aa07bfe8..1ebec94c 100644 +--- a/crates/lib/src/bootloader.rs ++++ b/crates/lib/src/bootloader.rs +@@ -3,6 +3,8 @@ use std::process::Command; + use anyhow::{anyhow, bail, Context, Result}; + use bootc_utils::CommandRunExt; + use camino::Utf8Path; ++use cap_std_ext::cap_std::fs::Dir; ++use cap_std_ext::dirext::CapStdExtDirExt; + use fn_error_context::context; + + use bootc_blockdev::PartitionTable; +@@ -11,6 +13,57 @@ use bootc_mount as mount; + /// The name of the mountpoint for efi (as a subdirectory of /boot, or at the toplevel) + pub(crate) const EFI_DIR: &str = "efi"; + ++/// Get the backing device for a filesystem at the given path ++fn get_backing_device(root_path: &Utf8Path) -> Result { ++ let fsinfo = mount::inspect_filesystem(root_path)?; ++ let mut dev = fsinfo.source; ++ loop { ++ let mut parents = bootc_blockdev::find_parent_devices(&dev)?.into_iter(); ++ let Some(parent) = parents.next() else { ++ break; ++ }; ++ dev = parent; ++ } ++ Ok(dev) ++} ++ ++/// Get ESP partition node based on the root path ++pub(crate) fn get_esp_partition_node(root_path: &Utf8Path) -> Result> { ++ let device = get_backing_device(root_path)?; ++ let base_partitions = bootc_blockdev::partitions_of(Utf8Path::new(&device))?; ++ let esp = base_partitions.find_partition_of_esp()?; ++ Ok(esp.map(|v| v.node.clone())) ++} ++ ++/// Mount ESP partition at /boot/efi if not already mounted ++pub(crate) fn mount_esp_part(root: &Dir, root_path: &Utf8Path, is_ostree: bool) -> Result<()> { ++ let efi_path = Utf8Path::new("boot").join(EFI_DIR); ++ let Some(esp_fd) = root ++ .open_dir_optional(&efi_path) ++ .context("Opening /boot/efi")? ++ else { ++ return Ok(()); ++ }; ++ ++ let Some(false) = esp_fd.is_mountpoint(".")? else { ++ return Ok(()); ++ }; ++ ++ tracing::debug!("Not a mountpoint: /boot/efi"); ++ // On ostree env, the physical root is at /target/sysroot ++ let physical_root_path = if is_ostree { ++ root_path.join("sysroot") ++ } else { ++ root_path.to_owned() ++ }; ++ ++ if let Some(esp_part) = get_esp_partition_node(&physical_root_path)? { ++ mount::mount(&esp_part, &root_path.join(&efi_path))?; ++ tracing::debug!("Mounted {esp_part} at /boot/efi"); ++ } ++ Ok(()) ++} ++ + #[context("Installing bootloader")] + pub(crate) fn install_via_bootupd( + device: &PartitionTable, +diff --git a/crates/lib/src/install.rs b/crates/lib/src/install.rs +index 156270dd..ba35419a 100644 +--- a/crates/lib/src/install.rs ++++ b/crates/lib/src/install.rs +@@ -612,6 +612,17 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result + // Another implementation: https://github.com/coreos/coreos-assembler/blob/3cd3307904593b3a131b81567b13a4d0b6fe7c90/src/create_disk.sh#L295 + crate::lsm::ensure_dir_labeled(rootfs_dir, "", Some("/".into()), 0o755.into(), sepolicy)?; + ++ // If we're installing alongside existing ostree and there's a separate boot partition, ++ // we need to mount it to the sysroot's /boot so ostree can write bootloader entries there ++ if has_ostree && root_setup.boot.is_some() { ++ if let Some(boot) = &root_setup.boot { ++ let source_boot = &boot.source; ++ let target_boot = root_setup.physical_root_path.join(BOOT); ++ tracing::debug!("Mount {source_boot} to {target_boot} on ostree"); ++ bootc_mount::mount(source_boot, &target_boot)?; ++ } ++ } ++ + // And also label /boot AKA xbootldr, if it exists + if rootfs_dir.try_exists("boot")? { + crate::lsm::ensure_dir_labeled(rootfs_dir, "boot", None, 0o755.into(), sepolicy)?; +@@ -927,9 +938,11 @@ pub(crate) struct RootSetup { + device_info: bootc_blockdev::PartitionTable, + /// Absolute path to the location where we've mounted the physical + /// root filesystem for the system we're installing. +- physical_root_path: Utf8PathBuf, ++ pub(crate) physical_root_path: Utf8PathBuf, + /// Directory file descriptor for the above physical root. +- physical_root: Dir, ++ pub(crate) physical_root: Dir, ++ /// Target root path /target. ++ pub(crate) target_root_path: Option, + rootfs_uuid: Option, + /// True if we should skip finalizing + skip_finalize: bool, +@@ -1332,7 +1345,10 @@ async fn install_with_sysroot( + } else { + crate::bootloader::install_via_bootupd( + &rootfs.device_info, +- &rootfs.physical_root_path, ++ &rootfs ++ .target_root_path ++ .clone() ++ .unwrap_or(rootfs.physical_root_path.clone()), + &state.config_opts, + &deployment_path.as_str(), + )?; +@@ -1616,30 +1632,66 @@ fn remove_all_in_dir_no_xdev(d: &Dir, mount_err: bool) -> Result<()> { + anyhow::Ok(()) + } + ++#[context("Removing boot directory content except loader dir on ostree")] ++fn remove_all_except_loader_dirs(bootdir: &Dir, is_ostree: bool) -> Result<()> { ++ let entries = bootdir ++ .entries() ++ .context("Reading boot directory entries")?; ++ ++ for entry in entries { ++ let entry = entry.context("Reading directory entry")?; ++ let file_name = entry.file_name(); ++ let file_name = if let Some(n) = file_name.to_str() { ++ n ++ } else { ++ anyhow::bail!("Invalid non-UTF8 filename: {file_name:?} in /boot"); ++ }; ++ ++ // TODO: Preserve basically everything (including the bootloader entries ++ // on non-ostree) by default until the very end of the install. And ideally ++ // make the "commit" phase an optional step after. ++ if is_ostree && file_name.starts_with("loader") { ++ continue; ++ } ++ ++ let etype = entry.file_type()?; ++ if etype == FileType::dir() { ++ // Open the directory and remove its contents ++ if let Some(subdir) = bootdir.open_dir_noxdev(&file_name)? { ++ remove_all_in_dir_no_xdev(&subdir, false) ++ .with_context(|| format!("Removing directory contents: {}", file_name))?; ++ bootdir.remove_dir(&file_name)?; ++ } ++ } else { ++ bootdir ++ .remove_file_optional(&file_name) ++ .with_context(|| format!("Removing file: {}", file_name))?; ++ } ++ } ++ Ok(()) ++} ++ + #[context("Removing boot directory content")] +-fn clean_boot_directories(rootfs: &Dir, is_ostree: bool) -> Result<()> { ++fn clean_boot_directories(rootfs: &Dir, rootfs_path: &Utf8Path, is_ostree: bool) -> Result<()> { + let bootdir = + crate::utils::open_dir_remount_rw(rootfs, BOOT.into()).context("Opening /boot")?; + +- if is_ostree { +- // On ostree systems, the boot directory already has our desired format, we should only +- // remove the bootupd-state.json file to avoid bootupctl complaining it already exists. +- bootdir +- .remove_file_optional("bootupd-state.json") +- .context("removing bootupd-state.json")?; +- } else { +- // This should not remove /boot/efi note. +- remove_all_in_dir_no_xdev(&bootdir, false).context("Emptying /boot")?; +- // TODO: Discover the ESP the same way bootupd does it; we should also +- // support not wiping the ESP. +- if ARCH_USES_EFI { +- if let Some(efidir) = bootdir +- .open_dir_optional(crate::bootloader::EFI_DIR) +- .context("Opening /boot/efi")? +- { +- remove_all_in_dir_no_xdev(&efidir, false) +- .context("Emptying EFI system partition")?; +- } ++ if ARCH_USES_EFI { ++ // On booted FCOS, esp is not mounted by default ++ // Mount ESP part at /boot/efi before clean ++ crate::bootloader::mount_esp_part(rootfs, rootfs_path, is_ostree)?; ++ } ++ ++ // This should not remove /boot/efi note. ++ remove_all_except_loader_dirs(&bootdir, is_ostree).context("Emptying /boot")?; ++ ++ // TODO: we should also support not wiping the ESP. ++ if ARCH_USES_EFI { ++ if let Some(efidir) = bootdir ++ .open_dir_optional(crate::bootloader::EFI_DIR) ++ .context("Opening /boot/efi")? ++ { ++ remove_all_in_dir_no_xdev(&efidir, false).context("Emptying EFI system partition")?; + } + } + +@@ -1767,6 +1819,18 @@ pub(crate) async fn install_to_filesystem( + .context("Mounting host / to {ALONGSIDE_ROOT_MOUNT}")?; + } + ++ let target_root_path = fsopts.root_path.clone(); ++ // Get a file descriptor for the root path /target ++ let target_rootfs_fd = ++ Dir::open_ambient_dir(&target_root_path, cap_std::ambient_authority()) ++ .with_context(|| format!("Opening target root directory {target_root_path}"))?; ++ ++ tracing::debug!("Target root filesystem: {target_root_path}"); ++ ++ if let Some(false) = target_rootfs_fd.is_mountpoint(".")? { ++ anyhow::bail!("Not a mountpoint: {target_root_path}"); ++ } ++ + // Check that the target is a directory + { + let root_path = &fsopts.root_path; +@@ -1780,10 +1844,7 @@ pub(crate) async fn install_to_filesystem( + + // Check to see if this happens to be the real host root + if !fsopts.acknowledge_destructive { +- let root_path = &fsopts.root_path; +- let rootfs_fd = Dir::open_ambient_dir(root_path, cap_std::ambient_authority()) +- .with_context(|| format!("Opening target root directory {root_path}"))?; +- warn_on_host_root(&rootfs_fd)?; ++ warn_on_host_root(&target_rootfs_fd)?; + } + + // If we're installing to an ostree root, then find the physical root from +@@ -1799,7 +1860,8 @@ pub(crate) async fn install_to_filesystem( + }; + + // Get a file descriptor for the root path +- let rootfs_fd = { ++ // It will be /target/sysroot on ostree OS, or will be /target ++ let rootfs_fd = if is_already_ostree { + let root_path = &fsopts.root_path; + let rootfs_fd = Dir::open_ambient_dir(&fsopts.root_path, cap_std::ambient_authority()) + .with_context(|| format!("Opening target root directory {root_path}"))?; +@@ -1810,6 +1872,8 @@ pub(crate) async fn install_to_filesystem( + anyhow::bail!("Not a mountpoint: {root_path}"); + } + rootfs_fd ++ } else { ++ target_rootfs_fd.try_clone()? + }; + + match fsopts.replace { +@@ -1819,7 +1883,9 @@ pub(crate) async fn install_to_filesystem( + tokio::task::spawn_blocking(move || remove_all_in_dir_no_xdev(&rootfs_fd, true)) + .await??; + } +- Some(ReplaceMode::Alongside) => clean_boot_directories(&rootfs_fd, is_already_ostree)?, ++ Some(ReplaceMode::Alongside) => { ++ clean_boot_directories(&target_rootfs_fd, &target_root_path, is_already_ostree)? ++ } + None => require_empty_rootdir(&rootfs_fd)?, + } + +@@ -1864,7 +1930,7 @@ pub(crate) async fn install_to_filesystem( + + let boot_is_mount = { + let root_dev = rootfs_fd.dir_metadata()?.dev(); +- let boot_dev = rootfs_fd ++ let boot_dev = target_rootfs_fd + .symlink_metadata_optional(BOOT)? + .ok_or_else(|| { + anyhow!("No /{BOOT} directory found in root; this is is currently required") +@@ -1875,9 +1941,10 @@ pub(crate) async fn install_to_filesystem( + }; + // Find the UUID of /boot because we need it for GRUB. + let boot_uuid = if boot_is_mount { +- let boot_path = fsopts.root_path.join(BOOT); ++ let boot_path = target_root_path.join(BOOT); ++ tracing::debug!("boot_path={boot_path}"); + let u = bootc_mount::inspect_filesystem(&boot_path) +- .context("Inspecting /{BOOT}")? ++ .with_context(|| format!("Inspecting /{BOOT}"))? + .uuid + .ok_or_else(|| anyhow!("No UUID found for /{BOOT}"))?; + Some(u) +@@ -1956,6 +2023,7 @@ pub(crate) async fn install_to_filesystem( + device_info, + physical_root_path: fsopts.root_path, + physical_root: rootfs_fd, ++ target_root_path: Some(target_root_path.clone()), + rootfs_uuid: inspect.uuid.clone(), + boot, + kargs, +diff --git a/crates/lib/src/install/baseline.rs b/crates/lib/src/install/baseline.rs +index 1cd48c48..fdafa9ac 100644 +--- a/crates/lib/src/install/baseline.rs ++++ b/crates/lib/src/install/baseline.rs +@@ -455,6 +455,7 @@ pub(crate) fn install_create_rootfs( + device_info, + physical_root_path, + physical_root, ++ target_root_path: None, + rootfs_uuid: Some(root_uuid.to_string()), + boot, + kargs, +-- +2.52.0 + diff --git a/SPECS/bootc.spec b/SPECS/bootc.spec index 7b156cc..17d31cd 100644 --- a/SPECS/bootc.spec +++ b/SPECS/bootc.spec @@ -13,7 +13,7 @@ Name: bootc Version: 1.8.0 -Release: 3%{?dist} +Release: 4.0.1%{?dist} Summary: Bootable container system # Apache-2.0 @@ -28,11 +28,13 @@ License: Apache-2.0 AND BSD-3-Clause AND MIT AND (Apache-2.0 OR BSL-1.0) URL: https://github.com/containers/bootc Source0: %{url}/releases/download/v%{version}/bootc-%{version}.tar.zstd Source1: %{url}/releases/download/v%{version}/bootc-%{version}-vendor.tar.zstd +Source2: bootc-oraclelinux-configs.tar.gz # Don't remove, downstream patch only # Patch for integration test RHEL 9.x and 10.x support Patch0: 0000-bootc-inistall-provision.patch Patch1: 0001-bootc-inistall-provision.patch +Patch2: 0001-install-Backport-PR-1752-add-target_root_path-for-Ro.patch # https://fedoraproject.org/wiki/Changes/EncourageI686LeafRemoval ExcludeArch: %{ix86} @@ -76,10 +78,21 @@ Recommends: podman %description -n system-reinstall-bootc This package provides a utility to simplify reinstalling the current system to a given bootc image. +%package oraclelinux-configs +Summary: Configuration files and tools to build Oracle Linux baseline bootc containers +Recommends: podman +# The reinstall subpackage intentionally does not require bootc, as it pulls in many unnecessary dependencies + +%description oraclelinux-configs +This package provides config files and utilities to simplify building baseline Oracle Linux bootc images from scratch + %global system_reinstall_bootc_install_podman_path %{_prefix}/lib/system-reinstall-bootc/install-podman %prep %autosetup -p1 -a1 +# unpack bootc config files +%setup -q -T -D -a2 + # Default -v vendor config doesn't support non-crates.io deps (i.e. git) cp .cargo/vendor-config.toml . %cargo_prep -N @@ -114,6 +127,9 @@ export SYSTEM_REINSTALL_BOOTC_INSTALL_PODMAN_PATH=%{system_reinstall_bootc_insta sed -i -e '/https:\/\//d' cargo-vendor.txt %cargo_license_summary %{cargo_license} > LICENSE.dependencies +#create directory for container config files and install configs +mkdir -p %{buildroot}%{_datarootdir}/ +%{__cp} -ar bootc-oraclelinux-configs %{buildroot}%{_datarootdir}/ %install %make_install INSTALL="install -p -c" @@ -127,6 +143,10 @@ exec dnf -y install podman EOF chmod +x %{?buildroot}/%{system_reinstall_bootc_install_podman_path} +#create directory for container config files and install configs +mkdir -p %{buildroot}%{_datarootdir}/ +%{__cp} -ar bootc-oraclelinux-configs %{buildroot}%{_datarootdir}/ + %if %{with check} %check %cargo_test @@ -152,7 +172,25 @@ chmod +x %{?buildroot}/%{system_reinstall_bootc_install_podman_path} %{_bindir}/system-reinstall-bootc %{system_reinstall_bootc_install_podman_path} +%files oraclelinux-configs +%{_datarootdir}/bootc-oraclelinux-configs +%attr(0755, root, root) %{_datarootdir}/bootc-oraclelinux-configs/ol9/build_container_image.sh +%attr(0755, root, root) %{_datarootdir}/bootc-oraclelinux-configs/ol10/build_container_image.sh +%attr(0755, root, root) %{_datarootdir}/bootc-oraclelinux-configs/image-builder/ol-image-builder.sh +%attr(0755, root, root) %{_datarootdir}/bootc-oraclelinux-configs/image-builder/qemu-boot-bootc-iso.sh +%attr(0755, root, root) %{_datarootdir}/bootc-oraclelinux-configs/image-builder/qemu-boot-bootc-qcow2.sh + + %changelog +* Tue Mar 24 2026 Darren Archibald - 1.8.0-4.0.1 +- Update bootc-oraclelinux-configs and image-builder scripts +- Also add image-builder helper scripts and configs +- Add bootc-oraclelinux-configs + +* Fri Jan 23 2026 Joseph Marrero - 1.8.0-4 +- Backport https://github.com/bootc-dev/bootc/pull/1752 + Resolves: #RHEL-143203 + * Wed Sep 10 2025 Joseph Marrero - 1.8.0-3 - Bump release as rhpkg needed an update to tag for 9.7.z Resolves: #RHEL-113361 @@ -258,4 +296,3 @@ chmod +x %{?buildroot}/%{system_reinstall_bootc_install_podman_path} * Mon Dec 11 2023 Colin Walters - 0.1.4-2 - Initial import from fedora -