Skip to content
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
12 changes: 10 additions & 2 deletions crates/lib/src/bootc_composefs/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use cap_std_ext::{cap_std::fs::Dir, dirext::CapStdExtDirExt};
use crate::{
bootc_composefs::{
boot::{BootType, get_efi_uuid_source},
gc::composefs_gc,
gc::{GCOpts, composefs_gc},
rollback::{composefs_rollback, rename_exchange_user_cfg},
status::{get_composefs_status, get_sorted_grub_uki_boot_entries},
},
Expand Down Expand Up @@ -261,7 +261,15 @@ pub(crate) async fn delete_composefs_deployment(

delete_depl_boot_entries(&depl_to_del, &storage, deleting_staged)?;

composefs_gc(storage, booted_cfs, false, true).await?;
composefs_gc(
storage,
booted_cfs,
GCOpts {
dry_run: false,
prune_repo: true,
},
)
.await?;

Ok(())
}
12 changes: 10 additions & 2 deletions crates/lib/src/bootc_composefs/finalize.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::Path;

use crate::bootc_composefs::boot::BootType;
use crate::bootc_composefs::gc::composefs_gc;
use crate::bootc_composefs::gc::{GCOpts, composefs_gc};
use crate::bootc_composefs::rollback::{rename_exchange_bls_entries, rename_exchange_user_cfg};
use crate::bootc_composefs::status::get_composefs_status;
use crate::composefs_consts::STATE_DIR_ABS;
Expand Down Expand Up @@ -150,7 +150,15 @@ pub(crate) async fn composefs_backend_finalize(

// Now that we have successfully updated bootloader entires, we can GC the unreferenced ones
// We do not prune the composefs repository here though
composefs_gc(storage, booted_cfs, false, false).await?;
composefs_gc(
storage,
booted_cfs,
GCOpts {
dry_run: false,
prune_repo: false,
},
)
.await?;

Ok(())
}
Expand Down
30 changes: 18 additions & 12 deletions crates/lib/src/bootc_composefs/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ fn unreferenced_boot_binaries<'a>(
.collect()
}

pub(crate) struct GCOpts {
pub(crate) dry_run: bool,
pub(crate) prune_repo: bool,
}
Comment thread
Johan-Liebert1 marked this conversation as resolved.

