diff options
Diffstat (limited to 'src/libvirt.rs')
-rw-r--r-- | src/libvirt.rs | 100 |
1 files changed, 84 insertions, 16 deletions
diff --git a/src/libvirt.rs b/src/libvirt.rs index 2162f3c..e65ea1e 100644 --- a/src/libvirt.rs +++ b/src/libvirt.rs @@ -13,9 +13,45 @@ use virt::domain::{ /// Errors from this module. #[derive(Debug, thiserror::Error)] pub enum VirtError { - /// Error creating virtual machine. - #[error(transparent)] - VirtError(#[from] virt::error::Error), + /// Error connecting to libvirtd. + #[error("couldn't connect to the libvirt daemon")] + Connect(#[source] virt::error::Error), + + /// Error listing domains. + #[error("couldn't list all domains")] + Domains(#[source] virt::error::Error), + + /// Error listing domains. + #[error("couldn't get name of domain")] + GetName(#[source] virt::error::Error), + + /// Error checking if domain is active. + #[error("couldn't check is domain {0} is active")] + IsActive(String, #[source] virt::error::Error), + + /// Error getting domain's XML description. + #[error("couldn't get domain's XML description: {0}")] + GetXml(String, #[source] virt::error::Error), + + /// Error detaching cloud-init ISO from domain + #[error("couldn't detach cloud-init ISO file from domain {0}")] + DetachIso(String, #[source] virt::error::Error), + + /// Error detaching drive from domain + #[error("couldn't create domain {0}")] + Create(String, #[source] virt::error::Error), + + /// Error shutting down domain + #[error("couldn't shut down domain {0}")] + Shutdown(String, #[source] virt::error::Error), + + /// Error undefining domain + #[error("couldn't undefine domain {0}")] + Undefine(String, #[source] virt::error::Error), + + /// Error undefining domain + #[error("couldn't set domain {0} to be autostarted")] + Autostart(String, #[source] virt::error::Error), /// Error doing I/O. #[error(transparent)] @@ -30,18 +66,21 @@ pub struct Libvirt { impl Libvirt { pub fn connect(url: &str) -> Result<Self, VirtError> { debug!("connecting to libvirtd {}", url); - let conn = Connect::open(url)?; + let conn = Connect::open(url).map_err(|err| VirtError::Connect(err))?; Ok(Self { conn }) } fn get_domains(&self) -> Result<Vec<Domain>, VirtError> { debug!("listing all domains"); - Ok(self.conn.list_all_domains(0)?) + Ok(self + .conn + .list_all_domains(0) + .map_err(|err| VirtError::Domains(err))?) } fn get_domain(&self, name: &str) -> Result<Option<Domain>, VirtError> { for domain in self.get_domains()? { - if domain.get_name()? == name { + if get_name(&domain)? == name { return Ok(Some(domain)); } } @@ -51,14 +90,14 @@ impl Libvirt { pub fn names(&self) -> Result<Vec<String>, VirtError> { let mut ret = vec![]; for domain in self.get_domains()? { - ret.push(domain.get_name()?); + ret.push(get_name(&domain)?); } Ok(ret) } pub fn is_active(&self, name: &str) -> Result<bool, VirtError> { if let Some(domain) = self.get_domain(name)? { - Ok(domain.is_active()?) + Ok(is_active(&domain, name)?) } else { Ok(false) } @@ -76,12 +115,14 @@ impl Libvirt { pub fn detach_cloud_init_iso(&self, name: &str) -> Result<(), VirtError> { if let Some(domain) = self.get_domain(name)? { debug!("detaching cloud-init ISO from {}", name); - let xml = domain.get_xml_desc(0)?; + let xml = get_xml(&domain, name)?; let disk = find_iso_xml(&xml); let flags = VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_CURRENT | VIR_DOMAIN_AFFECT_LIVE; if disk.len() > 0 { - domain.detach_device_flags(&disk, flags)?; + domain + .detach_device_flags(&disk, flags) + .map_err(|err| VirtError::DetachIso(name.to_string(), err))?; } } Ok(()) @@ -89,9 +130,11 @@ impl Libvirt { pub fn trigger_start(&self, name: &str) -> Result<(), VirtError> { if let Some(domain) = self.get_domain(name)? { - if !domain.is_active()? { + if !is_active(&domain, name)? { debug!("starting {}", name); - domain.create()?; + domain + .create() + .map_err(|err| VirtError::Create(name.to_string(), err))?; } } Ok(()) @@ -108,8 +151,10 @@ impl Libvirt { pub fn trigger_shutdown(&self, name: &str) -> Result<(), VirtError> { if let Some(domain) = self.get_domain(name)? { debug!("asking {} to shut down", name); - if domain.is_active()? { - domain.shutdown()?; + if is_active(&domain, name)? { + domain + .shutdown() + .map_err(|err| VirtError::Shutdown(name.to_string(), err))?; } } Ok(()) @@ -129,7 +174,9 @@ impl Libvirt { self.shutdown(name)?; debug!("undefine {}", name); - domain.undefine()?; + domain + .undefine() + .map_err(|err| VirtError::Undefine(name.to_string(), err))?; debug!("removing image file {}", image.display()); std::fs::remove_file(image)?; @@ -140,12 +187,33 @@ impl Libvirt { pub fn set_autostart(&self, name: &str, autostart: bool) -> Result<(), VirtError> { if let Some(domain) = self.get_domain(name)? { - domain.set_autostart(autostart)?; + domain + .set_autostart(autostart) + .map_err(|err| VirtError::Autostart(name.to_string(), err))?; } Ok(()) } } +fn get_name(domain: &Domain) -> Result<String, VirtError> { + let name = domain.get_name().map_err(|err| VirtError::GetName(err))?; + Ok(name) +} + +fn is_active(domain: &Domain, name: &str) -> Result<bool, VirtError> { + let is = domain + .is_active() + .map_err(|err| VirtError::IsActive(name.to_string(), err))?; + Ok(is) +} + +fn get_xml(domain: &Domain, name: &str) -> Result<String, VirtError> { + let is = domain + .get_xml_desc(0) + .map_err(|err| VirtError::GetXml(name.to_string(), err))?; + Ok(is) +} + fn wait_until_inactive(domain: &Domain, name: &str) { debug!("waiting for domain {} to become inactive", name); let briefly = Duration::from_millis(1000); |