Skip to content
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

install: Add ensure-completion verb, wire up ostree-deploy → bootc #915

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions lib/src/boundimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
//! pre-pulled (and in the future, pinned) before a new image root
//! is considered ready.

use std::num::NonZeroUsize;

use anyhow::{Context, Result};
use camino::Utf8Path;
use cap_std_ext::cap_std::fs::Dir;
Expand Down Expand Up @@ -49,7 +47,7 @@ pub(crate) async fn pull_bound_images(sysroot: &Storage, deployment: &Deployment

#[context("Querying bound images")]
pub(crate) fn query_bound_images_for_deployment(
sysroot: &Storage,
sysroot: &ostree_ext::ostree::Sysroot,
deployment: &Deployment,
) -> Result<Vec<BoundImage>> {
let deployment_root = &crate::utils::deployment_fd(sysroot, deployment)?;
Expand Down Expand Up @@ -153,15 +151,21 @@ pub(crate) async fn pull_images(
sysroot: &Storage,
bound_images: Vec<crate::boundimage::BoundImage>,
) -> Result<()> {
tracing::debug!("Pulling bound images: {}", bound_images.len());
// Yes, the usage of NonZeroUsize here is...maybe odd looking, but I find
// it an elegant way to divide (empty vector, non empty vector) since
// we want to print the length too below.
let Some(n) = NonZeroUsize::new(bound_images.len()) else {
return Ok(());
};
// Only do work like initializing the image storage if we have images to pull.
if bound_images.is_empty() {
return Ok(());
}
let imgstore = sysroot.get_ensure_imgstore()?;
pull_images_impl(imgstore, bound_images).await
}

#[context("Pulling bound images")]
pub(crate) async fn pull_images_impl(
imgstore: &crate::imgstorage::Storage,
bound_images: Vec<crate::boundimage::BoundImage>,
) -> Result<()> {
let n = bound_images.len();
tracing::debug!("Pulling bound images: {n}");
cgwalters marked this conversation as resolved.
Show resolved Hide resolved
// TODO: do this in parallel
for bound_image in bound_images {
let image = &bound_image.image;
Expand Down
27 changes: 27 additions & 0 deletions lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ pub(crate) enum InstallOpts {
/// will be wiped, but the content of the existing root will otherwise be retained, and will
/// need to be cleaned up if desired when rebooted into the new root.
ToExistingRoot(crate::install::InstallToExistingRootOpts),
/// Intended for use in environments that are performing an ostree-based installation, not bootc.
///
/// In this scenario the installation may be missing bootc specific features such as
/// kernel arguments, logically bound images and more. This command can be used to attempt
/// to reconcile. At the current time, the only tested environment is Anaconda using `ostreecontainer`
/// and it is recommended to avoid usage outside of that environment. Instead, ensure your
/// code is using `bootc install to-filesystem` from the start.
#[clap(hide = true)]
EnsureCompletion {},
/// Output JSON to stdout that contains the merged installation configuration
/// as it may be relevant to calling processes using `install to-filesystem`
/// that in particular want to discover the desired root filesystem type from the container image.
Expand Down Expand Up @@ -346,6 +355,15 @@ pub(crate) enum InternalsOpts {
#[clap(allow_hyphen_values = true)]
args: Vec<OsString>,
},
#[cfg(feature = "install")]
/// Invoked from ostree-ext to complete an installation.
BootcInstallCompletion {
/// Path to the sysroot
sysroot: Utf8PathBuf,

// The stateroot
stateroot: String,
},
}

#[derive(Debug, clap::Subcommand, PartialEq, Eq)]
Expand Down Expand Up @@ -989,6 +1007,10 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
crate::install::install_to_existing_root(opts).await
}
InstallOpts::PrintConfiguration => crate::install::print_configuration(),
InstallOpts::EnsureCompletion {} => {
let rootfs = &Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
crate::install::completion::run_from_anaconda(rootfs).await
}
},
#[cfg(feature = "install")]
Opt::ExecInHostMountNamespace { args } => {
Expand Down Expand Up @@ -1026,6 +1048,11 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
let sysroot = get_storage().await?;
crate::deploy::cleanup(&sysroot).await
}
#[cfg(feature = "install")]
InternalsOpts::BootcInstallCompletion { sysroot, stateroot } => {
let rootfs = &Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
crate::install::completion::run_from_ostree(rootfs, &sysroot, &stateroot).await
}
},
#[cfg(feature = "docgen")]
Opt::Man(manopts) => crate::docgen::generate_manpages(&manopts.directory),
Expand Down
5 changes: 4 additions & 1 deletion lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// This sub-module is the "basic" installer that handles creating basic block device
// and filesystem setup.
pub(crate) mod baseline;
pub(crate) mod completion;
pub(crate) mod config;
mod osbuild;
pub(crate) mod osconfig;
Expand Down Expand Up @@ -762,6 +763,7 @@ async fn install_container(
)?;
let kargsd = kargsd.iter().map(|s| s.as_str());

// Keep this in sync with install/completion.rs for the Anaconda fixups
let install_config_kargs = state
.install_config
.as_ref()
Expand All @@ -786,6 +788,7 @@ async fn install_container(
options.kargs = Some(kargs.as_slice());
options.target_imgref = Some(&state.target_imgref);
options.proxy_cfg = proxy_cfg;
options.skip_completion = true; // Must be set to avoid recursion!
options.no_clean = has_ostree;
let imgstate = crate::utils::async_task_with_spinner(
"Deploying container image",
Expand Down Expand Up @@ -1383,7 +1386,7 @@ async fn install_with_sysroot(
}
}
BoundImages::Unresolved(bound_images) => {
crate::boundimage::pull_images(sysroot, bound_images)
crate::boundimage::pull_images_impl(imgstore, bound_images)
.await
.context("pulling bound images")?;
}
Expand Down
Loading
Loading