mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 12:50:54 +00:00
hypha: init will now watch process in background
This commit is contained in:
parent
b6af5f54bd
commit
86c512474a
@ -1,10 +1,20 @@
|
||||
use std::env;
|
||||
use anyhow::Result;
|
||||
use anyhow::{anyhow, Result};
|
||||
use hypha::container::init::ContainerInit;
|
||||
use std::env;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
env_logger::init();
|
||||
if env::var("HYPHA_UNSAFE_ALWAYS_ALLOW_INIT").unwrap_or("0".to_string()) != "1" {
|
||||
let pid = std::process::id();
|
||||
if pid > 3 {
|
||||
return Err(anyhow!(
|
||||
"not running because the pid of {} indicates this is probably not \
|
||||
the right context for the init daemon. \
|
||||
run with HYPHA_UNSAFE_ALWAYS_ALLOW_INIT=1 to bypass this check",
|
||||
pid
|
||||
));
|
||||
}
|
||||
}
|
||||
let mut container = ContainerInit::new();
|
||||
container.init()?;
|
||||
Ok(())
|
||||
|
@ -1,4 +1,3 @@
|
||||
use std::env;
|
||||
use anyhow::{anyhow, Result};
|
||||
use clap::{Parser, Subcommand};
|
||||
use hypha::ctl::Controller;
|
||||
@ -47,7 +46,6 @@ enum Commands {
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
env_logger::init();
|
||||
|
||||
let args = ControllerArgs::parse();
|
||||
|
@ -1,16 +1,19 @@
|
||||
use crate::shared::LaunchInfo;
|
||||
use anyhow::{anyhow, Result};
|
||||
use log::trace;
|
||||
use nix::libc::dup2;
|
||||
use nix::unistd::execve;
|
||||
use nix::libc::{c_int, dup2, wait};
|
||||
use nix::unistd::{execve, fork, ForkResult, Pid};
|
||||
use oci_spec::image::{Config, ImageConfiguration};
|
||||
use std::ffi::CString;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fs;
|
||||
use std::fs::{File, OpenOptions, Permissions};
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::os::linux::fs::MetadataExt;
|
||||
use std::os::unix::fs::{chroot, PermissionsExt};
|
||||
use std::path::Path;
|
||||
use std::ptr::addr_of_mut;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use sys_mount::{FilesystemType, Mount, MountFlags};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
@ -65,9 +68,8 @@ impl ContainerInit {
|
||||
self.mount_new_root()?;
|
||||
self.nuke_initrd()?;
|
||||
self.bind_new_root()?;
|
||||
self.map_console(console)?;
|
||||
if let Some(cfg) = config.config() {
|
||||
self.run(cfg, &launch)?;
|
||||
self.run(console, cfg, &launch)?;
|
||||
} else {
|
||||
return Err(anyhow!(
|
||||
"unable to determine what to execute, image config doesn't tell us"
|
||||
@ -254,7 +256,7 @@ impl ContainerInit {
|
||||
}
|
||||
|
||||
fn map_console(&mut self, console: File) -> Result<()> {
|
||||
trace!("map console");
|
||||
trace!("mapping console");
|
||||
unsafe {
|
||||
dup2(console.as_raw_fd(), 0);
|
||||
dup2(console.as_raw_fd(), 1);
|
||||
@ -264,7 +266,7 @@ impl ContainerInit {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run(&mut self, config: &Config, launch: &LaunchInfo) -> Result<()> {
|
||||
fn run(&mut self, console: File, config: &Config, launch: &LaunchInfo) -> Result<()> {
|
||||
let mut cmd = match config.cmd() {
|
||||
None => vec![],
|
||||
Some(value) => value.clone(),
|
||||
@ -278,7 +280,6 @@ impl ContainerInit {
|
||||
cmd.push("/bin/sh".to_string());
|
||||
}
|
||||
|
||||
trace!("running container command: {}", cmd.join(" "));
|
||||
let path = cmd.remove(0);
|
||||
let mut env = match config.env() {
|
||||
None => vec![],
|
||||
@ -288,6 +289,9 @@ impl ContainerInit {
|
||||
if let Some(extra_env) = &launch.env {
|
||||
env.extend_from_slice(extra_env.as_slice());
|
||||
}
|
||||
|
||||
trace!("running container command: {}", cmd.join(" "));
|
||||
|
||||
let path_cstr = CString::new(path)?;
|
||||
let cmd_cstr = ContainerInit::strings_as_cstrings(cmd)?;
|
||||
let env_cstr = ContainerInit::strings_as_cstrings(env)?;
|
||||
@ -302,7 +306,7 @@ impl ContainerInit {
|
||||
}
|
||||
|
||||
std::env::set_current_dir(&working_dir)?;
|
||||
execve(&path_cstr, &cmd_cstr, &env_cstr)?;
|
||||
self.fork_and_exec(console, &path_cstr, cmd_cstr, env_cstr)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -313,4 +317,39 @@ impl ContainerInit {
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
fn fork_and_exec(
|
||||
&mut self,
|
||||
console: File,
|
||||
path: &CStr,
|
||||
cmd: Vec<CString>,
|
||||
env: Vec<CString>,
|
||||
) -> Result<()> {
|
||||
match unsafe { fork()? } {
|
||||
ForkResult::Parent { child } => self.background(child),
|
||||
ForkResult::Child => {
|
||||
self.map_console(console)?;
|
||||
execve(path, &cmd, &env)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn background(&mut self, executed: Pid) -> Result<()> {
|
||||
loop {
|
||||
let mut status: c_int = 0;
|
||||
let pid = unsafe { wait(addr_of_mut!(status)) };
|
||||
if executed.as_raw() == pid {
|
||||
return self.death(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn death(&mut self, code: c_int) -> Result<()> {
|
||||
println!("[hypha] container process exited: status = {}", code);
|
||||
println!("[hypha] looping forever");
|
||||
loop {
|
||||
sleep(Duration::from_secs(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ HYPHA_DIR="${PWD}"
|
||||
cargo build --release --target x86_64-unknown-linux-gnu
|
||||
INITRD_DIR="$(mktemp -d /tmp/hypha-initrd.XXXXXXXXXXXXX)"
|
||||
cp target/x86_64-unknown-linux-gnu/release/hyphactr "${INITRD_DIR}/init"
|
||||
chmod +x "${INITRD_DIR}/init"
|
||||
cd "${INITRD_DIR}"
|
||||
mkdir -p "${HYPHA_DIR}/target/initrd"
|
||||
find . | cpio -o -H newc --quiet > "${HYPHA_DIR}/target/initrd/initrd"
|
||||
find . | cpio -R 0:0 --reproducible -o -H newc --quiet > "${HYPHA_DIR}/target/initrd/initrd"
|
||||
rm -rf "${INITRD_DIR}"
|
||||
|
@ -273,8 +273,8 @@ impl BootImageLoader for ElfImageLoader {
|
||||
copy_slice.len()
|
||||
);
|
||||
copy(segment_dst, copy_slice);
|
||||
if memsz - filesz > 0 {
|
||||
let remaining = &mut segment_dst[filesz as usize..(memsz - filesz) as usize];
|
||||
if (memsz - filesz) > 0 {
|
||||
let remaining = &mut segment_dst[filesz as usize..memsz as usize];
|
||||
debug!(
|
||||
"ElfImageLoader load fill_zero hdr={:?} dst={:#x} len={}",
|
||||
header.p_offset,
|
||||
|
@ -55,7 +55,7 @@ pub trait XsdInterface {
|
||||
Ok(match self.read_string(path) {
|
||||
Ok(value) => Some(value),
|
||||
Err(error) => {
|
||||
if error.to_string() == "ENOENT" {
|
||||
if error.is_noent_response() {
|
||||
None
|
||||
} else {
|
||||
return Err(error);
|
||||
@ -68,7 +68,7 @@ pub trait XsdInterface {
|
||||
Ok(match self.list(path) {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
if error.to_string() == "ENOENT" {
|
||||
if error.is_noent_response() {
|
||||
Vec::new()
|
||||
} else {
|
||||
return Err(error);
|
||||
@ -115,7 +115,7 @@ impl XsdClient {
|
||||
trace!("rm tx={tx} path={path}");
|
||||
let result = self.socket.send_single(tx, XSD_RM, path);
|
||||
if let Err(error) = result {
|
||||
if error.to_string() == "ENOENT" {
|
||||
if error.is_noent_response() {
|
||||
return Ok(true);
|
||||
}
|
||||
return Err(error);
|
||||
|
@ -28,4 +28,13 @@ pub enum Error {
|
||||
InvalidPermissions,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn is_noent_response(&self) -> bool {
|
||||
match self {
|
||||
Error::ResponseError(message) => message == "ENOENT",
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
Loading…
Reference in New Issue
Block a user