mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 21:00:55 +00:00
hypha: implement the ability to override the command line to execute
This commit is contained in:
parent
e15ac71405
commit
3085a3738f
@ -30,6 +30,8 @@ enum Commands {
|
|||||||
mem: u64,
|
mem: u64,
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
config_bundle: Option<String>,
|
config_bundle: Option<String>,
|
||||||
|
#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
|
||||||
|
run: Vec<String>,
|
||||||
},
|
},
|
||||||
Destroy {
|
Destroy {
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
@ -67,6 +69,7 @@ fn main() -> Result<()> {
|
|||||||
cpus,
|
cpus,
|
||||||
mem,
|
mem,
|
||||||
config_bundle,
|
config_bundle,
|
||||||
|
run,
|
||||||
} => {
|
} => {
|
||||||
let kernel = map_kernel_path(&store_path, kernel);
|
let kernel = map_kernel_path(&store_path, kernel);
|
||||||
let initrd = map_initrd_path(&store_path, initrd);
|
let initrd = map_initrd_path(&store_path, initrd);
|
||||||
@ -77,6 +80,7 @@ fn main() -> Result<()> {
|
|||||||
&image,
|
&image,
|
||||||
cpus,
|
cpus,
|
||||||
mem,
|
mem,
|
||||||
|
if run.is_empty() { None } else { Some(run) },
|
||||||
)?;
|
)?;
|
||||||
println!("launched domain: {}", domid);
|
println!("launched domain: {}", domid);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::hypha_err;
|
use crate::hypha_err;
|
||||||
|
use crate::shared::LaunchInfo;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nix::libc::dup2;
|
use nix::libc::dup2;
|
||||||
use nix::unistd::execve;
|
use nix::unistd::execve;
|
||||||
@ -27,6 +28,7 @@ const OVERLAY_UPPER_PATH: &str = "/overlay/upper";
|
|||||||
|
|
||||||
const NEW_ROOT_PATH: &str = "/newroot";
|
const NEW_ROOT_PATH: &str = "/newroot";
|
||||||
const IMAGE_CONFIG_JSON_PATH: &str = "/config/image/config.json";
|
const IMAGE_CONFIG_JSON_PATH: &str = "/config/image/config.json";
|
||||||
|
const LAUNCH_CONFIG_JSON_PATH: &str = "/config/launch.json";
|
||||||
|
|
||||||
pub struct ContainerInit {}
|
pub struct ContainerInit {}
|
||||||
|
|
||||||
@ -49,12 +51,13 @@ impl ContainerInit {
|
|||||||
|
|
||||||
self.mount_squashfs_images()?;
|
self.mount_squashfs_images()?;
|
||||||
let config = self.parse_image_config()?;
|
let config = self.parse_image_config()?;
|
||||||
|
let launch = self.parse_launch_config()?;
|
||||||
self.mount_new_root()?;
|
self.mount_new_root()?;
|
||||||
self.nuke_initrd()?;
|
self.nuke_initrd()?;
|
||||||
self.bind_new_root()?;
|
self.bind_new_root()?;
|
||||||
self.map_console(console)?;
|
self.map_console(console)?;
|
||||||
if let Some(cfg) = config.config() {
|
if let Some(cfg) = config.config() {
|
||||||
self.run(cfg)?;
|
self.run(cfg, &launch)?;
|
||||||
} else {
|
} else {
|
||||||
return hypha_err!("unable to determine what to execute, image config doesn't tell us");
|
return hypha_err!("unable to determine what to execute, image config doesn't tell us");
|
||||||
}
|
}
|
||||||
@ -131,6 +134,12 @@ impl ContainerInit {
|
|||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_launch_config(&mut self) -> Result<LaunchInfo> {
|
||||||
|
trace!("parsing launch config");
|
||||||
|
let launch_config = Path::new(LAUNCH_CONFIG_JSON_PATH);
|
||||||
|
Ok(serde_json::from_str(&fs::read_to_string(launch_config)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
fn nuke_initrd(&mut self) -> Result<()> {
|
fn nuke_initrd(&mut self) -> Result<()> {
|
||||||
trace!("nuking initrd");
|
trace!("nuking initrd");
|
||||||
let initrd_dev = fs::metadata("/")?.st_dev();
|
let initrd_dev = fs::metadata("/")?.st_dev();
|
||||||
@ -189,14 +198,20 @@ impl ContainerInit {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&mut self, config: &Config) -> Result<()> {
|
fn run(&mut self, config: &Config, launch: &LaunchInfo) -> Result<()> {
|
||||||
let mut cmd = match config.cmd() {
|
let mut cmd = match config.cmd() {
|
||||||
None => vec![],
|
None => vec![],
|
||||||
Some(value) => value.clone(),
|
Some(value) => value.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if launch.run.is_some() {
|
||||||
|
cmd = launch.run.as_ref().unwrap().clone();
|
||||||
|
}
|
||||||
|
|
||||||
if cmd.is_empty() {
|
if cmd.is_empty() {
|
||||||
cmd.push("/bin/sh".to_string());
|
cmd.push("/bin/sh".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("running container command: {}", cmd.join(" "));
|
trace!("running container command: {}", cmd.join(" "));
|
||||||
let path = cmd.remove(0);
|
let path = cmd.remove(0);
|
||||||
let mut env = match config.env() {
|
let mut env = match config.env() {
|
||||||
@ -205,10 +220,8 @@ impl ContainerInit {
|
|||||||
};
|
};
|
||||||
env.push("HYPHA_CONTAINER=1".to_string());
|
env.push("HYPHA_CONTAINER=1".to_string());
|
||||||
let path_cstr = CString::new(path)?;
|
let path_cstr = CString::new(path)?;
|
||||||
let mut cmd_cstr = ContainerInit::strings_as_cstrings(cmd)?;
|
let cmd_cstr = ContainerInit::strings_as_cstrings(cmd)?;
|
||||||
cmd_cstr.push(CString::new("")?);
|
let env_cstr = ContainerInit::strings_as_cstrings(env)?;
|
||||||
let mut env_cstr = ContainerInit::strings_as_cstrings(env)?;
|
|
||||||
env_cstr.push(CString::new("")?);
|
|
||||||
let mut working_dir = config
|
let mut working_dir = config
|
||||||
.working_dir()
|
.working_dir()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::image::ImageInfo;
|
use crate::image::ImageInfo;
|
||||||
|
use crate::shared::LaunchInfo;
|
||||||
use backhand::{FilesystemWriter, NodeHeader};
|
use backhand::{FilesystemWriter, NodeHeader};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@ -32,12 +33,13 @@ impl ConfigBlock<'_> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(&self) -> Result<()> {
|
pub fn build(&self, launch_config: &LaunchInfo) -> Result<()> {
|
||||||
let config_bundle_content = match self.config_bundle {
|
let config_bundle_content = match self.config_bundle {
|
||||||
None => None,
|
None => None,
|
||||||
Some(path) => Some(fs::read(path)?),
|
Some(path) => Some(fs::read(path)?),
|
||||||
};
|
};
|
||||||
let manifest = self.image_info.config.to_string()?;
|
let manifest = self.image_info.config.to_string()?;
|
||||||
|
let launch = serde_json::to_string(launch_config)?;
|
||||||
let mut writer = FilesystemWriter::default();
|
let mut writer = FilesystemWriter::default();
|
||||||
writer.push_dir(
|
writer.push_dir(
|
||||||
"/image",
|
"/image",
|
||||||
@ -58,6 +60,16 @@ impl ConfigBlock<'_> {
|
|||||||
mtime: 0,
|
mtime: 0,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
writer.push_file(
|
||||||
|
launch.as_bytes(),
|
||||||
|
"/launch.json",
|
||||||
|
NodeHeader {
|
||||||
|
permissions: 384,
|
||||||
|
uid: 0,
|
||||||
|
gid: 0,
|
||||||
|
mtime: 0,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
if let Some(config_bundle_content) = config_bundle_content.as_ref() {
|
if let Some(config_bundle_content) = config_bundle_content.as_ref() {
|
||||||
writer.push_file(
|
writer.push_file(
|
||||||
config_bundle_content.as_slice(),
|
config_bundle_content.as_slice(),
|
||||||
|
@ -6,6 +6,7 @@ use crate::error::{HyphaError, Result};
|
|||||||
use crate::image::cache::ImageCache;
|
use crate::image::cache::ImageCache;
|
||||||
use crate::image::name::ImageName;
|
use crate::image::name::ImageName;
|
||||||
use crate::image::{ImageCompiler, ImageInfo};
|
use crate::image::{ImageCompiler, ImageInfo};
|
||||||
|
use crate::shared::LaunchInfo;
|
||||||
use loopdev::LoopControl;
|
use loopdev::LoopControl;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -59,6 +60,7 @@ impl Controller {
|
|||||||
compiler.compile(&image)
|
compiler.compile(&image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn launch(
|
pub fn launch(
|
||||||
&mut self,
|
&mut self,
|
||||||
kernel_path: &str,
|
kernel_path: &str,
|
||||||
@ -67,12 +69,15 @@ impl Controller {
|
|||||||
image: &str,
|
image: &str,
|
||||||
vcpus: u32,
|
vcpus: u32,
|
||||||
mem: u64,
|
mem: u64,
|
||||||
|
run: Option<Vec<String>>,
|
||||||
) -> Result<u32> {
|
) -> Result<u32> {
|
||||||
let uuid = Uuid::new_v4();
|
let uuid = Uuid::new_v4();
|
||||||
let name = format!("hypha-{uuid}");
|
let name = format!("hypha-{uuid}");
|
||||||
let image_info = self.compile(image)?;
|
let image_info = self.compile(image)?;
|
||||||
|
let launch_config = LaunchInfo { run };
|
||||||
|
|
||||||
let cfgblk = ConfigBlock::new(&uuid, &image_info, config_bundle_path)?;
|
let cfgblk = ConfigBlock::new(&uuid, &image_info, config_bundle_path)?;
|
||||||
cfgblk.build()?;
|
cfgblk.build(&launch_config)?;
|
||||||
|
|
||||||
let image_squashfs_path = image_info
|
let image_squashfs_path = image_info
|
||||||
.image_squashfs
|
.image_squashfs
|
||||||
|
@ -3,3 +3,4 @@ pub mod container;
|
|||||||
pub mod ctl;
|
pub mod ctl;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod image;
|
pub mod image;
|
||||||
|
mod shared;
|
||||||
|
6
hypha/src/shared/mod.rs
Normal file
6
hypha/src/shared/mod.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct LaunchInfo {
|
||||||
|
pub run: Option<Vec<String>>,
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user