Skip to content

Commit

Permalink
feat: addons mounting and kernel modules support
Browse files Browse the repository at this point in the history
  • Loading branch information
azenla committed Apr 25, 2024
1 parent ef57de8 commit 5dea89f
Show file tree
Hide file tree
Showing 14 changed files with 767 additions and 1,885 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ oci-spec = "0.6.4"
once_cell = "1.19.0"
path-absolutize = "3.1.1"
path-clean = "1.0.1"
platform-info = "2.0.3"
prost = "0.12.4"
prost-build = "0.12.4"
prost-reflect-build = "0.13.0"
Expand Down
8 changes: 5 additions & 3 deletions crates/daemon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ impl Daemon {
generated
};

let initrd_path = detect_guest_file(&store, "initrd")?;
let kernel_path = detect_guest_file(&store, "kernel")?;
let initrd_path = detect_guest_path(&store, "initrd")?;
let kernel_path = detect_guest_path(&store, "kernel")?;
let addons_path = detect_guest_path(&store, "addons.squashfs")?;

let packer = OciPackerService::new(None, &image_cache_dir, OciPlatform::current()).await?;
let runtime = Runtime::new().await?;
Expand All @@ -116,6 +117,7 @@ impl Daemon {
guest_reconciler_notify.clone(),
kernel_path,
initrd_path,
addons_path,
)?;

let guest_reconciler_task = guest_reconciler.launch(guest_reconciler_receiver).await?;
Expand Down Expand Up @@ -204,7 +206,7 @@ impl Drop for Daemon {
}
}

