summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2023-11-05 12:36:49 +0000
committerAlyssa Ross <hi@alyssa.is>2024-01-19 11:24:46 +0100
commit673c7dfc96cfd949b94caa23b944ed3489f4bf5d (patch)
treefcd6e42dd4247a742a4359d6bece05d035456245
parentb1d64acff3fdbe7a0e819ecdd2d3b27620af08b2 (diff)
downloadspectrum-673c7dfc96cfd949b94caa23b944ed3489f4bf5d.tar
spectrum-673c7dfc96cfd949b94caa23b944ed3489f4bf5d.tar.gz
spectrum-673c7dfc96cfd949b94caa23b944ed3489f4bf5d.tar.bz2
spectrum-673c7dfc96cfd949b94caa23b944ed3489f4bf5d.tar.lz
spectrum-673c7dfc96cfd949b94caa23b944ed3489f4bf5d.tar.xz
spectrum-673c7dfc96cfd949b94caa23b944ed3489f4bf5d.tar.zst
spectrum-673c7dfc96cfd949b94caa23b944ed3489f4bf5d.zip
host/start-vm: find config from /run/vm
Having a symlink in the service directory was a nice idea, but since
it has to be different for every service, it's not compatible with
templated services, and would prevent us switching to them.  The only
thing that varies between instances of templated services is the name,
so we have to introduce a mapping of VM name to config directory.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
-rw-r--r--host/rootfs/Makefile2
-rw-r--r--host/rootfs/etc/s6-rc/ext-rc-init/up5
-rw-r--r--host/start-vm/lib.rs12
-rw-r--r--host/start-vm/start-vm.rs3
-rw-r--r--host/start-vm/tests/vm_command-basic.rs11
-rw-r--r--host/start-vm/tests/vm_command-multiple-disks.rs9
-rw-r--r--host/start-vm/tests/vm_command-shared-dir.rs9
7 files changed, 30 insertions, 21 deletions
diff --git a/host/rootfs/Makefile b/host/rootfs/Makefile
index cf985c3..a108a29 100644
--- a/host/rootfs/Makefile
+++ b/host/rootfs/Makefile
@@ -37,7 +37,7 @@ FILES = \
 	usr/bin/vm-console \
 	usr/bin/vm-start \
 	usr/bin/vm-stop
-DIRS = dev etc/s6-linux-init/env ext run proc sys
+DIRS = dev etc/s6-linux-init/env etc/s6-linux-init/run-image/vm ext run proc sys
 
 # These are separate because they need to be included, but putting
 # them as make dependencies would confuse make.
