diff options
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | src/house.rs | 61 | ||||
-rw-r--r-- | src/lib.rs | 4 | ||||
-rw-r--r-- | src/vm.rs | 31 | ||||
-rw-r--r-- | src/waifu.rs | 67 |
5 files changed, 138 insertions, 33 deletions
@@ -7,6 +7,12 @@ edition = "2021" [dependencies] -virt = "0.2" +virt = { git = "https://gitlab.com/libvirt/libvirt-rust.git", rev = "10456b6e59ec73e8ef418cf0a29a9bf33be8ded6" } thiserror = "1" + +[dependencies.serde] +version = "1" +features = [ + "derive" +] diff --git a/src/house.rs b/src/house.rs new file mode 100644 index 0000000..6159c33 --- /dev/null +++ b/src/house.rs @@ -0,0 +1,61 @@ +/*! + * `House`s are where [crate::waifu::Waifu]s live (the physical hypervisors that + * libvirtd connects to + */ +use crate::waifu::*; +use crate::errors::Error; +use serde::{Serialize, Deserialize}; +use std::convert::TryFrom; +use virt::connect::Connect; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + +#[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: Address +} + +impl House { + pub fn new(hostname: String, addr: Address) -> Result<Self, Error> { + let mut c = Connect::open(&format!("qemu+ssh://{}/system", addr.to_string()))?; + + // If the connection succeeds, we've got one! + Ok(Self { + name: hostname.clone(), + address: addr + }) + } +} + +#[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()); + } +} @@ -1,3 +1,5 @@ pub mod errors; -pub mod vm; +pub mod waifu; + +pub mod house; diff --git a/src/vm.rs b/src/vm.rs deleted file mode 100644 index 8e17659..0000000 --- a/src/vm.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::convert::TryFrom; -use virt::{connect::Connect, domain::Domain;}; - -use crate::errors::Error; - - -/** - * Represents a virtual machine, that's active on some server - */ -pub struct VirtualMachine { - /// The assigned name of the VM - pub name: String, - /// The network address of the physical machine that's hosting this machine - pub host_server: String, - /// Whether or not the VM is active - pub is_active: bool, - /// The libvirtd-assigned UUID - pub uuid: String, - /// The network address of the VM - pub addr: Option<String>, - /// How much RAM (in MB) is assigned to the VM - pub assigned_mem_mb: u64, - /// How many vCPUs are assigned to the VM - pub assigned_cpus: u64, -} - -impl TryFrom<Domain> for VirtualMachine { - type Error = Error; - - fn try_from(d: Domain) -> Result<Self, Self::Error> { - diff --git a/src/waifu.rs b/src/waifu.rs new file mode 100644 index 0000000..a7dfba8 --- /dev/null +++ b/src/waifu.rs @@ -0,0 +1,67 @@ +use std::convert::TryFrom; +use virt::{connect::Connect, domain::Domain}; +use serde::{Serialize, Deserialize}; + +use crate::errors::Error; + +type Fqdn = String; + +/** + * Represents a virtual machine, that's active on some server + * + * In keeping with the theme, it's named [Waifu] :) + */ +#[derive(Debug, Serialize, Deserialize)] +pub struct Waifu { + /// The reference name of the machine + pub name: String, + + /// The physical machine where this one lives + pub host: Fqdn, + + /// The network address where this machine can be reached + pub addr: Option<String>, + + /// The amount of RAM (in MB) assigned to this machine + pub mem: u64, + + /// The amount of vCPUs assigned to this machine + pub cpu_count: u64, +} + +impl TryFrom<Domain> for Waifu { + type Error = Error; + + fn try_from(d: Domain) -> Result<Self, Self::Error> { + let c = d.get_connect()?; + + // This... feels wrong + // + // I know it probably works + let addr: Option<String> = if d.is_active()? { + let mut addr: Vec<String> = d + .interface_addresses(virt::domain::VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE, 0)? + .into_iter() + .map(|iface| iface.addrs.clone()) + .filter(|addrs| addrs.get(0).is_some()) + .map(|addrs| addrs.get(0).unwrap().clone().addr) + .collect(); + + if addr.get(0).is_none() { + Some(String::from("localhost")) + } else { + Some(addr.swap_remove(0)) + } + } else { + None + }; + + Ok(Self { + name: d.get_name()?, + host: c.get_hostname()?, + addr, + mem: d.get_max_memory()?, + cpu_count: d.get_max_vcpus()?, + }) + } +} |