aboutsummaryrefslogtreecommitdiff
path: root/src/house.rs
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2022-05-26 16:36:41 -0400
committerCara Salter <cara@devcara.com>2022-05-26 16:37:20 -0400
commit77fa95a342f09953e3207ea0346135301ffe2664 (patch)
tree5a53f154671a54993bafbfd904a6c447d486d45c /src/house.rs
parentee9be2d32e47a998858219362dd42f927aa8ce42 (diff)
downloadsolarlib-77fa95a342f09953e3207ea0346135301ffe2664.tar.gz
solarlib-77fa95a342f09953e3207ea0346135301ffe2664.zip
Project rename1.2.1
Diffstat (limited to 'src/house.rs')
-rw-r--r--src/house.rs247
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);
- }
-
-}