Skip to content

Commit b831efb

Browse files
committed
install: Rename install -> install to-disk, peer with to-filesystem
Take the current `install` verb and change it to be `bootc install to-disk`, and then `install-to-filesystem` becomes `bootc install to-filesystem` - they are obvious peers. The main motivation here is that in the end many use cases will want nontrivial filesystem customization, and while I like having a fully opinionated builtin flow to write to a target disk, we should really think of `to-filesystem` as a fully equal peer of `to-disk`. Signed-off-by: Colin Walters <[email protected]>
1 parent 2582ef2 commit b831efb

File tree

8 files changed

+55
-41
lines changed

8 files changed

+55
-41
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ jobs:
136136
run: |
137137
set -xeuo pipefail
138138
sudo podman run --rm -ti --privileged -v /:/target -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \
139-
quay.io/centos-bootc/fedora-bootc-dev:eln bootc install-to-filesystem --target-no-signature-verification \
139+
quay.io/centos-bootc/fedora-bootc-dev:eln bootc install to-filesystem --target-no-signature-verification \
140140
--karg=foo=bar --disable-selinux --replace=alongside /target
141141
ls -al /boot/loader/
142142
sudo grep foo=bar /boot/loader/entries/*.conf

docs/index.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,15 @@ First, build a derived container using any container build tooling.
8989

9090
#### Using `bootc install`
9191

92-
The `bootc install` command will write the current container to a disk, and set it up for booting.
92+
The `bootc install` command has two high level sub-commands; `to-disk` and `to-filesystem`.
93+
94+
The `bootc install to-disk` handles basically everything in taking the current container
95+
and writing it to a disk, and set it up for booting and future in-place upgrades.
96+
9397
In brief, the idea is that every container image shipping `bootc` also comes with a simple
94-
installer that can set a system up to boot from it. Crucially, if you create a
95-
*derivative* container image from a stock OS container image, it also automatically supports `bootc install`.
98+
installer that can set a system up to boot from it. Crucially, if you create a
99+
*derivative* container image from a stock OS container image, it also automatically
100+
supports `bootc install`.
96101

97102
For more information, please see [install.md](install.md).
98103

docs/install.md

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ The Linux kernel (and optionally initramfs) is embedded in the container image;
1717
is `/usr/lib/modules/$kver/vmlinuz`, and the initramfs should be in `initramfs.img`
1818
in that directory.
1919

20-
The `bootc install` and `boot install-to-filesystem` commands bridge the two worlds
21-
of a standard, runnable OCI image and a bootable system by running tooling logic embedded
20+
The `bootc install` command bridges the two worlds of a standard, runnable OCI image
21+
and a bootable system by running tooling logic embedded
2222
in the container image to create the filesystem and bootloader setup dynamically.
2323
This requires running the container via `--privileged`; it uses the running Linux kernel
2424
on the host to write the file content from the running container image; not the kernel
2525
inside the container.
2626

27+
There are two sub-commands: `bootc install to-disk` and `boot install to-filesystem`.
28+
2729
However, nothing *else* (external) is required to perform a basic installation
2830
to disk. (The one exception to host requirements today is that the host must
2931
have `skopeo` installed. This is a bug; more information in
@@ -44,8 +46,8 @@ image comes with a basic installer.
4446
## Executing `bootc install`
4547

4648
The two installation commands allow you to install the container image
47-
either directly to a block device (`bootc install`) or to an existing
48-
filesystem (`bootc install-to-filesystem`).
49+
either directly to a block device (`bootc install to-disk`) or to an existing
50+
filesystem (`bootc install to-filesystem`).
4951

5052
The installation commands **MUST** be run **from** the container image
5153
that will be installed, using `--privileged` and a few
@@ -56,7 +58,7 @@ to an existing system and install your container image. Failure to run
5658
Here's an example of using `bootc install` (root/elevated permission required):
5759

5860
```bash
59-
podman run --rm --privileged --pid=host --security-opt label=type:unconfined_t <image> bootc install --target-no-signature-verification /path/to/disk
61+
podman run --rm --privileged --pid=host --security-opt label=type:unconfined_t <image> bootc install to-disk --target-no-signature-verification /path/to/disk
6062
```
6163

6264
Note that while `--privileged` is used, this command will not perform any
@@ -68,7 +70,7 @@ The `--pid=host --security-opt label=type:unconfined_t` today
6870
make it more convenient for bootc to perform some privileged
6971
operations; in the future these requirement may be dropped.
7072

71-
Jump to the section for [`install-to-filesystem`](#more-advanced-installation) later
73+
Jump to the section for [`install to-filesystem`](#more-advanced-installation) later
7274
in this document for additional information about that method.
7375

7476
### "day 2" updates, security and fetch configuration
@@ -181,16 +183,16 @@ the files are underneath `/usr`. To rotate or change the set of keys,
181183
one would build a new container image. Client systems using `bootc upgrade`
182184
will transactionally update to this new system state.
183185

184-
## More advanced installation
186+
## More advanced installation with `to-filesystem`
185187

186-
The basic `bootc install` logic is really a pretty small (but opinionated) wrapper
188+
The basic `bootc install to-disk` logic is really a pretty small (but opinionated) wrapper
187189
for a set of lower level tools that can also be invoked independently.
188190

189-
The `bootc install` command is effectively:
191+
The `bootc install to-disk` command is effectively:
190192

191193
- `mkfs.$fs /dev/disk`
192194
- `mount /dev/disk /mnt`
193-
- `bootc install-to-filesystem --karg=root=UUID=<uuid of /mnt> --imgref $self /mnt`
195+
- `bootc install to-filesystem --karg=root=UUID=<uuid of /mnt> --imgref $self /mnt`
194196

195197
There may be a bit more involved here; for example configuring
196198
`--block-setup tpm2-luks` will configure the root filesystem
@@ -199,25 +201,22 @@ with LUKS bound to the TPM2 chip, currently via [systemd-cryptenroll](https://ww
199201
Some OS/distributions may not want to enable it at all; it
200202
can be configured off at build time via Cargo features.
201203

202-
### Using `bootc install-to-filesystem`
203-
204-
As noted above, there is also `bootc install-to-filesystem`, which allows
205-
an arbitrary process to create the root filesystem.
204+
### Using `bootc install to-filesystem`
206205

207206
The usual expected way for an external storage system to work
208207
is to provide `root=<UUID>` type kernel arguments. At the current
209208
time a separate `/boot` filesystem is also required (mainly to enable LUKS)
210209
so you will also need to provide e.g. `--boot-mount-spec UUID=...`.
211210

212-
The `bootc install-to-filesystem` command allows an operating
211+
The `bootc install to-filesystem` command allows an operating
213212
system or distribution to ship a separate installer that creates more complex block
214213
storage or filesystem setups, but reuses the "top half" of the logic.
215214
For example, a goal is to change [Anaconda](https://github.com/rhinstaller/anaconda/)
216215
to use this.
217216

218-
### Using `bootc install-to-filesystem --replace=alongside`
217+
### Using `bootc install to-filesystem --replace=alongside`
219218

220-
This is a variant of `install-to-filesystem`, which maximizes convenience for using
219+
This is a variant of `install to-filesystem`, which maximizes convenience for using
221220
an existing Linux system, converting it into the target container image. Note that
222221
the `/boot` (and `/boot/efi`) partitions *will be reinitialized* - so this is a
223222
somewhat destructive operation for the existing Linux installation.
@@ -231,7 +230,7 @@ The core command should look like this (root/elevated permission required):
231230
podman run --rm --privileged -v /:/target \
232231
--pid=host --security-opt label=type:unconfined_t \
233232
<image> \
234-
bootc install-to-filesystem --replace=alongside /target
233+
bootc install to-filesystem --replace=alongside /target
235234
```
236235

237236
At the current time, leftover data in `/` is **NOT** automatically cleaned up. This can

lib/src/cli.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,16 @@ pub(crate) struct StatusOpts {
9595
pub(crate) booted: bool,
9696
}
9797

98+
/// Options for internal testing
99+
#[cfg(feature = "install")]
100+
#[derive(Debug, clap::Subcommand)]
101+
pub(crate) enum InstallOpts {
102+
/// Install to the target block device
103+
ToDisk(crate::install::InstallToDiskOpts),
104+
/// Install to the target filesystem
105+
ToFilesystem(crate::install::InstallToFilesystemOpts),
106+
}
107+
98108
/// Options for man page generation
99109
#[derive(Debug, Parser)]
100110
pub(crate) struct ManOpts {
@@ -112,7 +122,7 @@ pub(crate) enum TestingOpts {
112122
RunContainerIntegration {},
113123
/// Block device setup for testing
114124
PrepTestInstallFilesystem { blockdev: Utf8PathBuf },
115-
/// e2e test of install-to-filesystem
125+
/// e2e test of install to-filesystem
116126
TestInstallFilesystem {
117127
image: String,
118128
blockdev: Utf8PathBuf,
@@ -150,17 +160,16 @@ pub(crate) enum Opt {
150160
/// Add a transient writable overlayfs on `/usr` that will be discarded on reboot.
151161
#[clap(alias = "usroverlay")]
152162
UsrOverlay,
153-
/// Install to the target block device
163+
/// Install the running container to a target
164+
#[clap(subcommand)]
154165
#[cfg(feature = "install")]
155-
Install(crate::install::InstallOpts),
166+
Install(InstallOpts),
156167
/// Execute the given command in the host mount namespace
157168
#[cfg(feature = "install")]
158169
#[clap(hide = true)]
159170
#[command(external_subcommand)]
160171
ExecInHostMountNamespace(Vec<OsString>),
161-
/// Install to the target filesystem.
162-
#[cfg(feature = "install")]
163-
InstallToFilesystem(crate::install::InstallToFilesystemOpts),
172+
164173
/// Internal integration testing helpers.
165174
#[clap(hide(true), subcommand)]
166175
#[cfg(feature = "internal-testing-api")]
@@ -454,9 +463,10 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
454463
Opt::Edit(opts) => edit(opts).await,
455464
Opt::UsrOverlay => usroverlay().await,
456465
#[cfg(feature = "install")]
457-
Opt::Install(opts) => crate::install::install(opts).await,
458-
#[cfg(feature = "install")]
459-
Opt::InstallToFilesystem(opts) => crate::install::install_to_filesystem(opts).await,
466+
Opt::Install(opts) => match opts {
467+
InstallOpts::ToDisk(opts) => crate::install::install_to_disk(opts).await,
468+
InstallOpts::ToFilesystem(opts) => crate::install::install_to_filesystem(opts).await,
469+
},
460470
#[cfg(feature = "install")]
461471
Opt::ExecInHostMountNamespace(args) => {
462472
crate::install::exec_in_host_mountns(args.as_slice())

lib/src/install.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! This module supports installing a bootc-compatible image to
44
//! a block device directly via the `install` verb, or to an externally
5-
//! set up filesystem via `install-to-filesystem`.
5+
//! set up filesystem via `install to-filesystem`.
66
77
// This sub-module is the "basic" installer that handles creating basic block device
88
// and filesystem setup.
@@ -118,7 +118,7 @@ pub(crate) struct InstallConfigOpts {
118118

119119
/// Perform an installation to a block device.
120120
#[derive(Debug, Clone, clap::Parser, Serialize, Deserialize)]
121-
pub(crate) struct InstallOpts {
121+
pub(crate) struct InstallToDiskOpts {
122122
#[clap(flatten)]
123123
#[serde(flatten)]
124124
pub(crate) block_opts: InstallBlockDeviceOpts,
@@ -1021,8 +1021,8 @@ fn installation_complete() {
10211021
println!("Installation complete!");
10221022
}
10231023

1024-
/// Implementation of the `bootc install` CLI command.
1025-
pub(crate) async fn install(opts: InstallOpts) -> Result<()> {
1024+
/// Implementation of the `bootc install to-disk` CLI command.
1025+
pub(crate) async fn install_to_disk(opts: InstallToDiskOpts) -> Result<()> {
10261026
let block_opts = opts.block_opts;
10271027
let state = prepare_install(opts.config_opts, opts.target_opts).await?;
10281028

@@ -1113,7 +1113,7 @@ fn clean_boot_directories(rootfs: &Dir) -> Result<()> {
11131113
Ok(())
11141114
}
11151115

1116-
/// Implementation of the `bootc install-to-filsystem` CLI command.
1116+
/// Implementation of the `bootc install to-filsystem` CLI command.
11171117
pub(crate) async fn install_to_filesystem(opts: InstallToFilesystemOpts) -> Result<()> {
11181118
// Gather global state, destructuring the provided options
11191119
let state = prepare_install(opts.config_opts, opts.target_opts).await?;
@@ -1252,7 +1252,7 @@ pub(crate) async fn install_to_filesystem(opts: InstallToFilesystemOpts) -> Resu
12521252

12531253
#[test]
12541254
fn install_opts_serializable() {
1255-
let c: InstallOpts = serde_json::from_value(serde_json::json!({
1255+
let c: InstallToDiskOpts = serde_json::from_value(serde_json::json!({
12561256
"device": "/dev/vda"
12571257
}))
12581258
.unwrap();

lib/src/install/baseline.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! This module handles creation of simple root filesystem setups. At the current time
44
//! it's very simple - just a direct filesystem (e.g. xfs, ext4, btrfs etc.). It is
55
//! intended to add opinionated handling of TPM2-bound LUKS too. But that's about it;
6-
//! other more complex flows should set things up externally and use `bootc install-to-filesystem`.
6+
//! other more complex flows should set things up externally and use `bootc install to-filesystem`.
77
88
use std::borrow::Cow;
99
use std::fmt::Display;

lib/src/privtests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ fn test_install_filesystem(image: &str, blockdev: &Utf8Path) -> Result<()> {
152152
let mountpoint: &Utf8Path = mountpoint_dir.path().try_into().unwrap();
153153

154154
// And run the install
155-
cmd!(sh, "podman run --rm --privileged --pid=host --env=RUST_LOG -v /usr/bin/bootc:/usr/bin/bootc -v {mountpoint}:/target-root {image} bootc install-to-filesystem --target-no-signature-verification /target-root").run()?;
155+
cmd!(sh, "podman run --rm --privileged --pid=host --env=RUST_LOG -v /usr/bin/bootc:/usr/bin/bootc -v {mountpoint}:/target-root {image} bootc install to-filesystem --target-no-signature-verification /target-root").run()?;
156156

157157
cmd!(sh, "umount -R {mountpoint}").run()?;
158158

tests/kolainst/install

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ case "${AUTOPKGTEST_REBOOT_MARK:-}" in
3030
EOF
3131
podman build -t localhost/testimage .
3232
podman run --rm -ti --privileged --pid=host --env RUST_LOG=error,bootc_lib::install=debug \
33-
localhost/testimage bootc install --target-no-signature-verification --skip-fetch-check --karg=foo=bar ${DEV}
33+
localhost/testimage bootc install to-disk --target-no-signature-verification --skip-fetch-check --karg=foo=bar ${DEV}
3434
# In theory we could e.g. wipe the bootloader setup on the primary disk, then reboot;
3535
# but for now let's just sanity test that the install command executes.
3636
lsblk ${DEV}
@@ -41,7 +41,7 @@ EOF
4141
umount /var/mnt
4242
echo "ok install"
4343

44-
# Now test install-to-filesystem
44+
# Now test install to-filesystem
4545
# Wipe the device
4646
ls ${DEV}* | tac | xargs wipefs -af
4747
# This prepares the device and also runs podman directliy

0 commit comments

Comments
 (0)