Previously, `BootedStorage::new()` unconditionally tried to open
`/sysroot` before checking the environment type. This caused
`bootc status` to fail on non-ostree/composefs systems.
(We did work in containers and we had tests for that; but
the container case is special cased even earlier)
Fixes: https://issues.redhat.com/browse/RHEL-135687
Assisted-by: Claude Code (Opus 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
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>
We have a lot of places where we mount the ESP temporarily and a lot of
switch cases for Grub's vs SystemdBoot's 'boot' directory.
We add a `boot_dir` field in Storage which points to `/sysroot/boot` for
systems with Grub as the bootloader and points to the ESP for systems
with SystemdBoot as the bootloader.
Also we mount the ESP temporarily while creating the storage struct,
which cleans up the code quite a bit.
Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
This implements readonly mounting of /sysroot for composefs systems,
matching the behavior that ostree systems already have. Previously,
composefs left /sysroot mounted read-write, which was inconsistent
and meant the readonly tests had to be skipped for composefs.
The implementation uses a direct `libc::syscall` wrapper for
`mount_setattr` since rustix doesn't yet provide this API. The
`MOUNT_ATTR_RDONLY` flag is applied to three mount
points during initramfs setup:
- The composefs rootfs image mount (becomes `/` after switch-root)
- The test root filesystem mount (used in testing scenarios)
- The sysroot clone mount (becomes `/sysroot` in the booted system)
With this change, the readonly /sysroot tests in test-status.nu
now run for both ostree and composefs systems without conditional
checks.
Assisted-by: Claude Code (Sonnet 4.5)
Co-authored-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Signed-off-by: Colin Walters <walters@verbum.org>
PR #1718 introduced a regression where /sysroot was left writable after
running `bootc status`. This occurred because BootedStorage::new()
unconditionally calls set_mount_namespace_in_use(), which tells ostree
it can safely remount /sysroot as writable. When sysroot.load() is called
without actually being in a mount namespace, it leaves the global /sysroot
writable.
Fix by introducing an Environment enum that detects the runtime environment
(ostree, composefs, container, or other) early in the execution flow. Callers
now detect the environment and call prepare_for_write() if needed before
constructing BootedStorage. This ensures a single call to prepare_for_write()
per execution path and eliminates the previous layering violation where storage
code called into CLI code.
The Environment abstraction also makes it clearer when mount namespace
setup is required and provides a foundation for future environment-specific
behavior.
Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
Change `BootedStorage::new()` to return `Result<Option<Self>>` instead
of taking a `prep_for_write` boolean parameter. This makes the API more
idiomatic and clearer about when the system is not booted via bootc.
Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
For ostree systems, before making any changes to the repo/boot entries
we call `prepare_for_write`. Before this we were calling it
unconditionally even if the command was `bootc status`, which was
causing test failures.
We pass in a flag now to `BootedStorage::new` which will conditionally
call `prepare_for_write`. We also need this to make sure we keep the API
more or less similar to what we had before
Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Signed-off-by: Colin Walters <walters@verbum.org>
There were a few checks that asserted ostree booted system even for
systems booted via composefs. Move the checks in `Storage::new`
Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Signed-off-by: Colin Walters <walters@verbum.org>
Refactor the storage layer to introduce new types that better encapsulate
boot context:
- Add BootedStorage wrapper that detects ostree vs composefs boot
- Add BootedOstree struct holding sysroot reference and deployment
- Add BootedComposefs struct holding repository and cmdline
- Add BootedStorageKind enum to discriminate between backends
This allows passing boot context as a cohesive unit rather than separate
parameters. Update the upgrade code path to use these new types:
- Change get_status() to accept &BootedOstree instead of separate params
- Update handle_staged_soft_reboot() similarly
- Update upgrade() to use structs throughout
Add comprehensive documentation to all new types and methods in store/mod.rs.
Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
While composefs is still experimental, after looking at this
I think the feature gating we're doing has a pretty high "pain:gain"
ratio - in other words, the risk we're mitigating by having it
off is very low.
Since composefs is a focus of development, let's just remove
the feature gate. We have good CI coverage for the non-composefs
case.
Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
- Change the install logic to detect UKIs and automatically
enable composefs
- Change the install logic to detect absence of bootupd
and default to installing systemd-boot
- Move sealing bits to the toplevel
- Add Justfile entrypoints
- Add basic end-to-end CI coverage (install + run) using
our integration tests
- Change lints to ignore `/boot/EFI`
Signed-off-by: Colin Walters <walters@verbum.org>
Naming things is hard, but as of right now since this storage
instance doesn't hold the booted host, let's call it
`podstorage` to make clear is association and purpose in
being used by podman and related tools.
Signed-off-by: Colin Walters <walters@verbum.org>
Previously we had two different `Storage` structs, this
ensures that the main one is primary and `CStorage` is secondary.
This should be less confusing.
Signed-off-by: Colin Walters <walters@verbum.org>
A while ago we added a trait in preparation for multiple backends.
The current composefs branch ignores it and has a bunch of
`if {} else {}`.
Looking at this, what I think will work better in the end is
actually a more refined version of the `if {} else {}` model
instead of trying to really flesh out this trait. It's
hard to say of course until we get there, but the trait
approach forces a high level of abstraction vs just trying
to factor out common code between two backends.
Signed-off-by: Colin Walters <walters@verbum.org>
This is prep for wider usage of it in this project.
Like the containers-image: storage, it is only initialized
on demand right now.
(An obvious next step is to redo things so the ostree storage is also on-demand)
- This is hardcoded to SHA512 right now...but we clearly want
a way to configure that or maybe we just really default to 512?
- We explicitly bridge between the ostree fsverity enablement
to the composefs verity enablement
- Right now the usage is just a stub but I plan to expose
more here
Signed-off-by: Colin Walters <walters@verbum.org>