Use quick-xml to serialize network definitions
This commit is contained in:
		| @@ -389,7 +389,7 @@ impl Handler<DefineNetwork> for LibVirtActor { | |||||||
|         log::debug!("Define network: {:?}", msg.1); |         log::debug!("Define network: {:?}", msg.1); | ||||||
|  |  | ||||||
|         log::debug!("Source network structure: {:#?}", msg.1); |         log::debug!("Source network structure: {:#?}", msg.1); | ||||||
|         let network_xml = msg.1.into_xml()?; |         let network_xml = msg.1.as_xml()?; | ||||||
|         log::debug!("Define network XML: {network_xml}"); |         log::debug!("Define network XML: {network_xml}"); | ||||||
|  |  | ||||||
|         let network = Network::define_xml(&self.m, &network_xml)?; |         let network = Network::define_xml(&self.m, &network_xml)?; | ||||||
|   | |||||||
| @@ -5,13 +5,9 @@ use std::net::{IpAddr, Ipv4Addr}; | |||||||
| #[derive(serde::Serialize, serde::Deserialize, Debug)] | #[derive(serde::Serialize, serde::Deserialize, Debug)] | ||||||
| #[serde(rename = "forward")] | #[serde(rename = "forward")] | ||||||
| pub struct NetworkForwardXML { | pub struct NetworkForwardXML { | ||||||
|     #[serde(rename(serialize = "@mode"))] |     #[serde(rename = "@mode")] | ||||||
|     pub mode: String, |     pub mode: String, | ||||||
|     #[serde( |     #[serde(default, rename = "@dev", skip_serializing_if = "String::is_empty")] | ||||||
|         default, |  | ||||||
|         rename(serialize = "@dev"), |  | ||||||
|         skip_serializing_if = "String::is_empty" |  | ||||||
|     )] |  | ||||||
|     pub dev: String, |     pub dev: String, | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -19,7 +15,7 @@ pub struct NetworkForwardXML { | |||||||
| #[derive(serde::Serialize, serde::Deserialize, Debug)] | #[derive(serde::Serialize, serde::Deserialize, Debug)] | ||||||
| #[serde(rename = "bridge")] | #[serde(rename = "bridge")] | ||||||
| pub struct NetworkBridgeXML { | pub struct NetworkBridgeXML { | ||||||
|     #[serde(rename(serialize = "@name"))] |     #[serde(rename = "@name")] | ||||||
|     pub name: String, |     pub name: String, | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -35,7 +31,7 @@ pub struct NetworkDNSXML { | |||||||
| #[serde(rename = "forwarder")] | #[serde(rename = "forwarder")] | ||||||
| pub struct NetworkDNSForwarderXML { | pub struct NetworkDNSForwarderXML { | ||||||
|     /// Address of the DNS server |     /// Address of the DNS server | ||||||
|     #[serde(rename(serialize = "@addr"))] |     #[serde(rename = "@addr")] | ||||||
|     pub addr: Ipv4Addr, |     pub addr: Ipv4Addr, | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -43,7 +39,7 @@ pub struct NetworkDNSForwarderXML { | |||||||
| #[derive(serde::Serialize, serde::Deserialize, Debug)] | #[derive(serde::Serialize, serde::Deserialize, Debug)] | ||||||
| #[serde(rename = "domain")] | #[serde(rename = "domain")] | ||||||
| pub struct NetworkDomainXML { | pub struct NetworkDomainXML { | ||||||
|     #[serde(rename(serialize = "@name"))] |     #[serde(rename = "@name")] | ||||||
|     pub name: String, |     pub name: String, | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -59,50 +55,20 @@ fn invalid_ip() -> IpAddr { | |||||||
| #[derive(serde::Serialize, serde::Deserialize, Debug)] | #[derive(serde::Serialize, serde::Deserialize, Debug)] | ||||||
| #[serde(rename = "ip")] | #[serde(rename = "ip")] | ||||||
| pub struct NetworkIPXML { | pub struct NetworkIPXML { | ||||||
|     #[serde(default, rename(serialize = "@family"))] |     #[serde(default, rename = "@family")] | ||||||
|     pub family: String, |     pub family: String, | ||||||
|     #[serde(rename(serialize = "@address"))] |     #[serde(rename = "@address")] | ||||||
|     pub address: IpAddr, |     pub address: IpAddr, | ||||||
|     /// Network Prefix |     /// Network Prefix | ||||||
|     #[serde(rename(serialize = "@prefix"), default = "invalid_prefix")] |     #[serde(rename = "@prefix", default = "invalid_prefix")] | ||||||
|     pub prefix: u32, |     pub prefix: u32, | ||||||
|     /// Network Netmask. This field is never serialized, but because we can't know if LibVirt will |     /// 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 |     /// provide us netmask or prefix, we need to handle both of these fields | ||||||
|     #[serde( |     #[serde(rename = "@netmask", default = "invalid_ip", skip_serializing)] | ||||||
|         rename(serialize = "@netmask"), |  | ||||||
|         default = "invalid_ip", |  | ||||||
|         skip_serializing |  | ||||||
|     )] |  | ||||||
|     pub netmask: IpAddr, |     pub netmask: IpAddr, | ||||||
|     pub dhcp: Option<NetworkDHCPXML>, |     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)] | #[derive(serde::Serialize, serde::Deserialize, Debug)] | ||||||
| #[serde(rename = "dhcp")] | #[serde(rename = "dhcp")] | ||||||
| pub struct NetworkDHCPXML { | pub struct NetworkDHCPXML { | ||||||
| @@ -114,20 +80,20 @@ pub struct NetworkDHCPXML { | |||||||
| #[derive(serde::Serialize, serde::Deserialize, Debug)] | #[derive(serde::Serialize, serde::Deserialize, Debug)] | ||||||
| #[serde(rename = "host")] | #[serde(rename = "host")] | ||||||
| pub struct NetworkDHCPHostXML { | pub struct NetworkDHCPHostXML { | ||||||
|     #[serde(rename(serialize = "@mac"), default)] |     #[serde(rename = "@mac", default, skip_serializing_if = "Option::is_none")] | ||||||
|     pub mac: String, |     pub mac: Option<String>, | ||||||
|     #[serde(rename(serialize = "@name"))] |     #[serde(rename = "@name")] | ||||||
|     pub name: String, |     pub name: String, | ||||||
|     #[serde(rename(serialize = "@ip"))] |     #[serde(rename = "@ip")] | ||||||
|     pub ip: IpAddr, |     pub ip: IpAddr, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(serde::Serialize, serde::Deserialize, Debug)] | #[derive(serde::Serialize, serde::Deserialize, Debug)] | ||||||
| #[serde(rename = "dhcp")] | #[serde(rename = "dhcp")] | ||||||
| pub struct NetworkDHCPRangeXML { | pub struct NetworkDHCPRangeXML { | ||||||
|     #[serde(rename(serialize = "@start"))] |     #[serde(rename = "@start")] | ||||||
|     pub start: IpAddr, |     pub start: IpAddr, | ||||||
|     #[serde(rename(serialize = "@end"))] |     #[serde(rename = "@end")] | ||||||
|     pub end: IpAddr, |     pub end: IpAddr, | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -156,25 +122,10 @@ pub struct NetworkXML { | |||||||
|  |  | ||||||
| impl NetworkXML { | impl NetworkXML { | ||||||
|     pub fn parse_xml(xml: &str) -> anyhow::Result<Self> { |     pub fn parse_xml(xml: &str) -> anyhow::Result<Self> { | ||||||
|         Ok(serde_xml_rs::from_str(xml)?) |         Ok(quick_xml::de::from_str(xml)?) | ||||||
|     } |     } | ||||||
|     pub fn into_xml(mut self) -> anyhow::Result<String> { |  | ||||||
|         // 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("<ip").unwrap(); |  | ||||||
|             ips_xml.push(ip_xml[start_offset..].to_string()); |  | ||||||
|         } |  | ||||||
|         self.ips = vec![]; |  | ||||||
|  |  | ||||||
|         let mut network_xml = serde_xml_rs::to_string(&self)?; |     pub fn as_xml(&self) -> anyhow::Result<String> { | ||||||
|         log::trace!("Serialize network XML start: {network_xml}"); |         Ok(quick_xml::se::to_string(self)?) | ||||||
|  |  | ||||||
|         let ips_xml = ips_xml.join("\n"); |  | ||||||
|         network_xml = network_xml.replacen("</network>", &format!("{ips_xml}</network>"), 1); |  | ||||||
|         Ok(network_xml) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -123,7 +123,7 @@ impl NetworkInfo { | |||||||
|                         .hosts |                         .hosts | ||||||
|                         .iter() |                         .iter() | ||||||
|                         .map(|c| NetworkDHCPHostXML { |                         .map(|c| NetworkDHCPHostXML { | ||||||
|                             mac: c.mac.to_string(), |                             mac: Some(c.mac.to_string()), | ||||||
|                             name: c.name.to_string(), |                             name: c.name.to_string(), | ||||||
|                             ip: c.ip.into(), |                             ip: c.ip.into(), | ||||||
|                         }) |                         }) | ||||||
| @@ -150,7 +150,7 @@ impl NetworkInfo { | |||||||
|                         .hosts |                         .hosts | ||||||
|                         .iter() |                         .iter() | ||||||
|                         .map(|h| NetworkDHCPHostXML { |                         .map(|h| NetworkDHCPHostXML { | ||||||
|                             mac: "".to_string(), |                             mac: None, | ||||||
|                             name: h.name.to_string(), |                             name: h.name.to_string(), | ||||||
|                             ip: h.ip.into(), |                             ip: h.ip.into(), | ||||||
|                         }) |                         }) | ||||||
| @@ -221,7 +221,7 @@ impl NetworkInfo { | |||||||
|                             .hosts |                             .hosts | ||||||
|                             .iter() |                             .iter() | ||||||
|                             .map(|h| DHCPv4HostReservation { |                             .map(|h| DHCPv4HostReservation { | ||||||
|                                 mac: h.mac.to_string(), |                                 mac: h.mac.clone().unwrap_or_default(), | ||||||
|                                 name: h.name.to_string(), |                                 name: h.name.to_string(), | ||||||
|                                 ip: extract_ipv4(h.ip), |                                 ip: extract_ipv4(h.ip), | ||||||
|                             }) |                             }) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user