163 lines
4.3 KiB
Rust
163 lines
4.3 KiB
Rust
|
use serde::{Deserialize, Serialize};
|
||
|
use std::{fmt, net::Ipv4Addr, str::FromStr};
|
||
|
use trust_dns_proto::rr::Name;
|
||
|
|
||
|
use crate::net::{cidr::CidrV4, mac::MacAddr};
|
||
|
|
||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||
|
#[repr(u32)]
|
||
|
pub enum DomainState {
|
||
|
NoState = 0u32,
|
||
|
Running,
|
||
|
Blocked,
|
||
|
Paused,
|
||
|
ShuttingDown,
|
||
|
ShutOff,
|
||
|
Crashed,
|
||
|
Suspended,
|
||
|
Unknown(u32),
|
||
|
}
|
||
|
|
||
|
impl Default for DomainState {
|
||
|
fn default() -> Self {
|
||
|
Self::NoState
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl From<u32> for DomainState {
|
||
|
fn from(value: u32) -> Self {
|
||
|
match value {
|
||
|
0 => Self::NoState,
|
||
|
1 => Self::Running,
|
||
|
2 => Self::Blocked,
|
||
|
3 => Self::Paused,
|
||
|
4 => Self::ShuttingDown,
|
||
|
5 => Self::ShutOff,
|
||
|
6 => Self::Crashed,
|
||
|
7 => Self::Suspended,
|
||
|
other => Self::Unknown(other),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl fmt::Display for DomainState {
|
||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
|
write!(
|
||
|
f,
|
||
|
"{}",
|
||
|
match self {
|
||
|
Self::NoState => "no state".to_owned(),
|
||
|
Self::Running => "running".to_owned(),
|
||
|
Self::Blocked => "blocked".to_owned(),
|
||
|
Self::Paused => "paused".to_owned(),
|
||
|
Self::ShuttingDown => "shutting down".to_owned(),
|
||
|
Self::ShutOff => "shut off".to_owned(),
|
||
|
Self::Crashed => "crashed".to_owned(),
|
||
|
Self::Suspended => "suspended".to_owned(),
|
||
|
Self::Unknown(code) => format!("unknown ({})", code),
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Struct representing a VM instance.
|
||
|
#[derive(Debug, Serialize, Deserialize)]
|
||
|
pub struct Instance {
|
||
|
pub name: String,
|
||
|
pub uuid: uuid::Uuid,
|
||
|
pub lease: Option<Lease>,
|
||
|
pub state: DomainState,
|
||
|
}
|
||
|
|
||
|
/// Struct representing a logical "lease" held by a VM.
|
||
|
#[derive(Debug, Serialize, Deserialize)]
|
||
|
pub struct Lease {
|
||
|
/// The IPv4 address held by the Lease
|
||
|
pub addr: CidrV4,
|
||
|
/// The MAC address associated by the Lease
|
||
|
pub mac_addr: MacAddr,
|
||
|
}
|
||
|
|
||
|
/// Struct representing a subnet used by the host for virtual
|
||
|
/// networking.
|
||
|
#[derive(Debug, Serialize, Deserialize)]
|
||
|
pub struct Subnet {
|
||
|
/// The name of the interface the subnet is accessible via.
|
||
|
pub ifname: IfaceStr,
|
||
|
pub data: SubnetData,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Serialize, Deserialize)]
|
||
|
pub struct SubnetData {
|
||
|
/// The network information for the subnet.
|
||
|
pub network: CidrV4,
|
||
|
/// The first host address that can be assigned dynamically
|
||
|
/// on the subnet.
|
||
|
pub start_host: Ipv4Addr,
|
||
|
/// The last host address that can be assigned dynamically
|
||
|
/// on the subnet.
|
||
|
pub end_host: Ipv4Addr,
|
||
|
/// The default gateway for the subnet.
|
||
|
pub gateway4: Option<Ipv4Addr>,
|
||
|
/// The primary DNS server for the subnet.
|
||
|
pub dns: Vec<Ipv4Addr>,
|
||
|
/// The base domain used for DNS lookup.
|
||
|
pub domain_name: Option<Name>,
|
||
|
}
|
||
|
|
||
|
/// A wrapper struct for [u8; 16], representing the maximum length
|
||
|
/// for an interface's name.
|
||
|
#[derive(Debug, Serialize, Deserialize)]
|
||
|
pub struct IfaceStr {
|
||
|
name: [u8; 16],
|
||
|
}
|
||
|
|
||
|
impl AsRef<[u8]> for IfaceStr {
|
||
|
fn as_ref(&self) -> &[u8] {
|
||
|
&self.name
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Serialize, Deserialize)]
|
||
|
pub enum ParseError {
|
||
|
BadSize(String),
|
||
|
}
|
||
|
|
||
|
impl fmt::Display for ParseError {
|
||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
|
write!(f, "Interface name must be at most 15 characters")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl std::error::Error for ParseError {}
|
||
|
|
||
|
impl FromStr for IfaceStr {
|
||
|
type Err = ParseError;
|
||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||
|
if s.bytes().len() > 15 {
|
||
|
Err(Self::Err::BadSize(s.to_owned()))
|
||
|
} else {
|
||
|
Ok(IfaceStr {
|
||
|
name: {
|
||
|
let mut ifstr = [0u8; 16];
|
||
|
let bytes = s.as_bytes();
|
||
|
ifstr[..bytes.len()].copy_from_slice(&bytes[..bytes.len()]);
|
||
|
ifstr
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl fmt::Display for IfaceStr {
|
||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
|
write!(
|
||
|
f,
|
||
|
"{}",
|
||
|
std::str::from_utf8(&self.name)
|
||
|
.map(|a| a.trim_end_matches(char::from(0)))
|
||
|
.map_err(|_| fmt::Error)?
|
||
|
)
|
||
|
}
|
||
|
}
|