Can define IP reservations for networks

This commit is contained in:
2023-12-19 17:57:38 +01:00
parent ed1bd806d7
commit afebe97395
7 changed files with 324 additions and 48 deletions

View File

@ -35,6 +35,7 @@ struct ServerConstraints {
disk_size: LenConstraints,
net_name_size: LenConstraints,
net_title_size: LenConstraints,
dhcp_reservation_host_name: LenConstraints,
}
pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
@ -66,6 +67,8 @@ pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
net_name_size: LenConstraints { min: 2, max: 50 },
net_title_size: LenConstraints { min: 0, max: 50 },
dhcp_reservation_host_name: LenConstraints { min: 2, max: 250 },
},
})
}

View File

@ -432,10 +432,49 @@ pub struct NetworkIPXML {
pub dhcp: Option<NetworkDHCPXML>,
}
impl NetworkIPXML {
pub fn into_xml(mut self) -> anyhow::Result<String> {
let mut hosts_xml = vec![];
if let Some(dhcp) = &mut self.dhcp {
for host in &dhcp.hosts {
let mut host_xml = serde_xml_rs::to_string(&host)?;
// In case of IPv6, mac address should not be specified
host_xml = host_xml.replace("mac=\"\"", "");
// strip xml tag
let start_offset = host_xml.find("<host").unwrap();
hosts_xml.push(host_xml[start_offset..].to_string());
}
dhcp.hosts = vec![];
}
let mut res = serde_xml_rs::to_string(&self)?;
let hosts_xml = hosts_xml.join("\n");
res = res.replace("</dhcp>", &format!("{hosts_xml}</dhcp>"));
Ok(res)
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug)]
#[serde(rename = "dhcp")]
pub struct NetworkDHCPXML {
pub range: NetworkDHCPRangeXML,
#[serde(default, rename = "host", skip_serializing_if = "Vec::is_empty")]
pub hosts: Vec<NetworkDHCPHostXML>,
}
#[derive(serde::Serialize, serde::Deserialize, Debug)]
#[serde(rename = "host")]
pub struct NetworkDHCPHostXML {
#[serde(rename(serialize = "@mac"), default)]
pub mac: String,
#[serde(rename(serialize = "@name"))]
pub name: String,
#[serde(rename(serialize = "@ip"))]
pub ip: IpAddr,
}
#[derive(serde::Serialize, serde::Deserialize, Debug)]
@ -474,7 +513,8 @@ impl NetworkXML {
let mut ips_xml = Vec::with_capacity(self.ips.len());
for ip in self.ips {
log::debug!("Serialize {ip:?}");
let ip_xml = serde_xml_rs::to_string(&ip)?;
let ip_xml = ip.into_xml()?;
// strip xml tag
let start_offset = ip_xml.find("<ip").unwrap();
ips_xml.push(ip_xml[start_offset..].to_string());
}

View File

@ -4,9 +4,9 @@ use crate::libvirt_lib_structures::{
DevicesXML, DiskBootXML, DiskDriverXML, DiskReadOnlyXML, DiskSourceXML, DiskTargetXML, DiskXML,
DomainCPUTopology, DomainCPUXML, DomainInputXML, DomainMemoryXML, DomainNetInterfaceXML,
DomainVCPUXML, DomainXML, FeaturesXML, GraphicsXML, NetIntSourceXML, NetMacAddress,
NetworkDHCPRangeXML, NetworkDHCPXML, NetworkDNSForwarderXML, NetworkDNSXML, NetworkDomainXML,
NetworkForwardXML, NetworkIPXML, NetworkXML, OSLoaderXML, OSTypeXML, TPMBackendXML,
TPMDeviceXML, VideoModelXML, VideoXML, XMLUuid, ACPIXML, OSXML,
NetworkDHCPHostXML, NetworkDHCPRangeXML, NetworkDHCPXML, NetworkDNSForwarderXML, NetworkDNSXML,
NetworkDomainXML, NetworkForwardXML, NetworkIPXML, NetworkXML, OSLoaderXML, OSTypeXML,
TPMBackendXML, TPMDeviceXML, VideoModelXML, VideoXML, XMLUuid, ACPIXML, OSXML,
};
use crate::libvirt_rest_structures::LibVirtStructError::StructureExtraction;
use crate::utils::disks_utils::Disk;
@ -442,18 +442,45 @@ pub enum NetworkForwardMode {
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_range: Option<[Ipv4Addr; 2]>,
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_range: Option<[Ipv6Addr; 2]>,
dhcp: Option<IPv6DHCPConfig>,
}
/// Network configuration
@ -510,11 +537,20 @@ impl NetworkInfo {
.unwrap()
.mask()
.into(),
dhcp: ipv4.dhcp_range.map(|[start, end]| NetworkDHCPXML {
dhcp: ipv4.dhcp.map(|dhcp| NetworkDHCPXML {
range: NetworkDHCPRangeXML {
start: IpAddr::V4(start),
end: IpAddr::V4(end),
start: IpAddr::V4(dhcp.start),
end: IpAddr::V4(dhcp.end),
},
hosts: dhcp
.hosts
.into_iter()
.map(|c| NetworkDHCPHostXML {
mac: c.mac,
name: c.name,
ip: c.ip.into(),
})
.collect::<Vec<_>>(),
}),
})
}
@ -528,11 +564,20 @@ impl NetworkInfo {
.unwrap()
.mask()
.into(),
dhcp: ipv6.dhcp_range.map(|[start, end]| NetworkDHCPXML {
dhcp: ipv6.dhcp.map(|dhcp| NetworkDHCPXML {
range: NetworkDHCPRangeXML {
start: IpAddr::V6(start),
end: IpAddr::V6(end),
start: IpAddr::V6(dhcp.start),
end: IpAddr::V6(dhcp.end),
},
hosts: dhcp
.hosts
.into_iter()
.map(|h| NetworkDHCPHostXML {
mac: "".to_string(),
name: h.name,
ip: h.ip.into(),
})
.collect(),
}),
})
}
@ -588,10 +633,19 @@ impl NetworkInfo {
as u32,
p => p,
},
dhcp_range: i
.dhcp
.as_ref()
.map(|d| [extract_ipv4(d.range.start), extract_ipv4(d.range.end)]),
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
@ -605,10 +659,18 @@ impl NetworkInfo {
as u32,
p => p,
},
dhcp_range: i
.dhcp
.as_ref()
.map(|d| [extract_ipv6(d.range.start), extract_ipv6(d.range.end)]),
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(),
}),
}),
})
}