diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de7c18902..0927f64b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,11 +113,23 @@ jobs: echo 'deb http://cz.archive.ubuntu.com/ubuntu lunar main universe' | sudo tee -a /etc/apt/sources.list sudo apt update sudo apt upgrade skopeo + - name: Build derived image + run: | + mkdir -p usr/lib/bootc/install + cat > usr/lib/bootc/install/50-test-kargs.toml << 'EOF' + [install] + kargs = ["localtestkarg=somevalue", "otherlocalkarg=42"] + EOF + cat >Containerfile << 'EOF' + FROM quay.io/centos-boot/fedora-tier-1:eln + COPY usr usr + EOF + sudo podman build -t localhost/testimage . - name: Integration tests run: | set -xeuo pipefail sudo podman run --rm -ti --privileged -v /:/target -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \ - quay.io/centos-boot/fedora-tier-1:eln bootc install-to-filesystem --target-no-signature-verification \ + localhost/testimage bootc install-to-filesystem --skip-fetch-check --target-no-signature-verification \ --karg=foo=bar --disable-selinux --replace=alongside /target - ls -al /boot/loader/ sudo grep foo=bar /boot/loader/entries/*.conf + sudo grep localtestkarg=somevalue /boot/loader/entries/*.conf diff --git a/docs/install.md b/docs/install.md index 9b461b020..78874d9bc 100644 --- a/docs/install.md +++ b/docs/install.md @@ -96,21 +96,32 @@ in that case you will need to specify `--skip-fetch-check`. ### Operating system install configuration required -The container image **MUST** define its default install configuration. For example, -create `/usr/lib/bootc/install/00-exampleos.toml` with the contents: +The container image **MUST** define its default install configuration. A key choice +that bootc by default lives up to the operating system image is the root filesystem +type. + +To enable `bootc install` as part of your OS/distribution base image, +create a file named `/usr/lib/bootc/install/00-.toml` with the contents of the form: ```toml [install] root-fs-type = "xfs" ``` -At the current time, `root-fs-type` is the only available configuration option, and it **MUST** be set. +The `root-fs-type` value **MUST** be set. Configuration files found in this directory will be merged, with higher alphanumeric values taking precedence. If for example you are building a derived container image from the above OS, you could create a `50-myos.toml` that sets `root-fs-type = "btrfs"` which will override the prior setting. +Other available options, also under the `[install]` section: + +`kargs`: This allows setting kernel arguments which apply only at the time of `bootc install`. +This option is particularly useful when creating derived/layered images; for example, a cloud +image may want to have its default `console=` set, in contrast with a default base image. +The values in this field are space separated. + ## Installing an "unconfigured" image The bootc project aims to support generic/general-purpose operating diff --git a/lib/src/install.rs b/lib/src/install.rs index 0fb81efbc..4972af6b7 100644 --- a/lib/src/install.rs +++ b/lib/src/install.rs @@ -381,7 +381,10 @@ pub(crate) mod config { #[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(rename = "install", rename_all = "kebab-case", deny_unknown_fields)] pub(crate) struct InstallConfiguration { + /// Root filesystem type pub(crate) root_fs_type: Option, + /// Kernel arguments, applied at installation time + pub(crate) kargs: Option>, } impl InstallConfiguration { @@ -392,7 +395,12 @@ pub(crate) mod config { *s = Some(o); } } - mergeopt(&mut self.root_fs_type, other.root_fs_type) + mergeopt(&mut self.root_fs_type, other.root_fs_type); + if let Some(other_kargs) = other.kargs { + self.kargs + .get_or_insert_with(|| Default::default()) + .extend(other_kargs) + } } } @@ -434,10 +442,43 @@ root-fs-type = "xfs" let other = InstallConfigurationToplevel { install: Some(InstallConfiguration { root_fs_type: Some(Filesystem::Ext4), + kargs: None, }), }; install.merge(other.install.unwrap()); assert_eq!(install.root_fs_type.unwrap(), Filesystem::Ext4); + + let c: InstallConfigurationToplevel = toml::from_str( + r##"[install] +root-fs-type = "ext4" +kargs = ["console=ttyS0", "foo=bar"] +"##, + ) + .unwrap(); + let mut install = c.install.unwrap(); + assert_eq!(install.root_fs_type.unwrap(), Filesystem::Ext4); + let other = InstallConfigurationToplevel { + install: Some(InstallConfiguration { + root_fs_type: None, + kargs: Some( + ["console=tty0", "nosmt"] + .into_iter() + .map(ToOwned::to_owned) + .collect(), + ), + }), + }; + install.merge(other.install.unwrap()); + assert_eq!(install.root_fs_type.unwrap(), Filesystem::Ext4); + assert_eq!( + install.kargs, + Some( + ["console=ttyS0", "foo=bar", "console=tty0", "nosmt"] + .into_iter() + .map(ToOwned::to_owned) + .collect() + ) + ) } } diff --git a/lib/src/install/baseline.rs b/lib/src/install/baseline.rs index a69f6190b..5a0edb7fa 100644 --- a/lib/src/install/baseline.rs +++ b/lib/src/install/baseline.rs @@ -350,6 +350,14 @@ pub(crate) fn install_create_rootfs( .into_iter() .flatten() .chain([rootarg, RW_KARG.to_string(), bootarg].into_iter()) + .chain( + state + .install_config + .kargs + .iter() + .flatten() + .map(ToOwned::to_owned), + ) .collect::>(); mount::mount(&rootdev, &rootfs)?;