particle-os-cli/process/drivers/rpm_ostree_driver.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

88 lines
2.2 KiB
Rust

use std::ops::Not;
use blue_build_utils::constants::OSTREE_UNVERIFIED_IMAGE;
use comlexr::cmd;
use log::trace;
use miette::{Context, IntoDiagnostic, bail};
use crate::logging::CommandLogging;
use super::{BootDriver, BootStatus, opts::SwitchOpts};
mod status;
pub use status::*;
pub struct RpmOstreeDriver;
impl BootDriver for RpmOstreeDriver {
fn status() -> miette::Result<Box<dyn BootStatus>> {
let output = {
let c = cmd!("rpm-ostree", "status", "--json");
trace!("{c:?}");
c
}
.output()
.into_diagnostic()?;
if !output.status.success() {
bail!("Failed to get `rpm-ostree` status!");
}
trace!("{}", String::from_utf8_lossy(&output.stdout));
Ok(Box::new(
serde_json::from_slice::<Status>(&output.stdout)
.into_diagnostic()
.wrap_err_with(|| {
format!(
"Failed to deserialize rpm-ostree status:\n{}",
String::from_utf8_lossy(&output.stdout)
)
})?,
))
}
fn switch(opts: SwitchOpts) -> miette::Result<()> {
let status = {
let c = cmd!(
"rpm-ostree",
"rebase",
format!("{OSTREE_UNVERIFIED_IMAGE}:containers-storage:{}", opts.image),
if opts.reboot => "--reboot",
);
trace!("{c:?}");
c
}
.build_status(format!("{}", opts.image), "Switching to new image")
.into_diagnostic()?;
if status.success().not() {
bail!("Failed to switch to image {}", opts.image);
}
Ok(())
}
fn upgrade(opts: SwitchOpts) -> miette::Result<()> {
let status = {
let c = cmd!(
"rpm-ostree",
"upgrade",
if opts.reboot => "--reboot",
);
trace!("{c:?}");
c
}
.build_status(format!("{}", opts.image), "Switching to new image")
.into_diagnostic()?;
if status.success().not() {
bail!("Failed to switch to image {}", opts.image);
}
Ok(())
}
}