Skip to content

Commit 6bb7538

Browse files
composefs: Fix install to-existing-root
Fix a few issues with composefs path for `install to-existing-root`. 1. Composefs repository initialization Since we mount `/sysroot:ro` at `/target`, composefs repository initialization would fail with `Read only filesystem`. Fix it by remounting `/target/sysroot` read-write 2. Handle bootloader Get the current bootloader by reading `LoaderInfo` and try to install the same one Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent c75b9de commit 6bb7538

4 files changed

Lines changed: 42 additions & 11 deletions

File tree

crates/lib/src/bootc_composefs/repo.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub(crate) fn open_composefs_repo(rootfs_dir: &Dir) -> Result<crate::store::Comp
7676
.context("Failed to open composefs repository")
7777
}
7878

79+
#[context("Initializing composefs repository")]
7980
pub(crate) async fn initialize_composefs_repository(
8081
state: &State,
8182
root_setup: &RootSetup,

crates/lib/src/install.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ use serde::{Deserialize, Serialize};
187187

188188
#[cfg(feature = "install-to-disk")]
189189
use self::baseline::InstallBlockDeviceOpts;
190-
use crate::bootc_composefs::status::ComposefsCmdline;
190+
use crate::bootc_composefs::status::{ComposefsCmdline, get_bootloader};
191191
use crate::bootc_composefs::{
192192
boot::setup_composefs_boot, repo::initialize_composefs_repository,
193193
status::get_container_manifest_and_config,
@@ -1542,12 +1542,21 @@ async fn verify_target_fetch(
15421542
}
15431543

15441544
/// Preparation for an install; validates and prepares some (thereafter immutable) global state.
1545+
///
1546+
/// # Parameters
1547+
/// - `config_opts`: Installation configuration options (root user setup, generic image, etc.)
1548+
/// - `source_opts`: Source image reference; if `None`, assumes running inside a container
1549+
/// - `target_opts`: Target image reference and root path options
1550+
/// - `composefs_options`: composefs-related settings for the installation
1551+
/// - `target_fs`: Target filesystem type; used for `install to-filesystem`
1552+
/// - `replace_mode`: If `Some`, indicates an `install to-filesystem` or `install to-existing-root` with the given replacement mode
15451553
async fn prepare_install(
15461554
mut config_opts: InstallConfigOpts,
15471555
source_opts: InstallSourceOpts,
15481556
mut target_opts: InstallTargetOpts,
15491557
mut composefs_options: InstallComposefsOpts,
15501558
target_fs: Option<FilesystemEnum>,
1559+
replace_mode: Option<ReplaceMode>,
15511560
) -> Result<Arc<State>> {
15521561
tracing::trace!("Preparing install");
15531562
let rootfs = cap_std::fs::Dir::open_ambient_dir("/", cap_std::ambient_authority())
@@ -1698,6 +1707,12 @@ async fn prepare_install(
16981707

16991708
setup_sys_mount("efivarfs", EFIVARFS)?;
17001709

1710+
// Read efivars to get the bootloader
1711+
// Only if the operation is to replace the existing installation
1712+
if let Some(..) = replace_mode {
1713+
config_opts.bootloader = Some(get_bootloader().context("Determining existing bootloader")?)
1714+
};
1715+
17011716
// Now, deal with SELinux state.
17021717
let selinux_state = reexecute_self_for_selinux_if_needed(&source, config_opts.disable_selinux)?;
17031718
tracing::debug!("SELinux state: {selinux_state:?}");
@@ -2171,6 +2186,7 @@ pub(crate) async fn install_to_disk(mut opts: InstallToDiskOpts) -> Result<()> {
21712186
opts.target_opts,
21722187
opts.composefs_opts,
21732188
block_opts.filesystem,
2189+
None,
21742190
)
21752191
.await?;
21762192

@@ -2560,6 +2576,7 @@ pub(crate) async fn install_to_filesystem(
25602576
opts.target_opts,
25612577
opts.composefs_opts,
25622578
Some(inspect.fstype.as_str().try_into()?),
2579+
fsopts.replace,
25632580
)
25642581
.await?;
25652582

@@ -2633,18 +2650,22 @@ pub(crate) async fn install_to_filesystem(
26332650
false
26342651
}
26352652
};
2653+
26362654
// Find the UUID of /boot because we need it for GRUB.
2637-
let boot_uuid = if boot_is_mount {
2638-
let boot_path = target_root_path.join(BOOT);
2639-
tracing::debug!("boot_path={boot_path}");
2640-
let u = bootc_mount::inspect_filesystem(&boot_path)
2641-
.with_context(|| format!("Inspecting /{BOOT}"))?
2642-
.uuid
2643-
.ok_or_else(|| anyhow!("No UUID found for /{BOOT}"))?;
2644-
Some(u)
2645-
} else {
2646-
None
2655+
let boot_uuid = match state.config_opts.bootloader {
2656+
Some(Bootloader::Grub) | None if boot_is_mount => {
2657+
let boot_path = target_root_path.join(BOOT);
2658+
tracing::debug!("boot_path={boot_path}");
2659+
let u = bootc_mount::inspect_filesystem(&boot_path)
2660+
.with_context(|| format!("Inspecting /{BOOT}"))?
2661+
.uuid
2662+
.ok_or_else(|| anyhow!("No UUID found for /{BOOT}"))?;
2663+
Some(u)
2664+
}
2665+
2666+
_ => None,
26472667
};
2668+
26482669
tracing::debug!("boot UUID: {boot_uuid:?}");
26492670

26502671
// Find the real underlying backing device for the root. This is currently just required

crates/lib/src/store/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,13 @@ pub(crate) const COMPOSEFS_MODE: Mode = Mode::from_raw_mode(0o700);
137137

138138
/// Ensure the composefs directory exists in the given physical root
139139
/// with the correct permissions (mode 0700).
140+
#[context("Ensuring composefs directory")]
140141
pub(crate) fn ensure_composefs_dir(physical_root: &Dir) -> Result<()> {
142+
// Usually the case with bootc install to-existing-root
143+
if matches!(physical_root.is_mountpoint("."), Ok(Some(true))) {
144+
crate::utils::open_dir_remount_rw(physical_root, ".".into())?;
145+
}
146+
141147
let mut db = DirBuilder::new();
142148
db.mode(COMPOSEFS_MODE.as_raw_mode());
143149
physical_root
@@ -608,6 +614,7 @@ impl Storage {
608614
///
609615
/// This lazily opens the composefs repository, creating the directory if needed
610616
/// and bootstrapping verity settings from the ostree configuration.
617+
#[context("Ensuring composefs")]
611618
pub(crate) fn get_ensure_composefs(&self) -> Result<Arc<ComposefsRepository>> {
612619
if let Some(composefs) = self.composefs.get() {
613620
return Ok(Arc::clone(composefs));

crates/system-reinstall-bootc/src/podman.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub(crate) fn reinstall_command(
3030
ssh_key_file: &str,
3131
has_clean: bool,
3232
) -> Result<Command> {
33+
// NOTE: We mount /sys/firmware/efi/efivars during installation setup in
34+
// [`bootc_lib::prepare_install`] so we don't explicitly need it here
3335
let mut podman_command_and_args = [
3436
// We use podman to run the bootc container. This might change in the future to remove the
3537
// podman dependency.

0 commit comments

Comments
 (0)