feat: oci compliance work (#85)

* chore: rework oci crate to be more composable

* feat: image pull is now internally explicit

* feat: utilize vfs for assembling oci images

* feat: rework oci to preserve permissions via a vfs
This commit is contained in:
Alex Zenla
2024-04-15 10:24:14 -07:00
committed by GitHub
parent 24c71e9725
commit 89055ef77c
33 changed files with 1500 additions and 1164 deletions

View File

@ -10,8 +10,7 @@ use krata::launchcfg::{
LaunchInfo, LaunchNetwork, LaunchNetworkIpv4, LaunchNetworkIpv6, LaunchNetworkResolver,
LaunchPackedFormat, LaunchRoot,
};
use krataoci::packer::OciPackerFormat;
use krataoci::progress::OciProgressContext;
use krataoci::packer::OciImagePacked;
use tokio::sync::Semaphore;
use uuid::Uuid;
use xenclient::{DomainChannel, DomainConfig, DomainDisk, DomainNetworkInterface};
@ -19,24 +18,19 @@ use xenstore::XsdInterface;
use crate::cfgblk::ConfigBlock;
use crate::RuntimeContext;
use krataoci::{
cache::ImageCache,
compiler::{ImageInfo, OciImageCompiler},
name::ImageName,
};
use super::{GuestInfo, GuestState};
pub struct GuestLaunchRequest<'a> {
pub struct GuestLaunchRequest {
pub format: LaunchPackedFormat,
pub uuid: Option<Uuid>,
pub name: Option<&'a str>,
pub image: &'a str,
pub name: Option<String>,
pub vcpus: u32,
pub mem: u64,
pub env: HashMap<String, String>,
pub run: Option<Vec<String>>,
pub debug: bool,
pub image: OciImagePacked,
}
pub struct GuestLauncher {
@ -48,26 +42,13 @@ impl GuestLauncher {
Ok(Self { launch_semaphore })
}
pub async fn launch<'r>(
pub async fn launch(
&mut self,
context: &RuntimeContext,
request: GuestLaunchRequest<'r>,
request: GuestLaunchRequest,
) -> Result<GuestInfo> {
let uuid = request.uuid.unwrap_or_else(Uuid::new_v4);
let xen_name = format!("krata-{uuid}");
let image_info = self
.compile(
&uuid.to_string(),
request.image,
&context.image_cache,
&context.oci_progress_context,
match request.format {
LaunchPackedFormat::Squashfs => OciPackerFormat::Squashfs,
LaunchPackedFormat::Erofs => OciPackerFormat::Erofs,
},
)
.await?;
let mut gateway_mac = MacAddr6::random();
gateway_mac.set_local(true);
gateway_mac.set_multicast(false);
@ -90,6 +71,7 @@ impl GuestLauncher {
hostname: Some(
request
.name
.as_ref()
.map(|x| x.to_string())
.unwrap_or_else(|| format!("krata-{}", uuid)),
),
@ -116,11 +98,12 @@ impl GuestLauncher {
run: request.run,
};
let cfgblk = ConfigBlock::new(&uuid, &image_info)?;
let cfgblk = ConfigBlock::new(&uuid, &request.image)?;
cfgblk.build(&launch_config)?;
let image_squashfs_path = image_info
let image_squashfs_path = request
.image
.path
.to_str()
.ok_or_else(|| anyhow!("failed to convert image path to string"))?;
@ -158,7 +141,6 @@ impl GuestLauncher {
cfgblk_dir_path,
),
),
("krata/image".to_string(), request.image.to_string()),
(
"krata/network/guest/ipv4".to_string(),
format!("{}/{}", guest_ipv4, ipv4_network_mask),
@ -185,8 +167,8 @@ impl GuestLauncher {
),
];
if let Some(name) = request.name {
extra_keys.push(("krata/name".to_string(), name.to_string()));
if let Some(name) = request.name.as_ref() {
extra_keys.push(("krata/name".to_string(), name.clone()));
}
let config = DomainConfig {
@ -227,10 +209,10 @@ impl GuestLauncher {
};
match context.xen.create(&config).await {
Ok(created) => Ok(GuestInfo {
name: request.name.map(|x| x.to_string()),
name: request.name.as_ref().map(|x| x.to_string()),
uuid,
domid: created.domid,
image: request.image.to_string(),
image: request.image.digest,
loops: vec![],
guest_ipv4: Some(IpNetwork::new(
IpAddr::V4(guest_ipv4),
@ -261,19 +243,6 @@ impl GuestLauncher {
}
}
async fn compile(
&self,
id: &str,
image: &str,
image_cache: &ImageCache,
progress: &OciProgressContext,
format: OciPackerFormat,
) -> Result<ImageInfo> {
let image = ImageName::parse(image)?;
let compiler = OciImageCompiler::new(image_cache, None, progress.clone())?;
compiler.compile(id, &image, format).await
}
async fn allocate_ipv4(&self, context: &RuntimeContext) -> Result<Ipv4Addr> {
let network = Ipv4Network::new(Ipv4Addr::new(10, 75, 80, 0), 24)?;
let mut used: Vec<Ipv4Addr> = vec![];