Skip to content

Conversation

@jmarrero
Copy link
Contributor

@jmarrero jmarrero commented Sep 9, 2025

lib: Add experimental unified storage support for install

Add an experimental --experimental-unified-storage flag to bootc install
that uses bootc's container storage (/usr/lib/bootc/storage) to pull
images first, then imports from there. This is the same approach used
for logically bound images (LBIs).

Background:
The unified storage approach allows bootc to share container images with
podman's storage, reducing disk space and enabling further integration
with the Podman ecosystem.

Changes:

  • Add --experimental-unified-storage CLI flag to install subcommands
  • Add sysroot_path parameter to prepare_for_pull_unified() and pull_unified()
    to handle the different mount points during install vs upgrade/switch
  • Handle localhost images specially by exporting from ostree to container
    storage first (these can't be pulled from a registry)
  • Skip pull in prepare_for_pull_unified() if image already exists in
    bootc storage
  • Add TMT test for install with unified storage flag
  • Add TMT test for switching to unified storage on running system

The sysroot_path fix is needed because during install the target disk
is mounted at a specific path (e.g., /var/mnt), not /sysroot. Skopeo
needs the actual filesystem path to find the bootc storage.

Relates: #20

Assisted-by: Claude Code (Sonnet 4.5 & Opus 4.5)

[core@cosa-devsh ~]$ sudo podman --storage-opt=additionalimagestore=/usr/lib/bootc/storage images
REPOSITORY                       TAG         IMAGE ID      CREATED       SIZE
quay.io/jmarrero_rh/soft-reboot  1           97f84fcb062e  25 hours ago  1.83 GB

@bootc-bot bootc-bot bot requested a review from cgwalters September 9, 2025 17:28
Copy link
Collaborator

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this!

/// Use podman/skopeo to pull image to additionalimagestore, then read from container storage.
/// This provides a unified approach that leverages existing container tooling.
#[clap(long)]
pub(crate) unified: bool,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be a CLI flag that operates just once; it should be something like bootc image --set-unified or so and act persistently.

Also we should support setting this at install time so that it happens from the very start.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(hmm my bad I thought we discussed this but I failed to update the issue #20 or something maybe?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh man yeah, we talked about saving the config on the origin file IIRC, I forgot.

use bootc_utils::CommandRunExt;

// Use podman pull with additionalimagestore pointing to bootc storage
let bootc_storage_path = "/usr/lib/bootc/storage";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use podstorage.rs instead please

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To elaborate on this, an important aspect here is currently the GC of the bootc/storage instance is rooted in the set of LBIs. That will need to be extended to include the host image.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another big task related to this - we'll eventually really want to use the podman HTTP APIs so we can properly monitor progress. Right now we are very crudely relying on doing this synchronously to the existing tty and reusing the podman CLI tty output. But that can't really work if we ever need to render our own progress APIs.

https://lib.rs/crates/bollard might be a good choice for this?

@jlebon
Copy link
Contributor

jlebon commented Oct 7, 2025

Do we get reflinks when importing from the alternate storage into the ostree repo?

@cgwalters
Copy link
Collaborator

Do we get reflinks when importing from the alternate storage into the ostree repo?

#20 links to containers/container-libs#144

@jlebon
Copy link
Contributor

jlebon commented Oct 7, 2025

Do we get reflinks when importing from the alternate storage into the ostree repo?

#20 links to containers/container-libs#144

Hmm, that's about copying between two container storages, but I was asking about the ostree import. But #20 does say:

From there, we do a reflink/hardlink copy into the ostree store (i.e. This would duplicate metadata, but not data on disk. Reflinks should always work.

Which kinda answers the question.

Basically without reflinks into the ostree storage, IMO this makes it a lot less obvious that this new option is objectively better and it instead becomes a discussion of trade-offs.

@jmarrero jmarrero force-pushed the unified-storage-wip branch from 1baf1e8 to 9c3ef81 Compare October 9, 2025 18:15
@jmarrero jmarrero changed the title WIP: Add --unified to use our container-storage for host images WIP: Use our container-storage for host images if the refspec exists on it Oct 9, 2025
@jmarrero jmarrero changed the title WIP: Use our container-storage for host images if the refspec exists on it WIP: Use our container-storage for host images if the refspec exists Oct 9, 2025
@jmarrero jmarrero force-pushed the unified-storage-wip branch 2 times, most recently from e891e6c to be75055 Compare October 15, 2025 17:57
@github-actions github-actions bot added the area/install Issues related to `bootc install` label Oct 15, 2025
@jmarrero jmarrero force-pushed the unified-storage-wip branch from 291fbd7 to fe10204 Compare November 11, 2025 19:53
@jmarrero jmarrero force-pushed the unified-storage-wip branch 3 times, most recently from 06be8fb to b801a17 Compare November 21, 2025 20:50
@github-actions github-actions bot added the area/system-reinstall-bootc Issues related to system-reinstall-botoc label Nov 21, 2025
@jmarrero jmarrero force-pushed the unified-storage-wip branch from b801a17 to 68b1ba6 Compare November 21, 2025 20:56
@jmarrero jmarrero force-pushed the unified-storage-wip branch 3 times, most recently from ee300e3 to 50c4f70 Compare December 2, 2025 19:28
@jmarrero jmarrero changed the title WIP: Use our container-storage for host images if the refspec exists lib: Add experimental unified storage support for install Dec 2, 2025
@jmarrero
Copy link
Contributor Author

jmarrero commented Dec 2, 2025

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces experimental support for unified storage, allowing bootc to pull images into its own container storage before importing them. This is a significant feature that touches installation, upgrade, and switch paths. The changes include new CLI options, a new image set-unified command, and the core logic for the unified pull mechanism.

The implementation is comprehensive and includes new integration tests. My review has identified a few areas for improvement:

  • A bug in the image reference formatting for unified storage checks during installation.
  • Inconsistent error handling when checking for images in the unified store.
  • A potential panic due to an .unwrap() call on a Result.

Addressing these points will improve the robustness and maintainability of this new feature.

@cgwalters
Copy link
Collaborator

On the progress status side maybe we can use https://lib.rs/crates/bollard to talk to podman and I think it should help us get data out of the events?

@jmarrero jmarrero force-pushed the unified-storage-wip branch 4 times, most recently from 3803e4c to bb9883e Compare December 10, 2025 15:41
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces experimental unified storage support for bootc install and related commands. The changes are extensive and well-thought-out, adding a new --experimental-unified-storage flag and the bootc image set-unified command. The implementation correctly handles different scenarios, such as install versus upgrade, and the special case of images originating from containers-storage. The addition of comprehensive integration and TMT tests is commendable. I've identified one high-severity logical issue in the implementation of bootc image set-unified where it could operate on a staged image instead of the booted one. I've also noted a correct and important bug fix in the image pruning logic. Overall, this is a solid contribution that adds a valuable feature.

Copy link
Collaborator

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! A first pass review here, this is looking quite plausible!

pub(crate) async fn should_use_unified_storage(
store: &Storage,
imgref: &ImageReference,
explicit_flag: Option<bool>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems strange to me; nothing AFAICS passes Some(false). And if Some(true) is passed the caller will just get back true. So why even call this?

// Check if the image already exists in the default containers-storage.
// This can happen if someone did a local build (e.g., podman build) and
// we don't want to overwrite it with an export from ostree.
ensure_floating_c_storage_initialized();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can put this global init somewhere farther up?

@jmarrero jmarrero force-pushed the unified-storage-wip branch from 7651032 to ddbba51 Compare December 11, 2025 03:41
@jmarrero
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces experimental support for unified storage in bootc install, which allows sharing container images with podman's storage to reduce disk usage and enable offline installations. The changes include a new --experimental-unified-storage flag, modifications to upgrade and switch to auto-detect and use unified storage, and special handling for localhost images. New integration and TMT tests are also added to cover these new code paths.

My review focuses on correctness and maintainability. I've identified a couple of areas for improvement:

  • An inconsistency in the image pulling strategy for unified storage, which could lead to unnecessary network operations.
  • A small opportunity to simplify code by removing a redundant check, improving readability and reflecting the guarantees provided by other functions.

Overall, the changes are well-structured and the addition of tests is great. Addressing these points will improve the robustness and maintainability of the new feature.

@jmarrero jmarrero force-pushed the unified-storage-wip branch 3 times, most recently from ba8e4ef to 7f11db8 Compare December 11, 2025 10:08
@cgwalters
Copy link
Collaborator

Hmm the failure of test-install is weird; I'm not seeing the job fail in e.g. #1846 or other PRs.

Copy link
Collaborator

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking as requested changes per incompatible change to install flow

@jmarrero
Copy link
Contributor Author

Failures on rawhide are the same we saw in another PR yesterday: #1849

Copy link
Collaborator

@cgwalters cgwalters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, just two nits

Add an experimental --experimental-unified-storage flag to bootc install
that uses bootc's container storage (/usr/lib/bootc/storage) to pull
images first, then imports from there. This is the same approach used
for logically bound images (LBIs).

Background:
The unified storage approach allows bootc to share container images with
podman's storage, reducing disk space and enabling better integration
with podman.

Changes:
- Add --experimental-unified-storage CLI flag to install subcommands
- Add sysroot_path parameter to prepare_for_pull_unified() and pull_unified()
  to handle the different mount points during install vs upgrade/switch
- Handle container-storage transport
- Skip pull in prepare_for_pull_unified() if image already exists in
  bootc storage
- Add TMT test for install with unified storage flag
- Add TMT test for switching to unified storage on running system

The sysroot_path fix is needed because during install the target disk
is mounted at a specific path (e.g., /var/mnt), not /sysroot. Skopeo
needs the actual filesystem path to find the bootc storage.

Relates: bootc-dev#20

Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Joseph Marrero Corchado <jmarrero@redhat.com>
Refactor the unified storage code to get the sysroot path from the
Storage struct instead of passing it as a parameter through multiple
function calls.

Why this change is needed:
The previous implementation passed sysroot_path as an Option parameter
to prepare_for_pull_unified() and pull_unified(). This was awkward
because:
- Callers had to know whether to pass None (for booted systems) or
  Some(path) (for install scenarios)
- The path is inherently tied to the Storage instance's lifecycle
- It required threading parameters through multiple layers

This follows the existing pattern where Storage already encapsulates
storage-related state, and addresses review feedback to "get this stuff
from the Storage".

Assisted-by: Claude Code (Opus 4.5)
Signed-off-by: Joseph Marrero Corchado <jmarrero@redhat.com>
@jmarrero jmarrero force-pushed the unified-storage-wip branch from 52f5e25 to 39ace6a Compare December 13, 2025 18:03
let sysroot_base = sysroot_path
.map(|p| p.to_string())
.unwrap_or_else(|| "/sysroot".to_string());
// Use the physical path to bootc storage from the Storage struct
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is OK but I've been trying to ensure that bootc uses file descriptors and not file paths as much as possible. The problem here is the case where we have a fd but need to pass that state down to a subprocess which expects a file path.

podstorage.rs goes to quite some effort to do this for the primary storage, see new_podman_cmd_in - I think we could use a similar technique here.

@cgwalters cgwalters merged commit 68d5cea into bootc-dev:main Dec 14, 2025
44 of 46 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/documentation Updates to the documentation area/install Issues related to `bootc install` area/system-reinstall-bootc Issues related to system-reinstall-botoc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants