particle-os-cli/process/drivers/bootc_driver/status.rs
Gerald Pinder 3a0be4099a
feat: Add bootc support (#448)
Adds support for using `bootc` as the preferred method for booting from
a locally created image. This new method gets rid of the need to create
a tarball and move it to the correct place and instead it will make use
of `podman scp` which copies the image to the root `containers-storage`
and then has `rpm-ostree` and `bootc` boot from that store.

Closes #418 
Closes #200
2025-08-09 14:05:59 -04:00

85 lines
2.7 KiB
Rust

use std::{borrow::Cow, path::PathBuf};
use blue_build_utils::constants::OCI_ARCHIVE;
use log::warn;
use oci_distribution::Reference;
use serde::Deserialize;
use crate::drivers::{BootStatus, types::ImageRef};
#[derive(Deserialize, Debug, Clone)]
pub struct BootcStatus {
status: BootcStatusExt,
}
#[derive(Deserialize, Debug, Clone)]
struct BootcStatusExt {
staged: Option<BootcStatusImage>,
booted: BootcStatusImage,
}
#[derive(Deserialize, Debug, Clone)]
struct BootcStatusImage {
image: BootcStatusImageInfo,
}
#[derive(Deserialize, Debug, Clone)]
struct BootcStatusImageInfo {
image: BootcStatusImageInfoRef,
}
#[derive(Deserialize, Debug, Clone)]
struct BootcStatusImageInfoRef {
image: String,
transport: String,
}
impl BootStatus for BootcStatus {
fn transaction_in_progress(&self) -> bool {
// Any call to bootc when a transaction is in progress
// will cause the process to block effectively making
// this check useless since bootc will continue with
// the operation as soon as the current transaction is
// completed.
false
}
fn booted_image(&self) -> Option<ImageRef<'_>> {
match self.status.booted.image.image.transport.as_str() {
"registry" | "containers-storage" => Some(ImageRef::Remote(Cow::Owned(
Reference::try_from(self.status.booted.image.image.image.as_str())
.inspect_err(|e| {
warn!(
"Failed to parse image ref {}:\n{e}",
self.status.booted.image.image.image
);
})
.ok()?,
))),
transport if transport == OCI_ARCHIVE => Some(ImageRef::LocalTar(Cow::Owned(
PathBuf::from(&self.status.booted.image.image.image),
))),
_ => None,
}
}
fn staged_image(&self) -> Option<ImageRef<'_>> {
let staged = self.status.staged.as_ref()?;
match staged.image.image.transport.as_str() {
"registry" | "containers-storage" => Some(ImageRef::Remote(Cow::Owned(
Reference::try_from(staged.image.image.image.as_str())
.inspect_err(|e| {
warn!(
"Failed to parse image ref {}:\n{e}",
staged.image.image.image
);
})
.ok()?,
))),
transport if transport == OCI_ARCHIVE => Some(ImageRef::LocalTar(Cow::Owned(
PathBuf::from(&staged.image.image.image),
))),
_ => None,
}
}
}