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!("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}");
 | 
			
		||||
 | 
			
		||||
        let network = Network::define_xml(&self.m, &network_xml)?;
 | 
			
		||||
 
 | 
			
		||||
@@ -5,13 +5,9 @@ use std::net::{IpAddr, Ipv4Addr};
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
			
		||||
#[serde(rename = "forward")]
 | 
			
		||||
pub struct NetworkForwardXML {
 | 
			
		||||
    #[serde(rename(serialize = "@mode"))]
 | 
			
		||||
    #[serde(rename = "@mode")]
 | 
			
		||||
    pub mode: String,
 | 
			
		||||
    #[serde(
 | 
			
		||||
        default,
 | 
			
		||||
        rename(serialize = "@dev"),
 | 
			
		||||
        skip_serializing_if = "String::is_empty"
 | 
			
		||||
    )]
 | 
			
		||||
    #[serde(default, rename = "@dev", skip_serializing_if = "String::is_empty")]
 | 
			
		||||
    pub dev: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -19,7 +15,7 @@ pub struct NetworkForwardXML {
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
			
		||||
#[serde(rename = "bridge")]
 | 
			
		||||
pub struct NetworkBridgeXML {
 | 
			
		||||
    #[serde(rename(serialize = "@name"))]
 | 
			
		||||
    #[serde(rename = "@name")]
 | 
			
		||||
    pub name: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -35,7 +31,7 @@ pub struct NetworkDNSXML {
 | 
			
		||||
#[serde(rename = "forwarder")]
 | 
			
		||||
pub struct NetworkDNSForwarderXML {
 | 
			
		||||
    /// Address of the DNS server
 | 
			
		||||
    #[serde(rename(serialize = "@addr"))]
 | 
			
		||||
    #[serde(rename = "@addr")]
 | 
			
		||||
    pub addr: Ipv4Addr,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -43,7 +39,7 @@ pub struct NetworkDNSForwarderXML {
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
			
		||||
#[serde(rename = "domain")]
 | 
			
		||||
pub struct NetworkDomainXML {
 | 
			
		||||
    #[serde(rename(serialize = "@name"))]
 | 
			
		||||
    #[serde(rename = "@name")]
 | 
			
		||||
    pub name: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -59,50 +55,20 @@ fn invalid_ip() -> IpAddr {
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
			
		||||
#[serde(rename = "ip")]
 | 
			
		||||
pub struct NetworkIPXML {
 | 
			
		||||
    #[serde(default, rename(serialize = "@family"))]
 | 
			
		||||
    #[serde(default, rename = "@family")]
 | 
			
		||||
    pub family: String,
 | 
			
		||||
    #[serde(rename(serialize = "@address"))]
 | 
			
		||||
    #[serde(rename = "@address")]
 | 
			
		||||
    pub address: IpAddr,
 | 
			
		||||
    /// Network Prefix
 | 
			
		||||
    #[serde(rename(serialize = "@prefix"), default = "invalid_prefix")]
 | 
			
		||||
    #[serde(rename = "@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
 | 
			
		||||
    )]
 | 
			
		||||
    #[serde(rename = "@netmask", default = "invalid_ip", skip_serializing)]
 | 
			
		||||
    pub netmask: IpAddr,
 | 
			
		||||
    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 {
 | 
			
		||||
@@ -114,20 +80,20 @@ pub struct NetworkDHCPXML {
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
			
		||||
#[serde(rename = "host")]
 | 
			
		||||
pub struct NetworkDHCPHostXML {
 | 
			
		||||
    #[serde(rename(serialize = "@mac"), default)]
 | 
			
		||||
    pub mac: String,
 | 
			
		||||
    #[serde(rename(serialize = "@name"))]
 | 
			
		||||
    #[serde(rename = "@mac", default, skip_serializing_if = "Option::is_none")]
 | 
			
		||||
    pub mac: Option<String>,
 | 
			
		||||
    #[serde(rename = "@name")]
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    #[serde(rename(serialize = "@ip"))]
 | 
			
		||||
    #[serde(rename = "@ip")]
 | 
			
		||||
    pub ip: IpAddr,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
 | 
			
		||||
#[serde(rename = "dhcp")]
 | 
			
		||||
pub struct NetworkDHCPRangeXML {
 | 
			
		||||
    #[serde(rename(serialize = "@start"))]
 | 
			
		||||
    #[serde(rename = "@start")]
 | 
			
		||||
    pub start: IpAddr,
 | 
			
		||||
    #[serde(rename(serialize = "@end"))]
 | 
			
		||||
    #[serde(rename = "@end")]
 | 
			
		||||
    pub end: IpAddr,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -156,25 +122,10 @@ pub struct NetworkXML {
 | 
			
		||||
 | 
			
		||||
impl NetworkXML {
 | 
			
		||||
    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)?;
 | 
			
		||||
        log::trace!("Serialize network XML start: {network_xml}");
 | 
			
		||||
 | 
			
		||||
        let ips_xml = ips_xml.join("\n");
 | 
			
		||||
        network_xml = network_xml.replacen("</network>", &format!("{ips_xml}</network>"), 1);
 | 
			
		||||
        Ok(network_xml)
 | 
			
		||||
    pub fn as_xml(&self) -> anyhow::Result<String> {
 | 
			
		||||
        Ok(quick_xml::se::to_string(self)?)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@ impl NetworkInfo {
 | 
			
		||||
                        .hosts
 | 
			
		||||
                        .iter()
 | 
			
		||||
                        .map(|c| NetworkDHCPHostXML {
 | 
			
		||||
                            mac: c.mac.to_string(),
 | 
			
		||||
                            mac: Some(c.mac.to_string()),
 | 
			
		||||
                            name: c.name.to_string(),
 | 
			
		||||
                            ip: c.ip.into(),
 | 
			
		||||
                        })
 | 
			
		||||
@@ -150,7 +150,7 @@ impl NetworkInfo {
 | 
			
		||||
                        .hosts
 | 
			
		||||
                        .iter()
 | 
			
		||||
                        .map(|h| NetworkDHCPHostXML {
 | 
			
		||||
                            mac: "".to_string(),
 | 
			
		||||
                            mac: None,
 | 
			
		||||
                            name: h.name.to_string(),
 | 
			
		||||
                            ip: h.ip.into(),
 | 
			
		||||
                        })
 | 
			
		||||
@@ -221,7 +221,7 @@ impl NetworkInfo {
 | 
			
		||||
                            .hosts
 | 
			
		||||
                            .iter()
 | 
			
		||||
                            .map(|h| DHCPv4HostReservation {
 | 
			
		||||
                                mac: h.mac.to_string(),
 | 
			
		||||
                                mac: h.mac.clone().unwrap_or_default(),
 | 
			
		||||
                                name: h.name.to_string(),
 | 
			
		||||
                                ip: extract_ipv4(h.ip),
 | 
			
		||||
                            })
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user