From 3664233d0f702e7f1c8ba0ae939e097735f87714 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Mon, 10 Oct 2022 23:28:42 +0000 Subject: host/start-vm: implement shared directories Signed-off-by: Alyssa Ross Message-Id: <20221010232909.1953738-3-hi@alyssa.is> --- host/start-vm/lib.rs | 26 ++++++++++++++++++ host/start-vm/tests/meson.build | 2 ++ host/start-vm/tests/vm_command-shared-dir.rs | 41 ++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 host/start-vm/tests/vm_command-shared-dir.rs diff --git a/host/start-vm/lib.rs b/host/start-vm/lib.rs index 9a92ab7..3959566 100644 --- a/host/start-vm/lib.rs +++ b/host/start-vm/lib.rs @@ -112,6 +112,32 @@ pub fn vm_command(dir: PathBuf, config_root: &Path) -> Result { return Err("no block devices specified".to_string()); } + let shared_dirs_dir = config_dir.join("shared-dirs"); + match shared_dirs_dir.read_dir().map(Iterator::peekable) { + Ok(mut entries) => { + if entries.peek().is_some() { + command.arg("--fs"); + } + + for result in entries { + let entry = result + .map_err(|e| format!("examining directory entry: {}", e))? + .file_name(); + + let mut arg = OsString::from("tag="); + arg.push(&entry); + arg.push(",socket=../"); + arg.push(vm_name); + arg.push("-fs-"); + arg.push(&entry); + arg.push("/env/virtiofsd.sock"); + command.arg(arg); + } + } + Err(e) if e.kind() == ErrorKind::NotFound => {} + Err(e) => return Err(format!("reading directory {:?}: {}", shared_dirs_dir, e)), + } + command.arg("--serial").arg({ let mut serial = OsString::from("file=/run/"); serial.push(&vm_name); diff --git a/host/start-vm/tests/meson.build b/host/start-vm/tests/meson.build index 00bd33d..857414b 100644 --- a/host/start-vm/tests/meson.build +++ b/host/start-vm/tests/meson.build @@ -31,3 +31,5 @@ test('tap_open (name too long)', executable('tap_open-name-too-long', test('vm_command-basic', executable('vm_command-basic', 'vm_command-basic.rs', link_with : [rust_lib, rust_helper])) +test('vm_command-shared-dir', executable('vm_command-shared-dir', + 'vm_command-shared-dir.rs', link_with : [rust_lib, rust_helper])) diff --git a/host/start-vm/tests/vm_command-shared-dir.rs b/host/start-vm/tests/vm_command-shared-dir.rs new file mode 100644 index 0000000..2b13663 --- /dev/null +++ b/host/start-vm/tests/vm_command-shared-dir.rs @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: EUPL-1.2+ +// SPDX-FileCopyrightText: 2022 Alyssa Ross + +use std::fs::{create_dir, create_dir_all, File}; +use std::os::unix::fs::symlink; + +use start_vm::vm_command; +use test_helper::TempDir; + +fn contains_seq, N>(haystack: &[H], needle: &[N]) -> bool { + let start_indexes = 0..=(haystack.len() - needle.len()); + let mut candidates = start_indexes.map(|i| &haystack[i..][..needle.len()]); + candidates.any(|c| c == needle) +} + +fn main() -> std::io::Result<()> { + let tmp_dir = TempDir::new()?; + + let service_dir = tmp_dir.path().join("testvm"); + let vm_config = tmp_dir.path().join("svc/data/testvm"); + + create_dir(&service_dir)?; + create_dir_all(&vm_config)?; + File::create(vm_config.join("vmlinux"))?; + create_dir(vm_config.join("blk"))?; + symlink("/dev/null", vm_config.join("blk/root.img"))?; + + create_dir(vm_config.join("shared-dirs"))?; + create_dir(vm_config.join("shared-dirs/root"))?; + symlink("/", vm_config.join("shared-dirs/root/dir"))?; + + let expected_args = [ + "--fs", + "tag=root,socket=../testvm-fs-root/env/virtiofsd.sock", + ]; + + let command = vm_command(service_dir, &tmp_dir.path().join("svc/data")).unwrap(); + let args: Box<[_]> = command.get_args().collect(); + assert!(contains_seq(&args, &expected_args)); + Ok(()) +} -- cgit 1.4.1