|
1 | 1 | use std::cell::OnceCell;
|
2 | 2 | use std::env;
|
3 | 3 | use std::ops::Deref;
|
| 4 | +use std::sync::Arc; |
4 | 5 |
|
5 | 6 | use anyhow::{Context, Result};
|
6 | 7 | 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 _}; |
8 | 9 | use cap_std_ext::dirext::CapStdExtDirExt;
|
9 | 10 | use clap::ValueEnum;
|
10 | 11 | use fn_error_context::context;
|
11 | 12 |
|
12 | 13 | use ostree_ext::container::OstreeImageReference;
|
13 | 14 | use ostree_ext::keyfileext::KeyFileExt;
|
14 |
| -use ostree_ext::ostree; |
15 | 15 | use ostree_ext::sysroot::SysrootLock;
|
| 16 | +use ostree_ext::{composefs, ostree}; |
| 17 | +use rustix::fs::Mode; |
16 | 18 |
|
17 | 19 | use crate::lsm;
|
18 | 20 | use crate::spec::ImageStatus;
|
19 | 21 | use crate::utils::deployment_fd;
|
20 | 22 |
|
21 | 23 | mod ostree_container;
|
22 | 24 |
|
| 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 | + |
23 | 36 | /// The path to the bootc root directory, relative to the physical
|
24 | 37 | /// system root
|
25 | 38 | pub(crate) const BOOTC_ROOT: &str = "ostree/bootc";
|
26 | 39 |
|
27 | 40 | pub(crate) struct Storage {
|
| 41 | + /// Directory holding the physical root |
| 42 | + pub physical_root: Dir, |
| 43 | + |
| 44 | + /// The OSTree storage |
28 | 45 | pub sysroot: SysrootLock,
|
29 |
| - run: Dir, |
| 46 | + /// The composefs storage |
| 47 | + pub composefs: OnceCell<Arc<ComposefsRepository>>, |
| 48 | + /// The containers-image storage used foR LBIs |
30 | 49 | 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 |
31 | 56 | pub store: Box<dyn ContainerImageStoreImpl>,
|
32 | 57 | }
|
33 | 58 |
|
@@ -71,12 +96,29 @@ impl Storage {
|
71 | 96 | }),
|
72 | 97 | Err(_) => crate::spec::Store::default(),
|
73 | 98 | };
|
74 |
| - |
75 | 99 | let store = load(store);
|
76 | 100 |
|
| 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 | + |
77 | 117 | Ok(Self {
|
| 118 | + physical_root, |
78 | 119 | sysroot,
|
79 | 120 | run,
|
| 121 | + composefs: Default::default(), |
80 | 122 | store,
|
81 | 123 | imgstore: Default::default(),
|
82 | 124 | })
|
@@ -111,6 +153,31 @@ impl Storage {
|
111 | 153 | Ok(self.imgstore.get_or_init(|| imgstore))
|
112 | 154 | }
|
113 | 155 |
|
| 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 | + |
114 | 181 | /// Update the mtime on the storage root directory
|
115 | 182 | #[context("Updating storage root mtime")]
|
116 | 183 | pub(crate) fn update_mtime(&self) -> Result<()> {
|
|
0 commit comments