Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/krunvm-changevm.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions docs/krunvm-create.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions docs/krunvm-start.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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_.
Expand Down
40 changes: 40 additions & 0 deletions src/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<u32>() {
Expand Down Expand Up @@ -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();

Expand Down
5 changes: 2 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down
80 changes: 44 additions & 36 deletions src/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<CString>) {
unsafe fn exec_vm(vmcfg: &VmConfig, rootfs: &str, cmd: Option<&str>, args: Vec<CString>) {
//bindings::krun_set_log_level(9);

let ctx = bindings::krun_create_ctx() as u32;
Expand Down Expand Up @@ -102,39 +102,43 @@ unsafe fn exec_vm(vmcfg: &VmConfig, rootfs: &str, cmd: &str, args: Vec<CString>)
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);
Expand Down Expand Up @@ -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) {
Expand All @@ -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<CString> = match matches.values_of("ARGS") {
Some(a) => a.map(|val| CString::new(val).unwrap()).collect(),
None => Vec::new(),
let args: Vec<CString> = 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();
Expand Down
2 changes: 2 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{KrunvmConfig, VmConfig, APP_NAME};

pub enum BuildahCommand {
From,
Inspect,
Mount,
Unmount,
Remove,
Expand All @@ -18,6 +19,7 @@ pub enum BuildahCommand {
pub fn get_buildah_args(_cfg: &KrunvmConfig, cmd: BuildahCommand) -> Vec<String> {
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()],
Expand Down