Repository navigation
UKI Addons Support - #2448
UKI Addons Support#2448Johan-Liebert1 wants to merge 18 commits into
Conversation
2579e09 to
e31ce45
Compare
|
Can we install UKI addons as part of a deployment with |
| pub(crate) enum UkiAddonCliOpts { | ||
| /// List all installed UKI Addons | ||
| List { | ||
| /// Output in JSON format |
That's in the docs here right? |
|
Or well actually, I think what you may be asking about is external UKI addons (i.e. not included in the container image), in which case it would totally make sense to do. |
Yea I wasn't super clear but that was what I was thinking about 🙂 |
3422e57 to
4b63be2
Compare
cgwalters
left a comment
There was a problem hiding this comment.
How about bootc install --included-uki-addon foo --external-uki-addon /path/to/external.efi i.e. we always disambiguate between internal and external?
I don't understand what we mean by external here? I'm guessing it doesn't mean "global" addons |
|
external ➡️ #2448 (comment) |
bcafaf3 to
77db443
Compare
b3b9d76 to
3ca9715
Compare
c11883b to
ec66b3d
Compare
|
@cgwalters This should be good to go |
da19937 to
b267228
Compare
Introduce a function to gather all currently installed addons, scoped and global. On upgrade/switch, gather all installed addons and if an addon with the same name is found in the upgrade image, update that particular addon automatically Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
We were partially supporting global addons, but they were lumped in with scoped/local addons. Add a new cli option to composefs installs called `--global-uki-addon` which would determine which global addon to install. Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
b267228 to
850b488
Compare
Here is what we do now with UKI Addons - Accept `--uki-addon` and `--global-uki-addon` cli options for bootc switch/upgrade commands - If we find an installed addon with the same name as the one in the new image, we update it Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Assisted-by: AI Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Prefix global addon filenames with the bootc identifier in the ESP so we can distinguish bootc-managed global addons from third-party ones Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Add `bootc uki-addon` subcommand with three operations: - `bootc uki-addon list`: List installed UKI addons Supports `--json` for JSON output - `bootc uki-addon add <name> <global|scoped>`: Install an addon from the booted image onto the ESP - `bootc uki-addon remove <name> [deployment_id]`: Remove an addon Add Display and Serialize to UkiAddonType/UkiAddonsList Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
- Add GC tests for Addons - Add CLI tests Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Mark UKI Addons as experimental Assisted-by: Claude-Code (Opus) Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
UkiAddonOpts is now flattened into both upgrade and switch commands, which don't have a --composefs-backend flag. The `requires = "composefs_backend"` constraint causes a panic at clap validation time because the referenced argument doesn't exist in those command contexts. This is generally safe as the options are ignored for ostree installs anyway Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Extract cmdline parsing from write_pe_to_esp into parse_uki_cmdline so it runs for both the UKI and UKI addons. The `composefs=` parameter can now be found in the main UKI or a scoped addon - At most one composefs= cmdline across all PE binaries (UKI + addons). A second one is rejected even if the digest matches. - Global UKI addons must never contain `composefs=` cmdline - At least one `composefs=` cmdline must be found or the install fails Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Before removing a scoped addon, parse its PE binary and check for a composefs= kernel parameter. If found, early exit as removing that addon would make the system unbootable Global addons are not checked because `composefs=` is rejected at install time for global addons Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Test that bootc rejects composefs= in the wrong places - Build a global addon containing composefs= from `bootc compute-composefs-digest`, attempt switch with --global-uki-addon, assert failure - Build a scoped addon containing composefs= alongside the UKI (which already has it), attempt switch with --uki-addon, assert failure due to duplicate composefs= It's a shame that we can't test UKI Addon only cmdline without piling on a bunch of hacks since `bootc container ukify` unconditionally puts the cmdline inside the UKI Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
This option lists all the UKI Addons across all deployments. Also, it associates global addons with the deployments that reference them. It is useful for GC-ing global UKI Addons if no deployments refer to them Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Similar to how we GC UKIs and scoped UKI Addons, GC Global UKI addons if we have no EROFS images remaining that hold a reference to them, which means that the deployments that depended on the Global addons have been removed Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Reject an addon whose cmdline embeds a `composefs=` or `composefs.digest=` argument before copying it. An addon added this way must not be able to override the composefs digest. Write the addon with `atomic_replace_with` and fsync the destination directory, so a crash mid add can't leave a truncated PE on the ESP. Add a tmt test to verify. Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
`--uki-addon` was a no-op on ostree backend, now we bail if it's passed during ostree installs/upgrades Also, bail if we fail to find an addon in the image instead of just logging as info Update manpage links Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
850b488 to
2aea32e
Compare
|
Rebased and fixed conflicts |
There was a problem hiding this comment.
🟡 Changes recommended
Backend auto-detection, stale addon cleanup, legacy migration, and silently ignored option paths introduce blocking correctness regressions.
14 open findings
Clear inherited scoped addon directories before copying · New Strip prefixes only from global addon filenames · New Reject UKI addons for composefs BLS targets · New Reject addon options in non-deploying upgrade modes · New Reject uki-addon commands on composefs BLS systems · New Preserve uki_addon serialization key · New Validate UKI addons after composefs backend detection · New Fix the nonexistent fs-verity option in the warning · New Test list-referenced human and JSON output · New Correct add and remove addon suffix help · New Correct the addon suffix documentation · New Describe addon command-line parameters as optional · New Document garbage collection of unreferenced global addons · New Document the list-referenced subcommand · New
What changed in this PR
Adds composefs UKI addon lifecycle management across installation, upgrades, garbage collection, CLI operations, documentation, and integration testing.
Changes:
- Adds scoped/global addon installation and automatic upgrade handling.
- Adds
bootc uki-addonmanagement commands and JSON output. - Adds addon-aware garbage collection, documentation, and integration tests.
| File | Description |
|---|---|
tmt/tests/tests.fmf |
Registers addon integration test. |
tmt/tests/booted/test-composefs-uki-addons.nu |
Tests addon lifecycle and CLI. |
tmt/tests/booted/test-composefs-gc-uki.nu |
Extends UKI GC coverage. |
tmt/tests/booted/tap.nu |
Supports building test addons. |
tmt/plans/integration.fmf |
Adds addon test plan. |
docs/src/SUMMARY.md |
Links addon manuals. |
docs/src/man/bootc.8.md |
Documents addon subcommand. |
docs/src/man/bootc-upgrade.8.md |
Documents upgrade options. |
docs/src/man/bootc-uki-addon.8.md |
Adds command overview. |
docs/src/man/bootc-uki-addon-remove.8.md |
Documents removal. |
docs/src/man/bootc-uki-addon-list.8.md |
Documents listing. |
docs/src/man/bootc-uki-addon-list-referenced.8.md |
Documents referenced-addon listing. |
docs/src/man/bootc-uki-addon-add.8.md |
Documents addition. |
docs/src/man/bootc-switch.8.md |
Documents switch options. |
docs/src/man/bootc-install-to-filesystem.8.md |
Documents install options. |
docs/src/man/bootc-install-to-existing-root.8.md |
Documents existing-root options. |
docs/src/man/bootc-install-to-disk.8.md |
Documents disk-install options. |
crates/lib/src/install.rs |
Adds scoped/global install options. |
crates/lib/src/composefs_consts.rs |
Clarifies addon naming. |
crates/lib/src/cli.rs |
Adds CLI commands and options. |
crates/lib/src/bootc_composefs/update.rs |
Passes addons into upgrades. |
crates/lib/src/bootc_composefs/uki_addons_cli.rs |
Implements addon CLI operations. |
crates/lib/src/bootc_composefs/uki_addon.rs |
Implements addon discovery. |
crates/lib/src/bootc_composefs/switch.rs |
Passes switch addon options. |
crates/lib/src/bootc_composefs/mod.rs |
Exposes addon modules. |
crates/lib/src/bootc_composefs/gc.rs |
Collects unreferenced global addons. |
crates/lib/src/bootc_composefs/boot.rs |
Selects, validates, and writes addons. |
contrib/packaging/finalize-uki |
Copies generated addons into images. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # If we have a UKI Addon dir, add it | ||
| if [[ -d "${uki_src}/${kver}.efi.extra.d" ]]; then | ||
| cp -r "${uki_src}/${kver}.efi.extra.d" /boot/EFI/Linux | ||
| fi |
| match addon_name.strip_prefix(UKI_NAME_PREFIX) { | ||
| Some(addon_name) => { | ||
| addons.push(UkiAddonsList { | ||
| name: addon_name.to_string(), | ||
| addon_type: addon_type.clone(), | ||
| }); | ||
| } | ||
| None => match addon_type { | ||
| UkiAddonType::Scoped { .. } => { | ||
| addons.push(UkiAddonsList { | ||
| name: addon_name.to_string(), | ||
| addon_type: addon_type.clone(), | ||
| }); | ||
| } | ||
| // We only prefix global UKI Addons for identification | ||
| UkiAddonType::Global => { | ||
| tracing::info!("Global UKI Addon not managed by bootc found: {addon_name}") | ||
| } | ||
| }, | ||
| } |
| let (boot_digest, deploy_id) = match boot_type { | ||
| BootType::Bls => ( | ||
| setup_composefs_bls_boot( | ||
| BootSetupType::Upgrade((storage, booted_cfs, &host)), | ||
| BootSetupType::Upgrade((storage, booted_cfs, &host, None)), | ||
| &repo, |
| // This is kinda unfortunate that we can't gate this only for composefs systems | ||
| #[clap(flatten)] | ||
| pub(crate) uki_addon_opts: UkiAddonOpts, |
| match storage.kind()? { | ||
| BootedStorageKind::Ostree(_) => { | ||
| anyhow::bail!("UKI Addons are only supported for Composefs Backend") | ||
| } | ||
| BootedStorageKind::Composefs(booted_cfs) => { | ||
| handle_addon_cli_cmd(storage, &booted_cfs, &opts) | ||
| } |
| }, | ||
| /// Remove a UKI Addon | ||
| Remove { | ||
| /// Addon name to be provided without the `.efi.addon` suffix |
| /// Name of the local/scoped UKI addons to install without the ".efi.addon" suffix. | ||
| /// This option can be provided multiple times if multiple addons are to be installed | ||
| /// (composefs backend only). |
| UKI addons are PE binaries that systemd-stub loads alongside the main UKI at | ||
| boot. Each addon carries extra kernel command-line parameters that get merged | ||
| into the boot configuration. |
| - **Global** addons apply to every UKI on the ESP. They persist across | ||
| deployments and are not removed by garbage collection. |
| **remove** | ||
| : Remove a UKI addon from the ESP. See **bootc-uki-addon-remove**(8). |


uki-addon: Update addons on update/switch
Introduce a function to gather all currently installed addons, scoped
and global. On upgrade/switch, gather all installed addons and if an
addon with the same name is found in the upgrade image, update that
particular addon automatically
uki/addon: Support global addons
We were partially supporting global addons, but they were lumped in with
scoped/local addons. Add a new cli option to composefs installs called
--global-uki-addonwhich would determine which global addon toinstall.
cfs/upgrade/switch: Handle UKI Addons
Here is what we do now with UKI Addons
Accept
--uki-addonand--global-uki-addoncli options for bootcswitch/upgrade commands
If we find an installed addon with the same name as the one in the new
image, we update it
global-uki-addons: Add prefix to name
Prefix global addon filenames with the bootc identifier in the ESP so
we can distinguish bootc-managed global addons from third-party ones
uki-addon: Add CLI for managing UKI Addons
Add
bootc uki-addonsubcommand with three operations:bootc uki-addon list: List installed UKI addonsSupports
--jsonfor JSON outputbootc uki-addon add <name> <global|scoped>: Install an addon fromthe booted image onto the ESP
bootc uki-addon remove <name> [deployment_id]: Remove an addonAdd Display and Serialize to UkiAddonType/UkiAddonsList