Skip to content

Commit 7578551

Browse files
authored
Merge pull request #1471 from cgwalters/store-composefs
store: Add support for composefs-rs
2 parents 825f7ac + 07faf7d commit 7578551

File tree

5 files changed

+100
-7
lines changed

5 files changed

+100
-7
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ anyhow = "1.0.82"
3636
camino = "1.1.6"
3737
canon-json = "0.2.1"
3838
cap-std-ext = "4.0.3"
39+
composefs = { git = "https://github.com/containers/composefs-rs", rev = "28d4721f77f973f0e394d60d6a69d9b39cb38d7f", package = "composefs", features = ["rhel9"] }
40+
composefs-boot = { git = "https://github.com/containers/composefs-rs", rev = "28d4721f77f973f0e394d60d6a69d9b39cb38d7f", package = "composefs-boot" }
41+
composefs-oci = { git = "https://github.com/containers/composefs-rs", rev = "28d4721f77f973f0e394d60d6a69d9b39cb38d7f", package = "composefs-oci" }
3942
chrono = { version = "0.4.38", default-features = false }
4043
clap = "4.5.4"
4144
clap_mangen = { version = "0.2.20" }

crates/lib/src/cli.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use ostree::gio;
1919
use ostree_container::store::PrepareResult;
2020
use ostree_ext::composefs::fsverity;
2121
use ostree_ext::composefs::fsverity::FsVerityHashValue;
22+
use ostree_ext::composefs::splitstream::SplitStreamWriter;
2223
use ostree_ext::container as ostree_container;
2324
use ostree_ext::container_utils::ostree_booted;
2425
use ostree_ext::keyfileext::KeyFileExt;
@@ -462,6 +463,8 @@ pub(crate) enum InternalsOpts {
462463
#[clap(allow_hyphen_values = true)]
463464
args: Vec<OsString>,
464465
},
466+
/// Ensure that a composefs repository is initialized
467+
TestComposefs,
465468
/// Loopback device cleanup helper (internal use only)
466469
LoopbackCleanupHelper {
467470
/// Device path to clean up
@@ -1226,6 +1229,18 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
12261229
)
12271230
.await
12281231
}
1232+
InternalsOpts::TestComposefs => {
1233+
// This is a stub to be replaced
1234+
let storage = get_storage().await?;
1235+
let cfs = storage.get_ensure_composefs()?;
1236+
let testdata = b"some test data";
1237+
let testdata_digest = openssl::sha::sha256(testdata);
1238+
let mut w = SplitStreamWriter::new(&cfs, None, Some(testdata_digest));
1239+
w.write_inline(testdata);
1240+
let object = cfs.write_stream(w, Some("testobject"))?.to_hex();
1241+
assert_eq!(object, "5d94ceb0b2bb3a78237e0a74bc030a262239ab5f47754a5eb2e42941056b64cb21035d64a8f7c2f156e34b820802fa51884de2b1f7dc3a41b9878fc543cd9b07");
1242+
Ok(())
1243+
}
12291244
// We don't depend on fsverity-utils today, so re-expose some helpful CLI tools.
12301245
InternalsOpts::Fsverity(args) => match args {
12311246
FsverityOpts::Measure { path } => {

crates/lib/src/store/mod.rs

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,58 @@
11
use std::cell::OnceCell;
22
use std::env;
33
use std::ops::Deref;
4+
use std::sync::Arc;
45

56
use anyhow::{Context, Result};
67
use cap_std_ext::cap_std;
7-
use cap_std_ext::cap_std::fs::Dir;
8+
use cap_std_ext::cap_std::fs::{Dir, DirBuilder, DirBuilderExt as _};
89
use cap_std_ext::dirext::CapStdExtDirExt;
910
use clap::ValueEnum;
1011
use fn_error_context::context;
1112

1213
use ostree_ext::container::OstreeImageReference;
1314
use ostree_ext::keyfileext::KeyFileExt;
14-
use ostree_ext::ostree;
1515
use ostree_ext::sysroot::SysrootLock;
16+
use ostree_ext::{composefs, ostree};
17+
use rustix::fs::Mode;
1618

1719
use crate::lsm;
1820
use crate::spec::ImageStatus;
1921
use crate::utils::deployment_fd;
2022

2123
mod ostree_container;
2224

25+
/// See https://github.com/containers/composefs-rs/issues/159
26+
pub type ComposefsRepository =
27+
composefs::repository::Repository<composefs::fsverity::Sha512HashValue>;
28+
29+
/// Path to the physical root
30+
pub const SYSROOT: &str = "sysroot";
31+
32+
/// The toplevel composefs directory path
33+
pub const COMPOSEFS: &str = "composefs";
34+
pub const COMPOSEFS_MODE: Mode = Mode::from_raw_mode(0o700);
35+
2336
/// The path to the bootc root directory, relative to the physical
2437
/// system root
2538
pub(crate) const BOOTC_ROOT: &str = "ostree/bootc";
2639

2740
pub(crate) struct Storage {
41+
/// Directory holding the physical root
42+
pub physical_root: Dir,
43+
44+
/// The OSTree storage
2845
pub sysroot: SysrootLock,
29-
run: Dir,
46+
/// The composefs storage
47+
pub composefs: OnceCell<Arc<ComposefsRepository>>,
48+
/// The containers-image storage used foR LBIs
3049
imgstore: OnceCell<crate::imgstorage::Storage>,
50+
51+
/// Our runtime state
52+
run: Dir,
53+
54+
/// This is a stub abstraction that tries to hide ostree
55+
/// that we aren't really using right now
3156
pub store: Box<dyn ContainerImageStoreImpl>,
3257
}
3358

@@ -71,12 +96,29 @@ impl Storage {
7196
}),
7297
Err(_) => crate::spec::Store::default(),
7398
};
74-
7599
let store = load(store);
76100

