use arcbox_core::Runtime;
use arcbox_core::machine::{BootShim, MachineRootfs};
use arcbox_core::machine_image::{self, ImageSelector, MachineImage};
use connectrpc::ConnectError;
pub(super) async fn pull_image(
runtime: &Runtime,
machine: &str,
distro: &str,
version: &str,
arch: &str,
) -> Result<MachineImage, ConnectError> {
let arch = if arch.is_empty() {
machine_image::host_image_arch().to_string()
} else {
machine_image::image_arch(arch).to_string()
};
let selector = ImageSelector::Distro {
distro: distro.to_owned(),
release: (!version.is_empty()).then(|| version.to_owned()),
arch,
};
let image = runtime
.machine_image_manager()
.pull(&selector, |done, total| {
tracing::debug!(machine, done, total, "machine image pull");
})
.await
.map_err(|e| match &e {
arcbox_image::ImageError::Common(c) if c.is_not_found() => {
ConnectError::not_found(e.to_string())
}
_ => ConnectError::internal(e.to_string()),
})?;
tracing::info!(
machine,
image = %format!("{}@{}", image.manifest.name, image.manifest.version),
"machine image ready"
);
Ok(image)
}
pub(super) async fn rootfs_for(
runtime: &Runtime,
image: &MachineImage,
) -> Result<MachineRootfs, ConnectError> {
let shim = async {
let provider = arcbox_core::boot_assets::BootAssetProvider::new(
runtime.config().data_dir.join("boot"),
)?;
let assets = provider.get_assets().await?;
Ok::<_, arcbox_core::error::CoreError>(BootShim {
kernel: assets.kernel,
rootfs: assets.rootfs_image,
})
}
.await
.map_err(|e| ConnectError::internal(format!("resolve boot shim: {e}")))?;
Ok(MachineRootfs {
path: image.rootfs_path(),
format: image.manifest.rootfs.format.clone(),
shim: Some(shim),
})
}