Use quick-xml to serialize domains definitions
This commit is contained in:
parent
9256b76495
commit
d741e12653
@ -128,7 +128,7 @@ impl Handler<DefineDomainReq> for LibVirtActor {
|
|||||||
type Result = anyhow::Result<XMLUuid>;
|
type Result = anyhow::Result<XMLUuid>;
|
||||||
|
|
||||||
fn handle(&mut self, mut msg: DefineDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, mut msg: DefineDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
let xml = msg.1.into_xml()?;
|
let xml = msg.1.as_xml()?;
|
||||||
|
|
||||||
log::debug!("Define domain:\n{}", xml);
|
log::debug!("Define domain:\n{}", xml);
|
||||||
let domain = Domain::define_xml(&self.m, &xml)?;
|
let domain = Domain::define_xml(&self.m, &xml)?;
|
||||||
|
@ -4,7 +4,7 @@ use crate::libvirt_lib_structures::XMLUuid;
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "os")]
|
#[serde(rename = "os")]
|
||||||
pub struct OSXML {
|
pub struct OSXML {
|
||||||
#[serde(rename(serialize = "@firmware"), default)]
|
#[serde(rename = "@firmware", default)]
|
||||||
pub firmware: String,
|
pub firmware: String,
|
||||||
pub r#type: OSTypeXML,
|
pub r#type: OSTypeXML,
|
||||||
pub loader: Option<OSLoaderXML>,
|
pub loader: Option<OSLoaderXML>,
|
||||||
@ -14,9 +14,9 @@ pub struct OSXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "os")]
|
#[serde(rename = "os")]
|
||||||
pub struct OSTypeXML {
|
pub struct OSTypeXML {
|
||||||
#[serde(rename(serialize = "@arch"))]
|
#[serde(rename = "@arch")]
|
||||||
pub arch: String,
|
pub arch: String,
|
||||||
#[serde(rename(serialize = "@machine"))]
|
#[serde(rename = "@machine")]
|
||||||
pub machine: String,
|
pub machine: String,
|
||||||
#[serde(rename = "$value")]
|
#[serde(rename = "$value")]
|
||||||
pub body: String,
|
pub body: String,
|
||||||
@ -26,7 +26,7 @@ pub struct OSTypeXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "loader")]
|
#[serde(rename = "loader")]
|
||||||
pub struct OSLoaderXML {
|
pub struct OSLoaderXML {
|
||||||
#[serde(rename(serialize = "@secure"))]
|
#[serde(rename = "@secure")]
|
||||||
pub secure: String,
|
pub secure: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,28 +45,28 @@ pub struct ACPIXML {}
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "mac")]
|
#[serde(rename = "mac")]
|
||||||
pub struct NetMacAddress {
|
pub struct NetMacAddress {
|
||||||
#[serde(rename(serialize = "@address"))]
|
#[serde(rename = "@address")]
|
||||||
pub address: String,
|
pub address: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "source")]
|
#[serde(rename = "source")]
|
||||||
pub struct NetIntSourceXML {
|
pub struct NetIntSourceXML {
|
||||||
#[serde(rename(serialize = "@network"))]
|
#[serde(rename = "@network")]
|
||||||
pub network: String,
|
pub network: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "model")]
|
#[serde(rename = "model")]
|
||||||
pub struct NetIntModelXML {
|
pub struct NetIntModelXML {
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "interface")]
|
#[serde(rename = "interface")]
|
||||||
pub struct DomainNetInterfaceXML {
|
pub struct DomainNetInterfaceXML {
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
pub mac: NetMacAddress,
|
pub mac: NetMacAddress,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
@ -78,24 +78,24 @@ pub struct DomainNetInterfaceXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "input")]
|
#[serde(rename = "input")]
|
||||||
pub struct DomainInputXML {
|
pub struct DomainInputXML {
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "backend")]
|
#[serde(rename = "backend")]
|
||||||
pub struct TPMBackendXML {
|
pub struct TPMBackendXML {
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
|
|
||||||
#[serde(rename(serialize = "@version"))]
|
#[serde(rename = "@version")]
|
||||||
pub r#version: String,
|
pub r#version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "tpm")]
|
#[serde(rename = "tpm")]
|
||||||
pub struct TPMDeviceXML {
|
pub struct TPMDeviceXML {
|
||||||
#[serde(rename(serialize = "@model"))]
|
#[serde(rename = "@model")]
|
||||||
pub model: String,
|
pub model: String,
|
||||||
pub backend: TPMBackendXML,
|
pub backend: TPMBackendXML,
|
||||||
}
|
}
|
||||||
@ -133,9 +133,9 @@ pub struct DevicesXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "graphics")]
|
#[serde(rename = "graphics")]
|
||||||
pub struct GraphicsXML {
|
pub struct GraphicsXML {
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
#[serde(rename(serialize = "@socket"))]
|
#[serde(rename = "@socket")]
|
||||||
pub socket: String,
|
pub socket: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ pub struct VideoXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "model")]
|
#[serde(rename = "model")]
|
||||||
pub struct VideoModelXML {
|
pub struct VideoModelXML {
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,9 +158,9 @@ pub struct VideoModelXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "disk")]
|
#[serde(rename = "disk")]
|
||||||
pub struct DiskXML {
|
pub struct DiskXML {
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
#[serde(rename(serialize = "@device"))]
|
#[serde(rename = "@device")]
|
||||||
pub r#device: String,
|
pub r#device: String,
|
||||||
|
|
||||||
pub driver: DiskDriverXML,
|
pub driver: DiskDriverXML,
|
||||||
@ -176,27 +176,27 @@ pub struct DiskXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "driver")]
|
#[serde(rename = "driver")]
|
||||||
pub struct DiskDriverXML {
|
pub struct DiskDriverXML {
|
||||||
#[serde(rename(serialize = "@name"))]
|
#[serde(rename = "@name")]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
#[serde(default, rename(serialize = "@cache"))]
|
#[serde(default, rename = "@cache")]
|
||||||
pub r#cache: String,
|
pub r#cache: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "source")]
|
#[serde(rename = "source")]
|
||||||
pub struct DiskSourceXML {
|
pub struct DiskSourceXML {
|
||||||
#[serde(rename(serialize = "@file"))]
|
#[serde(rename = "@file")]
|
||||||
pub file: String,
|
pub file: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "target")]
|
#[serde(rename = "target")]
|
||||||
pub struct DiskTargetXML {
|
pub struct DiskTargetXML {
|
||||||
#[serde(rename(serialize = "@dev"))]
|
#[serde(rename = "@dev")]
|
||||||
pub dev: String,
|
pub dev: String,
|
||||||
#[serde(rename(serialize = "@bus"))]
|
#[serde(rename = "@bus")]
|
||||||
pub bus: String,
|
pub bus: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,34 +207,26 @@ pub struct DiskReadOnlyXML {}
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "boot")]
|
#[serde(rename = "boot")]
|
||||||
pub struct DiskBootXML {
|
pub struct DiskBootXML {
|
||||||
#[serde(rename(serialize = "@order"))]
|
#[serde(rename = "@order")]
|
||||||
pub order: String,
|
pub order: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "address")]
|
#[serde(rename = "address")]
|
||||||
pub struct DiskAddressXML {
|
pub struct DiskAddressXML {
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
#[serde(
|
#[serde(
|
||||||
default,
|
default,
|
||||||
skip_serializing_if = "Option::is_none",
|
skip_serializing_if = "Option::is_none",
|
||||||
rename(serialize = "@controller")
|
rename = "@controller"
|
||||||
)]
|
)]
|
||||||
pub r#controller: Option<String>,
|
pub r#controller: Option<String>,
|
||||||
#[serde(rename(serialize = "@bus"))]
|
#[serde(rename = "@bus")]
|
||||||
pub r#bus: String,
|
pub r#bus: String,
|
||||||
#[serde(
|
#[serde(default, skip_serializing_if = "Option::is_none", rename = "@target")]
|
||||||
default,
|
|
||||||
skip_serializing_if = "Option::is_none",
|
|
||||||
rename(serialize = "@target")
|
|
||||||
)]
|
|
||||||
pub r#target: Option<String>,
|
pub r#target: Option<String>,
|
||||||
#[serde(
|
#[serde(default, skip_serializing_if = "Option::is_none", rename = "@unit")]
|
||||||
default,
|
|
||||||
skip_serializing_if = "Option::is_none",
|
|
||||||
rename(serialize = "@unit")
|
|
||||||
)]
|
|
||||||
pub r#unit: Option<String>,
|
pub r#unit: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +234,7 @@ pub struct DiskAddressXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "memory")]
|
#[serde(rename = "memory")]
|
||||||
pub struct DomainMemoryXML {
|
pub struct DomainMemoryXML {
|
||||||
#[serde(rename(serialize = "@unit"))]
|
#[serde(rename = "@unit")]
|
||||||
pub unit: String,
|
pub unit: String,
|
||||||
|
|
||||||
#[serde(rename = "$value")]
|
#[serde(rename = "$value")]
|
||||||
@ -252,11 +244,11 @@ pub struct DomainMemoryXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "topology")]
|
#[serde(rename = "topology")]
|
||||||
pub struct DomainCPUTopology {
|
pub struct DomainCPUTopology {
|
||||||
#[serde(rename(serialize = "@sockets"))]
|
#[serde(rename = "@sockets")]
|
||||||
pub sockets: usize,
|
pub sockets: usize,
|
||||||
#[serde(rename(serialize = "@cores"))]
|
#[serde(rename = "@cores")]
|
||||||
pub cores: usize,
|
pub cores: usize,
|
||||||
#[serde(rename(serialize = "@threads"))]
|
#[serde(rename = "@threads")]
|
||||||
pub threads: usize,
|
pub threads: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +262,7 @@ pub struct DomainVCPUXML {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "cpu")]
|
#[serde(rename = "cpu")]
|
||||||
pub struct DomainCPUXML {
|
pub struct DomainCPUXML {
|
||||||
#[serde(rename(serialize = "@mode"))]
|
#[serde(rename = "@mode")]
|
||||||
pub mode: String,
|
pub mode: String,
|
||||||
pub topology: Option<DomainCPUTopology>,
|
pub topology: Option<DomainCPUTopology>,
|
||||||
}
|
}
|
||||||
@ -280,7 +272,7 @@ pub struct DomainCPUXML {
|
|||||||
#[serde(rename = "domain")]
|
#[serde(rename = "domain")]
|
||||||
pub struct DomainXML {
|
pub struct DomainXML {
|
||||||
/// Domain type (kvm)
|
/// Domain type (kvm)
|
||||||
#[serde(rename(serialize = "@type"))]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
|
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -310,37 +302,12 @@ pub struct DomainXML {
|
|||||||
impl DomainXML {
|
impl DomainXML {
|
||||||
/// Decode Domain structure from XML definition
|
/// Decode Domain structure from XML definition
|
||||||
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)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turn this domain into its XML definition
|
/// Turn this domain into its XML definition
|
||||||
pub fn into_xml(mut self) -> anyhow::Result<String> {
|
pub fn as_xml(&self) -> anyhow::Result<String> {
|
||||||
// A issue with the disks & network interface definition serialization needs them to be serialized aside
|
Ok(quick_xml::se::to_string(self)?)
|
||||||
let mut devices_xml = Vec::with_capacity(self.devices.disks.len());
|
|
||||||
for disk in self.devices.disks {
|
|
||||||
let disk_xml = serde_xml_rs::to_string(&disk)?;
|
|
||||||
let start_offset = disk_xml.find("<disk").unwrap();
|
|
||||||
devices_xml.push(disk_xml[start_offset..].to_string());
|
|
||||||
}
|
|
||||||
for network in self.devices.net_interfaces {
|
|
||||||
let network_xml = serde_xml_rs::to_string(&network)?;
|
|
||||||
let start_offset = network_xml.find("<interface").unwrap();
|
|
||||||
devices_xml.push(network_xml[start_offset..].to_string());
|
|
||||||
}
|
|
||||||
for input in self.devices.inputs {
|
|
||||||
let input_xml = serde_xml_rs::to_string(&input)?;
|
|
||||||
let start_offset = input_xml.find("<input").unwrap();
|
|
||||||
devices_xml.push(input_xml[start_offset..].to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.devices.disks = vec![];
|
|
||||||
self.devices.net_interfaces = vec![];
|
|
||||||
self.devices.inputs = vec![];
|
|
||||||
|
|
||||||
let mut xml = serde_xml_rs::to_string(&self)?;
|
|
||||||
let disks_xml = devices_xml.join("\n");
|
|
||||||
xml = xml.replacen("<devices>", &format!("<devices>{disks_xml}"), 1);
|
|
||||||
Ok(xml)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user