Refacto structures definition
This commit is contained in:
177
virtweb_backend/src/libvirt_lib_structures/network.rs
Normal file
177
virtweb_backend/src/libvirt_lib_structures/network.rs
Normal file
@ -0,0 +1,177 @@
|
||||
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<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)]
|
||||
#[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<XMLUuid>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub title: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub description: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub forward: Option<NetworkForwardXML>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub bridge: Option<NetworkBridgeXML>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub dns: Option<NetworkDNSXML>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub domain: Option<NetworkDomainXML>,
|
||||
#[serde(default, rename = "ip")]
|
||||
pub ips: Vec<NetworkIPXML>,
|
||||
}
|
||||
|
||||
impl NetworkXML {
|
||||
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)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user