Skip to content

Commit 3b9f4e4

Browse files
authored
Merge pull request #915 from cgwalters/install-fixup
install: Add `ensure-completion` verb, wire up ostree-deploy → bootc
2 parents 4690143 + c5852ad commit 3b9f4e4

File tree

5 files changed

+378
-11
lines changed

5 files changed

+378
-11
lines changed

lib/src/boundimage.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
//! pre-pulled (and in the future, pinned) before a new image root
66
//! is considered ready.
77
8-
use std::num::NonZeroUsize;
9-
108
use anyhow::{Context, Result};
119
use camino::Utf8Path;
1210
use cap_std_ext::cap_std::fs::Dir;
@@ -49,7 +47,7 @@ pub(crate) async fn pull_bound_images(sysroot: &Storage, deployment: &Deployment
4947

5048
#[context("Querying bound images")]
5149
pub(crate) fn query_bound_images_for_deployment(
52-
sysroot: &Storage,
50+
sysroot: &ostree_ext::ostree::Sysroot,
5351
deployment: &Deployment,
5452
) -> Result<Vec<BoundImage>> {
5553
let deployment_root = &crate::utils::deployment_fd(sysroot, deployment)?;
@@ -153,15 +151,21 @@ pub(crate) async fn pull_images(
153151
sysroot: &Storage,
154152
bound_images: Vec<crate::boundimage::BoundImage>,
155153
) -> Result<()> {
156-
tracing::debug!("Pulling bound images: {}", bound_images.len());
157-
// Yes, the usage of NonZeroUsize here is...maybe odd looking, but I find
158-
// it an elegant way to divide (empty vector, non empty vector) since
159-
// we want to print the length too below.
160-
let Some(n) = NonZeroUsize::new(bound_images.len()) else {
161-
return Ok(());
162-
};
163154
// Only do work like initializing the image storage if we have images to pull.
155+
if bound_images.is_empty() {
156+
return Ok(());
157+
}
164158
let imgstore = sysroot.get_ensure_imgstore()?;
159+
pull_images_impl(imgstore, bound_images).await
160+
}
161+
162+
#[context("Pulling bound images")]
163+
pub(crate) async fn pull_images_impl(
164+
imgstore: &crate::imgstorage::Storage,
165+
bound_images: Vec<crate::boundimage::BoundImage>,
166+
) -> Result<()> {
167+
let n = bound_images.len();
168+
tracing::debug!("Pulling bound images: {n}");
165169
// TODO: do this in parallel
166170
for bound_image in bound_images {
167171
let image = &bound_image.image;

lib/src/cli.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ pub(crate) enum InstallOpts {
182182
/// will be wiped, but the content of the existing root will otherwise be retained, and will
183183
/// need to be cleaned up if desired when rebooted into the new root.
184184
ToExistingRoot(crate::install::InstallToExistingRootOpts),
185+
/// Intended for use in environments that are performing an ostree-based installation, not bootc.
186+
///
187+
/// In this scenario the installation may be missing bootc specific features such as
188+
/// kernel arguments, logically bound images and more. This command can be used to attempt
189+
/// to reconcile. At the current time, the only tested environment is Anaconda using `ostreecontainer`
190+
/// and it is recommended to avoid usage outside of that environment. Instead, ensure your
191+
/// code is using `bootc install to-filesystem` from the start.
192+
#[clap(hide = true)]
193+
EnsureCompletion {},
185194
/// Output JSON to stdout that contains the merged installation configuration
186195
/// as it may be relevant to calling processes using `install to-filesystem`
187196
/// that in particular want to discover the desired root filesystem type from the container image.
@@ -346,6 +355,15 @@ pub(crate) enum InternalsOpts {
346355
#[clap(allow_hyphen_values = true)]
347356
args: Vec<OsString>,
348357
},
358+
#[cfg(feature = "install")]
359+
/// Invoked from ostree-ext to complete an installation.
360+
BootcInstallCompletion {
361+
/// Path to the sysroot
362+
sysroot: Utf8PathBuf,
363+
364+
// The stateroot
365+
stateroot: String,
366+
},
349367
}
350368

351369
#[derive(Debug, clap::Subcommand, PartialEq, Eq)]
@@ -989,6 +1007,10 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
9891007
crate::install::install_to_existing_root(opts).await
9901008
}
9911009
InstallOpts::PrintConfiguration => crate::install::print_configuration(),
1010+
InstallOpts::EnsureCompletion {} => {
1011+
let rootfs = &Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
1012+
crate::install::completion::run_from_anaconda(rootfs).await
1013+
}
9921014
},
9931015
#[cfg(feature = "install")]
9941016
Opt::ExecInHostMountNamespace { args } => {
@@ -1026,6 +1048,11 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
10261048
let sysroot = get_storage().await?;
10271049
crate::deploy::cleanup(&sysroot).await
10281050
}
1051+
#[cfg(feature = "install")]
1052+
InternalsOpts::BootcInstallCompletion { sysroot, stateroot } => {
1053+
let rootfs = &Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
1054+
crate::install::completion::run_from_ostree(rootfs, &sysroot, &stateroot).await
1055+
}
10291056
},
10301057
#[cfg(feature = "docgen")]
10311058
Opt::Man(manopts) => crate::docgen::generate_manpages(&manopts.directory),

lib/src/install.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// This sub-module is the "basic" installer that handles creating basic block device
88
// and filesystem setup.
99
pub(crate) mod baseline;
10+
pub(crate) mod completion;
1011
pub(crate) mod config;
1112
mod osbuild;
1213
pub(crate) mod osconfig;
@@ -750,6 +751,7 @@ async fn install_container(
750751
)?;
751752
let kargsd = kargsd.iter().map(|s| s.as_str());
752753

754+
// Keep this in sync with install/completion.rs for the Anaconda fixups
753755
let install_config_kargs = state
754756
.install_config
755757
.as_ref()
@@ -774,6 +776,7 @@ async fn install_container(
774776
options.kargs = Some(kargs.as_slice());
775777
options.target_imgref = Some(&state.target_imgref);
776778
options.proxy_cfg = proxy_cfg;
779+
options.skip_completion = true; // Must be set to avoid recursion!
777780
options.no_clean = has_ostree;
778781
let imgstate = crate::utils::async_task_with_spinner(
779782
"Deploying container image",
@@ -1331,7 +1334,7 @@ async fn install_with_sysroot(
13311334
}
13321335
}
13331336
BoundImages::Unresolved(bound_images) => {
1334-
crate::boundimage::pull_images(sysroot, bound_images)
1337+
crate::boundimage::pull_images_impl(imgstore, bound_images)
13351338
.await
13361339
.context("pulling bound images")?;
13371340
}

0 commit comments

Comments
 (0)