Skip to content
Merged
Show file tree
Hide file tree
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
7 changes: 6 additions & 1 deletion crates/lib/src/bootloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,12 @@ pub(crate) fn install_via_bootupd(
println!("Installing bootloader via bootupd");

// Build the bootupctl arguments
let mut bootupd_args: Vec<&str> = vec!["backend", "install", "--write-uuid"];
let mut bootupd_args: Vec<&str> = vec!["backend", "install"];
if configopts.bootupd_skip_boot_uuid {
bootupd_args.push("--with-static-configs")
} else {
bootupd_args.push("--write-uuid");
}
if let Some(v) = verbose {
bootupd_args.push(v);
}
Expand Down
18 changes: 16 additions & 2 deletions crates/lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ pub(crate) struct InstallConfigOpts {
/// The stateroot name to use. Defaults to `default`.
#[clap(long)]
pub(crate) stateroot: Option<String>,

/// Don't pass --write-uuid to bootupd during bootloader installation.
#[clap(long)]
#[serde(default)]
pub(crate) bootupd_skip_boot_uuid: bool,
}

#[derive(Debug, Default, Clone, clap::Parser, Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -1512,7 +1517,7 @@ async fn verify_target_fetch(

/// Preparation for an install; validates and prepares some (thereafter immutable) global state.
async fn prepare_install(
config_opts: InstallConfigOpts,
mut config_opts: InstallConfigOpts,
source_opts: InstallSourceOpts,
target_opts: InstallTargetOpts,
mut composefs_options: InstallComposefsOpts,
Expand Down Expand Up @@ -1637,8 +1642,17 @@ async fn prepare_install(
}

let install_config = config::load_config()?;
if install_config.is_some() {
if let Some(ref config) = install_config {
tracing::debug!("Loaded install configuration");
// Merge config file values into config_opts (CLI takes precedence)
// Only apply config file value if CLI didn't explicitly set it
if !config_opts.bootupd_skip_boot_uuid {
config_opts.bootupd_skip_boot_uuid = config
.bootupd
.as_ref()
.and_then(|b| b.skip_boot_uuid)
.unwrap_or(false);
}
} else {
tracing::debug!("No install configuration found");
}
Expand Down
78 changes: 78 additions & 0 deletions crates/lib/src/install/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ pub(crate) struct BasicFilesystems {
/// Configuration for ostree repository
pub(crate) type OstreeRepoOpts = ostree_ext::repo_options::RepoOptions;

/// Configuration options for bootupd, responsible for setting up the bootloader.
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub(crate) struct Bootupd {
/// Whether to skip writing the boot partition UUID to the bootloader configuration.
/// When true, bootupd is invoked with `--with-static-configs` instead of `--write-uuid`.
/// Defaults to false (UUIDs are written by default).
pub(crate) skip_boot_uuid: Option<bool>,
}

/// The serialized `[install]` section
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename = "install", rename_all = "kebab-case", deny_unknown_fields)]
Expand All @@ -85,6 +95,8 @@ pub(crate) struct InstallConfiguration {
pub(crate) root_mount_spec: Option<String>,
/// Mount specification for the /boot filesystem.
pub(crate) boot_mount_spec: Option<String>,
/// Bootupd configuration
pub(crate) bootupd: Option<Bootupd>,
}

fn merge_basic<T>(s: &mut Option<T>, o: Option<T>, _env: &EnvProperties) {
Expand Down Expand Up @@ -142,6 +154,13 @@ impl Mergeable for OstreeRepoOpts {
}
}

impl Mergeable for Bootupd {
/// Apply any values in other, overriding any existing values in `self`.
fn merge(&mut self, other: Self, env: &EnvProperties) {
merge_basic(&mut self.skip_boot_uuid, other.skip_boot_uuid, env)
}
}

impl Mergeable for InstallConfiguration {
/// Apply any values in other, overriding any existing values in `self`.
fn merge(&mut self, other: Self, env: &EnvProperties) {
Expand All @@ -160,6 +179,7 @@ impl Mergeable for InstallConfiguration {
merge_basic(&mut self.stateroot, other.stateroot, env);
merge_basic(&mut self.root_mount_spec, other.root_mount_spec, env);
merge_basic(&mut self.boot_mount_spec, other.boot_mount_spec, env);
self.bootupd.merge(other.bootupd, env);
if let Some(other_kargs) = other.kargs {
self.kargs
.get_or_insert_with(Default::default)
Expand Down Expand Up @@ -731,4 +751,62 @@ boot-mount-spec = ""
assert_eq!(install.root_mount_spec.as_deref().unwrap(), "");
assert_eq!(install.boot_mount_spec.as_deref().unwrap(), "");
}

#[test]
fn test_parse_bootupd_skip_boot_uuid() {
// Test parsing true
let c: InstallConfigurationToplevel = toml::from_str(
r#"[install.bootupd]
skip-boot-uuid = true
"#,
)
.unwrap();
assert_eq!(
c.install.unwrap().bootupd.unwrap().skip_boot_uuid.unwrap(),
true
);

// Test parsing false
let c: InstallConfigurationToplevel = toml::from_str(
r#"[install.bootupd]
skip-boot-uuid = false
"#,
)
.unwrap();
assert_eq!(
c.install.unwrap().bootupd.unwrap().skip_boot_uuid.unwrap(),
false
);

// Test default (not specified) is None
let c: InstallConfigurationToplevel = toml::from_str(
r#"[install]
root-fs-type = "xfs"
"#,
)
.unwrap();
assert!(c.install.unwrap().bootupd.is_none());
}

#[test]
fn test_merge_bootupd_skip_boot_uuid() {
let env = EnvProperties {
sys_arch: "x86_64".to_string(),
};
let mut install: InstallConfiguration = toml::from_str(
r#"[bootupd]
skip-boot-uuid = false
"#,
)
.unwrap();
let other = InstallConfiguration {
bootupd: Some(Bootupd {
skip_boot_uuid: Some(true),
}),
..Default::default()
};
install.merge(other, &env);
// skip_boot_uuid should be overridden to true
assert_eq!(install.bootupd.unwrap().skip_boot_uuid.unwrap(), true);
}
}
8 changes: 8 additions & 0 deletions docs/src/man/bootc-install-config.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ Configuration options for the ostree repository. There is one valid field:
Boot Loader Spec entries, except for the default entry. This is useful for configuring
arguments that should only apply to non-default deployments.

# bootupd

Configuration options for bootupd, responsible of setting up the bootloader.
There is only one valid field:
- `skip-boot-uuid`: A boolean that controls whether to skip writing partition UUIDs
to the bootloader configuration. When `true`, bootupd is invoked with `--with-static-configs`
instead of `--write-uuid`. Defaults to `false` (UUIDs are written by default).

# Examples

```toml
Expand Down