use derivative::Derivative;
use std::{borrow::Cow, path::Path};
use super::Builder;
#[derive(Debug)]
pub struct Jailer<'j> {
gid: u32,
uid: u32,
numa_node: Option<i32>,
exec_file: Cow<'j, Path>,
jailer_binary: Cow<'j, Path>,
chroot_base_dir: Cow<'j, Path>,
workspace_dir: Cow<'j, Path>,
pub(crate) mode: JailerMode<'j>,
}
impl<'j> Jailer<'j> {
pub fn gid(&self) -> u32 {
self.gid
}
pub fn uid(&self) -> u32 {
self.uid
}
pub fn numa_node(&self) -> Option<i32> {
self.numa_node
}
pub fn exec_file(&self) -> &Path {
&self.exec_file
}
pub fn jailer_binary(&self) -> &Path {
&self.jailer_binary
}
pub fn chroot_base_dir(&self) -> &Path {
&self.chroot_base_dir
}
pub fn mode(&self) -> &JailerMode {
&self.mode
}
pub(crate) fn workspace_dir(&self) -> &Path {
&self.workspace_dir
}
}
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub enum JailerMode<'j> {
#[derivative(Default)]
Attached(Stdio),
Daemon,
Tmux(Option<Cow<'j, str>>),
}
#[derive(Derivative)]
#[derivative(Debug, Default)]
pub struct Stdio {
pub stdout: Option<std::process::Stdio>,
pub stderr: Option<std::process::Stdio>,
pub stdin: Option<std::process::Stdio>,
}
#[derive(Debug)]
pub struct JailerBuilder<'j> {
jailer: Jailer<'j>,
config_builder: Builder<'j>,
}
impl<'j> JailerBuilder<'j> {
pub(crate) fn new(config_builder: Builder<'j>) -> Self {
Self {
config_builder,
jailer: Jailer {
gid: users::get_effective_gid(),
uid: users::get_effective_uid(),
numa_node: None,
exec_file: Path::new("/usr/bin/firecracker").into(),
jailer_binary: Path::new("jailer").into(),
chroot_base_dir: Path::new("/srv/jailer").into(),
workspace_dir: Path::new("/srv/jailer/firecracker/root").into(),
mode: JailerMode::default(),
},
}
}
pub fn gid(mut self, gid: u32) -> Self {
self.jailer.gid = gid;
self
}
pub fn uid(mut self, uid: u32) -> Self {
self.jailer.uid = uid;
self
}
pub fn numa_node(mut self, numa_node: i32) -> Self {
self.jailer.numa_node = Some(numa_node);
self
}
pub fn exec_file<P>(mut self, exec_file: P) -> Self
where
P: Into<Cow<'j, Path>>,
{
self.jailer.exec_file = exec_file.into();
self
}
pub fn jailer_binary<P>(mut self, jailer_binary: P) -> Self
where
P: Into<Cow<'j, Path>>,
{
self.jailer.jailer_binary = jailer_binary.into();
self
}
pub fn chroot_base_dir<P>(mut self, chroot_base_dir: P) -> Self
where
P: Into<Cow<'j, Path>>,
{
self.jailer.chroot_base_dir = chroot_base_dir.into();
self
}
pub fn mode(mut self, mode: JailerMode<'j>) -> Self {
self.jailer.mode = mode;
self
}
pub fn build(mut self) -> Builder<'j> {
let exec_file_base = self
.jailer
.exec_file()
.file_name()
.expect("invalid jailer exec file path");
let id_str = self.config_builder.0.vm_id().to_string();
self.jailer.workspace_dir = self
.jailer
.chroot_base_dir()
.join(exec_file_base)
.join(&id_str)
.join("root")
.into();
self.config_builder.0.jailer_cfg = Some(self.jailer);
self.config_builder
}
}