nazrin/api/src/model.rs

163 lines
4.3 KiB
Rust
Raw Normal View History

2022-12-30 06:06:14 +00:00
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)?
)
}
}