-
Notifications
You must be signed in to change notification settings - Fork 169
Composefs changes #1915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Composefs changes #1915
Conversation
There was a problem hiding this 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 several enhancements to composefs functionality. It adds an option to reset the soft reboot state and modifies the soft reboot logic to align with the ostree API, where a soft reboot is only initiated if --apply is passed. Additionally, it updates the image digest query format to match recent changes in composefs-rs. The changes are well-structured and improve the consistency and usability of the soft reboot feature. My review includes a suggestion to refactor a part of the new reset_soft_reboot function to improve code clarity and maintainability.
0193cf9 to
364e600
Compare
|
Setting up boot components seem to be failing in centos9, f42 with |
|
I guess #1926 is related |
| const NEXTROOT: &str = "/run/nextroot"; | ||
|
|
||
| #[context("Resetting soft reboot state")] | ||
| fn reset_soft_reboot() -> Result<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think functions like this should accept their global state, like Storage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels a bit weird to have an argument when they don't use it. We could use run from the Storage, but we need to bind mount /run from host any to unmount nextroot, unless I'm missing something here
|
|
||
| let Some(nextroot) = nextroot else { | ||
| tracing::debug!("Nextroot is not a directory"); | ||
| println!("No deployment staged for soft rebooting"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we share these output messages between the two backends
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be great, but afaik the implementation for soft reboot for ostree backend is in the ostree repo and not bootc. In the ostree path, we don't print anything if there is no deployment staged for soft rebooting. I have updated the final messages, i.e. soft reboot prep complete and soft reboot state reset messages, to match the ostree ones
|
|
||
| if opts.soft_reboot.is_some() { | ||
| prepare_soft_reboot_composefs(storage, booted_cfs, &id.to_hex(), true).await?; | ||
| prepare_soft_reboot_composefs(storage, booted_cfs, Some(&id.to_hex()), true, false).await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having more than one boolean value to functions I think leads to confusion as to what they mean. I think this can become an enum since they're mutually exclusive no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is from an older commit? I had changed this to an enum
364e600 to
ad5fa7f
Compare
Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Aligning with ostree API, now we only initiate soft-reboot if `--apply` is passed to `bootc update`, `bootc switch`, else we only prepare the soft reboot Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
After bootc/commit/49d753f996747a9b1f531abf35ba4e207cf4f020, composefs-rs saves config in the format `oci-config-sha256:`. Update to match the same Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
When `--download-only` is passed, only download the image into the composefs repository but don't finalize it. Conver the /run/composefs/staged-deployment to a JSON file and Add a finalization_locked field depending upon which the finalize service will either finalize the staged deployment or leave it as is for garbage collection (even though GC is not fully implemented right now). Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
ad5fa7f to
3793354
Compare
| // We want the digest in the form of "sha256:abc123" | ||
| let config_digest = format!("{}", imginfo.manifest.config().digest()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm isn't this us losing type safety in that basically composefs-rs is using a different type alias for digests than exists in https://docs.rs/oci-spec/latest/oci_spec/image/struct.Digest.html ?
I think we could probably impl From<oci_spec::Digest> for composefs_rs::Sha256Digest or so?
Having to go through strings is definitely a big trap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm isn't this us losing type safety in that basically composefs-rs is using a different type alias for digests
I don't think that's the case, as composefs streams are now named as oci-layer-sha256:<digest>. The <digest> here is the same as the config digest. It's just that previously the streams were stored only as <digest> without the sha256: or any other prefix.
Maybe it'd be cleaner to export https://github.com/containers/composefs-rs/blob/6cbdb428b06d6121993c469337a57390c5895544/crates/composefs-oci/src/lib.rs#L31 from composefs-rs
| #[context("Resetting soft reboot state")] | ||
| pub(crate) fn reset_soft_reboot() -> Result<()> { | ||
| let run = Utf8Path::new("/run"); | ||
| bind_mount_from_pidns(PID1, &run, &run, true).context("Bind mounting /run")?; |
There was a problem hiding this comment.
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 is necessary, we only need to do that when run under podman.
| return Ok(()); | ||
| } | ||
|
|
||
| unmount(NEXTROOT, UnmountFlags::DETACH).context("Unmounting nextroot")?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work though? We always enter a mount namespace, so this is where...ohhhh, I see that's why you did the bind mount of /run from the host mountns above.
And indeed I think we have similar code in ostree.
But...hmmm I think it'd be cleaner to avoid mutating global state this way - we could fork a child process that does the umount (look at similar code in bind_mount_from_pidns) or we could always pull in the real /run right after we do the re-exec to enter a new mountns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could always pull in the real /run right after we do the re-exec to enter a new mountns.
I think we do have an fd for /run in the pid/1 mount ns inside of global storage Struct, iirc. I might be imagining things though...
we could fork a child process that does the umount
wdyt about a function similar to bind_mount_from_pidns but it takes a lambda to run and only runs that instead of doing move_mount afterwards?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
takes a lambda to run and only runs that
this would be in the forked child process
dcb44e8 to
709b25a
Compare
Until now while checking if a deployment is capable of being soft rebooted, we were not taking into account any differences in SELinux policies between the two deployments. This commit adds such a check We only check for policy diff if SELinux is enabled Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com> composefs: Refactor Add doc comments for StagedDeployment struct Use `serde_json::to_writer` to prevent intermediate string allocation Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
709b25a to
bccc94c
Compare
| return true; | ||
| } | ||
|
|
||
| const SELINUX_CONFIG_PATH: &str = "etc/selinux/config"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's split this out into a mod selinux. And while we're here...deduplicate with the similar code in composefs-rs
| let filename = entry.file_name(); | ||
| let filename = filename | ||
| .to_str() | ||
| .ok_or_else(|| anyhow::anyhow!("Filename is not proper UTF-8"))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use Dir::entries_utf8 (probably have other places like this)
| if !filename.starts_with(POLICY_FILE_PREFIX) { | ||
| continue; | ||
| } | ||
|
|
||
| match filename.split_once(".") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think moving the . into the prefix then use filename.strip_prefix(POLICY_FILE_PREFIX) is more elegant
|
|
||
| return compare_cmdline_skip_cfs(depl_cmdline, booted_cmdline) | ||
| && compare_cmdline_skip_cfs(booted_cmdline, depl_cmdline); | ||
| return Ok( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor style personally I prefer
let r = <complex computation>;
Ok(r)
in cases like this
| return Ok(None); | ||
| } | ||
|
|
||
| let selinux_config = deployment_root |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stuff below here is easily unit testable (again in the selinux mod) operating on a Dir without any booted bits etc
| #[context("Resetting soft reboot state")] | ||
| pub(crate) fn reset_soft_reboot() -> Result<()> { | ||
| let run = Utf8Path::new("/run"); | ||
| bind_mount_from_pidns(PID1, &run, &run, true).context("Bind mounting /run")?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment like /// Note: By default bootc runs in an unshared mount namespace; this sets up our /runto actually be the same as the host/runso theumount below actually affects the host
Most of this is in prep for #1913
Add option to reset soft reboot state
Don't soft-reboot automatically
Aligning with ostree API, now we only initiate soft-reboot if
--applyis passed to
bootc update,bootc switch, else we only prepare thesoft reboot
Update image digest query format
After bootc/commit/49d753f996747a9b1f531abf35ba4e207cf4f020,
composefs-rs saves config in the format
oci-config-sha256:.Update to match the same
composefs/update: Handle --download-only flag
When
--download-onlyis passed, only download the image into thecomposefs repository but don't finalize it.
Conver the /run/composefs/staged-deployment to a JSON file and Add a
finalization_locked field depending upon which the finalize service will
either finalize the staged deployment or leave it as is for garbage
collection (even though GC is not fully implemented right now).
composefs/soft-reboot: Check for SELinux policy divergence
Until now while checking if a deployment is capable of being soft
rebooted, we were not taking into account any differences in SELinux
policies between the two deployments. This commit adds such a check
We only check for policy diff if SELinux is enabled
Some commits are split from #1913