summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-07-25 10:45:27 +0300
committerLars Wirzenius <liw@liw.fi>2021-07-25 11:44:44 +0300
commit40f951a3adbbba94942e007434946a2192eb8989 (patch)
tree47653653c827b3899d95a4bf37e8ce5d528c02ff
parentbe53a50f86c3f9dcbc003d2ced9824829ee81f19 (diff)
downloadvmadm-40f951a3adbbba94942e007434946a2192eb8989.tar.gz
feat: allow use to add a VM on virtual networks
Sponsored-by: author
-rw-r--r--src/cmd/config.rs4
-rw-r--r--src/cmd/spec.rs10
-rw-r--r--src/config.rs3
-rw-r--r--src/install.rs22
-rw-r--r--src/spec.rs1
-rw-r--r--vmadm.md57
6 files changed, 91 insertions, 6 deletions
diff --git a/src/cmd/config.rs b/src/cmd/config.rs
index 396f089..0a78a64 100644
--- a/src/cmd/config.rs
+++ b/src/cmd/config.rs
@@ -6,7 +6,9 @@ use crate::config::Configuration;
/// The `config` sub-command.
///
-/// Write the actual run-time configuration to stdout.
+/// Write the actual run-time configuration to stdout as JSON. We
+/// convert the config to JSON to make it clear we parse it the right
+/// way.
pub fn config(config: &Configuration) -> Result<(), std::io::Error> {
let config = serde_json::to_vec(&config).unwrap();
std::io::stdout().write_all(&config)?;
diff --git a/src/cmd/spec.rs b/src/cmd/spec.rs
index b41f234..7922cb5 100644
--- a/src/cmd/spec.rs
+++ b/src/cmd/spec.rs
@@ -6,11 +6,11 @@ use crate::spec::Specification;
/// The `spec` sub-command.
///
-/// Write the actual VM specifications to stdout.
+/// Write the actual VM specifications to stdout as JSON. We convert
+/// the spec to JSON to make it more clear that we parse the config
+/// and spec in the right way.
pub fn spec(specs: &[Specification]) -> Result<(), std::io::Error> {
- for spec in specs {
- let spec = serde_yaml::to_vec(&spec).unwrap();
- std::io::stdout().write_all(&spec)?;
- }
+ let spec = serde_json::to_vec(specs).unwrap();
+ std::io::stdout().write_all(&spec)?;
Ok(())
}
diff --git a/src/config.rs b/src/config.rs
index 7a38942..4786bdb 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -29,6 +29,9 @@ pub struct Configuration {
/// Should new VM be started automatically on host boot?
pub default_autostart: Option<bool>,
+ /// List of default networks to add to hosts.
+ pub default_networks: Option<Vec<String>>,
+
/// Directory where new VM images should be created, if given.
pub image_directory: Option<PathBuf>,
diff --git a/src/install.rs b/src/install.rs
index 94c703c..c84f30a 100644
--- a/src/install.rs
+++ b/src/install.rs
@@ -40,6 +40,7 @@ pub struct VirtInstallArgs {
vcpus: u64,
image: VirtualMachineImage,
init: CloudInitConfig,
+ networks: Vec<String>,
}
impl VirtInstallArgs {
@@ -51,6 +52,7 @@ impl VirtInstallArgs {
vcpus: 1,
image: image.clone(),
init: init.clone(),
+ networks: vec![],
}
}
@@ -88,12 +90,31 @@ impl VirtInstallArgs {
pub fn init(&self) -> &CloudInitConfig {
&self.init
}
+
+ /// Add another network to add to the VM.
+ pub fn add_network(&mut self, network: &str) {
+ self.networks.push(network.to_string());
+ }
+
+ /// Return list of networks to add to the VM.
+ pub fn networks(&self) -> Vec<String> {
+ self.networks.clone()
+ }
}
/// Create new VM with virt-install.
pub fn virt_install(args: &VirtInstallArgs, iso: &Path) -> Result<PathBuf, VirtInstallError> {
args.init().create_iso(&iso)?;
+ let networks: Vec<String> = if args.networks.is_empty() {
+ vec!["--network=default".to_string()]
+ } else {
+ args.networks
+ .iter()
+ .map(|s| format!("--network={}", s))
+ .collect()
+ };
+
let r = Command::new("virt-install")
.arg("--name")
.arg(args.name())
@@ -115,6 +136,7 @@ pub fn virt_install(args: &VirtInstallArgs, iso: &Path) -> Result<PathBuf, VirtI
.arg("--graphics=spice")
.arg("--noautoconsole")
.arg("--quiet")
+ .args(&networks)
.output()
.map_err(VirtInstallError::Run)?;
if !r.status.success() {
diff --git a/src/spec.rs b/src/spec.rs
index bf622c0..1470fdb 100644
--- a/src/spec.rs
+++ b/src/spec.rs
@@ -31,6 +31,7 @@ struct OneVmInputSpecification {
pub cpus: Option<u64>,
pub generate_host_certificate: Option<bool>,
pub autostart: Option<bool>,
+ pub networks: Option<Vec<String>>,
pub ca_key: Option<PathBuf>,
}
diff --git a/vmadm.md b/vmadm.md
index 34ba73f..8c29443 100644
--- a/vmadm.md
+++ b/vmadm.md
@@ -50,6 +50,8 @@ default_memory_mib: 2048
default_cpus: 1
default_generate_host_certificate: true
default_autostart: true
+default_networks:
+- default
ca_key: ca_key
authorized_keys:
- ~/.ssh/id_rsa.pub
@@ -64,6 +66,9 @@ authorized_keys:
"default_cpus": 1,
"default_generate_host_certificate": true,
"default_autostart": true,
+ "default_networks": [
+ "default"
+ ],
"ca_key": "ca_key",
"authorized_keys": [
"~/.ssh/id_rsa.pub"
@@ -71,6 +76,39 @@ authorized_keys:
}
~~~
+~~~{#spec.yaml .file .yaml}
+foo:
+ networks: ["lan", "wan"]
+~~~
+
+~~~{#fullspec.json .file .json}
+[
+ {
+ "name": "foo",
+ "ssh_keys": [
+ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChZ6mVuGLBpW7SarFU/Tu6TemquNxatbMUZuTk8RqVtbkvTKeWFZ5h5tntWPHgST8ykYFaIrr8eYuKQkKdBxHW7H8kejTNwRu/rDbRYX5wxTn4jw4RVopGTpxMlGrWeu5CkWPoLAhQtIzzUAnrDGp9sqG6P1G4ohI61wZMFQta9R2uNxXnnes+e2r4Y78GxmlQH/o0ouI8fBnsxRK0IoSfFs2LutO6wjyzR59FdC9TT7wufd5kXMRzxsmPGeXzNcaqvHGxBvRucGFclCkqSRwk3GNEpXZQhlCIoTIoRu0IPAp/430tlx9zJMhhwDlZsOOXRrFYpdWVMSTAAKECLSYx liw@exolobe1"
+ ],
+ "networks": ["lan", "wan"],
+ "rsa_host_key": null,
+ "rsa_host_cert": null,
+ "dsa_host_key": null,
+ "dsa_host_cert": null,
+ "ecdsa_host_key": null,
+ "ecdsa_host_cert": null,
+ "ed25519_host_key": null,
+ "ed25519_host_cert": null,
+ "base": "~/base.qcow2",
+ "image": "~/images/foo.qcow2",
+ "image_size_gib": 5,
+ "memory_mib": 2048,
+ "cpus": 1,
+ "generate_host_certificate": true,
+ "autostart": true,
+ "ca_key": "ca_key"
+ }
+]
+~~~
+
~~~{#ssh_key_pub .file}
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChZ6mVuGLBpW7SarFU/Tu6TemquNxatbMUZuTk8RqVtbkvTKeWFZ5h5tntWPHgST8ykYFaIrr8eYuKQkKdBxHW7H8kejTNwRu/rDbRYX5wxTn4jw4RVopGTpxMlGrWeu5CkWPoLAhQtIzzUAnrDGp9sqG6P1G4ohI61wZMFQta9R2uNxXnnes+e2r4Y78GxmlQH/o0ouI8fBnsxRK0IoSfFs2LutO6wjyzR59FdC9TT7wufd5kXMRzxsmPGeXzNcaqvHGxBvRucGFclCkqSRwk3GNEpXZQhlCIoTIoRu0IPAp/430tlx9zJMhhwDlZsOOXRrFYpdWVMSTAAKECLSYx liw@exolobe1
~~~
@@ -231,6 +269,25 @@ when I run vmadm config
then stdout, as JSON, matches file fullconfig.json with tilde expansion
~~~
+# Dump specification
+
+This scenario verifies that vmadm can show the actual specification it
+will use.
+
+~~~scenario
+given an installed vmadm
+given a Debian 10 OpenStack cloud image
+given file .config/vmadm/config.yaml from config.yaml
+given file ca_key
+given file .ssh/id_rsa from ssh_key
+given file .ssh/id_rsa.pub from ssh_key_pub
+given file .ssh/config from ssh_config
+given file .ssh/known_hosts from known_hosts
+given file spec.yaml
+given file fullspec.json
+when I run vmadm spec spec.yaml
+then stdout, as JSON, matches file fullspec.json with tilde expansion
+~~~
# Colophon