mirror of
				https://github.com/edera-dev/krata.git
				synced 2025-11-03 07:19:37 +00:00 
			
		
		
		
	hypha: init will now watch process in background
This commit is contained in:
		@ -1,10 +1,20 @@
 | 
				
			|||||||
use std::env;
 | 
					use anyhow::{anyhow, Result};
 | 
				
			||||||
use anyhow::Result;
 | 
					 | 
				
			||||||
use hypha::container::init::ContainerInit;
 | 
					use hypha::container::init::ContainerInit;
 | 
				
			||||||
 | 
					use std::env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() -> Result<()> {
 | 
					fn main() -> Result<()> {
 | 
				
			||||||
    env::set_var("RUST_BACKTRACE", "1");
 | 
					    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();
 | 
					    let mut container = ContainerInit::new();
 | 
				
			||||||
    container.init()?;
 | 
					    container.init()?;
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
use std::env;
 | 
					 | 
				
			||||||
use anyhow::{anyhow, Result};
 | 
					use anyhow::{anyhow, Result};
 | 
				
			||||||
use clap::{Parser, Subcommand};
 | 
					use clap::{Parser, Subcommand};
 | 
				
			||||||
use hypha::ctl::Controller;
 | 
					use hypha::ctl::Controller;
 | 
				
			||||||
@ -47,7 +46,6 @@ enum Commands {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() -> Result<()> {
 | 
					fn main() -> Result<()> {
 | 
				
			||||||
    env::set_var("RUST_BACKTRACE", "1");
 | 
					 | 
				
			||||||
    env_logger::init();
 | 
					    env_logger::init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let args = ControllerArgs::parse();
 | 
					    let args = ControllerArgs::parse();
 | 
				
			||||||
 | 
				
			|||||||
@ -1,16 +1,19 @@
 | 
				
			|||||||
use crate::shared::LaunchInfo;
 | 
					use crate::shared::LaunchInfo;
 | 
				
			||||||
use anyhow::{anyhow, Result};
 | 
					use anyhow::{anyhow, Result};
 | 
				
			||||||
use log::trace;
 | 
					use log::trace;
 | 
				
			||||||
use nix::libc::dup2;
 | 
					use nix::libc::{c_int, dup2, wait};
 | 
				
			||||||
use nix::unistd::execve;
 | 
					use nix::unistd::{execve, fork, ForkResult, Pid};
 | 
				
			||||||
use oci_spec::image::{Config, ImageConfiguration};
 | 
					use oci_spec::image::{Config, ImageConfiguration};
 | 
				
			||||||
use std::ffi::CString;
 | 
					use std::ffi::{CStr, CString};
 | 
				
			||||||
use std::fs;
 | 
					use std::fs;
 | 
				
			||||||
use std::fs::{File, OpenOptions, Permissions};
 | 
					use std::fs::{File, OpenOptions, Permissions};
 | 
				
			||||||
use std::os::fd::AsRawFd;
 | 
					use std::os::fd::AsRawFd;
 | 
				
			||||||
use std::os::linux::fs::MetadataExt;
 | 
					use std::os::linux::fs::MetadataExt;
 | 
				
			||||||
use std::os::unix::fs::{chroot, PermissionsExt};
 | 
					use std::os::unix::fs::{chroot, PermissionsExt};
 | 
				
			||||||
use std::path::Path;
 | 
					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 sys_mount::{FilesystemType, Mount, MountFlags};
 | 
				
			||||||
use walkdir::WalkDir;
 | 
					use walkdir::WalkDir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,9 +68,8 @@ impl ContainerInit {
 | 
				
			|||||||
        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)?;
 | 
					 | 
				
			||||||
        if let Some(cfg) = config.config() {
 | 
					        if let Some(cfg) = config.config() {
 | 
				
			||||||
            self.run(cfg, &launch)?;
 | 
					            self.run(console, cfg, &launch)?;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return Err(anyhow!(
 | 
					            return Err(anyhow!(
 | 
				
			||||||
                "unable to determine what to execute, image config doesn't tell us"
 | 
					                "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<()> {
 | 
					    fn map_console(&mut self, console: File) -> Result<()> {
 | 
				
			||||||
        trace!("map console");
 | 
					        trace!("mapping console");
 | 
				
			||||||
        unsafe {
 | 
					        unsafe {
 | 
				
			||||||
            dup2(console.as_raw_fd(), 0);
 | 
					            dup2(console.as_raw_fd(), 0);
 | 
				
			||||||
            dup2(console.as_raw_fd(), 1);
 | 
					            dup2(console.as_raw_fd(), 1);
 | 
				
			||||||
@ -264,7 +266,7 @@ impl ContainerInit {
 | 
				
			|||||||
        Ok(())
 | 
					        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() {
 | 
					        let mut cmd = match config.cmd() {
 | 
				
			||||||
            None => vec![],
 | 
					            None => vec![],
 | 
				
			||||||
            Some(value) => value.clone(),
 | 
					            Some(value) => value.clone(),
 | 
				
			||||||
@ -278,7 +280,6 @@ impl ContainerInit {
 | 
				
			|||||||
            cmd.push("/bin/sh".to_string());
 | 
					            cmd.push("/bin/sh".to_string());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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() {
 | 
				
			||||||
            None => vec![],
 | 
					            None => vec![],
 | 
				
			||||||
@ -288,6 +289,9 @@ impl ContainerInit {
 | 
				
			|||||||
        if let Some(extra_env) = &launch.env {
 | 
					        if let Some(extra_env) = &launch.env {
 | 
				
			||||||
            env.extend_from_slice(extra_env.as_slice());
 | 
					            env.extend_from_slice(extra_env.as_slice());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        trace!("running container command: {}", cmd.join(" "));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let path_cstr = CString::new(path)?;
 | 
					        let path_cstr = CString::new(path)?;
 | 
				
			||||||
        let cmd_cstr = ContainerInit::strings_as_cstrings(cmd)?;
 | 
					        let cmd_cstr = ContainerInit::strings_as_cstrings(cmd)?;
 | 
				
			||||||
        let env_cstr = ContainerInit::strings_as_cstrings(env)?;
 | 
					        let env_cstr = ContainerInit::strings_as_cstrings(env)?;
 | 
				
			||||||
@ -302,7 +306,7 @@ impl ContainerInit {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::env::set_current_dir(&working_dir)?;
 | 
					        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(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -313,4 +317,39 @@ impl ContainerInit {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(results)
 | 
					        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
 | 
					cargo build --release --target x86_64-unknown-linux-gnu
 | 
				
			||||||
INITRD_DIR="$(mktemp -d /tmp/hypha-initrd.XXXXXXXXXXXXX)"
 | 
					INITRD_DIR="$(mktemp -d /tmp/hypha-initrd.XXXXXXXXXXXXX)"
 | 
				
			||||||
cp target/x86_64-unknown-linux-gnu/release/hyphactr "${INITRD_DIR}/init"
 | 
					cp target/x86_64-unknown-linux-gnu/release/hyphactr "${INITRD_DIR}/init"
 | 
				
			||||||
 | 
					chmod +x "${INITRD_DIR}/init"
 | 
				
			||||||
cd "${INITRD_DIR}"
 | 
					cd "${INITRD_DIR}"
 | 
				
			||||||
mkdir -p "${HYPHA_DIR}/target/initrd"
 | 
					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}"
 | 
					rm -rf "${INITRD_DIR}"
 | 
				
			||||||
 | 
				
			|||||||
@ -273,8 +273,8 @@ impl BootImageLoader for ElfImageLoader {
 | 
				
			|||||||
                copy_slice.len()
 | 
					                copy_slice.len()
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            copy(segment_dst, copy_slice);
 | 
					            copy(segment_dst, copy_slice);
 | 
				
			||||||
            if memsz - filesz > 0 {
 | 
					            if (memsz - filesz) > 0 {
 | 
				
			||||||
                let remaining = &mut segment_dst[filesz as usize..(memsz - filesz) as usize];
 | 
					                let remaining = &mut segment_dst[filesz as usize..memsz as usize];
 | 
				
			||||||
                debug!(
 | 
					                debug!(
 | 
				
			||||||
                    "ElfImageLoader load fill_zero hdr={:?} dst={:#x} len={}",
 | 
					                    "ElfImageLoader load fill_zero hdr={:?} dst={:#x} len={}",
 | 
				
			||||||
                    header.p_offset,
 | 
					                    header.p_offset,
 | 
				
			||||||
 | 
				
			|||||||
@ -55,7 +55,7 @@ pub trait XsdInterface {
 | 
				
			|||||||
        Ok(match self.read_string(path) {
 | 
					        Ok(match self.read_string(path) {
 | 
				
			||||||
            Ok(value) => Some(value),
 | 
					            Ok(value) => Some(value),
 | 
				
			||||||
            Err(error) => {
 | 
					            Err(error) => {
 | 
				
			||||||
                if error.to_string() == "ENOENT" {
 | 
					                if error.is_noent_response() {
 | 
				
			||||||
                    None
 | 
					                    None
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    return Err(error);
 | 
					                    return Err(error);
 | 
				
			||||||
@ -68,7 +68,7 @@ pub trait XsdInterface {
 | 
				
			|||||||
        Ok(match self.list(path) {
 | 
					        Ok(match self.list(path) {
 | 
				
			||||||
            Ok(value) => value,
 | 
					            Ok(value) => value,
 | 
				
			||||||
            Err(error) => {
 | 
					            Err(error) => {
 | 
				
			||||||
                if error.to_string() == "ENOENT" {
 | 
					                if error.is_noent_response() {
 | 
				
			||||||
                    Vec::new()
 | 
					                    Vec::new()
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    return Err(error);
 | 
					                    return Err(error);
 | 
				
			||||||
@ -115,7 +115,7 @@ impl XsdClient {
 | 
				
			|||||||
        trace!("rm tx={tx} path={path}");
 | 
					        trace!("rm tx={tx} path={path}");
 | 
				
			||||||
        let result = self.socket.send_single(tx, XSD_RM, path);
 | 
					        let result = self.socket.send_single(tx, XSD_RM, path);
 | 
				
			||||||
        if let Err(error) = result {
 | 
					        if let Err(error) = result {
 | 
				
			||||||
            if error.to_string() == "ENOENT" {
 | 
					            if error.is_noent_response() {
 | 
				
			||||||
                return Ok(true);
 | 
					                return Ok(true);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return Err(error);
 | 
					            return Err(error);
 | 
				
			||||||
 | 
				
			|||||||
@ -28,4 +28,13 @@ pub enum Error {
 | 
				
			|||||||
    InvalidPermissions,
 | 
					    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>;
 | 
					pub type Result<T> = std::result::Result<T, Error>;
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user