summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-08-06 09:41:34 +0300
committerLars Wirzenius <liw@liw.fi>2021-08-06 10:21:58 +0300
commita54cbbb7f3d3750f4c3fea3ba999dac978ec394a (patch)
treeab941b542ff104664af5feb174e97eb271bbfc54 /src/cmd
parent6fc3ad8a6758bb6c764ba208d814c1ab82d764ac (diff)
downloadvmadm-a54cbbb7f3d3750f4c3fea3ba999dac978ec394a.tar.gz
feat: add progress reporting
Sponsored-by: author
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/cloud_init.rs14
-rw-r--r--src/cmd/config.rs5
-rw-r--r--src/cmd/delete.rs12
-rw-r--r--src/cmd/list.rs4
-rw-r--r--src/cmd/new.rs21
-rw-r--r--src/cmd/shutdown.rs12
-rw-r--r--src/cmd/spec.rs5
-rw-r--r--src/cmd/start.rs10
8 files changed, 55 insertions, 28 deletions
diff --git a/src/cmd/cloud_init.rs b/src/cmd/cloud_init.rs
index dc9af66..cfa08f9 100644
--- a/src/cmd/cloud_init.rs
+++ b/src/cmd/cloud_init.rs
@@ -1,8 +1,8 @@
//! The `cloud-init` sub-command.
use crate::cloudinit::{CloudInitConfig, CloudInitError};
+use crate::progress::Progress;
use crate::spec::Specification;
-use log::{debug, info};
use std::path::Path;
/// Errors from this module.
@@ -22,18 +22,22 @@ pub enum CloudInitCommandError {
/// This sub-command generates the cloud-init configuration based on
/// specifications provided by the caller and writes them to files in
/// a directory named by the caller.
-pub fn cloud_init(specs: &[Specification], dirname: &Path) -> Result<(), CloudInitCommandError> {
+pub fn cloud_init(
+ specs: &[Specification],
+ progress: &Progress,
+ dirname: &Path,
+) -> Result<(), CloudInitCommandError> {
for spec in specs {
let dirname = dirname.join(&spec.name);
- info!(
+ progress.chatty(&format!(
"generating cloud-init configuration for {} into {}",
spec.name,
dirname.display()
- );
+ ));
let init = CloudInitConfig::from(spec)?;
- debug!("creating directory {}", dirname.display());
+ progress.chatty(&format!("creating directory {}", dirname.display()));
std::fs::create_dir_all(&dirname)?;
init.create_dir(&dirname)?;
}
diff --git a/src/cmd/config.rs b/src/cmd/config.rs
index 0a78a64..e45f7c0 100644
--- a/src/cmd/config.rs
+++ b/src/cmd/config.rs
@@ -3,13 +3,16 @@
use std::io::Write;
use crate::config::Configuration;
+use crate::progress::Progress;
/// The `config` sub-command.
///
/// 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> {
+pub fn config(config: &Configuration, progress: &Progress) -> Result<(), std::io::Error> {
+ progress.chatty("showing runtime configuration");
+
let config = serde_json::to_vec(&config).unwrap();
std::io::stdout().write_all(&config)?;
Ok(())
diff --git a/src/cmd/delete.rs b/src/cmd/delete.rs
index fbb6ab5..620ec98 100644
--- a/src/cmd/delete.rs
+++ b/src/cmd/delete.rs
@@ -1,22 +1,26 @@
//! The `delete` sub-command.
use crate::libvirt::{Libvirt, VirtError};
+use crate::progress::Progress;
use crate::spec::Specification;
-use log::info;
/// Delete VMs corresponding to specifications.
///
/// Delete the VM corresponding to each specification provided by the caller.
-pub fn delete(specs: &[Specification]) -> Result<(), VirtError> {
+pub fn delete(specs: &[Specification], progress: &Progress) -> Result<(), VirtError> {
+ progress.chatty("deleting virtual machines");
+
let libvirt = Libvirt::connect("qemu:///system")?;
for spec in specs {
- info!("asking virtual machine {} to shutdown", spec.name);
+ progress.chatty(&format!("asking virtual machine {} to shutdown", spec.name));
libvirt.trigger_shutdown(&spec.name)?;
}
for spec in specs {
- info!("deleting virtual machine {}", spec.name);
+ progress.step(&format!("deleting virtual machine {}", spec.name));
libvirt.shutdown(&spec.name)?;
libvirt.delete(&spec.name, &spec.image)?;
}
+
+ progress.chatty("deletion successful");
Ok(())
}
diff --git a/src/cmd/list.rs b/src/cmd/list.rs
index 40a1910..1148fd9 100644
--- a/src/cmd/list.rs
+++ b/src/cmd/list.rs
@@ -2,12 +2,14 @@
use crate::config::Configuration;
use crate::libvirt::{Libvirt, VirtError};
+use crate::progress::Progress;
/// The `list` sub-command.
///
/// Return the names of all the virtual machines existing on the
/// libvirt instance.
-pub fn list(_config: &Configuration) -> Result<(), VirtError> {
+pub fn list(_config: &Configuration, progress: &Progress) -> Result<(), VirtError> {
+ progress.chatty("listing virtual machines");
let libvirt = Libvirt::connect("qemu:///system")?;
for name in libvirt.names()? {
println!("{}", name);
diff --git a/src/cmd/new.rs b/src/cmd/new.rs
index 197b3dc..8583ae9 100644
--- a/src/cmd/new.rs
+++ b/src/cmd/new.rs
@@ -4,11 +4,11 @@ use crate::cloudinit::{CloudInitConfig, CloudInitError};
use crate::image::{ImageError, VirtualMachineImage};
use crate::install::{virt_install, VirtInstallArgs, VirtInstallError};
use crate::libvirt::{Libvirt, VirtError};
+use crate::progress::Progress;
use crate::spec::Specification;
use crate::util::wait_for_ssh;
use bytesize::GIB;
-use log::info;
use tempfile::tempdir;
/// Errors returned by this module.
@@ -39,25 +39,27 @@ pub enum NewError {
///
/// Create all the new virtual machines specified by the caller. Wait
/// until each VM's SSH port listens for connections.
-pub fn new(specs: &[Specification]) -> Result<(), NewError> {
+pub fn new(specs: &[Specification], progress: &Progress) -> Result<(), NewError> {
+ progress.chatty("Creating new virtual machines");
+
let libvirt = Libvirt::connect("qemu:///system")?;
for spec in specs {
- info!("creating new VM {}", spec.name);
+ progress.step(&format!("creating new VM {}", spec.name));
- info!("creating cloud-init config");
+ progress.chatty("creating cloud-init config");
let init = CloudInitConfig::from(spec)?;
- info!(
+ progress.chatty(&format!(
"creating VM image {} from {}",
spec.image.display(),
spec.base.display()
- );
+ ));
let image = VirtualMachineImage::new_from_base(&spec.base, &spec.image)?;
- info!("resizing image to {} GiB", spec.image_size_gib);
+ progress.chatty(&format!("resizing image to {} GiB", spec.image_size_gib));
image.resize(spec.image_size_gib * GIB)?;
- info!("creating VM");
+ progress.chatty("creating VM");
let dir = tempdir()?;
let iso = dir.path().join("cloudinit.iso");
let mut args = VirtInstallArgs::new(&spec.name, &image, &init);
@@ -70,12 +72,13 @@ pub fn new(specs: &[Specification]) -> Result<(), NewError> {
}
for spec in specs {
- info!("waiting for {} to open its SSH port", spec.name);
+ progress.chatty(&format!("waiting for {} to open its SSH port", spec.name));
wait_for_ssh(&spec.name);
libvirt.detach_cloud_init_iso(&spec.name)?;
libvirt.set_autostart(&spec.name, spec.autostart)?;
}
+ progress.chatty("creation successful");
Ok(())
}
diff --git a/src/cmd/shutdown.rs b/src/cmd/shutdown.rs
index cdd3069..1226b5c 100644
--- a/src/cmd/shutdown.rs
+++ b/src/cmd/shutdown.rs
@@ -1,19 +1,23 @@
//! The `shutdown` sub-command.
use crate::libvirt::{Libvirt, VirtError};
+use crate::progress::Progress;
use crate::spec::Specification;
-use log::{debug, info};
/// Shut down VMs corresponding to specifications.
-pub fn shutdown(specs: &[Specification]) -> Result<(), VirtError> {
+pub fn shutdown(specs: &[Specification], progress: &Progress) -> Result<(), VirtError> {
+ progress.chatty("shutting down virtual machines");
+
let libvirt = Libvirt::connect("qemu:///system")?;
for spec in specs {
- info!("shutting down virtual machine {}", spec.name);
+ progress.step(&format!("shutting down virtual machine {}", spec.name));
libvirt.trigger_shutdown(&spec.name)?;
}
for spec in specs {
- debug!("waiting for {} to become inactive", spec.name);
+ progress.chatty(&format!("waiting for {} to become inactive", spec.name));
libvirt.wait_for_inactive(&spec.name)?;
}
+
+ progress.chatty("shut down OK");
Ok(())
}
diff --git a/src/cmd/spec.rs b/src/cmd/spec.rs
index 7922cb5..4f1a764 100644
--- a/src/cmd/spec.rs
+++ b/src/cmd/spec.rs
@@ -2,6 +2,7 @@
use std::io::Write;
+use crate::progress::Progress;
use crate::spec::Specification;
/// The `spec` sub-command.
@@ -9,7 +10,9 @@ use crate::spec::Specification;
/// 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> {
+pub fn spec(specs: &[Specification], progress: &Progress) -> Result<(), std::io::Error> {
+ progress.chatty("showing specification for virtual machines");
+
let spec = serde_json::to_vec(specs).unwrap();
std::io::stdout().write_all(&spec)?;
Ok(())
diff --git a/src/cmd/start.rs b/src/cmd/start.rs
index 8e74c49..8590d80 100644
--- a/src/cmd/start.rs
+++ b/src/cmd/start.rs
@@ -1,9 +1,9 @@
//! The `start` sub-command.
use crate::libvirt::{Libvirt, VirtError};
+use crate::progress::Progress;
use crate::spec::Specification;
use crate::util::wait_for_ssh;
-use log::info;
/// Errors from this module.
#[derive(Debug, thiserror::Error)]
@@ -18,14 +18,18 @@ pub enum StartError {
}
/// Start existing VMs corresponding to specifications.
-pub fn start(specs: &[Specification]) -> Result<(), StartError> {
+pub fn start(specs: &[Specification], progress: &Progress) -> Result<(), StartError> {
+ progress.chatty("starting virtual machines");
+
let libvirt = Libvirt::connect("qemu:///system")?;
for spec in specs {
- info!("starting virtual machine {}", spec.name);
+ progress.step(&format!("starting virtual machine {}", spec.name));
libvirt.trigger_start(&spec.name)?;
}
for spec in specs {
wait_for_ssh(&spec.name);
}
+
+ progress.chatty("started OK");
Ok(())
}