101+
// ostree has historically always relied on
102+
// having ostree -> sysroot/ostree as a symlink in the image to
103+
// make it so that code doesn't need to distinguish between booted
104+
// vs offline target. The ostree code all just looks at the ostree/
105+
// directory, and will follow the link in the booted case.
106+
//
107+
// For composefs we aren't going to do a similar thing, so here
108+
// we need to explicitly distinguish the two and the storage
109+
// here hence holds a reference to the physical root.
110+
let ostree_sysroot_dir = crate::utils::sysroot_dir(&sysroot)?;
111+
let physical_root = if sysroot.is_booted() {
112+
ostree_sysroot_dir.open_dir(SYSROOT)?
113+
} else {
114+
ostree_sysroot_dir
115+
};
116+
77117
Ok(Self {
118+
physical_root,
78119
sysroot,
79120
run,
121+
composefs: Default::default(),
80122
store,
81123
imgstore: Default::default(),
82124
})
@@ -111,6 +153,31 @@ impl Storage {
111153
Ok(self.imgstore.get_or_init(|| imgstore))
112154
}
113155

156+
pub(crate) fn get_ensure_composefs(&self) -> Result<Arc<ComposefsRepository>> {
157+
if let Some(composefs) = self.composefs.get() {
158+
return Ok(Arc::clone(composefs));
159+
}
160+
161+
let mut db = DirBuilder::new();
162+
db.mode(COMPOSEFS_MODE.as_raw_mode());
163+
self.physical_root.ensure_dir_with(COMPOSEFS, &db)?;
164+
165+
let mut composefs =
166+
ComposefsRepository::open_path(&self.physical_root.open_dir(COMPOSEFS)?, ".")?;
167+
168+
// Bootstrap verity off of the ostree state. In practice this means disabled by
169+
// default right now.
170+
let ostree_repo = &self.sysroot.repo();
171+
let ostree_verity = ostree_ext::fsverity::is_verity_enabled(ostree_repo)?;
172+
if !ostree_verity.enabled {
173+
tracing::debug!("Setting insecure mode for composefs repo");
174+
composefs.set_insecure(true);
175+
}
176+
let composefs = Arc::new(composefs);
177+
let r = Arc::clone(self.composefs.get_or_init(|| composefs));
178+
Ok(r)
179+
}
180+
114181
/// Update the mtime on the storage root directory
115182
#[context("Updating storage root mtime")]
116183
pub(crate) fn update_mtime(&self) -> Result<()> {

crates/ostree-ext/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ ostree = { features = ["v2025_2"], version = "0.20" }
1616
anyhow = { workspace = true }
1717
bootc-utils = { package = "bootc-internal-utils", path = "../utils", version = "0.0.0" }
1818
camino = { workspace = true, features = ["serde1"] }
19-
composefs = { git = "https://github.com/containers/composefs-rs", rev = "28d4721f77f973f0e394d60d6a69d9b39cb38d7f", package = "composefs", features = ["rhel9"] }
20-
composefs-boot = { git = "https://github.com/containers/composefs-rs", rev = "28d4721f77f973f0e394d60d6a69d9b39cb38d7f", package = "composefs-boot" }
21-
composefs-oci = { git = "https://github.com/containers/composefs-rs", rev = "28d4721f77f973f0e394d60d6a69d9b39cb38d7f", package = "composefs-oci" }
19+
composefs = { workspace = true }
20+
composefs-boot = { workspace = true }
21+
composefs-oci = { workspace = true }
2222
chrono = { workspace = true }
2323
clap = { workspace = true, features = ["derive","cargo"] }
2424
clap_mangen = { workspace = true, optional = true }
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use std assert
2+
use tap.nu
3+
4+
tap begin "composefs integration smoke test"
5+
6+
bootc internals test-composefs
7+
8+
tap ok

0 commit comments

Comments
 (0)