/// 1. List all bootloader entries
/// 2. List all EROFS images
/// 3. List all state directories
Expand All @@ -212,8 +217,7 @@ fn unreferenced_boot_binaries<'a>(
pub(crate) async fn composefs_gc(
storage: &Storage,
booted_cfs: &BootedComposefs,
dry_run: bool,
prune_repo: bool,
gc_opts: GCOpts,
) -> Result<GcResult> {
const COMPOSEFS_GC_JOURNAL_ID: &str = "3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7";

Expand Down Expand Up @@ -284,12 +288,14 @@ pub(crate) async fn composefs_gc(

for (ty, verity) in unreferenced_boot_binaries {
match ty {
BootType::Bls => delete_kernel_initrd(storage, &get_type1_dir_name(verity), dry_run)?,
BootType::Uki => delete_uki(storage, verity, dry_run)?,
BootType::Bls => {
delete_kernel_initrd(storage, &get_type1_dir_name(verity), gc_opts.dry_run)?
}
BootType::Uki => delete_uki(storage, verity, gc_opts.dry_run)?,
}
}

if !prune_repo {
if !gc_opts.prune_repo {
return Ok(GcResult::default());
}

Expand Down Expand Up @@ -329,13 +335,13 @@ pub(crate) async fn composefs_gc(

for verity in &orphaned_state_dirs {
tracing::debug!("Cleaning up orphaned state dir: {verity}");
delete_staged(staged, &all_orphans, dry_run)?;
delete_state_dir(&sysroot, verity, dry_run)?;
delete_staged(staged, &all_orphans, gc_opts.dry_run)?;
delete_state_dir(&sysroot, verity, gc_opts.dry_run)?;
}

for verity in &orphaned_boot_entries {
tracing::debug!("Cleaning up orphaned bootloader entry: {verity}");
delete_staged(staged, &all_orphans, dry_run)?;
delete_staged(staged, &all_orphans, gc_opts.dry_run)?;
}

// Collect the set of manifest digests referenced by live deployments,
Expand Down Expand Up @@ -431,7 +437,7 @@ pub(crate) async fn composefs_gc(
.any(|(tag_name, _)| tag_name == &expected_tag);
if !has_tag {
tracing::info!("Creating missing bootc tag for live deployment: {expected_tag}");
if !dry_run {
if !gc_opts.dry_run {
composefs_oci::tag_image(&*booted_cfs.repo, manifest_digest, &expected_tag)
.with_context(|| format!("Creating migration tag {expected_tag}"))?;
}
Expand All @@ -450,7 +456,7 @@ pub(crate) async fn composefs_gc(

if !live_manifest_digests.iter().any(|d| d == manifest_digest) {
tracing::debug!("Removing unreferenced bootc tag: {tag_name}");
if !dry_run {
if !gc_opts.dry_run {
composefs_oci::untag_image(&*booted_cfs.repo, tag_name)
.with_context(|| format!("Removing tag {tag_name}"))?;
}
Expand All @@ -463,7 +469,7 @@ pub(crate) async fn composefs_gc(
.collect::<Vec<_>>();

// Prune containers-storage: remove images not backing any live deployment.
if !dry_run && !live_container_images.is_empty() {
if !gc_opts.dry_run && !live_container_images.is_empty() {
let subpath = crate::podstorage::CStorage::subpath();
if sysroot.try_exists(&subpath).unwrap_or(false) {
let run = Dir::open_ambient_dir("/run", cap_std_ext::cap_std::ambient_authority())?;
Expand All @@ -482,7 +488,7 @@ pub(crate) async fn composefs_gc(
// images for deployments that predate the manifest→image link;
// once all deployments have been pulled with the new code, these
// become redundant.
let gc_result = if dry_run {
let gc_result = if gc_opts.dry_run {
booted_cfs.repo.gc_dry_run(&additional_roots)?
} else {
booted_cfs.repo.gc(&additional_roots)?
Expand Down
26 changes: 17 additions & 9 deletions crates/lib/src/bootc_composefs/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,22 +405,30 @@ pub(crate) async fn get_container_manifest_and_config(

#[context("Getting bootloader")]
pub(crate) fn get_bootloader() -> Result<Bootloader> {
match read_uefi_var(EFI_LOADER_INFO) {
static BOOTLOADER: OnceLock<Bootloader> = OnceLock::new();

if let Some(bootloader) = BOOTLOADER.get() {
return Ok(*bootloader);
}

let bootloader = match read_uefi_var(EFI_LOADER_INFO) {
Ok(loader) => {
if loader.to_lowercase().contains("systemd-boot") {
return Ok(Bootloader::Systemd);
Bootloader::Systemd
} else {
Bootloader::Grub
}

return Ok(Bootloader::Grub);
}

Err(efi_error) => match efi_error {
EfiError::SystemNotUEFI => return Ok(Bootloader::Grub),
EfiError::MissingVar => return Ok(Bootloader::Grub),

e => return Err(anyhow::anyhow!("Failed to read EfiLoaderInfo: {e:?}")),
EfiError::SystemNotUEFI | EfiError::MissingVar => Bootloader::Grub,
e => anyhow::bail!("Failed to read EfiLoaderInfo: {e:?}"),
},
}
};

BOOTLOADER.get_or_init(|| bootloader);

return Ok(bootloader);
}

/// Retrieves the OCI manifest and config for a deployment from the composefs repository.
Expand Down
11 changes: 10 additions & 1 deletion crates/lib/src/bootc_composefs/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use fn_error_context::context;
use ocidir::cap_std::ambient_authority;
use ostree_ext::container::ManifestDiff;

use crate::bootc_composefs::gc::GCOpts;
use crate::{
bootc_composefs::{
boot::{BootSetupType, BootType, setup_composefs_bls_boot, setup_composefs_uki_boot},
Expand Down Expand Up @@ -324,7 +325,15 @@ pub(crate) async fn do_upgrade(

// We take into account the staged bootloader entries so this won't remove
// the currently staged entry
composefs_gc(storage, booted_cfs, false, true).await?;
composefs_gc(
storage,
booted_cfs,
GCOpts {
dry_run: false,
prune_repo: true,
},
)
.await?;

apply_upgrade(storage, booted_cfs, &id.to_hex(), opts).await
}
Expand Down
18 changes: 12 additions & 6 deletions crates/lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use schemars::schema_for;
use serde::{Deserialize, Serialize};

use crate::bootc_composefs::delete::delete_composefs_deployment;
use crate::bootc_composefs::gc::composefs_gc;
use crate::bootc_composefs::gc::{GCOpts, composefs_gc};
use crate::bootc_composefs::soft_reboot::{prepare_soft_reboot_composefs, reset_soft_reboot};
use crate::bootc_composefs::{
digest::{compute_composefs_digest, new_temp_composefs_repo},
Expand Down Expand Up @@ -2231,12 +2231,18 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
}

BootedStorageKind::Composefs(booted_cfs) => {
let effective_dry_run = dry_run || assert_no_op;
let gc_result =
composefs_gc(storage, &booted_cfs, effective_dry_run, prune_repo)
.await?;
let dry_run = dry_run || assert_no_op;
let gc_result = composefs_gc(
storage,
&booted_cfs,
GCOpts {
dry_run,
prune_repo,
},
)
.await?;

if effective_dry_run {
if dry_run {
println!("Dry run (no files deleted)");
}

Expand Down
2 changes: 1 addition & 1 deletion crates/lib/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ pub struct BootEntryOstree {

/// Bootloader type to determine whether system was booted via Grub or Systemd
#[derive(
clap::ValueEnum, Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema,
clap::ValueEnum, Debug, Default, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema,
)]
#[serde(rename_all = "kebab-case")]
pub enum Bootloader {
Expand Down