mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-07 07:01:31 +00:00
feat: working erofs backend
This commit is contained in:
@ -5,6 +5,7 @@ use std::{
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use krata::launchcfg::LaunchPackedFormat;
|
||||
use krata::v1::{
|
||||
common::{
|
||||
guest_image_spec::Image, Guest, GuestErrorInfo, GuestExitInfo, GuestNetworkState,
|
||||
@ -238,6 +239,7 @@ impl GuestReconciler {
|
||||
let info = self
|
||||
.runtime
|
||||
.launch(GuestLaunchRequest {
|
||||
format: LaunchPackedFormat::Squashfs,
|
||||
uuid: Some(uuid),
|
||||
name: if spec.name.is_empty() {
|
||||
None
|
||||
|
@ -4,7 +4,7 @@ use futures::stream::TryStreamExt;
|
||||
use ipnetwork::IpNetwork;
|
||||
use krata::ethtool::EthtoolHandle;
|
||||
use krata::idm::client::IdmClient;
|
||||
use krata::launchcfg::{LaunchInfo, LaunchNetwork};
|
||||
use krata::launchcfg::{LaunchInfo, LaunchNetwork, LaunchPackedFormat};
|
||||
use libc::{sethostname, setsid, TIOCSCTTY};
|
||||
use log::{trace, warn};
|
||||
use nix::ioctl_write_int_bad;
|
||||
@ -80,11 +80,13 @@ impl GuestInit {
|
||||
let idm = IdmClient::open("/dev/hvc1")
|
||||
.await
|
||||
.map_err(|x| anyhow!("failed to open idm client: {}", x))?;
|
||||
self.mount_squashfs_images().await?;
|
||||
self.mount_config_image().await?;
|
||||
|
||||
let config = self.parse_image_config().await?;
|
||||
let launch = self.parse_launch_config().await?;
|
||||
|
||||
self.mount_root_image(launch.root.format.clone()).await?;
|
||||
|
||||
self.mount_new_root().await?;
|
||||
self.bind_new_root().await?;
|
||||
|
||||
@ -185,24 +187,41 @@ impl GuestInit {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn mount_squashfs_images(&mut self) -> Result<()> {
|
||||
trace!("mounting squashfs images");
|
||||
let image_mount_path = Path::new(IMAGE_MOUNT_PATH);
|
||||
async fn mount_config_image(&mut self) -> Result<()> {
|
||||
trace!("mounting config image");
|
||||
let config_mount_path = Path::new(CONFIG_MOUNT_PATH);
|
||||
self.mount_squashfs(Path::new(IMAGE_BLOCK_DEVICE_PATH), image_mount_path)
|
||||
.await?;
|
||||
self.mount_squashfs(Path::new(CONFIG_BLOCK_DEVICE_PATH), config_mount_path)
|
||||
self.mount_image(
|
||||
Path::new(CONFIG_BLOCK_DEVICE_PATH),
|
||||
config_mount_path,
|
||||
LaunchPackedFormat::Squashfs,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn mount_root_image(&mut self, format: LaunchPackedFormat) -> Result<()> {
|
||||
trace!("mounting root image");
|
||||
let image_mount_path = Path::new(IMAGE_MOUNT_PATH);
|
||||
self.mount_image(Path::new(IMAGE_BLOCK_DEVICE_PATH), image_mount_path, format)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn mount_squashfs(&mut self, from: &Path, to: &Path) -> Result<()> {
|
||||
trace!("mounting squashfs image {:?} to {:?}", from, to);
|
||||
async fn mount_image(
|
||||
&mut self,
|
||||
from: &Path,
|
||||
to: &Path,
|
||||
format: LaunchPackedFormat,
|
||||
) -> Result<()> {
|
||||
trace!("mounting {:?} image {:?} to {:?}", format, from, to);
|
||||
if !to.is_dir() {
|
||||
fs::create_dir(to).await?;
|
||||
}
|
||||
Mount::builder()
|
||||
.fstype(FilesystemType::Manual("squashfs"))
|
||||
.fstype(FilesystemType::Manual(match format {
|
||||
LaunchPackedFormat::Squashfs => "squashfs",
|
||||
LaunchPackedFormat::Erofs => "erofs",
|
||||
}))
|
||||
.flags(MountFlags::RDONLY)
|
||||
.mount(from, to)?;
|
||||
Ok(())
|
||||
|
@ -2,24 +2,30 @@ use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum LaunchPackedFormat {
|
||||
Squashfs,
|
||||
Erofs,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct LaunchNetworkIpv4 {
|
||||
pub address: String,
|
||||
pub gateway: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct LaunchNetworkIpv6 {
|
||||
pub address: String,
|
||||
pub gateway: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct LaunchNetworkResolver {
|
||||
pub nameservers: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct LaunchNetwork {
|
||||
pub link: String,
|
||||
pub ipv4: LaunchNetworkIpv4,
|
||||
@ -27,8 +33,14 @@ pub struct LaunchNetwork {
|
||||
pub resolver: LaunchNetworkResolver,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct LaunchRoot {
|
||||
pub format: LaunchPackedFormat,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct LaunchInfo {
|
||||
pub root: LaunchRoot,
|
||||
pub hostname: Option<String>,
|
||||
pub network: Option<LaunchNetwork>,
|
||||
pub env: HashMap<String, String>,
|
||||
|
@ -48,7 +48,7 @@ async fn main() -> Result<()> {
|
||||
println!(
|
||||
"generated squashfs of {} to {}",
|
||||
image,
|
||||
info.image_squashfs.to_string_lossy()
|
||||
info.image.to_string_lossy()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -28,10 +28,10 @@ impl ImageCache {
|
||||
config_path.push(format!("{}.config.json", digest));
|
||||
Ok(
|
||||
if fs_path.exists() && manifest_path.exists() && config_path.exists() {
|
||||
let squashfs_metadata = fs::metadata(&fs_path).await?;
|
||||
let image_metadata = fs::metadata(&fs_path).await?;
|
||||
let manifest_metadata = fs::metadata(&manifest_path).await?;
|
||||
let config_metadata = fs::metadata(&config_path).await?;
|
||||
if squashfs_metadata.is_file()
|
||||
if image_metadata.is_file()
|
||||
&& manifest_metadata.is_file()
|
||||
&& config_metadata.is_file()
|
||||
{
|
||||
@ -64,7 +64,7 @@ impl ImageCache {
|
||||
fs_path.push(format!("{}.{}", digest, format.extension()));
|
||||
manifest_path.push(format!("{}.manifest.json", digest));
|
||||
config_path.push(format!("{}.config.json", digest));
|
||||
fs::copy(&info.image_squashfs, &fs_path).await?;
|
||||
fs::copy(&info.image, &fs_path).await?;
|
||||
let manifest_text = serde_json::to_string_pretty(&info.manifest)?;
|
||||
fs::write(&manifest_path, manifest_text).await?;
|
||||
let config_text = serde_json::to_string_pretty(&info.config)?;
|
||||
|
@ -20,19 +20,19 @@ use uuid::Uuid;
|
||||
pub const IMAGE_PACKER_VERSION: u64 = 2;
|
||||
|
||||
pub struct ImageInfo {
|
||||
pub image_squashfs: PathBuf,
|
||||
pub image: PathBuf,
|
||||
pub manifest: ImageManifest,
|
||||
pub config: ImageConfiguration,
|
||||
}
|
||||
|
||||
impl ImageInfo {
|
||||
pub fn new(
|
||||
squashfs: PathBuf,
|
||||
image: PathBuf,
|
||||
manifest: ImageManifest,
|
||||
config: ImageConfiguration,
|
||||
) -> Result<ImageInfo> {
|
||||
Ok(ImageInfo {
|
||||
image_squashfs: squashfs,
|
||||
image,
|
||||
manifest,
|
||||
config,
|
||||
})
|
||||
@ -76,8 +76,8 @@ impl OciImageCompiler<'_> {
|
||||
layer_dir.push("layer");
|
||||
fs::create_dir_all(&layer_dir).await?;
|
||||
|
||||
let mut squash_file = tmp_dir.clone();
|
||||
squash_file.push("image.squashfs");
|
||||
let mut packed_file = tmp_dir.clone();
|
||||
packed_file.push("image.packed");
|
||||
|
||||
let _guard = scopeguard::guard(tmp_dir.to_path_buf(), |delete| {
|
||||
tokio::task::spawn(async move {
|
||||
@ -85,7 +85,7 @@ impl OciImageCompiler<'_> {
|
||||
});
|
||||
});
|
||||
let info = self
|
||||
.download_and_compile(id, image, &layer_dir, &image_dir, &squash_file, format)
|
||||
.download_and_compile(id, image, &layer_dir, &image_dir, &packed_file, format)
|
||||
.await?;
|
||||
Ok(info)
|
||||
}
|
||||
@ -96,7 +96,7 @@ impl OciImageCompiler<'_> {
|
||||
image: &ImageName,
|
||||
layer_dir: &Path,
|
||||
image_dir: &Path,
|
||||
squash_file: &Path,
|
||||
packed_file: &Path,
|
||||
format: OciPackerFormat,
|
||||
) -> Result<ImageInfo> {
|
||||
let mut progress = OciProgress {
|
||||
@ -191,23 +191,24 @@ impl OciImageCompiler<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
let image_dir_squash = image_dir.to_path_buf();
|
||||
let squash_file_squash = squash_file.to_path_buf();
|
||||
let progress_squash = progress.clone();
|
||||
let image_dir_pack = image_dir.to_path_buf();
|
||||
let packed_file_pack = packed_file.to_path_buf();
|
||||
let progress_pack = progress.clone();
|
||||
let progress_context = self.progress.clone();
|
||||
let format_pack = format;
|
||||
progress = tokio::task::spawn_blocking(move || {
|
||||
OciImageCompiler::pack(
|
||||
OciPackerFormat::Squashfs,
|
||||
&image_dir_squash,
|
||||
&squash_file_squash,
|
||||
progress_squash,
|
||||
format_pack,
|
||||
&image_dir_pack,
|
||||
&packed_file_pack,
|
||||
progress_pack,
|
||||
progress_context,
|
||||
)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let info = ImageInfo::new(
|
||||
squash_file.to_path_buf(),
|
||||
packed_file.to_path_buf(),
|
||||
local.image.manifest,
|
||||
local.config,
|
||||
)?;
|
||||
@ -371,14 +372,13 @@ impl OciImageCompiler<'_> {
|
||||
fn pack(
|
||||
format: OciPackerFormat,
|
||||
image_dir: &Path,
|
||||
squash_file: &Path,
|
||||
packed_file: &Path,
|
||||
mut progress: OciProgress,
|
||||
progress_context: OciProgressContext,
|
||||
) -> Result<OciProgress> {
|
||||
progress_context.update(&progress);
|
||||
let backend = format.detect_best_backend();
|
||||
let backend = backend.create();
|
||||
backend.pack(&mut progress, &progress_context, image_dir, squash_file)?;
|
||||
backend.pack(&mut progress, &progress_context, image_dir, packed_file)?;
|
||||
std::fs::remove_dir_all(image_dir)?;
|
||||
progress.phase = OciProgressPhase::Packing;
|
||||
progress.value = progress.total;
|
||||
|
@ -8,6 +8,7 @@ use anyhow::{anyhow, Result};
|
||||
use ipnetwork::{IpNetwork, Ipv4Network};
|
||||
use krata::launchcfg::{
|
||||
LaunchInfo, LaunchNetwork, LaunchNetworkIpv4, LaunchNetworkIpv6, LaunchNetworkResolver,
|
||||
LaunchPackedFormat, LaunchRoot,
|
||||
};
|
||||
use krataoci::packer::OciPackerFormat;
|
||||
use krataoci::progress::OciProgressContext;
|
||||
@ -27,6 +28,7 @@ use krataoci::{
|
||||
use super::{GuestInfo, GuestState};
|
||||
|
||||
pub struct GuestLaunchRequest<'a> {
|
||||
pub format: LaunchPackedFormat,
|
||||
pub uuid: Option<Uuid>,
|
||||
pub name: Option<&'a str>,
|
||||
pub image: &'a str,
|
||||
@ -59,7 +61,10 @@ impl GuestLauncher {
|
||||
request.image,
|
||||
&context.image_cache,
|
||||
&context.oci_progress_context,
|
||||
OciPackerFormat::Squashfs,
|
||||
match request.format {
|
||||
LaunchPackedFormat::Squashfs => OciPackerFormat::Squashfs,
|
||||
LaunchPackedFormat::Erofs => OciPackerFormat::Erofs,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -79,6 +84,9 @@ impl GuestLauncher {
|
||||
let ipv6_network_mask: u32 = 10;
|
||||
|
||||
let launch_config = LaunchInfo {
|
||||
root: LaunchRoot {
|
||||
format: request.format.clone(),
|
||||
},
|
||||
hostname: Some(
|
||||
request
|
||||
.name
|
||||
@ -112,9 +120,9 @@ impl GuestLauncher {
|
||||
cfgblk.build(&launch_config)?;
|
||||
|
||||
let image_squashfs_path = image_info
|
||||
.image_squashfs
|
||||
.image
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("failed to convert image squashfs path to string"))?;
|
||||
.ok_or_else(|| anyhow!("failed to convert image path to string"))?;
|
||||
|
||||
let cfgblk_dir_path = cfgblk
|
||||
.dir
|
||||
|
Reference in New Issue
Block a user