Skip to content

WIP: composefs branch #1444

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

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft

WIP: composefs branch #1444

wants to merge 19 commits into from

Conversation

cgwalters
Copy link
Collaborator

Moved from #1314 (a lot of prior discussion and reviews there!)

Tracking issue: #1190

This is now a branch on the main repo to make it easier for folks to collaborate.

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 composefs as a new backend, which is a significant and extensive change. The new code paths for installation, upgrades, switching, and rollbacks for composefs are well-structured.

My review has identified a few issues, including a potential bug with a hardcoded transport value and an assert! that could lead to a panic. I've also included some suggestions for improving code style and robustness. Given this is a work-in-progress, these findings are not unexpected. Overall, this is a solid foundation for the new composefs functionality.

anyhow::bail!("Target image is undefined")
};

let (repo, entries, id) = pull_composefs_repo(&"docker".into(), &target_imgref.image).await?;
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The transport is hardcoded to "docker". The target_imgref variable already contains the correct transport from the user's options. Using a hardcoded value will likely cause switch to fail for other transports.

    let (repo, entries, id) = pull_composefs_repo(&target_imgref.transport, &target_imgref.image).await?;

cfg.version = idx as u32;
}

assert!(all_configs.len() == 2);
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Using assert! here will cause a panic if the number of boot configurations is not exactly 2. This can happen if there's only one deployment. It would be more robust to use anyhow::ensure! to return a proper error that can be handled gracefully.

Suggested change
assert!(all_configs.len() == 2);
anyhow::ensure!(
all_configs.len() == 2,
"Expected exactly 2 boot configurations for rollback, found {}",
all_configs.len()
);

@@ -881,6 +931,63 @@
let sigverify = sigpolicy_from_opt(opts.enforce_container_sigpolicy);
let target = ostree_container::OstreeImageReference { sigverify, imgref };
let target = ImageReference::from(target);

return Ok(target);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

In Rust, it's more idiomatic to omit the return keyword for the final expression in a function.

    Ok(target)


all_configs.sort_by(|a, b| if ascending { a.cmp(b) } else { b.cmp(a) });

return Ok(all_configs);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

In Rust, it's more idiomatic to omit the return keyword for the final expression in a function.

Suggested change
return Ok(all_configs);
Ok(all_configs)

"#
);

return s;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

In Rust, it's more idiomatic to omit the return keyword for the final expression in a function.

Suggested change
return s;
s


origin_file
.write(config.to_string().as_bytes())
.context("Falied to write to .origin file")?;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There's a typo in the error message: "Falied" should be "Failed".

Suggested change
.context("Falied to write to .origin file")?;
.context("Failed to write to .origin file")?;

Comment on lines +2071 to +2176
tracing::warn!(
"id = {id}, verity = {verity}",
id = hex::encode(id),
verity = verity.to_hex()
);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using tracing::warn! here seems inappropriate, as logging the image ID and verity hash is informational rather than a warning. Consider using tracing::info! or tracing::debug! instead to better reflect the nature of this log message.

Suggested change
tracing::warn!(
"id = {id}, verity = {verity}",
id = hex::encode(id),
verity = verity.to_hex()
);
tracing::info!(
"id = {id}, verity = {verity}",
id = hex::encode(id),
verity = verity.to_hex()
);

composefs: Some(crate::spec::BootEntryComposefs { verity, boot_type }),
};

return Ok(e);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

In Rust, it's more idiomatic to omit the return keyword for the final expression in a function.

Suggested change
return Ok(e);
Ok(e)

@cgwalters cgwalters mentioned this pull request Aug 1, 2025
1 task
@cgwalters
Copy link
Collaborator Author

cgwalters commented Aug 4, 2025

I'm going to rebase this. In the interest of preserving history I've saved a copy of the branch as composefs-branch-20250804

@cgwalters cgwalters force-pushed the composefs-backend branch 2 times, most recently from 33e4511 to 7d596fe Compare August 4, 2025 19:56
@cgwalters
Copy link
Collaborator Author

OK at least this passes the existing tests.

Johan-Liebert1 and others added 2 commits August 7, 2025 10:53
Signed-off-by: Pragyan Poudyal <[email protected]>
Signed-off-by: Colin Walters <[email protected]>
@cgwalters
Copy link
Collaborator Author

I rebased 🏄 this again (and in the process reworked the composefs karg stuff to use the new kernel_cmdline &str APIs)

Johan-Liebert1 and others added 17 commits August 12, 2025 09:53
Parse the Grub menuentry file, `boot/grub2/user.cfg` to get a list of
bootable UKIs and figure out if a rollback is currently queued.

Signed-off-by: Johan-Liebert1 <[email protected]>
Returning a local reference to a `&str` is quite tricky with rust.
Update `title` and `chainloader`, the two dynamic fields in the grub
menuentry, to be `String` instead of `&str`

Signed-off-by: Johan-Liebert1 <[email protected]>
We parse the grub menuentries, get the rollback deployment then perform
the rollback, which basically consists of writing a new .staged
menuentry file then atomically swapping the staged and the current
menuentry.

Rollback while there is a staged deployment is still to be handled.

Signed-off-by: Johan-Liebert1 <[email protected]>
If two deployments have the same VMLinuz + Initrd then, we can use the
same binaries for both the deployments.

Before writing the BLS entries to disk we calculate the SHA256Sum
of VMLinuz + Initrd combo, then test if any other deployment has the
same SHA256Sum for the binaries. Store the hash in the origin file under
`boot -> hash` for future lookups.

Signed-off-by: Johan-Liebert1 <[email protected]>
Centralize all constants in a separate file

Signed-off-by: Johan-Liebert1 <[email protected]>
Instead of `/sysroot/state/os/fedora` use `/sysroot/state/os/default` as
the default state directory.

Signed-off-by: Johan-Liebert1 <[email protected]>
Instaed of writing all present menuentries, only write the menuentry for
switch/upgrade and the menuentry for the currently booted deployment.

Signed-off-by: Johan-Liebert1 <[email protected]>
This allows for easier testing

Signed-off-by: Pragyan Poudyal <[email protected]>
Add tests for functions `get_sorted_bls_boot_entries` and
`get_sorted_uki_boot_entries`

Signed-off-by: Pragyan Poudyal <[email protected]>
composefs: Add missed commits when rebasing
install: Use read_file from composefs-boot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants