Skip to content
Open
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
13 changes: 8 additions & 5 deletions crates/lib/src/bootc_composefs/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ use bootc_utils::try_deserialize_timestamp;
use cap_std_ext::{cap_std::fs::Dir, dirext::CapStdExtDirExt};
use ostree_container::OstreeImageReference;
use ostree_ext::container::{self as ostree_container};
use ostree_ext::containers_image_proxy;
use ostree_ext::containers_image_proxy::{ImageProxy, ImageReference};

use ostree_ext::oci_spec;
use ostree_ext::{container::deploy::ORIGIN_CONTAINER, oci_spec::image::ImageConfiguration};

Expand Down Expand Up @@ -379,14 +380,16 @@ pub(crate) fn list_bootloader_entries(storage: &Storage) -> Result<Vec<Bootloade
/// imgref = transport:image_name
#[context("Getting container info")]
pub(crate) async fn get_container_manifest_and_config(
imgref: &String,
imgref: &ImageReference,
) -> Result<ImgConfigManifest> {
let mut config = crate::deploy::new_proxy_config();
ostree_ext::container::merge_default_container_proxy_opts(&mut config)?;
let proxy = containers_image_proxy::ImageProxy::new_with_config(config).await?;

ostree_ext::container::apply_container_proxy_opts_for_transport(&mut config, imgref.transport)?;

let proxy = ImageProxy::new_with_config(config).await?;

let img = proxy
.open_image(&imgref)
.open_image_ref(&imgref)
.await
.with_context(|| format!("Opening image {imgref}"))?;

Expand Down
2 changes: 1 addition & 1 deletion crates/lib/src/bootc_composefs/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub(crate) async fn is_image_pulled(
imgref: &ImageReference,
) -> Result<(Option<Sha512HashValue>, ImgConfigManifest)> {
let imgref_repr = imgref.to_image_proxy_ref()?;
let img_config_manifest = get_container_manifest_and_config(&imgref_repr.to_string()).await?;
let img_config_manifest = get_container_manifest_and_config(&imgref_repr).await?;

let img_digest = img_config_manifest.manifest.config().digest().digest();

Expand Down
31 changes: 31 additions & 0 deletions crates/lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,13 @@ pub(crate) enum ContainerOpts {
#[clap(long)]
write_dumpfile_to: Option<Utf8PathBuf>,

/// The directory containing the kernel and initramfs.img

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// The directory containing the kernel and initramfs.img
/// The directory containing the kernel and initramfs.img.

/// Must be of the format /parent/$kernel_version

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe?

Suggested change
/// Must be of the format /parent/$kernel_version
/// Must be of the format `/parent/$kernel_version`.

///
/// Ex. /boot/6.18.7-100.fc42.x86_64
#[clap(long)]
kernel_dir: Option<Utf8PathBuf>,

/// Additional arguments to pass to ukify (after `--`).
#[clap(last = true)]
args: Vec<OsString>,
Expand Down Expand Up @@ -1902,12 +1909,36 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
kargs,
allow_missing_verity,
write_dumpfile_to,
kernel_dir,
args,
} => {
let kernel = match kernel_dir {
Some(kernel_dir) => {
let kver = kernel_dir
.components()
.last()
.ok_or_else(|| anyhow::anyhow!("Could not determine kernel version"))?;

Some(crate::kernel::KernelInternal {
kernel: crate::kernel::Kernel {
unified: false,
version: kver.to_string(),
},
k_type: crate::kernel::KernelType::Vmlinuz {
path: kernel_dir.join("vmlinuz"),
initramfs: kernel_dir.join("initramfs.img"),
},
})
}

None => None,
};

crate::ukify::build_ukify(
&rootfs,
&kargs,
&args,
kernel,
allow_missing_verity,
write_dumpfile_to.as_deref(),
)
Expand Down
3 changes: 1 addition & 2 deletions crates/lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2017,8 +2017,7 @@ async fn install_to_filesystem_impl(
// Pre-flight disk space check for native composefs install path.
{
let imgref = &state.source.imageref;
let imgref_repr = imgref.to_string();
let img_manifest_config = get_container_manifest_and_config(&imgref_repr).await?;
let img_manifest_config = get_container_manifest_and_config(&imgref).await?;
crate::store::ensure_composefs_dir(&rootfs.physical_root)?;
// Use init_path since the repo may not exist yet during install
let (cfs_repo, _created) = crate::store::ComposefsRepository::init_path(
Expand Down
54 changes: 36 additions & 18 deletions crates/lib/src/ukify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use fn_error_context::context;

use crate::bootc_composefs::digest::compute_composefs_digest;
use crate::bootc_composefs::status::ComposefsCmdline;
use crate::kernel::KernelInternal;

/// Build a UKI from the given rootfs.
///
Expand All @@ -30,6 +31,7 @@ pub(crate) async fn build_ukify(
rootfs: &Utf8Path,
extra_kargs: &[String],
args: &[OsString],
kernel: Option<KernelInternal>,
allow_missing_fsverity: bool,
write_dumpfile_to: Option<&Utf8Path>,
) -> Result<()> {
Expand All @@ -52,30 +54,46 @@ pub(crate) async fn build_ukify(
let root = Dir::open_ambient_dir(rootfs, cap_std_ext::cap_std::ambient_authority())
.with_context(|| format!("Opening rootfs {rootfs}"))?;

// Find the kernel
let kernel = crate::kernel::find_kernel(&root)?
.ok_or_else(|| anyhow::anyhow!("No kernel found in {rootfs}"))?;
let kernel_final = match kernel {
Some(ref kernel) => kernel,
None => &crate::kernel::find_kernel(&root)?
.ok_or_else(|| anyhow::anyhow!("No kernel found in {rootfs}"))?,
};

// Extract vmlinuz and initramfs paths, or bail if this is already a UKI
let (vmlinuz_path, initramfs_path) = match kernel.k_type {
let (vmlinuz_path, initramfs_path) = match &kernel_final.k_type {
crate::kernel::KernelType::Vmlinuz { path, initramfs } => (path, initramfs),
crate::kernel::KernelType::Uki { path, .. } => {
anyhow::bail!("Cannot build UKI: rootfs already contains a UKI at {path}");
}
};

// Verify kernel and initramfs exist
if !root
.try_exists(&vmlinuz_path)
.context("Checking for vmlinuz")?
{
anyhow::bail!("Kernel not found at {vmlinuz_path}");
}
if !root
.try_exists(&initramfs_path)
.context("Checking for initramfs")?
{
anyhow::bail!("Initramfs not found at {initramfs_path}");
//
// NOTE: Not using cap_std here as the vmlinuz/initramfs path from
// args can be outside of "rootfs"
if kernel.is_some() {
if !vmlinuz_path.exists() {
anyhow::bail!("Kernel not found at {vmlinuz_path}");
}

if !initramfs_path.exists() {
anyhow::bail!("Initramfs not found at {initramfs_path}");
}
} else {
if !root
.try_exists(&vmlinuz_path)
.context("Checking for vmlinuz")?
{
anyhow::bail!("Kernel not found at {vmlinuz_path}");
}

if !root
.try_exists(&initramfs_path)
.context("Checking for initramfs")?
{
anyhow::bail!("Initramfs not found at {initramfs_path}");
}
}

// Compute the composefs digest
Expand Down Expand Up @@ -105,7 +123,7 @@ pub(crate) async fn build_ukify(
.arg("--initrd")
.arg(&initramfs_path)
.arg("--uname")
.arg(&kernel.kernel.version)
.arg(&kernel_final.kernel.version)
.arg("--cmdline")
.arg(&cmdline_str)
.arg("--os-release")
Expand Down Expand Up @@ -134,7 +152,7 @@ mod tests {
let tempdir = tempfile::tempdir().unwrap();
let path = Utf8Path::from_path(tempdir.path()).unwrap();

let result = build_ukify(path, &[], &[], false, None).await;
let result = build_ukify(path, &[], &[], None, false, None).await;
assert!(result.is_err());
let err = format!("{:#}", result.unwrap_err());
assert!(
Expand All @@ -156,7 +174,7 @@ mod tests {
)
.unwrap();

let result = build_ukify(path, &[], &[], false, None).await;
let result = build_ukify(path, &[], &[], None, false, None).await;
assert!(result.is_err());
let err = format!("{:#}", result.unwrap_err());
assert!(
Expand Down
14 changes: 14 additions & 0 deletions crates/ostree-ext/src/container/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,20 @@ pub fn version_for_config(config: &oci_spec::image::ImageConfiguration) -> Optio
None
}

/// Apply appropriate container proxy options based on transport type
pub fn apply_container_proxy_opts_for_transport(
config: &mut containers_image_proxy::ImageProxyConfig,
transport: Transport,
) -> Result<()> {
if transport == Transport::ContainerStorage {
// Fetching from containers-storage, may require privileges to read files
merge_default_container_proxy_opts_with_isolation(config, None)
} else {
// Apply our defaults to the proxy config
merge_default_container_proxy_opts(config)
}
}

pub mod deploy;
mod encapsulate;
pub use encapsulate::*;
Expand Down
8 changes: 1 addition & 7 deletions crates/ostree-ext/src/container/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,13 +635,7 @@ impl ImageImporter {
imgref: &OstreeImageReference,
mut config: ImageProxyConfig,
) -> Result<Self> {
if imgref.imgref.transport == Transport::ContainerStorage {
// Fetching from containers-storage, may require privileges to read files
merge_default_container_proxy_opts_with_isolation(&mut config, None)?;
} else {
// Apply our defaults to the proxy config
merge_default_container_proxy_opts(&mut config)?;
}
apply_container_proxy_opts_for_transport(&mut config, imgref.imgref.transport)?;
let proxy = ImageProxy::new_with_config(config).await?;

system_repo_journal_print(
Expand Down
4 changes: 4 additions & 0 deletions docs/src/man/bootc-container-ukify.8.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ Any additional arguments after `--` are passed through to ukify unchanged.

Write a dumpfile to this path

**--kernel-dir**=*KERNEL_DIR*

The directory containing the kernel and initramfs.img Must be of the format /parent/$kernel_version

<!-- END GENERATED OPTIONS -->

# EXAMPLES
Expand Down
2 changes: 2 additions & 0 deletions tmt/plans/integration.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ execute:
how: fmf
test:
- /tmt/tests/tests/test-37-install-no-boot-dir
extra-fixme_skip_if_composefs: true

/plan-37-upgrade-check-status:
summary: Verify upgrade --check populates cached update in status
Expand All @@ -232,6 +233,7 @@ execute:
how: fmf
test:
- /tmt/tests/tests/test-38-install-bootloader-none
extra-fixme_skip_if_composefs: true

/plan-39-upgrade-tag:
summary: Test bootc upgrade --tag functionality with containers-storage
Expand Down
5 changes: 4 additions & 1 deletion tmt/tests/booted/test-install-bootloader-none.nu
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
# tmt:
# summary: Test bootc install with --bootloader=none
# duration: 30m
#
# extra:
# # bootloader=none is not supported for composefs
# fixme_skip_if_composefs: true

use std assert
use tap.nu

Expand Down
9 changes: 7 additions & 2 deletions tmt/tests/booted/test-install-no-boot-dir.nu
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
# tmt:
# summary: Test bootc install to-filesystem without /boot directory
# duration: 30m
#
# extra:
# # bootloader=none is not supported for composefs and this test fails
# # when trying to install bootloader for composefs. For ostree, the
# # bootloader installation is simply skipped
# fixme_skip_if_composefs: true

use std assert
use tap.nu

Expand All @@ -19,7 +24,7 @@ def main [] {
mount -o loop disk.img /var/mnt

setenforce 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

tap run_install $"bootc install to-filesystem --disable-selinux --bootloader=none --source-imgref ($target_image) /var/mnt"

umount /var/mnt
Expand Down
Loading