1
0
mirror of https://github.com/containers/bootc.git synced 2026-02-05 06:45:13 +01:00

install: Allow root and boot mount-specs in config

Allow configuring the root and boot filesystem mount
specs via the install configuration file under [install].

As for other options, CLI arguments take precedence.

For the to-existing-root flow, mount specs from config are ignored.
Example configuration:
```
[install]
root-mount-spec = "LABEL=rootfs"
boot-mount-spec = "UUID=abcd-1234"
```

Fixes https://github.com/bootc-dev/bootc/issues/1939

Assisted-by: Opencode (Claude Opus 4.5)
Signed-off-by: jbtrystram <jbtrystram@redhat.com>
This commit is contained in:
jbtrystram
2026-01-22 15:39:02 +01:00
committed by Colin Walters
parent a17413c979
commit 4c22d1664e
3 changed files with 81 additions and 2 deletions

View File

@@ -2239,7 +2239,12 @@ pub(crate) async fn install_to_filesystem(
// We support overriding the mount specification for root (i.e. LABEL vs UUID versus
// raw paths).
// We also support an empty specification as a signal to omit any mountspec kargs.
let root_info = if let Some(s) = fsopts.root_mount_spec {
// CLI takes precedence over config file.
let config_root_mount_spec = state
.install_config
.as_ref()
.and_then(|c| c.root_mount_spec.as_ref());
let root_info = if let Some(s) = fsopts.root_mount_spec.as_ref().or(config_root_mount_spec) {
RootMountInfo {
mount_spec: s.to_string(),
kargs: Vec::new(),
@@ -2320,7 +2325,12 @@ pub(crate) async fn install_to_filesystem(
let device_info = bootc_blockdev::partitions_of(Utf8Path::new(&backing_device))?;
let rootarg = format!("root={}", root_info.mount_spec);
let mut boot = if let Some(spec) = fsopts.boot_mount_spec {
// CLI takes precedence over config file.
let config_boot_mount_spec = state
.install_config
.as_ref()
.and_then(|c| c.boot_mount_spec.as_ref());
let mut boot = if let Some(spec) = fsopts.boot_mount_spec.as_ref().or(config_boot_mount_spec) {
// An empty boot mount spec signals to omit the mountspec kargs
// See https://github.com/bootc-dev/bootc/issues/1441
if spec.is_empty() {

View File

@@ -80,6 +80,11 @@ pub(crate) struct InstallConfiguration {
pub(crate) ostree: Option<OstreeRepoOpts>,
/// The stateroot name to use. Defaults to `default`
pub(crate) stateroot: Option<String>,
/// Source device specification for the root filesystem.
/// For example, `UUID=2e9f4241-229b-4202-8429-62d2302382e1` or `LABEL=rootfs`.
pub(crate) root_mount_spec: Option<String>,
/// Mount specification for the /boot filesystem.
pub(crate) boot_mount_spec: Option<String>,
}
fn merge_basic<T>(s: &mut Option<T>, o: Option<T>, _env: &EnvProperties) {
@@ -153,6 +158,8 @@ impl Mergeable for InstallConfiguration {
self.filesystem.merge(other.filesystem, env);
self.ostree.merge(other.ostree, env);
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);
if let Some(other_kargs) = other.kargs {
self.kargs
.get_or_insert_with(Default::default)
@@ -672,4 +679,56 @@ stateroot = "custom"
install.merge(other, &env);
assert_eq!(install.stateroot.unwrap(), "newroot");
}
#[test]
fn test_parse_mount_specs() {
let c: InstallConfigurationToplevel = toml::from_str(
r#"[install]
root-mount-spec = "LABEL=rootfs"
boot-mount-spec = "UUID=abcd-1234"
"#,
)
.unwrap();
let install = c.install.unwrap();
assert_eq!(install.root_mount_spec.unwrap(), "LABEL=rootfs");
assert_eq!(install.boot_mount_spec.unwrap(), "UUID=abcd-1234");
}
#[test]
fn test_merge_mount_specs() {
let env = EnvProperties {
sys_arch: "x86_64".to_string(),
};
let mut install: InstallConfiguration = toml::from_str(
r#"root-mount-spec = "UUID=old"
boot-mount-spec = "UUID=oldboot"
"#,
)
.unwrap();
let other = InstallConfiguration {
root_mount_spec: Some("LABEL=newroot".to_string()),
..Default::default()
};
install.merge(other, &env);
// root_mount_spec should be overridden
assert_eq!(install.root_mount_spec.as_deref().unwrap(), "LABEL=newroot");
// boot_mount_spec should remain unchanged
assert_eq!(install.boot_mount_spec.as_deref().unwrap(), "UUID=oldboot");
}
/// Empty mount specs are valid and signal to omit mount kargs entirely.
/// See https://github.com/bootc-dev/bootc/issues/1441
#[test]
fn test_parse_empty_mount_specs() {
let c: InstallConfigurationToplevel = toml::from_str(
r#"[install]
root-mount-spec = ""
boot-mount-spec = ""
"#,
)
.unwrap();
let install = c.install.unwrap();
assert_eq!(install.root_mount_spec.as_deref().unwrap(), "");
assert_eq!(install.boot_mount_spec.as_deref().unwrap(), "");
}
}