use crate::libvirt_lib_structures::XMLUuid; use std::net::{IpAddr, Ipv4Addr}; /// Network forward information #[derive(serde::Serialize, serde::Deserialize, Debug)] #[serde(rename = "forward")] pub struct NetworkForwardXML { #[serde(rename(serialize = "@mode"))] pub mode: String, #[serde( default, rename(serialize = "@dev"), skip_serializing_if = "String::is_empty" )] pub dev: String, } /// Network bridge information #[derive(serde::Serialize, serde::Deserialize, Debug)] #[serde(rename = "bridge")] pub struct NetworkBridgeXML { #[serde(rename(serialize = "@name"))] pub name: String, } /// Network DNS information #[derive(serde::Serialize, serde::Deserialize, Debug)] #[serde(rename = "dns")] pub struct NetworkDNSXML { pub forwarder: NetworkDNSForwarderXML, } /// Network DNS information #[derive(serde::Serialize, serde::Deserialize, Debug)] #[serde(rename = "forwarder")] pub struct NetworkDNSForwarderXML { /// Address of the DNS server #[serde(rename(serialize = "@addr"))] pub addr: Ipv4Addr, } /// Network DNS information #[derive(serde::Serialize, serde::Deserialize, Debug)] #[serde(rename = "domain")] pub struct NetworkDomainXML { #[serde(rename(serialize = "@name"))] pub name: String, } fn invalid_prefix() -> u32 { u32::MAX } fn invalid_ip() -> IpAddr { IpAddr::V4(Ipv4Addr::BROADCAST) } /// Network ip information #[derive(serde::Serialize, serde::Deserialize, Debug)] #[serde(rename = "ip")] pub struct NetworkIPXML { #[serde(default, rename(serialize = "@family"))] pub family: String, #[serde(rename(serialize = "@address"))] pub address: IpAddr, /// Network Prefix #[serde(rename(serialize = "@prefix"), default = "invalid_prefix")] pub prefix: u32, /// Network Netmask. This field is never serialized, but because we can't know if LibVirt will /// provide us netmask or prefix, we need to handle both of these fields #[serde( rename(serialize = "@netmask"), default = "invalid_ip", skip_serializing )] pub netmask: IpAddr, pub dhcp: Option, } impl NetworkIPXML { pub fn into_xml(mut self) -> anyhow::Result { 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("", &format!("{hosts_xml}")); 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, } #[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)] #[serde(rename = "dhcp")] pub struct NetworkDHCPRangeXML { #[serde(rename(serialize = "@start"))] pub start: IpAddr, #[serde(rename(serialize = "@end"))] pub end: IpAddr, } /// Network information, see https://libvirt.org/formatnetwork.html #[derive(serde::Serialize, serde::Deserialize, Debug)] #[serde(rename = "network")] pub struct NetworkXML { pub name: String, #[serde(skip_serializing_if = "Option::is_none")] pub uuid: Option, #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, #[serde(skip_serializing_if = "Option::is_none")] pub forward: Option, #[serde(skip_serializing_if = "Option::is_none")] pub bridge: Option, #[serde(skip_serializing_if = "Option::is_none")] pub dns: Option, #[serde(skip_serializing_if = "Option::is_none")] pub domain: Option, #[serde(default, rename = "ip")] pub ips: Vec, } impl NetworkXML { pub fn into_xml(mut self) -> anyhow::Result { // A issue with the IPs definition serialization needs them to be serialized aside let mut ips_xml = Vec::with_capacity(self.ips.len()); for ip in self.ips { log::debug!("Serialize {ip:?}"); let ip_xml = ip.into_xml()?; // strip xml tag let start_offset = ip_xml.find("", &format!("{ips_xml}"), 1); Ok(network_xml) } }