aboutsummaryrefslogtreecommitdiff
path: root/src/planet.rs
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2022-05-27 11:59:53 -0400
committerCara Salter <cara@devcara.com>2022-05-27 11:59:53 -0400
commitbd1218eca88438d28afd4d171a2505ecc9c0bb23 (patch)
tree019237ea676bd70ffcd5e3ff33601a2ca9dcbb16 /src/planet.rs
parent77fa95a342f09953e3207ea0346135301ffe2664 (diff)
downloadsolarlib-bd1218eca88438d28afd4d171a2505ecc9c0bb23.tar.gz
solarlib-bd1218eca88438d28afd4d171a2505ecc9c0bb23.zip
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.
Diffstat (limited to 'src/planet.rs')
-rw-r--r--src/planet.rs131
1 files changed, 120 insertions, 11 deletions
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<u64> for Memory {
@@ -19,7 +19,7 @@ impl From<u64> 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<u64> for CpuCount {
@@ -37,7 +37,7 @@ impl From<u64> 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>,
+ domain: Option<Arc<Domain>>,
}
impl PartialEq for Planet {
@@ -103,7 +103,7 @@ 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(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<u32> for Health {
+ type Error = Error;
+ fn try_from(value: u32) -> Result<Self, Self::Error> {
+ 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<Health, Error> {
- 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);
}
}