Skip to content

Commit

Permalink
install: Add kargs to installation config
Browse files Browse the repository at this point in the history
We know we eventually want "day 2" management of kargs, but
supporting "install time" kargs in a somewhat container-native
way will let us more properly set up things like the `console=`
karg only for cloud images for example.

Signed-off-by: Colin Walters <walters@verbum.org>
  • Loading branch information
cgwalters committed Nov 19, 2023
1 parent 670962c commit d7d4235
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 6 deletions.
1 change: 1 addition & 0 deletions ci/Dockerfile.fcos
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ RUN make test-bin-archive

FROM quay.io/fedora/fedora-coreos:testing-devel
COPY --from=builder /src/target/bootc.tar.zst /tmp
COPY ci/usr usr
RUN tar -xvf /tmp/bootc.tar.zst && ostree container commit
5 changes: 4 additions & 1 deletion ci/run-kola.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ cd "${tmpdir}"
kola_args=()
if test -n "${JOB_NAME_HASH:-}"; then
oc registry login --to auth.json
cat > pull-secret.bu << 'EOF'
cat > pull-secret.bu << EOF
variant: fcos
version: 1.1.0
storage:
files:
- path: /etc/ostree/auth.json
contents:
local: auth.json
- path: /etc/target-image
contents:
inline: ${TARGET_IMAGE}
systemd:
units:
- name: zincati.service
Expand Down
2 changes: 2 additions & 0 deletions ci/usr/lib/bootc/install/50-test-kargs.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[install]
kargs = ["localtestkarg=somevalue", "otherlocalkarg=42"]
17 changes: 14 additions & 3 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 leaves 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-<osname>.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
Expand Down
44 changes: 43 additions & 1 deletion lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<super::baseline::Filesystem>,
/// Kernel arguments, applied at installation time
pub(crate) kargs: Option<Vec<String>>,
}

impl InstallConfiguration {
Expand All @@ -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)
}
}
}

Expand All @@ -416,6 +424,7 @@ pub(crate) mod config {
}
if let Some(config) = config.as_mut() {
if let Some(install) = c.install {
tracing::debug!("Merging install config: {install:?}");
config.merge(install);
}
} else {
Expand All @@ -441,10 +450,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()
)
)
}
}

Expand Down
8 changes: 8 additions & 0 deletions lib/src/install/baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Vec<_>>();

mount::mount(&rootdev, &rootfs)?;
Expand Down
19 changes: 18 additions & 1 deletion tests/kolainst/install
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,29 @@ cd $(mktemp -d)

case "${AUTOPKGTEST_REBOOT_MARK:-}" in
"")
podman run --rm -ti --privileged --pid=host -v /usr/bin/bootc:/usr/bin/bootc ${IMAGE} bootc install --target-no-signature-verification --karg=foo=bar ${DEV}
mkdir -p ~/.config/containers
cp -a /etc/ostree/auth.json ~/.config/containers
target_image=$(cat /etc/target-image)
mkdir -p usr/{lib,bin}
cp -a /usr/lib/bootc usr/lib
cp -a /usr/bin/bootc usr/bin
cat > usr/lib/bootc/install/10-ci-rootfs.toml << 'EOF'
[install]
root-fs-type = "xfs"
EOF
cat > Dockerfile << EOF
FROM ${target_image}
COPY usr usr
EOF
podman build -t localhost/testimage .
podman run --rm -ti --privileged --pid=host --env RUST_LOG=error,bootc_lib::install=debug \
localhost/testimage bootc install --target-no-signature-verification --skip-fetch-check --karg=foo=bar ${DEV}
# In theory we could e.g. wipe the bootloader setup on the primary disk, then reboot;
# but for now let's just sanity test that the install command executes.
lsblk ${DEV}
mount /dev/vda3 /var/mnt
grep foo=bar /var/mnt/loader/entries/*.conf
grep localtestkarg=somevalue /var/mnt/loader/entries/*.conf
grep -Ee '^linux /boot/ostree' /var/mnt/loader/entries/*.conf
umount /var/mnt
echo "ok install"
Expand Down

0 comments on commit d7d4235

Please sign in to comment.