fn detect_guest_file(store: &str, name: &str) -> Result<PathBuf> {
fn detect_guest_path(store: &str, name: &str) -> Result<PathBuf> {
let mut path = PathBuf::from(format!("{}/guest/{}", store, name));
if path.is_file() {
return Ok(path);
Expand Down
4 changes: 4 additions & 0 deletions crates/daemon/src/reconcile/guest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub struct GuestReconciler {
packer: OciPackerService,
kernel_path: PathBuf,
initrd_path: PathBuf,
addons_path: PathBuf,
tasks: Arc<Mutex<HashMap<Uuid, GuestReconcilerEntry>>>,
guest_reconciler_notify: Sender<Uuid>,
reconcile_lock: Arc<RwLock<()>>,
Expand All @@ -81,6 +82,7 @@ impl GuestReconciler {
guest_reconciler_notify: Sender<Uuid>,
kernel_path: PathBuf,
initrd_path: PathBuf,
modules_path: PathBuf,
) -> Result<Self> {
Ok(Self {
devices,
Expand All @@ -91,6 +93,7 @@ impl GuestReconciler {
packer,
kernel_path,
initrd_path,
addons_path: modules_path,
tasks: Arc::new(Mutex::new(HashMap::new())),
guest_reconciler_notify,
reconcile_lock: Arc::new(RwLock::with_max_readers((), PARALLEL_LIMIT)),
Expand Down Expand Up @@ -278,6 +281,7 @@ impl GuestReconciler {
devices: &self.devices,
kernel_path: &self.kernel_path,
initrd_path: &self.initrd_path,
addons_path: &self.addons_path,
packer: &self.packer,
glt: &self.glt,
runtime: &self.runtime,
Expand Down
2 changes: 2 additions & 0 deletions crates/daemon/src/reconcile/guest/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub struct GuestStarter<'a> {
pub devices: &'a DaemonDeviceManager,
pub kernel_path: &'a Path,
pub initrd_path: &'a Path,
pub addons_path: &'a Path,
pub packer: &'a OciPackerService,
pub glt: &'a GuestLookupTable,
pub runtime: &'a Runtime,
Expand Down Expand Up @@ -206,6 +207,7 @@ impl GuestStarter<'_> {
.collect::<HashMap<_, _>>(),
run: empty_vec_optional(task.command.clone()),
debug: false,
addons_image: Some(self.addons_path.to_path_buf()),
})
.await?;
self.glt.associate(uuid, info.domid).await;
Expand Down
1 change: 1 addition & 0 deletions crates/guest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ log = { workspace = true }
nix = { workspace = true, features = ["ioctl", "process", "fs"] }
oci-spec = { workspace = true }
path-absolutize = { workspace = true }
platform-info = { workspace = true }
rtnetlink = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
Expand Down
65 changes: 59 additions & 6 deletions crates/guest/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use nix::ioctl_write_int_bad;
use nix::unistd::{dup2, execve, fork, ForkResult, Pid};
use oci_spec::image::{Config, ImageConfiguration};
use path_absolutize::Absolutize;
use platform_info::{PlatformInfo, PlatformInfoAPI, UNameAPI};
use std::collections::HashMap;
use std::ffi::CString;
use std::fs::{File, OpenOptions, Permissions};
Expand Down Expand Up @@ -50,6 +51,10 @@ const NEW_ROOT_DEV_PATH: &str = "/newroot/dev";
const IMAGE_CONFIG_JSON_PATH: &str = "/config/image/config.json";
const LAUNCH_CONFIG_JSON_PATH: &str = "/config/launch.json";

const ADDONS_DEVICE_PATH: &str = "/dev/xvdc";
const ADDONS_MOUNT_PATH: &str = "/addons";
const ADDONS_MODULES_PATH: &str = "/addons/modules";

ioctl_write_int_bad!(set_controlling_terminal, TIOCSCTTY);

pub struct GuestInit {}
Expand Down Expand Up @@ -88,7 +93,10 @@ impl GuestInit {

self.mount_root_image(launch.root.format.clone()).await?;

self.mount_addons().await?;

self.mount_new_root().await?;
self.mount_kernel_modules().await?;
self.bind_new_root().await?;

if let Some(hostname) = launch.hostname.clone() {
Expand Down Expand Up @@ -137,16 +145,60 @@ impl GuestInit {
self.create_dir("/root", Some(0o0700)).await?;
self.create_dir("/tmp", None).await?;
self.create_dir("/run", Some(0o0755)).await?;
self.mount_kernel_fs("devtmpfs", "/dev", "mode=0755", None)
self.mount_kernel_fs("devtmpfs", "/dev", "mode=0755", None, None)
.await?;
self.mount_kernel_fs("proc", "/proc", "", None, None)
.await?;
self.mount_kernel_fs("sysfs", "/sys", "", None, None)
.await?;
self.create_dir("/dev/pts", Some(0o0755)).await?;
self.mount_kernel_fs("devpts", "/dev/pts", "", None, Some("/dev/ptmx"))
.await?;
self.mount_kernel_fs("proc", "/proc", "", None).await?;
self.mount_kernel_fs("sysfs", "/sys", "", None).await?;
fs::symlink("/proc/self/fd", "/dev/fd").await?;
fs::symlink("/proc/self/fd/0", "/dev/stdin").await?;
fs::symlink("/proc/self/fd/1", "/dev/stdout").await?;
fs::symlink("/proc/self/fd/2", "/dev/stderr").await?;
self.mount_kernel_fs("cgroup2", "/sys/fs/cgroup", "", Some(MountFlags::RELATIME))
.await?;
self.mount_kernel_fs(
"cgroup2",
"/sys/fs/cgroup",
"",
Some(MountFlags::RELATIME),
None,
)
.await?;
Ok(())
}

async fn mount_addons(&mut self) -> Result<()> {
if !fs::try_exists(ADDONS_DEVICE_PATH).await? {
return Ok(());
}

self.mount_image(
&PathBuf::from(ADDONS_DEVICE_PATH),
&PathBuf::from(ADDONS_MOUNT_PATH),
LaunchPackedFormat::Squashfs,
)
.await?;
Ok(())
}

async fn mount_kernel_modules(&mut self) -> Result<()> {
if !fs::try_exists(ADDONS_MODULES_PATH).await? {
return Ok(());
}

let Some(platform_info) = PlatformInfo::new().ok() else {
return Ok(());
};

let kernel_release = platform_info.release().to_string_lossy().to_string();
let modules_path = format!("/newroot/lib/modules/{}", kernel_release);
fs::create_dir_all(&modules_path).await?;
Mount::builder()
.fstype(FilesystemType::Manual("none"))
.flags(MountFlags::BIND | MountFlags::RDONLY)
.mount(ADDONS_MODULES_PATH, modules_path)?;
Ok(())
}
Expand All @@ -170,13 +222,14 @@ impl GuestInit {
path: &str,
data: &str,
flags: Option<MountFlags>,
source: Option<&str>,
) -> Result<()> {
trace!("mounting kernel fs {} to {}", fstype, path);
Mount::builder()
.fstype(FilesystemType::Manual(fstype))
.flags(MountFlags::NOEXEC | MountFlags::NOSUID | flags.unwrap_or(MountFlags::empty()))
.data(data)
.mount(fstype, path)?;
.mount(source.unwrap_or(fstype), path)?;
Ok(())
}

Expand Down
1 change: 1 addition & 0 deletions crates/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ krata-xenclient = { path = "../xen/xenclient", version = "^0.0.10" }
krata-xenevtchn = { path = "../xen/xenevtchn", version = "^0.0.10" }
krata-xengnt = { path = "../xen/xengnt", version = "^0.0.10" }
krata-xenstore = { path = "../xen/xenstore", version = "^0.0.10" }
walkdir = { workspace = true }

[lib]
name = "kratart"
Expand Down
12 changes: 7 additions & 5 deletions crates/runtime/src/cfgblk.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use anyhow::Result;
use backhand::{FilesystemWriter, NodeHeader};
use backhand::compression::Compressor;
use backhand::{FilesystemCompressor, FilesystemWriter, NodeHeader};
use krata::launchcfg::LaunchInfo;
use krataoci::packer::OciPackedImage;
use log::trace;
Expand All @@ -8,14 +9,14 @@ use std::fs::File;
use std::path::PathBuf;
use uuid::Uuid;

pub struct ConfigBlock<'a> {
pub image: &'a OciPackedImage,
pub struct ConfigBlock {
pub image: OciPackedImage,
pub file: PathBuf,
pub dir: PathBuf,
}

impl ConfigBlock<'_> {
pub fn new<'a>(uuid: &Uuid, image: &'a OciPackedImage) -> Result<ConfigBlock<'a>> {
impl ConfigBlock {
pub fn new(uuid: &Uuid, image: OciPackedImage) -> Result<ConfigBlock> {
let mut dir = std::env::temp_dir().clone();
dir.push(format!("krata-cfg-{}", uuid));
fs::create_dir_all(&dir)?;
Expand All @@ -29,6 +30,7 @@ impl ConfigBlock<'_> {
let config = self.image.config.raw();
let launch = serde_json::to_string(launch_config)?;
let mut writer = FilesystemWriter::default();
writer.set_compressor(FilesystemCompressor::new(Compressor::Gzip, None)?);
writer.push_dir(
"/image",
NodeHeader {
Expand Down
Loading

0 comments on commit 5dea89f

Please sign in to comment.