From bd1218eca88438d28afd4d171a2505ecc9c0bb23 Mon Sep 17 00:00:00 2001 From: Cara Salter Date: Fri, 27 May 2022 11:59:53 -0400 Subject: planet: Utility methods for managing state New functions: - get_status - shutdown - start - pause In short, a way for users of the lib to manage the state of their VMs. --- src/planet.rs | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 11 deletions(-) (limited to 'src/planet.rs') diff --git a/src/planet.rs b/src/planet.rs index c29fb69..004f223 100644 --- a/src/planet.rs +++ b/src/planet.rs @@ -1,4 +1,4 @@ -use std::convert::TryFrom; +use std::{convert::TryFrom, sync::Arc}; use virt::{domain::{Domain, DomainState}}; use serde::{Serialize, Deserialize}; @@ -7,7 +7,7 @@ use crate::errors::Error; /** * Defines the amount of memory a planet has */ -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] pub struct Memory(pub u64); impl From for Memory { @@ -19,7 +19,7 @@ impl From for Memory { /** * Defines the number of vCPUs a planet has */ -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] pub struct CpuCount(pub u64); impl From for CpuCount { @@ -37,7 +37,7 @@ impl From for CpuCount { * be (de)serialized, and, if needed across a network, should be recreated from the `host` and * `uuid` attributes using [virt::domain::lookup_from_uuid_string] */ -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct Planet { /// The reference name of the machine pub name: String, @@ -58,7 +58,7 @@ pub struct Planet { pub cpu_count: CpuCount, #[serde(skip)] - domain: Option, + domain: Option>, } impl PartialEq for Planet { @@ -103,7 +103,7 @@ impl TryFrom for Planet { uuid: d.get_uuid_string()?, mem: d.get_max_memory()?.into(), cpu_count: d.get_max_vcpus()?.into(), - domain: Some(d), + domain: Some(Arc::new(d)), }) } } @@ -138,6 +138,8 @@ impl TryFrom<&Domain> for Planet { None }; + let new_d = Domain::lookup_by_uuid_string(&c, &d.get_uuid_string()?)?; + Ok(Self { name: d.get_name()?, host: c.get_hostname()?, @@ -145,13 +147,12 @@ impl TryFrom<&Domain> for Planet { uuid: d.get_uuid_string()?, mem: d.get_max_memory()?.into(), cpu_count: d.get_max_vcpus()?.into(), - domain: Some(*d), + domain: Some(Arc::new(new_d)), }) } } -#[repr(u32)] -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug, PartialEq)] pub enum Health { Unknown = 0, Running = 1, @@ -163,9 +164,27 @@ pub enum Health { GuestSuspended = 7 } +impl TryFrom for Health { + type Error = Error; + fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Health::Unknown), + 1 => Ok(Health::Running), + 2 => Ok(Health::Blocked), + 3 => Ok(Health::Paused), + 4 => Ok(Health::ShuttingDown), + 5 => Ok(Health::ShutDown), + 6 => Ok(Health::Crashed), + 7 => Ok(Health::GuestSuspended), + _ => { + Err(Error::Other(String::from("Invalid Planet state"))) + } + } + } +} impl Planet { fn get_status(&self) -> Result { - let d = match self.domain { + let d = match &self.domain { Some(d) => d, None => { return Err(Error::Other(String::from("No domain connection found"))); @@ -174,6 +193,96 @@ impl Planet { let state = d.get_state()?; - Ok(state.0 as Health) + Ok(state.0.try_into()?) + } + + fn shutdown(&self) -> Result<(), Error> { + let d = match &self.domain { + Some(d) => d, + None => { + return Err(Error::Other(String::from("No domain connection found"))); + } + }; + + d.shutdown()?; + + Ok(()) + } + + fn start(&self) -> Result<(), Error> { + let d = match &self.domain { + Some(d) => d, + None => { + return Err(Error::Other(String::from("No domain connection found"))); + } + }; + + d.create()?; + + Ok(()) + } + + fn pause(&self) -> Result<(), Error> { + let d = match &self.domain { + Some(d) => d, + None => { + return Err(Error::Other(String::from("No domain connection found"))); + } + }; + + d.suspend()?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + use crate::star::Star; + + #[test] + fn domain_status() { + let mut s = Star::new("test:///default".to_string()).unwrap(); + + let p = &s.inhabitants().unwrap()[0]; + + let p_status = p.get_status().unwrap(); + + assert_eq!(p_status, Health::Running); + } + + #[test] + fn domain_shutdown() { + let mut s = Star::new("test:///default".to_string()).unwrap(); + + let p = &s.inhabitants().unwrap()[0]; + + p.shutdown().unwrap(); + + assert_eq!(p.get_status().unwrap(), Health::ShutDown); + } + + #[test] + fn domain_startup() { + let mut s = Star::new("test:///default".to_string()).unwrap(); + + let p = &s.inhabitants().unwrap()[0]; + + p.start().unwrap(); + + assert_eq!(p.get_status().unwrap(), Health::Running); + } + + #[test] + fn domain_pause() { + let mut s = Star::new("test:///default".to_string()).unwrap(); + + let p = &s.inhabitants().unwrap()[0]; + + p.pause().unwrap(); + + assert_eq!(p.get_status().unwrap(), Health::Paused); } } -- cgit v1.2.3