diff --git a/host/rootfs/etc/s6-rc/ext-rc-init/up b/host/rootfs/etc/s6-rc/ext-rc-init/up
index f6d0e77..7c5764a 100644
--- a/host/rootfs/etc/s6-rc/ext-rc-init/up
+++ b/host/rootfs/etc/s6-rc/ext-rc-init/up
@@ -10,8 +10,9 @@ if {
   forx -po0 -E dir { $dirs }
   backtick -E name { basename -- $dir }
 
-  if { mkdir vm-${name} vm-${name}/data vm-${name}/dependencies.d vm-${name}/env }
-  if { ln -s $dir vm-${name}/data/config }
+  if { ln -s $dir /run/vm/${name} }
+
+  if { mkdir vm-${name} vm-${name}/dependencies.d vm-${name}/env }
   if { redirfd -w 1 vm-${name}/type echo longrun }
   if { redirfd -w 1 vm-${name}/notification-fd echo 3 }
   if { redirfd -w 1 vm-${name}/run printf "#!/bin/execlineb -P\n/bin/start-vm" }
diff --git a/host/start-vm/lib.rs b/host/start-vm/lib.rs
index 33c19bb..f60a822 100644
--- a/host/start-vm/lib.rs
+++ b/host/start-vm/lib.rs
@@ -47,8 +47,12 @@ pub fn create_api_socket() -> Result<UnixListener, String> {
     Ok(api_socket)
 }
 
-pub fn vm_command(dir: &Path, api_socket_fd: RawFd) -> Result<Command, String> {
-    let vm_name = dir
+pub fn vm_command(
+    service_dir: &Path,
+    vm_dir: &Path,
+    api_socket_fd: RawFd,
+) -> Result<Command, String> {
+    let vm_name = service_dir
         .file_name()
         .ok_or_else(|| "directory has no name".to_string())?
         .as_bytes();
@@ -63,7 +67,7 @@ pub fn vm_command(dir: &Path, api_socket_fd: RawFd) -> Result<Command, String> {
 
     let vm_name = OsStr::from_bytes(&vm_name[3..]);
 
-    let config_dir = dir.join("data/config");
+    let config_dir = vm_dir.join(vm_name);
 
     let mut command = Command::new("cloud-hypervisor");
     command.args(["--api-socket", &format!("fd={api_socket_fd}")]);
@@ -186,7 +190,7 @@ mod tests {
 
     #[test]
     fn test_vm_name_comma() {
-        assert!(vm_command(Path::new("/vm-,"), -1)
+        assert!(vm_command(Path::new("/vm-,"), Path::new(""), -1)
             .unwrap_err()
             .contains("comma"));
     }
diff --git a/host/start-vm/start-vm.rs b/host/start-vm/start-vm.rs
index bbe80bd..7dfca09 100644
--- a/host/start-vm/start-vm.rs
+++ b/host/start-vm/start-vm.rs
@@ -3,6 +3,7 @@
 
 use std::env::current_dir;
 use std::os::unix::prelude::*;
+use std::path::Path;
 use std::process::exit;
 
 use start_vm::{create_api_socket, notify_readiness, prog_name, vm_command};
@@ -25,7 +26,7 @@ unsafe fn run() -> String {
         return e;
     }
 
-    match vm_command(&dir, api_socket.into_raw_fd()) {
+    match vm_command(&dir, Path::new("/run/vm"), api_socket.into_raw_fd()) {
         Ok(mut command) => format!("failed to exec: {}", command.exec()),
         Err(e) => e,
     }
diff --git a/host/start-vm/tests/vm_command-basic.rs b/host/start-vm/tests/vm_command-basic.rs
index 92d78d8..b70b6a8 100644
--- a/host/start-vm/tests/vm_command-basic.rs
+++ b/host/start-vm/tests/vm_command-basic.rs
@@ -8,18 +8,19 @@ use start_vm::vm_command;
 use test_helper::TempDir;
 
 fn main() -> std::io::Result<()> {
-    let tmp_dir = TempDir::new()?;
+    let service_dir_parent = TempDir::new()?;
+    let service_dir = service_dir_parent.path().join("vm-testvm");
 
-    let service_dir = tmp_dir.path().join("vm-testvm");
+    let vm_dir = TempDir::new()?;
 
-    let kernel_path = service_dir.join("data/config/vmlinux");
-    let image_path = service_dir.join("data/config/blk/root.img");
+    let kernel_path = vm_dir.path().join("testvm/vmlinux");
+    let image_path = vm_dir.path().join("testvm/blk/root.img");
 
     create_dir_all(image_path.parent().unwrap())?;
     File::create(&kernel_path)?;
     File::create(&image_path)?;
 
-    let command = vm_command(&service_dir, 4).unwrap();
+    let command = vm_command(&service_dir, vm_dir.path(), 4).unwrap();
     assert_eq!(command.get_program(), "cloud-hypervisor");
 
     let mut expected_disk_arg = OsString::from("path=");
diff --git a/host/start-vm/tests/vm_command-multiple-disks.rs b/host/start-vm/tests/vm_command-multiple-disks.rs
index e17d505..cd1e997 100644
--- a/host/start-vm/tests/vm_command-multiple-disks.rs
+++ b/host/start-vm/tests/vm_command-multiple-disks.rs
@@ -10,10 +10,11 @@ use start_vm::vm_command;
 use test_helper::TempDir;
 
 fn main() -> std::io::Result<()> {
-    let tmp_dir = TempDir::new()?;
+    let service_dir_parent = TempDir::new()?;
+    let service_dir = service_dir_parent.path().join("vm-testvm");
 
-    let service_dir = tmp_dir.path().join("vm-testvm");
-    let vm_config = service_dir.join("data/config");
+    let vm_dir = TempDir::new()?;
+    let vm_config = vm_dir.path().join("testvm");
 
     create_dir_all(&vm_config)?;
     File::create(vm_config.join("vmlinux"))?;
@@ -27,7 +28,7 @@ fn main() -> std::io::Result<()> {
         symlink("/dev/null", image_path)?;
     }
 
-    let command = vm_command(&service_dir, -1).unwrap();
+    let command = vm_command(&service_dir, vm_dir.path(), -1).unwrap();
     let mut args = command.get_args();
 
     assert!(args.any(|arg| arg == "--disk"));
diff --git a/host/start-vm/tests/vm_command-shared-dir.rs b/host/start-vm/tests/vm_command-shared-dir.rs
index d310d09..6183f6d 100644
--- a/host/start-vm/tests/vm_command-shared-dir.rs
+++ b/host/start-vm/tests/vm_command-shared-dir.rs
@@ -10,10 +10,11 @@ use start_vm::vm_command;
 use test_helper::TempDir;
 
 fn main() -> std::io::Result<()> {
-    let tmp_dir = TempDir::new()?;
+    let service_dir_parent = TempDir::new()?;
+    let service_dir = service_dir_parent.path().join("vm-testvm");
 
-    let service_dir = tmp_dir.path().join("vm-testvm");
-    let vm_config = service_dir.join("data/config");
+    let vm_dir = TempDir::new()?;
+    let vm_config = vm_dir.path().join("testvm");
 
     create_dir_all(&vm_config)?;
     File::create(vm_config.join("vmlinux"))?;
@@ -28,7 +29,7 @@ fn main() -> std::io::Result<()> {
     create_dir(vm_config.join("shared-dirs/dir2"))?;
     symlink("/", vm_config.join("shared-dirs/dir2/dir"))?;
 
-    let command = vm_command(&service_dir, -1).unwrap();
+    let command = vm_command(&service_dir, vm_dir.path(), -1).unwrap();
     let mut args = command.get_args();
 
     assert!(args.any(|arg| arg == "--fs"));