diff --git a/docs/krunvm-changevm.1.txt b/docs/krunvm-changevm.1.txt index bbcc877..4f14e90 100644 --- a/docs/krunvm-changevm.1.txt +++ b/docs/krunvm-changevm.1.txt @@ -57,6 +57,9 @@ host visible in the guest. *-w, --workdir* _GUEST_PATH_:: Configures _GUEST_PATH_ as the working directory for the first binary executed in the microVM. ++ +An empty string ("") tells krunvm to not set a working directory +explicitly, letting libkrun decide which one should be set. SEE ALSO diff --git a/docs/krunvm-create.1.txt b/docs/krunvm-create.1.txt index 66a6971..d63f3f8 100644 --- a/docs/krunvm-create.1.txt +++ b/docs/krunvm-create.1.txt @@ -49,6 +49,9 @@ host visible in the guest. *-w, --workdir* _GUEST_PATH_:: Configures _GUEST_PATH_ as the working directory for the first binary executed in the microVM. ++ +An empty string ("") tells krunvm to not set a working directory +explicitly, letting libkrun decide which one should be set. SEE ALSO diff --git a/docs/krunvm-start.1.txt b/docs/krunvm-start.1.txt index d78ce04..b1ba5ef 100644 --- a/docs/krunvm-start.1.txt +++ b/docs/krunvm-start.1.txt @@ -18,8 +18,8 @@ and attaches stdin/stdout to its virtio-console providing a seamless experience for interacting with the guest running inside it. _COMMAND_ is the first binary to be executed in the microVM. If it's -not present in the command line, krunvm-start(1) defaults to executing -_/bin/sh_. +not present in the command line, krunvm-start(1) lets libkrun decide +which binary will be executed. Additional arguments for _COMMAND_ can be specified in the command line by appending _--_ followed by _ARGS_. diff --git a/src/create.rs b/src/create.rs index cfbfe7a..a3c3dbd 100644 --- a/src/create.rs +++ b/src/create.rs @@ -22,6 +22,45 @@ fn fix_resolv_conf(rootfs: &str, dns: &str) -> Result<(), std::io::Error> { Ok(()) } +fn export_container_config( + cfg: &KrunvmConfig, + rootfs: &str, + image: &str, +) -> Result<(), std::io::Error> { + let mut args = get_buildah_args(cfg, BuildahCommand::Inspect); + args.push(image.to_string()); + + let output = match Command::new("buildah") + .args(&args) + .stderr(std::process::Stdio::inherit()) + .output() + { + Ok(output) => output, + Err(err) => { + if err.kind() == std::io::ErrorKind::NotFound { + println!("{} requires buildah to manage the OCI images, and it wasn't found on this system.", APP_NAME); + } else { + println!("Error executing buildah: {}", err); + } + std::process::exit(-1); + } + }; + + let exit_code = output.status.code().unwrap_or(-1); + if exit_code != 0 { + println!( + "buildah returned an error: {}", + std::str::from_utf8(&output.stdout).unwrap() + ); + std::process::exit(-1); + } + + let mut file = fs::File::create(format!("{}/.krun_config.json", rootfs))?; + file.write_all(&output.stdout)?; + + Ok(()) +} + pub fn create(cfg: &mut KrunvmConfig, matches: &ArgMatches) { let cpus = match matches.value_of("cpus") { Some(c) => match c.parse::() { @@ -120,6 +159,7 @@ pub fn create(cfg: &mut KrunvmConfig, matches: &ArgMatches) { }; let rootfs = mount_container(cfg, &vmcfg).unwrap(); + export_container_config(cfg, &rootfs, image).unwrap(); fix_resolv_conf(&rootfs, dns).unwrap(); umount_container(cfg, &vmcfg).unwrap(); diff --git a/src/main.rs b/src/main.rs index a805050..fc718c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -271,7 +271,7 @@ fn main() { .short("w") .help("Working directory inside the microVM") .takes_value(true) - .default_value("/root"), + .default_value(""), ) .arg( Arg::with_name("volume") @@ -334,8 +334,7 @@ fn main() { .arg( Arg::with_name("COMMAND") .help("Command to run inside the VM") - .index(2) - .default_value("/bin/sh"), + .index(2), ) .arg( Arg::with_name("ARGS") diff --git a/src/start.rs b/src/start.rs index 01354f5..5f6a1bb 100644 --- a/src/start.rs +++ b/src/start.rs @@ -66,7 +66,7 @@ fn map_volumes(ctx: u32, vmcfg: &VmConfig, rootfs: &str) { } } -unsafe fn exec_vm(vmcfg: &VmConfig, rootfs: &str, cmd: &str, args: Vec) { +unsafe fn exec_vm(vmcfg: &VmConfig, rootfs: &str, cmd: Option<&str>, args: Vec) { //bindings::krun_set_log_level(9); let ctx = bindings::krun_create_ctx() as u32; @@ -102,39 +102,43 @@ unsafe fn exec_vm(vmcfg: &VmConfig, rootfs: &str, cmd: &str, args: Vec) std::process::exit(-1); } - let c_workdir = CString::new(vmcfg.workdir.clone()).unwrap(); - let ret = bindings::krun_set_workdir(ctx, c_workdir.as_ptr() as *const i8); - if ret < 0 { - println!("Error setting VM workdir"); - std::process::exit(-1); + if !vmcfg.workdir.is_empty() { + let c_workdir = CString::new(vmcfg.workdir.clone()).unwrap(); + let ret = bindings::krun_set_workdir(ctx, c_workdir.as_ptr() as *const i8); + if ret < 0 { + println!("Error setting VM workdir"); + std::process::exit(-1); + } } - let mut argv: Vec<*const i8> = Vec::new(); - for a in args.iter() { - argv.push(a.as_ptr() as *const i8); - } - argv.push(std::ptr::null()); - - let hostname = CString::new(format!("HOSTNAME={}", vmcfg.name)).unwrap(); - let home = CString::new("HOME=/root").unwrap(); - let path = CString::new("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin").unwrap(); - let env: [*const i8; 4] = [ - hostname.as_ptr() as *const i8, - home.as_ptr() as *const i8, - path.as_ptr() as *const i8, - std::ptr::null(), - ]; - - let c_cmd = CString::new(cmd).unwrap(); - let ret = bindings::krun_set_exec( - ctx, - c_cmd.as_ptr() as *const i8, - argv.as_ptr() as *const *const i8, - env.as_ptr() as *const *const i8, - ); - if ret < 0 { - println!("Error setting VM config"); - std::process::exit(-1); + if let Some(cmd) = cmd { + let mut argv: Vec<*const i8> = Vec::new(); + for a in args.iter() { + argv.push(a.as_ptr() as *const i8); + } + argv.push(std::ptr::null()); + + let hostname = CString::new(format!("HOSTNAME={}", vmcfg.name)).unwrap(); + let home = CString::new("HOME=/root").unwrap(); + let path = CString::new("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin").unwrap(); + let env: [*const i8; 4] = [ + hostname.as_ptr() as *const i8, + home.as_ptr() as *const i8, + path.as_ptr() as *const i8, + std::ptr::null(), + ]; + + let c_cmd = CString::new(cmd).unwrap(); + let ret = bindings::krun_set_exec( + ctx, + c_cmd.as_ptr() as *const i8, + argv.as_ptr() as *const *const i8, + env.as_ptr() as *const *const i8, + ); + if ret < 0 { + println!("Error setting VM config"); + std::process::exit(-1); + } } let ret = bindings::krun_start_enter(ctx); @@ -176,7 +180,7 @@ fn set_lock(rootfs: &str) -> File { } pub fn start(cfg: &KrunvmConfig, matches: &ArgMatches) { - let cmd = matches.value_of("COMMAND").unwrap(); + let cmd = matches.value_of("COMMAND"); let name = matches.value_of("NAME").unwrap(); let vmcfg = match cfg.vmconfig_map.get(name) { @@ -190,9 +194,13 @@ pub fn start(cfg: &KrunvmConfig, matches: &ArgMatches) { umount_container(cfg, vmcfg).expect("Error unmounting container"); let rootfs = mount_container(cfg, vmcfg).expect("Error mounting container"); - let args: Vec = match matches.values_of("ARGS") { - Some(a) => a.map(|val| CString::new(val).unwrap()).collect(), - None => Vec::new(), + let args: Vec = if cmd.is_some() { + match matches.values_of("ARGS") { + Some(a) => a.map(|val| CString::new(val).unwrap()).collect(), + None => Vec::new(), + } + } else { + Vec::new() }; set_rlimits(); diff --git a/src/utils.rs b/src/utils.rs index 394e3e7..8669ca7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -9,6 +9,7 @@ use crate::{KrunvmConfig, VmConfig, APP_NAME}; pub enum BuildahCommand { From, + Inspect, Mount, Unmount, Remove, @@ -18,6 +19,7 @@ pub enum BuildahCommand { pub fn get_buildah_args(_cfg: &KrunvmConfig, cmd: BuildahCommand) -> Vec { match cmd { BuildahCommand::From => vec!["from".to_string()], + BuildahCommand::Inspect => vec!["inspect".to_string()], BuildahCommand::Mount => vec!["mount".to_string()], BuildahCommand::Unmount => vec!["umount".to_string()], BuildahCommand::Remove => vec!["rm".to_string()],