diff options
author | Cara Salter <cara@devcara.com> | 2022-05-26 16:36:41 -0400 |
---|---|---|
committer | Cara Salter <cara@devcara.com> | 2022-05-26 16:37:20 -0400 |
commit | 77fa95a342f09953e3207ea0346135301ffe2664 (patch) | |
tree | 5a53f154671a54993bafbfd904a6c447d486d45c /src/house.rs | |
parent | ee9be2d32e47a998858219362dd42f927aa8ce42 (diff) | |
download | solarlib-77fa95a342f09953e3207ea0346135301ffe2664.tar.gz solarlib-77fa95a342f09953e3207ea0346135301ffe2664.zip |
Project rename1.2.1
Diffstat (limited to 'src/house.rs')
-rw-r--r-- | src/house.rs | 247 |
1 files changed, 0 insertions, 247 deletions
diff --git a/src/house.rs b/src/house.rs deleted file mode 100644 index abd0eef..0000000 --- a/src/house.rs +++ /dev/null @@ -1,247 +0,0 @@ -/*! - * `House`s are where [crate::waifu::Waifu]s live (the physical hypervisors that - * libvirtd connects to - */ -use crate::waifu::*; -use crate::errors::Error; -use crate::van::Van; -use serde::{Serialize, Deserialize}; -use virt::{connect::Connect, domain::Domain}; -use std::process::{ExitStatus}; -use std::os::unix::process::ExitStatusExt; -use rand::Rng; - -use tokio::{process::Command}; - -#[derive(Serialize, Deserialize, Debug)] -pub enum Address { - IP(String), - Domain(String) -} - -impl ToString for Address { - fn to_string(&self) -> String { - match self { - Address::IP(s) => s.clone(), - Address::Domain(s) => s.clone(), - } - } -} - -/// Defines a "house" where waifus live -#[derive(Debug, Serialize, Deserialize)] -pub struct House { - /// Hostname - pub name: String, - /// FQDN or IP address, a way to talk to the house - pub address: String, - - /// Whether or not the House is local (same machine) or remote (networked machine) - pub remote: bool, - - /// Connection to the House, if available - #[serde(skip)] - con: Option<Connect>, -} - -impl House { - /// Creates a new House based on a libvirtd connect URL - /// - /// Example: - /// ``` - /// use waifulib::house::House; - /// let mut h: House = House::new("test:///default".to_string()).unwrap(); - /// ``` - pub fn new(url: String) -> Result<Self, Error> { - let c = Connect::open(&url.clone())?; - - let remote = if url.contains("qemu:///") || url.contains("localhost") || url.contains("127.0.0.1") { - true - } else { - false - }; - - // If the connection succeeds, we've got one! - Ok(Self { - name: c.get_hostname()?, - address: c.get_uri()?, - remote, - con: Some(c), - }) - } - - /// Lists the "inhabitants" of the House (the [Waifu]s on the machine - /// - /// ``` - /// use waifulib::house::House; - /// let mut h: House = House::new("test:///default".to_string()).unwrap(); - /// - /// assert_eq!(h.inhabitants().unwrap().len(), 1); - /// ``` - pub fn inhabitants(&mut self) -> Result<Vec<Waifu>, Error> { - match &self.con { - Some(c) => { - let domains = c.list_all_domains(0)?; - - let mut waifus: Vec<Waifu> = Vec::new(); - - for d in domains.iter() { - waifus.push(d.clone().try_into()?); - } - Ok(waifus) - }, - None => { - return Err(Error::Connection("Domain connection was None".to_string())); - } - } - } - - /// Introduces a new Waifu into the House, taking care of everything needed to make the VM run - /// fine - /// - /// If the installation image doesn't exist in the default libvirtd pool, this will fail with - /// [`Error::MissingImage`][crate::errors::Error::MissingImage]. - /// - /// ``` - /// use waifulib::house::House - /// - /// let mut h: House = House::new("test:///default".to_string()).unwrap(); - /// - /// h.introduce("test-2", 1024, 1, 20000, "test.iso").unwrap(); - /// ``` - pub async fn introduce(&mut self, name: String, max_mem: Memory, max_cpus: CpuCount, disk_size_mb: u64, van: Van) -> Result<Waifu, Error> { - // Check for image on host machine - - if self.remote { - let mut output = Command::new("ssh") - .args([ - "-oStrictHostKeyChecking=accept-new", - &self.address.clone(), - "stat", - &format!("/var/lib/libvirt/images/{}", van.make_pretty_name().clone()) - ]) - .output() - .await?; - - if output.status != ExitStatus::from_raw(0) { - return Err(Error::MissingImage(van.name.clone())); - } - - // Allocate VM disk - output = Command::new("ssh") - .args([ - "-oStrictHostKeyChecking=accept-new", - &self.address.clone(), - "qemu-img", - "create", - "-f", - "qcow2", - &format!("/var/lib/libvirt/images/{}.qcow2", name.clone()), - &format!("{}M", disk_size_mb) - ]) - .output() - .await?; - - if output.status != ExitStatus::from_raw(0) { - return Err(Error::Allocation(String::from_utf8(output.stdout).unwrap())); - } - } else { - // It's local - let mut output = Command::new("stat") - .args([ - &format!("/var/lib/libvirt/images/{}", van.make_pretty_name().clone()), - ]) - .output() - .await?; - - if output.status != ExitStatus::from_raw(0) { - return Err(Error::MissingImage(van.name.clone())); - } - - output = Command::new("qemu-img") - .args([ - "create", - "-f", - "qcow2", - &format!("/var/lib/libvirt/images/{}.qcow2", name.clone()), - &format!("{}M", disk_size_mb) - ]) - .output() - .await?; - - if output.status != ExitStatus::from_raw(0) { - return Err(Error::Allocation(String::from_utf8(output.stdout).unwrap())); - } - } - - let uuid = uuid::Uuid::new_v4(); - - // Let's get that XML ready - let mut buf: Vec<u8> = vec![]; - - crate::templates::vm_xml( - &mut buf, - name.clone(), - uuid.to_string(), - random_mac().clone(), - true, - max_mem.0, - max_cpus.0, - "blank".to_string() - )?; - - let buf = String::from_utf8(buf).unwrap(); - - println!("{}", buf); - - let dom: Domain = match &self.con { - Some(c) => { - let dom = Domain::define_xml(&c, &buf)?; - - dom.create()?; - - dom - }, - None => { - return Err(Error::Connection("Connection was None".to_string())); - } - }; - - dom.try_into() - } - -} - -fn random_mac() -> String { - let mut addr = rand::thread_rng().gen::<[u8; 6]>(); - addr[0] = (addr[0] | 2) & 0xfe; - mac_address::MacAddress::new(addr).to_string() -} - -#[cfg(test)] -mod test { - use super::*; - /// Kind of a stupid test, but just a sanity check to make sure that [ToString] impl up above - /// is still working - #[test] - fn addr_to_string() { - let a: Address = Address::IP("127.0.0.1".to_string()); - let d: Address = Address::Domain("example.com".to_string()); - - assert_eq!(String::from("127.0.0.1"), a.to_string()); - assert_eq!("example.com".to_string(), d.to_string()); - } - - #[test] - fn connect_to_house() { - let _: House = House::new("test:///default".to_string()).unwrap(); - } - - #[test] - fn list_inhabitants() { - let mut h: House = House::new("test:///default".to_string()).unwrap(); - - assert_eq!(h.inhabitants().unwrap().len(), 1); - } - -} |