-
Notifications
You must be signed in to change notification settings - Fork 116
Composefs backend #1314
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 backend #1314
Changes from 3 commits
6cfb4be
d03feb2
6be5560
b3d1952
83227f5
97b902c
3f0d7e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,12 +38,20 @@ use chrono::prelude::*; | |
use clap::ValueEnum; | ||
use fn_error_context::context; | ||
use ostree::gio; | ||
use ostree_ext::composefs::{ | ||
fsverity::{FsVerityHashValue, Sha256HashValue}, | ||
oci::pull as composefs_oci_pull, | ||
repository::Repository as ComposefsRepository, | ||
util::Sha256Digest, | ||
}; | ||
use ostree_ext::oci_spec; | ||
use ostree_ext::ostree; | ||
use ostree_ext::ostree_prepareroot::{ComposefsState, Tristate}; | ||
use ostree_ext::prelude::Cast; | ||
use ostree_ext::sysroot::SysrootLock; | ||
use ostree_ext::{container as ostree_container, ostree_prepareroot}; | ||
use ostree_ext::{ | ||
container as ostree_container, container::ImageReference as OstreeExtImgRef, ostree_prepareroot, | ||
}; | ||
#[cfg(feature = "install-to-disk")] | ||
use rustix::fs::FileTypeExt; | ||
use rustix::fs::MetadataExt as _; | ||
|
@@ -241,6 +249,9 @@ pub(crate) struct InstallToDiskOpts { | |
#[clap(long)] | ||
#[serde(default)] | ||
pub(crate) via_loopback: bool, | ||
|
||
#[clap(long)] | ||
pub(crate) composefs: bool, | ||
} | ||
|
||
#[derive(ValueEnum, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||
|
@@ -363,6 +374,7 @@ pub(crate) struct SourceInfo { | |
} | ||
|
||
// Shared read-only global state | ||
#[derive(Debug)] | ||
pub(crate) struct State { | ||
pub(crate) source: SourceInfo, | ||
/// Force SELinux off in target system | ||
|
@@ -1425,10 +1437,32 @@ impl BoundImages { | |
} | ||
} | ||
|
||
async fn initialize_composefs_repository( | ||
state: &State, | ||
root_setup: &RootSetup, | ||
) -> Result<(Sha256Digest, impl FsVerityHashValue)> { | ||
let rootfs_dir = &root_setup.physical_root; | ||
|
||
rootfs_dir | ||
.create_dir_all("composefs") | ||
.context("Creating dir 'composefs'")?; | ||
|
||
tracing::warn!("STATE: {state:#?}"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd recommend There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I intend to remove all these logs. They were only for debugging purposes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep that makes sense, what I meant is that use |
||
|
||
let repo: ComposefsRepository<Sha256HashValue> = | ||
ComposefsRepository::open_path(rootfs_dir, "composefs").expect("failed to open_path"); | ||
|
||
let OstreeExtImgRef { transport, name } = &state.target_imgref.imgref; | ||
|
||
// transport's display is already of type "<transport_type>:" | ||
composefs_oci_pull(&Arc::new(repo), &format!("{transport}{name}",), None).await | ||
} | ||
|
||
async fn install_to_filesystem_impl( | ||
state: &State, | ||
rootfs: &mut RootSetup, | ||
cleanup: Cleanup, | ||
composefs: bool, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this would make sense as part of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was conflicted on where to put this. Thanks for the review. I'll add this to |
||
) -> Result<()> { | ||
if matches!(state.selinux_state, SELinuxFinalState::ForceTargetDisabled) { | ||
rootfs.kargs.push("selinux=0".to_string()); | ||
|
@@ -1457,34 +1491,45 @@ async fn install_to_filesystem_impl( | |
|
||
let bound_images = BoundImages::from_state(state).await?; | ||
|
||
// Initialize the ostree sysroot (repo, stateroot, etc.) | ||
if composefs { | ||
// Load a fd for the mounted target physical root | ||
let (id, verity) = initialize_composefs_repository(state, rootfs).await?; | ||
|
||
{ | ||
let (sysroot, has_ostree, imgstore) = initialize_ostree_root(state, rootfs).await?; | ||
|
||
install_with_sysroot( | ||
state, | ||
rootfs, | ||
&sysroot, | ||
&boot_uuid, | ||
bound_images, | ||
has_ostree, | ||
&imgstore, | ||
) | ||
.await?; | ||
tracing::warn!( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment re There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yes. We can keep this one as debug |
||
"id = {id}, verity = {verity}", | ||
id = hex::encode(id), | ||
verity = verity.to_hex() | ||
); | ||
} else { | ||
// Initialize the ostree sysroot (repo, stateroot, etc.) | ||
|
||
{ | ||
let (sysroot, has_ostree, imgstore) = initialize_ostree_root(state, rootfs).await?; | ||
|
||
install_with_sysroot( | ||
state, | ||
rootfs, | ||
&sysroot, | ||
&boot_uuid, | ||
bound_images, | ||
has_ostree, | ||
&imgstore, | ||
) | ||
.await?; | ||
|
||
if matches!(cleanup, Cleanup::TriggerOnNextBoot) { | ||
let sysroot_dir = crate::utils::sysroot_dir(&sysroot)?; | ||
tracing::debug!("Writing {DESTRUCTIVE_CLEANUP}"); | ||
sysroot_dir.atomic_write(format!("etc/{}", DESTRUCTIVE_CLEANUP), b"")?; | ||
} | ||
if matches!(cleanup, Cleanup::TriggerOnNextBoot) { | ||
let sysroot_dir = crate::utils::sysroot_dir(&sysroot)?; | ||
tracing::debug!("Writing {DESTRUCTIVE_CLEANUP}"); | ||
sysroot_dir.atomic_write(format!("etc/{}", DESTRUCTIVE_CLEANUP), b"")?; | ||
} | ||
|
||
// We must drop the sysroot here in order to close any open file | ||
// descriptors. | ||
}; | ||
// We must drop the sysroot here in order to close any open file | ||
// descriptors. | ||
}; | ||
|
||
// Run this on every install as the penultimate step | ||
install_finalize(&rootfs.physical_root_path).await?; | ||
// Run this on every install as the penultimate step | ||
install_finalize(&rootfs.physical_root_path).await?; | ||
} | ||
|
||
// Finalize mounted filesystems | ||
if !rootfs.skip_finalize { | ||
|
@@ -1547,7 +1592,7 @@ pub(crate) async fn install_to_disk(mut opts: InstallToDiskOpts) -> Result<()> { | |
(rootfs, loopback_dev) | ||
}; | ||
|
||
install_to_filesystem_impl(&state, &mut rootfs, Cleanup::Skip).await?; | ||
install_to_filesystem_impl(&state, &mut rootfs, Cleanup::Skip, opts.composefs).await?; | ||
|
||
// Drop all data about the root except the bits we need to ensure any file descriptors etc. are closed. | ||
let (root_path, luksdev) = rootfs.into_storage(); | ||
|
@@ -1933,7 +1978,7 @@ pub(crate) async fn install_to_filesystem( | |
skip_finalize, | ||
}; | ||
|
||
install_to_filesystem_impl(&state, &mut rootfs, cleanup).await?; | ||
install_to_filesystem_impl(&state, &mut rootfs, cleanup, false).await?; | ||
|
||
// Drop all data about the root except the path to ensure any file descriptors etc. are closed. | ||
drop(rootfs); | ||
|
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 should be squashed with the previous commit, and it may make sense to have a "bump composefs-rs" prep PR split out right?
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.
Right, that makes sense. I'll put this in a separate PR