From 3d29a686456ff1b05772fd8a5b9861a925a289c5 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Tue, 16 Apr 2024 05:53:58 +0000 Subject: [PATCH] feat: oci tar format support --- crates/ctl/src/cli/launch.rs | 18 ++++++++----- crates/ctl/src/cli/pull.rs | 8 +++--- crates/daemon/src/control.rs | 16 +++++++----- crates/daemon/src/reconcile/guest.rs | 11 +++++--- crates/krata/proto/krata/v1/common.proto | 12 +++++---- crates/krata/proto/krata/v1/control.proto | 4 +-- crates/oci/src/packer/backend.rs | 32 ++++++++++++++++++++++- crates/oci/src/packer/mod.rs | 3 +++ 8 files changed, 75 insertions(+), 29 deletions(-) diff --git a/crates/ctl/src/cli/launch.rs b/crates/ctl/src/cli/launch.rs index d202d3f..f91823b 100644 --- a/crates/ctl/src/cli/launch.rs +++ b/crates/ctl/src/cli/launch.rs @@ -1,13 +1,13 @@ use std::collections::HashMap; use anyhow::Result; -use clap::Parser; +use clap::{Parser, ValueEnum}; use krata::{ events::EventStream, v1::{ common::{ - guest_image_spec::Image, GuestImageSpec, GuestOciImageFormat, GuestOciImageSpec, - GuestSpec, GuestStatus, GuestTaskSpec, GuestTaskSpecEnvVar, + guest_image_spec::Image, GuestImageSpec, GuestOciImageSpec, GuestSpec, GuestStatus, + GuestTaskSpec, GuestTaskSpecEnvVar, OciImageFormat, }, control::{ 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 super::pull::PullImageFormat; +#[derive(ValueEnum, Clone, Debug, PartialEq, Eq)] +pub enum LaunchImageFormat { + Squashfs, + Erofs, +} #[derive(Parser)] #[command(about = "Launch a new guest")] pub struct LauchCommand { #[arg(short = 'S', long, default_value = "squashfs", help = "Image format")] - image_format: PullImageFormat, + image_format: LaunchImageFormat, #[arg(short, long, help = "Name of the guest")] name: Option, #[arg( @@ -78,8 +82,8 @@ impl LauchCommand { .pull_image(PullImageRequest { image: self.oci.clone(), format: match self.image_format { - PullImageFormat::Squashfs => GuestOciImageFormat::Squashfs.into(), - PullImageFormat::Erofs => GuestOciImageFormat::Erofs.into(), + LaunchImageFormat::Squashfs => OciImageFormat::Squashfs.into(), + LaunchImageFormat::Erofs => OciImageFormat::Erofs.into(), }, }) .await?; diff --git a/crates/ctl/src/cli/pull.rs b/crates/ctl/src/cli/pull.rs index 50ab84c..9398c1d 100644 --- a/crates/ctl/src/cli/pull.rs +++ b/crates/ctl/src/cli/pull.rs @@ -1,7 +1,7 @@ use anyhow::Result; use clap::{Parser, ValueEnum}; use krata::v1::{ - common::GuestOciImageFormat, + common::OciImageFormat, control::{control_service_client::ControlServiceClient, PullImageRequest}, }; @@ -13,6 +13,7 @@ use crate::pull::pull_interactive_progress; pub enum PullImageFormat { Squashfs, Erofs, + Tar, } #[derive(Parser)] @@ -30,8 +31,9 @@ impl PullCommand { .pull_image(PullImageRequest { image: self.image.clone(), format: match self.image_format { - PullImageFormat::Squashfs => GuestOciImageFormat::Squashfs.into(), - PullImageFormat::Erofs => GuestOciImageFormat::Erofs.into(), + PullImageFormat::Squashfs => OciImageFormat::Squashfs.into(), + PullImageFormat::Erofs => OciImageFormat::Erofs.into(), + PullImageFormat::Tar => OciImageFormat::Tar.into(), }, }) .await?; diff --git a/crates/daemon/src/control.rs b/crates/daemon/src/control.rs index 2a81c1a..778f232 100644 --- a/crates/daemon/src/control.rs +++ b/crates/daemon/src/control.rs @@ -6,7 +6,7 @@ use krata::{ IdmMetricsRequest, }, v1::{ - common::{Guest, GuestOciImageFormat, GuestState, GuestStatus}, + common::{Guest, GuestState, GuestStatus, OciImageFormat}, control::{ control_service_server::ControlService, ConsoleDataReply, ConsoleDataRequest, CreateGuestReply, CreateGuestRequest, DestroyGuestReply, DestroyGuestRequest, @@ -362,9 +362,10 @@ impl ControlService for DaemonControlService { message: err.to_string(), })?; let format = match request.format() { - GuestOciImageFormat::Unknown => OciPackedFormat::Squashfs, - GuestOciImageFormat::Squashfs => OciPackedFormat::Squashfs, - GuestOciImageFormat::Erofs => OciPackedFormat::Erofs, + OciImageFormat::Unknown => OciPackedFormat::Squashfs, + OciImageFormat::Squashfs => OciPackedFormat::Squashfs, + OciImageFormat::Erofs => OciPackedFormat::Erofs, + OciImageFormat::Tar => OciPackedFormat::Tar, }; let (sender, mut receiver) = channel::(100); let context = OciProgressContext::new(sender); @@ -388,7 +389,7 @@ impl ControlService for DaemonControlService { let reply = PullImageReply { progress: Some(convert_oci_progress(progress)), digest: String::new(), - format: GuestOciImageFormat::Unknown.into(), + format: OciImageFormat::Unknown.into(), }; yield reply; } @@ -405,8 +406,9 @@ impl ControlService for DaemonControlService { progress: None, digest: packed.digest, format: match packed.format { - OciPackedFormat::Squashfs => GuestOciImageFormat::Squashfs.into(), - OciPackedFormat::Erofs => GuestOciImageFormat::Erofs.into(), + OciPackedFormat::Squashfs => OciImageFormat::Squashfs.into(), + OciPackedFormat::Erofs => OciImageFormat::Erofs.into(), + _ => OciImageFormat::Unknown.into(), }, }; yield reply; diff --git a/crates/daemon/src/reconcile/guest.rs b/crates/daemon/src/reconcile/guest.rs index ef8478e..5e1876c 100644 --- a/crates/daemon/src/reconcile/guest.rs +++ b/crates/daemon/src/reconcile/guest.rs @@ -9,7 +9,7 @@ use krata::launchcfg::LaunchPackedFormat; use krata::v1::{ common::{ guest_image_spec::Image, Guest, GuestErrorInfo, GuestExitInfo, GuestNetworkState, - GuestOciImageFormat, GuestState, GuestStatus, + GuestState, GuestStatus, OciImageFormat, }, control::GuestChangedEvent, }; @@ -244,9 +244,12 @@ impl GuestReconciler { .recall( &oci.digest, match oci.format() { - GuestOciImageFormat::Unknown => OciPackedFormat::Squashfs, - GuestOciImageFormat::Squashfs => OciPackedFormat::Squashfs, - GuestOciImageFormat::Erofs => OciPackedFormat::Erofs, + OciImageFormat::Unknown => OciPackedFormat::Squashfs, + OciImageFormat::Squashfs => OciPackedFormat::Squashfs, + OciImageFormat::Erofs => OciPackedFormat::Erofs, + OciImageFormat::Tar => { + return Err(anyhow!("tar image format is not supported for guests")); + } }, ) .await?; diff --git a/crates/krata/proto/krata/v1/common.proto b/crates/krata/proto/krata/v1/common.proto index 78bc7ed..1c20875 100644 --- a/crates/krata/proto/krata/v1/common.proto +++ b/crates/krata/proto/krata/v1/common.proto @@ -29,15 +29,17 @@ message GuestImageSpec { } } -enum GuestOciImageFormat { - GUEST_OCI_IMAGE_FORMAT_UNKNOWN = 0; - GUEST_OCI_IMAGE_FORMAT_SQUASHFS = 1; - GUEST_OCI_IMAGE_FORMAT_EROFS = 2; +enum OciImageFormat { + OCI_IMAGE_FORMAT_UNKNOWN = 0; + OCI_IMAGE_FORMAT_SQUASHFS = 1; + OCI_IMAGE_FORMAT_EROFS = 2; + // Tar format is not launchable, and is intended for kernel images. + OCI_IMAGE_FORMAT_TAR = 3; } message GuestOciImageSpec { string digest = 1; - GuestOciImageFormat format = 2; + OciImageFormat format = 2; } message GuestTaskSpec { diff --git a/crates/krata/proto/krata/v1/control.proto b/crates/krata/proto/krata/v1/control.proto index 61cf91b..692eba8 100644 --- a/crates/krata/proto/krata/v1/control.proto +++ b/crates/krata/proto/krata/v1/control.proto @@ -124,11 +124,11 @@ message PullImageProgress { message PullImageRequest { string image = 1; - krata.v1.common.GuestOciImageFormat format = 2; + krata.v1.common.OciImageFormat format = 2; } message PullImageReply { PullImageProgress progress = 1; string digest = 2; - krata.v1.common.GuestOciImageFormat format = 3; + krata.v1.common.OciImageFormat format = 3; } diff --git a/crates/oci/src/packer/backend.rs b/crates/oci/src/packer/backend.rs index 45b0302..6103640 100644 --- a/crates/oci/src/packer/backend.rs +++ b/crates/oci/src/packer/backend.rs @@ -7,12 +7,13 @@ use crate::{ }; use anyhow::{anyhow, Result}; use log::warn; -use tokio::{pin, process::Command, select}; +use tokio::{fs::File, pin, process::Command, select}; #[derive(Debug, Clone, Copy)] pub enum OciPackerBackendType { MkSquashfs, MkfsErofs, + Tar, } impl OciPackerBackendType { @@ -20,6 +21,7 @@ impl OciPackerBackendType { match self { OciPackerBackendType::MkSquashfs => OciPackedFormat::Squashfs, OciPackerBackendType::MkfsErofs => OciPackedFormat::Erofs, + OciPackerBackendType::Tar => OciPackedFormat::Tar, } } @@ -31,6 +33,7 @@ impl OciPackerBackendType { OciPackerBackendType::MkfsErofs => { Box::new(OciPackerMkfsErofs {}) as Box } + OciPackerBackendType::Tar => Box::new(OciPackerTar {}) as Box, } } } @@ -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, 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(()) + } +} diff --git a/crates/oci/src/packer/mod.rs b/crates/oci/src/packer/mod.rs index 7ddbc93..fe9b83f 100644 --- a/crates/oci/src/packer/mod.rs +++ b/crates/oci/src/packer/mod.rs @@ -14,6 +14,7 @@ pub enum OciPackedFormat { #[default] Squashfs, Erofs, + Tar, } impl OciPackedFormat { @@ -21,6 +22,7 @@ impl OciPackedFormat { match self { OciPackedFormat::Squashfs => "squashfs", OciPackedFormat::Erofs => "erofs", + OciPackedFormat::Tar => "tar", } } @@ -28,6 +30,7 @@ impl OciPackedFormat { match self { OciPackedFormat::Squashfs => OciPackerBackendType::MkSquashfs, OciPackedFormat::Erofs => OciPackerBackendType::MkfsErofs, + OciPackedFormat::Tar => OciPackerBackendType::Tar, } } }