Refacto structures definition

This commit is contained in:
2023-12-28 19:29:26 +01:00
parent f7777fe085
commit 9d4f19822d
20 changed files with 1860 additions and 1839 deletions

View File

@ -0,0 +1,258 @@
use crate::libvirt_lib_structures::network::*;
use crate::libvirt_lib_structures::XMLUuid;
use crate::libvirt_rest_structures::LibVirtStructError::StructureExtraction;
use crate::utils::net_utils::{extract_ipv4, extract_ipv6};
use ipnetwork::{Ipv4Network, Ipv6Network};
use lazy_regex::regex;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
#[derive(serde::Serialize, serde::Deserialize, Copy, Clone, Debug)]
pub enum NetworkForwardMode {
NAT,
Isolated,
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub struct DHCPv4HostReservation {
mac: String,
name: String,
ip: Ipv4Addr,
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub struct IPv4DHCPConfig {
start: Ipv4Addr,
end: Ipv4Addr,
hosts: Vec<DHCPv4HostReservation>,
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub struct IPV4Config {
bridge_address: Ipv4Addr,
prefix: u32,
dhcp: Option<IPv4DHCPConfig>,
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub struct DHCPv6HostReservation {
name: String,
ip: Ipv6Addr,
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub struct IPv6DHCPConfig {
start: Ipv6Addr,
end: Ipv6Addr,
hosts: Vec<DHCPv6HostReservation>,
}
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub struct IPV6Config {
bridge_address: Ipv6Addr,
prefix: u32,
dhcp: Option<IPv6DHCPConfig>,
}
/// Network configuration
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
pub struct NetworkInfo {
pub name: String,
pub uuid: Option<XMLUuid>,
title: Option<String>,
description: Option<String>,
forward_mode: NetworkForwardMode,
device: Option<String>,
bridge_name: Option<String>,
dns_server: Option<Ipv4Addr>,
domain: Option<String>,
ip_v4: Option<IPV4Config>,
ip_v6: Option<IPV6Config>,
}
impl NetworkInfo {
pub fn as_virt_network(&self) -> anyhow::Result<NetworkXML> {
if !regex!("^[a-zA-Z0-9]+$").is_match(&self.name) {
return Err(StructureExtraction("network name is invalid!").into());
}
if let Some(n) = &self.title {
if n.contains('\n') {
return Err(StructureExtraction("Network title contain newline char!").into());
}
}
if let Some(dev) = &self.device {
if !regex!("^[a-zA-Z0-9]+$").is_match(dev) {
return Err(StructureExtraction("Network device name is invalid!").into());
}
}
if let Some(bridge) = &self.bridge_name {
if !regex!("^[a-zA-Z0-9]+$").is_match(bridge) {
return Err(StructureExtraction("Network bridge name is invalid!").into());
}
}
if let Some(domain) = &self.domain {
if !regex!("^[a-zA-Z0-9.]+$").is_match(domain) {
return Err(StructureExtraction("Domain name is invalid!").into());
}
}
let mut ips = Vec::with_capacity(2);
if let Some(ipv4) = &self.ip_v4 {
if ipv4.prefix > 32 {
return Err(StructureExtraction("IPv4 prefix is invalid!").into());
}
ips.push(NetworkIPXML {
family: "ipv4".to_string(),
address: IpAddr::V4(ipv4.bridge_address),
prefix: ipv4.prefix,
netmask: Ipv4Network::new(ipv4.bridge_address, ipv4.prefix as u8)
.unwrap()
.mask()
.into(),
dhcp: ipv4.dhcp.as_ref().map(|dhcp| NetworkDHCPXML {
range: NetworkDHCPRangeXML {
start: IpAddr::V4(dhcp.start),
end: IpAddr::V4(dhcp.end),
},
hosts: dhcp
.hosts
.iter()
.map(|c| NetworkDHCPHostXML {
mac: c.mac.to_string(),
name: c.name.to_string(),
ip: c.ip.into(),
})
.collect::<Vec<_>>(),
}),
})
}
if let Some(ipv6) = &self.ip_v6 {
ips.push(NetworkIPXML {
family: "ipv6".to_string(),
address: IpAddr::V6(ipv6.bridge_address),
prefix: ipv6.prefix,
netmask: Ipv6Network::new(ipv6.bridge_address, ipv6.prefix as u8)
.unwrap()
.mask()
.into(),
dhcp: ipv6.dhcp.as_ref().map(|dhcp| NetworkDHCPXML {
range: NetworkDHCPRangeXML {
start: IpAddr::V6(dhcp.start),
end: IpAddr::V6(dhcp.end),
},
hosts: dhcp
.hosts
.iter()
.map(|h| NetworkDHCPHostXML {
mac: "".to_string(),
name: h.name.to_string(),
ip: h.ip.into(),
})
.collect(),
}),
})
}
Ok(NetworkXML {
name: self.name.to_string(),
uuid: self.uuid,
title: self.title.clone(),
description: self.description.clone(),
forward: match self.forward_mode {
NetworkForwardMode::NAT => Some(NetworkForwardXML {
mode: "nat".to_string(),
dev: self.device.clone().unwrap_or_default(),
}),
NetworkForwardMode::Isolated => None,
},
bridge: self.bridge_name.clone().map(|b| NetworkBridgeXML {
name: b.to_string(),
}),
dns: self.dns_server.map(|addr| NetworkDNSXML {
forwarder: NetworkDNSForwarderXML { addr },
}),
domain: self.domain.clone().map(|name| NetworkDomainXML { name }),
ips,
})
}
pub fn from_xml(xml: NetworkXML) -> anyhow::Result<Self> {
Ok(Self {
name: xml.name,
uuid: xml.uuid,
title: xml.title,
description: xml.description,
forward_mode: match xml.forward {
None => NetworkForwardMode::Isolated,
Some(_) => NetworkForwardMode::NAT,
},
device: xml
.forward
.map(|f| match f.dev.is_empty() {
true => None,
false => Some(f.dev),
})
.unwrap_or(None),
bridge_name: xml.bridge.map(|b| b.name),
dns_server: xml.dns.map(|d| d.forwarder.addr),
domain: xml.domain.map(|d| d.name),
ip_v4: xml
.ips
.iter()
.find(|i| i.family != "ipv6")
.map(|i| IPV4Config {
bridge_address: extract_ipv4(i.address),
prefix: match i.prefix {
u32::MAX => ipnetwork::ipv4_mask_to_prefix(extract_ipv4(i.netmask))
.expect("Failed to convert IPv4 netmask to network")
as u32,
p => p,
},
dhcp: i.dhcp.as_ref().map(|d| IPv4DHCPConfig {
start: extract_ipv4(d.range.start),
end: extract_ipv4(d.range.end),
hosts: d
.hosts
.iter()
.map(|h| DHCPv4HostReservation {
mac: h.mac.to_string(),
name: h.name.to_string(),
ip: extract_ipv4(h.ip),
})
.collect(),
}),
}),
ip_v6: xml
.ips
.iter()
.find(|i| i.family == "ipv6")
.map(|i| IPV6Config {
bridge_address: extract_ipv6(i.address),
prefix: match i.prefix {
u32::MAX => ipnetwork::ipv6_mask_to_prefix(extract_ipv6(i.netmask))
.expect("Failed to convert IPv6 netmask to network")
as u32,
p => p,
},
dhcp: i.dhcp.as_ref().map(|d| IPv6DHCPConfig {
start: extract_ipv6(d.range.start),
end: extract_ipv6(d.range.end),
hosts: d
.hosts
.iter()
.map(|h| DHCPv6HostReservation {
name: h.name.to_string(),
ip: extract_ipv6(h.ip),
})
.collect(),
}),
}),
})
}
}