summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-03-25 12:29:44 +0200
committerLars Wirzenius <liw@liw.fi>2021-03-25 13:16:13 +0200
commit00dc4a7a85b32c4337dd3672adec2cbfe3597bfe (patch)
tree20df497a743e8442f9725c2f5ab552747363a9d1
parent7d906d7f5436705ec3f2f3f5c4d8629c79f98fde (diff)
downloadvmadm-00dc4a7a85b32c4337dd3672adec2cbfe3597bfe.tar.gz
feat: allow ~/ in config, specification files
-rw-r--r--src/config.rs12
-rw-r--r--src/libvirt.rs2
-rw-r--r--src/spec.rs10
-rw-r--r--src/util.rs34
-rw-r--r--vmadm.md12
5 files changed, 61 insertions, 9 deletions
diff --git a/src/config.rs b/src/config.rs
index 1866971..3f1b341 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,5 +1,6 @@
//! Tool configuration.
+use crate::util::{expand_optional_pathbuf, expand_optional_pathbufs};
use log::debug;
use serde::Deserialize;
use std::default::Default;
@@ -57,11 +58,20 @@ impl Configuration {
debug!("reading configuration file {}", filename.display());
let config = fs::read(filename)
.map_err(|err| ConfigurationError::ReadError(filename.to_path_buf(), err))?;
- let config: Configuration = serde_yaml::from_slice(&config)?;
+ let mut config: Configuration = serde_yaml::from_slice(&config)?;
+ config.expand_tildes();
debug!("config: {:#?}", config);
Ok(config)
} else {
Ok(Self::default())
}
}
+
+ fn expand_tildes(&mut self) {
+ expand_optional_pathbuf(&mut self.default_base_image);
+ expand_optional_pathbuf(&mut self.image_directory);
+ expand_optional_pathbuf(&mut self.image_directory);
+ expand_optional_pathbuf(&mut self.ca_key);
+ expand_optional_pathbufs(&mut self.authorized_keys)
+ }
}
diff --git a/src/libvirt.rs b/src/libvirt.rs
index b144d11..4bf8590 100644
--- a/src/libvirt.rs
+++ b/src/libvirt.rs
@@ -116,7 +116,7 @@ impl Libvirt {
let disk = find_iso_xml(&xml);
let flags =
VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_CURRENT | VIR_DOMAIN_AFFECT_LIVE;
- if disk.is_empty() {
+ if !disk.is_empty() {
domain
.detach_device_flags(&disk, flags)
.map_err(|err| VirtError::DetachIso(name.to_string(), err))?;
diff --git a/src/spec.rs b/src/spec.rs
index a1d1c2f..a00a5e8 100644
--- a/src/spec.rs
+++ b/src/spec.rs
@@ -1,6 +1,7 @@
//! Virtual machine specification.
use crate::config::Configuration;
+use crate::util::expand_tilde;
use log::debug;
use serde::{Deserialize, Serialize};
@@ -293,8 +294,8 @@ impl Specification {
ecdsa_host_cert: input.ecdsa_host_cert.clone(),
ed25519_host_key: input.ed25519_host_key.clone(),
ed25519_host_cert: input.ed25519_host_cert.clone(),
- base: input.base_image(config, name)?,
- image: input.image(config, name)?,
+ base: expand_tilde(&input.base_image(config, name)?),
+ image: expand_tilde(&input.image(config, name)?),
image_size_gib: input.image_size_gib(config, name)?,
memory_mib: input.memory_mib(config, name)?,
cpus: input.cpus(config, name)?,
@@ -311,8 +312,9 @@ impl Specification {
fn ssh_keys(filenames: &[PathBuf]) -> Result<Vec<String>, SpecificationError> {
let mut keys = vec![];
for filename in filenames {
- let key = std::fs::read(filename)
- .map_err(|e| SpecificationError::SshKeyRead(filename.to_path_buf(), e))?;
+ let filename = expand_tilde(filename);
+ let key =
+ std::fs::read(&filename).map_err(|e| SpecificationError::SshKeyRead(filename, e))?;
let key = String::from_utf8(key)?;
let key = key.strip_suffix("\n").or(Some(&key)).unwrap();
keys.push(key.to_string());
diff --git a/src/util.rs b/src/util.rs
index f3e104b..c641ea6 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -2,6 +2,7 @@
use log::debug;
use std::net::TcpStream;
+use std::path::{Path, PathBuf};
const SSH_PORT: i32 = 22;
@@ -15,3 +16,36 @@ pub fn wait_for_ssh(name: &str) {
}
}
}
+
+/// Expand a ~/ at the beginning of a Path to refer to the home directory.
+pub fn expand_tilde(path: &Path) -> PathBuf {
+ if path.starts_with("~/") {
+ if let Some(home) = std::env::var_os("HOME") {
+ let mut expanded = PathBuf::from(home);
+ for comp in path.components().skip(1) {
+ expanded.push(comp);
+ }
+ expanded
+ } else {
+ path.to_path_buf()
+ }
+ } else {
+ path.to_path_buf()
+ }
+}
+
+pub fn expand_optional_pathbuf(maybe_path: &mut Option<PathBuf>) {
+ if let Some(path) = maybe_path {
+ *maybe_path = Some(expand_tilde(path));
+ }
+}
+
+pub fn expand_optional_pathbufs(maybe_paths: &mut Option<Vec<PathBuf>>) {
+ if let Some(paths) = maybe_paths {
+ let mut expanded = vec![];
+ for path in paths {
+ expanded.push(expand_tilde(&path));
+ }
+ *maybe_paths = Some(expanded);
+ }
+}
diff --git a/vmadm.md b/vmadm.md
index 24ffe5c..2d97876 100644
--- a/vmadm.md
+++ b/vmadm.md
@@ -36,9 +36,15 @@ V4cecTlFJGBtUOUAAAAMbGl3QGV4b2xvYmUxAQIDBAUGBw==
-----END OPENSSH PRIVATE KEY-----
~~~
+Note that we use *tilde expansion* in filenames to indicate they go
+into the home directory. The Subplot test runner sets the `HOME`
+environment variable to a suitable directory, so that the files don't
+go into the actual home directory of the person running the generated
+test program
+
~~~{#config.yaml .file .yaml}
-image_directory: images
-default_base_image: base.qcow2
+image_directory: ~/images
+default_base_image: ~/base.qcow2
default_image_gib: 5
default_memory_mib: 2048
default_cpus: 1
@@ -46,7 +52,7 @@ default_generate_host_certificate: true
default_autostart: true
ca_key: ca_key
authorized_keys:
- - .ssh/id_rsa.pub
+ - ~/.ssh/id_rsa.pub
~~~
~~~{#ssh_key_pub .file}