feat: oci tar format support

This commit is contained in:
Alex Zenla
2024-04-16 05:53:58 +00:00
parent e88fadd3bc
commit 3d29a68645
8 changed files with 75 additions and 29 deletions

View File

@ -1,13 +1,13 @@
use std::collections::HashMap; use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::{Parser, ValueEnum};
use krata::{ use krata::{
events::EventStream, events::EventStream,
v1::{ v1::{
common::{ common::{
guest_image_spec::Image, GuestImageSpec, GuestOciImageFormat, GuestOciImageSpec, guest_image_spec::Image, GuestImageSpec, GuestOciImageSpec, GuestSpec, GuestStatus,
GuestSpec, GuestStatus, GuestTaskSpec, GuestTaskSpecEnvVar, GuestTaskSpec, GuestTaskSpecEnvVar, OciImageFormat,
}, },
control::{ control::{
control_service_client::ControlServiceClient, watch_events_reply::Event, control_service_client::ControlServiceClient, watch_events_reply::Event,
@ -21,13 +21,17 @@ use tonic::{transport::Channel, Request};
use crate::{console::StdioConsoleStream, pull::pull_interactive_progress}; use crate::{console::StdioConsoleStream, pull::pull_interactive_progress};
use super::pull::PullImageFormat; #[derive(ValueEnum, Clone, Debug, PartialEq, Eq)]
pub enum LaunchImageFormat {
Squashfs,
Erofs,
}
#[derive(Parser)] #[derive(Parser)]
#[command(about = "Launch a new guest")] #[command(about = "Launch a new guest")]
pub struct LauchCommand { pub struct LauchCommand {
#[arg(short = 'S', long, default_value = "squashfs", help = "Image format")] #[arg(short = 'S', long, default_value = "squashfs", help = "Image format")]
image_format: PullImageFormat, image_format: LaunchImageFormat,
#[arg(short, long, help = "Name of the guest")] #[arg(short, long, help = "Name of the guest")]
name: Option<String>, name: Option<String>,
#[arg( #[arg(
@ -78,8 +82,8 @@ impl LauchCommand {
.pull_image(PullImageRequest { .pull_image(PullImageRequest {
image: self.oci.clone(), image: self.oci.clone(),
format: match self.image_format { format: match self.image_format {
PullImageFormat::Squashfs => GuestOciImageFormat::Squashfs.into(), LaunchImageFormat::Squashfs => OciImageFormat::Squashfs.into(),
PullImageFormat::Erofs => GuestOciImageFormat::Erofs.into(), LaunchImageFormat::Erofs => OciImageFormat::Erofs.into(),
}, },
}) })
.await?; .await?;

View File

@ -1,7 +1,7 @@
use anyhow::Result; use anyhow::Result;
use clap::{Parser, ValueEnum}; use clap::{Parser, ValueEnum};
use krata::v1::{ use krata::v1::{
common::GuestOciImageFormat, common::OciImageFormat,
control::{control_service_client::ControlServiceClient, PullImageRequest}, control::{control_service_client::ControlServiceClient, PullImageRequest},
}; };
@ -13,6 +13,7 @@ use crate::pull::pull_interactive_progress;
pub enum PullImageFormat { pub enum PullImageFormat {
Squashfs, Squashfs,
Erofs, Erofs,
Tar,
} }
#[derive(Parser)] #[derive(Parser)]
@ -30,8 +31,9 @@ impl PullCommand {
.pull_image(PullImageRequest { .pull_image(PullImageRequest {
image: self.image.clone(), image: self.image.clone(),
format: match self.image_format { format: match self.image_format {
PullImageFormat::Squashfs => GuestOciImageFormat::Squashfs.into(), PullImageFormat::Squashfs => OciImageFormat::Squashfs.into(),
PullImageFormat::Erofs => GuestOciImageFormat::Erofs.into(), PullImageFormat::Erofs => OciImageFormat::Erofs.into(),
PullImageFormat::Tar => OciImageFormat::Tar.into(),
}, },
}) })
.await?; .await?;

View File

@ -6,7 +6,7 @@ use krata::{
IdmMetricsRequest, IdmMetricsRequest,
}, },
v1::{ v1::{
common::{Guest, GuestOciImageFormat, GuestState, GuestStatus}, common::{Guest, GuestState, GuestStatus, OciImageFormat},
control::{ control::{
control_service_server::ControlService, ConsoleDataReply, ConsoleDataRequest, control_service_server::ControlService, ConsoleDataReply, ConsoleDataRequest,
CreateGuestReply, CreateGuestRequest, DestroyGuestReply, DestroyGuestRequest, CreateGuestReply, CreateGuestRequest, DestroyGuestReply, DestroyGuestRequest,
@ -362,9 +362,10 @@ impl ControlService for DaemonControlService {
message: err.to_string(), message: err.to_string(),
})?; })?;
let format = match request.format() { let format = match request.format() {
GuestOciImageFormat::Unknown => OciPackedFormat::Squashfs, OciImageFormat::Unknown => OciPackedFormat::Squashfs,
GuestOciImageFormat::Squashfs => OciPackedFormat::Squashfs, OciImageFormat::Squashfs => OciPackedFormat::Squashfs,
GuestOciImageFormat::Erofs => OciPackedFormat::Erofs, OciImageFormat::Erofs => OciPackedFormat::Erofs,
OciImageFormat::Tar => OciPackedFormat::Tar,
}; };
let (sender, mut receiver) = channel::<OciProgress>(100); let (sender, mut receiver) = channel::<OciProgress>(100);
let context = OciProgressContext::new(sender); let context = OciProgressContext::new(sender);
@ -388,7 +389,7 @@ impl ControlService for DaemonControlService {
let reply = PullImageReply { let reply = PullImageReply {
progress: Some(convert_oci_progress(progress)), progress: Some(convert_oci_progress(progress)),
digest: String::new(), digest: String::new(),
format: GuestOciImageFormat::Unknown.into(), format: OciImageFormat::Unknown.into(),
}; };
yield reply; yield reply;
} }
@ -405,8 +406,9 @@ impl ControlService for DaemonControlService {
progress: None, progress: None,
digest: packed.digest, digest: packed.digest,
format: match packed.format { format: match packed.format {
OciPackedFormat::Squashfs => GuestOciImageFormat::Squashfs.into(), OciPackedFormat::Squashfs => OciImageFormat::Squashfs.into(),
OciPackedFormat::Erofs => GuestOciImageFormat::Erofs.into(), OciPackedFormat::Erofs => OciImageFormat::Erofs.into(),
_ => OciImageFormat::Unknown.into(),
}, },
}; };
yield reply; yield reply;

View File

@ -9,7 +9,7 @@ use krata::launchcfg::LaunchPackedFormat;
use krata::v1::{ use krata::v1::{
common::{ common::{
guest_image_spec::Image, Guest, GuestErrorInfo, GuestExitInfo, GuestNetworkState, guest_image_spec::Image, Guest, GuestErrorInfo, GuestExitInfo, GuestNetworkState,
GuestOciImageFormat, GuestState, GuestStatus, GuestState, GuestStatus, OciImageFormat,
}, },
control::GuestChangedEvent, control::GuestChangedEvent,
}; };
@ -244,9 +244,12 @@ impl GuestReconciler {
.recall( .recall(
&oci.digest, &oci.digest,
match oci.format() { match oci.format() {
GuestOciImageFormat::Unknown => OciPackedFormat::Squashfs, OciImageFormat::Unknown => OciPackedFormat::Squashfs,
GuestOciImageFormat::Squashfs => OciPackedFormat::Squashfs, OciImageFormat::Squashfs => OciPackedFormat::Squashfs,
GuestOciImageFormat::Erofs => OciPackedFormat::Erofs, OciImageFormat::Erofs => OciPackedFormat::Erofs,
OciImageFormat::Tar => {
return Err(anyhow!("tar image format is not supported for guests"));
}
}, },
) )
.await?; .await?;

View File

@ -29,15 +29,17 @@ message GuestImageSpec {
} }
} }
enum GuestOciImageFormat { enum OciImageFormat {
GUEST_OCI_IMAGE_FORMAT_UNKNOWN = 0; OCI_IMAGE_FORMAT_UNKNOWN = 0;
GUEST_OCI_IMAGE_FORMAT_SQUASHFS = 1; OCI_IMAGE_FORMAT_SQUASHFS = 1;
GUEST_OCI_IMAGE_FORMAT_EROFS = 2; OCI_IMAGE_FORMAT_EROFS = 2;
// Tar format is not launchable, and is intended for kernel images.
OCI_IMAGE_FORMAT_TAR = 3;
} }
message GuestOciImageSpec { message GuestOciImageSpec {
string digest = 1; string digest = 1;
GuestOciImageFormat format = 2; OciImageFormat format = 2;
} }
message GuestTaskSpec { message GuestTaskSpec {

View File

@ -124,11 +124,11 @@ message PullImageProgress {
message PullImageRequest { message PullImageRequest {
string image = 1; string image = 1;
krata.v1.common.GuestOciImageFormat format = 2; krata.v1.common.OciImageFormat format = 2;
} }
message PullImageReply { message PullImageReply {
PullImageProgress progress = 1; PullImageProgress progress = 1;
string digest = 2; string digest = 2;
krata.v1.common.GuestOciImageFormat format = 3; krata.v1.common.OciImageFormat format = 3;
} }

View File

@ -7,12 +7,13 @@ use crate::{
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use log::warn; use log::warn;
use tokio::{pin, process::Command, select}; use tokio::{fs::File, pin, process::Command, select};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum OciPackerBackendType { pub enum OciPackerBackendType {
MkSquashfs, MkSquashfs,
MkfsErofs, MkfsErofs,
Tar,
} }
impl OciPackerBackendType { impl OciPackerBackendType {
@ -20,6 +21,7 @@ impl OciPackerBackendType {
match self { match self {
OciPackerBackendType::MkSquashfs => OciPackedFormat::Squashfs, OciPackerBackendType::MkSquashfs => OciPackedFormat::Squashfs,
OciPackerBackendType::MkfsErofs => OciPackedFormat::Erofs, OciPackerBackendType::MkfsErofs => OciPackedFormat::Erofs,
OciPackerBackendType::Tar => OciPackedFormat::Tar,
} }
} }
@ -31,6 +33,7 @@ impl OciPackerBackendType {
OciPackerBackendType::MkfsErofs => { OciPackerBackendType::MkfsErofs => {
Box::new(OciPackerMkfsErofs {}) as Box<dyn OciPackerBackend> Box::new(OciPackerMkfsErofs {}) as Box<dyn OciPackerBackend>
} }
OciPackerBackendType::Tar => Box::new(OciPackerTar {}) as Box<dyn OciPackerBackend>,
} }
} }
} }
@ -199,3 +202,30 @@ impl OciPackerBackend for OciPackerMkfsErofs {
} }
} }
} }
pub struct OciPackerTar {}
#[async_trait::async_trait]
impl OciPackerBackend for OciPackerTar {
async fn pack(&self, progress: OciBoundProgress, vfs: Arc<VfsTree>, file: &Path) -> Result<()> {
progress
.update(|progress| {
progress.phase = OciProgressPhase::Packing;
progress.total = 1;
progress.value = 0;
})
.await;
let file = File::create(file).await?;
vfs.write_to_tar(file).await?;
progress
.update(|progress| {
progress.phase = OciProgressPhase::Packing;
progress.total = 1;
progress.value = 1;
})
.await;
Ok(())
}
}

View File

@ -14,6 +14,7 @@ pub enum OciPackedFormat {
#[default] #[default]
Squashfs, Squashfs,
Erofs, Erofs,
Tar,
} }
impl OciPackedFormat { impl OciPackedFormat {
@ -21,6 +22,7 @@ impl OciPackedFormat {
match self { match self {
OciPackedFormat::Squashfs => "squashfs", OciPackedFormat::Squashfs => "squashfs",
OciPackedFormat::Erofs => "erofs", OciPackedFormat::Erofs => "erofs",
OciPackedFormat::Tar => "tar",
} }
} }
@ -28,6 +30,7 @@ impl OciPackedFormat {
match self { match self {
OciPackedFormat::Squashfs => OciPackerBackendType::MkSquashfs, OciPackedFormat::Squashfs => OciPackerBackendType::MkSquashfs,
OciPackedFormat::Erofs => OciPackerBackendType::MkfsErofs, OciPackedFormat::Erofs => OciPackerBackendType::MkfsErofs,
OciPackedFormat::Tar => OciPackerBackendType::Tar,
} }
} }
} }