Can assign a group to VMs
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
91fe291341
commit
55b49699eb
@ -21,7 +21,7 @@ struct VMUuid {
|
|||||||
|
|
||||||
/// Create a new VM
|
/// Create a new VM
|
||||||
pub async fn create(client: LibVirtReq, req: web::Json<VMInfo>) -> HttpResult {
|
pub async fn create(client: LibVirtReq, req: web::Json<VMInfo>) -> HttpResult {
|
||||||
let domain = match req.0.as_tomain() {
|
let domain = match req.0.as_domain() {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to extract domain info! {e}");
|
log::error!("Failed to extract domain info! {e}");
|
||||||
@ -83,6 +83,8 @@ pub async fn get_single(client: LibVirtReq, id: web::Path<SingleVMUUidReq>) -> H
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log::debug!("INFO={info:#?}");
|
||||||
|
|
||||||
let state = client.get_domain_state(id.uid).await?;
|
let state = client.get_domain_state(id.uid).await?;
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(VMInfoAndState {
|
Ok(HttpResponse::Ok().json(VMInfoAndState {
|
||||||
@ -112,7 +114,7 @@ pub async fn update(
|
|||||||
id: web::Path<SingleVMUUidReq>,
|
id: web::Path<SingleVMUUidReq>,
|
||||||
req: web::Json<VMInfo>,
|
req: web::Json<VMInfo>,
|
||||||
) -> HttpResult {
|
) -> HttpResult {
|
||||||
let mut domain = match req.0.as_tomain() {
|
let mut domain = match req.0.as_domain() {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to extract domain info! {e}");
|
log::error!("Failed to extract domain info! {e}");
|
||||||
|
@ -1,7 +1,25 @@
|
|||||||
use crate::libvirt_lib_structures::XMLUuid;
|
use crate::libvirt_lib_structures::XMLUuid;
|
||||||
|
|
||||||
|
/// VirtWeb specific metadata
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Default, Debug, Clone)]
|
||||||
|
#[serde(rename = "virtweb", default)]
|
||||||
|
pub struct DomainMetadataVirtWebXML {
|
||||||
|
#[serde(rename = "@xmlns:virtweb", default)]
|
||||||
|
pub ns: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub group: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Domain metadata
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, Default, Debug, Clone)]
|
||||||
|
#[serde(rename = "metadata")]
|
||||||
|
pub struct DomainMetadataXML {
|
||||||
|
#[serde(rename = "virtweb:metadata", default)]
|
||||||
|
pub virtweb: DomainMetadataVirtWebXML,
|
||||||
|
}
|
||||||
|
|
||||||
/// OS information
|
/// OS information
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "os")]
|
#[serde(rename = "os")]
|
||||||
pub struct OSXML {
|
pub struct OSXML {
|
||||||
#[serde(rename = "@firmware", default)]
|
#[serde(rename = "@firmware", default)]
|
||||||
@ -11,7 +29,7 @@ pub struct OSXML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// OS Type information
|
/// OS Type information
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "os")]
|
#[serde(rename = "os")]
|
||||||
pub struct OSTypeXML {
|
pub struct OSTypeXML {
|
||||||
#[serde(rename = "@arch")]
|
#[serde(rename = "@arch")]
|
||||||
@ -23,7 +41,7 @@ pub struct OSTypeXML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// OS Loader information
|
/// OS Loader information
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "loader")]
|
#[serde(rename = "loader")]
|
||||||
pub struct OSLoaderXML {
|
pub struct OSLoaderXML {
|
||||||
#[serde(rename = "@secure")]
|
#[serde(rename = "@secure")]
|
||||||
@ -31,39 +49,39 @@ pub struct OSLoaderXML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Hypervisor features
|
/// Hypervisor features
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Default)]
|
#[derive(serde::Serialize, serde::Deserialize, Default, Debug)]
|
||||||
#[serde(rename = "features")]
|
#[serde(rename = "features")]
|
||||||
pub struct FeaturesXML {
|
pub struct FeaturesXML {
|
||||||
pub acpi: ACPIXML,
|
pub acpi: ACPIXML,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ACPI feature
|
/// ACPI feature
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Default)]
|
#[derive(serde::Serialize, serde::Deserialize, Default, Debug)]
|
||||||
#[serde(rename = "acpi")]
|
#[serde(rename = "acpi")]
|
||||||
pub struct ACPIXML {}
|
pub struct ACPIXML {}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "mac")]
|
#[serde(rename = "mac")]
|
||||||
pub struct NetMacAddress {
|
pub struct NetMacAddress {
|
||||||
#[serde(rename = "@address")]
|
#[serde(rename = "@address")]
|
||||||
pub address: String,
|
pub address: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "source")]
|
#[serde(rename = "source")]
|
||||||
pub struct NetIntSourceXML {
|
pub struct NetIntSourceXML {
|
||||||
#[serde(rename = "@network")]
|
#[serde(rename = "@network")]
|
||||||
pub network: String,
|
pub network: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "model")]
|
#[serde(rename = "model")]
|
||||||
pub struct NetIntModelXML {
|
pub struct NetIntModelXML {
|
||||||
#[serde(rename = "@type")]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "filterref")]
|
#[serde(rename = "filterref")]
|
||||||
pub struct NetIntFilterParameterXML {
|
pub struct NetIntFilterParameterXML {
|
||||||
#[serde(rename = "@name")]
|
#[serde(rename = "@name")]
|
||||||
@ -72,7 +90,7 @@ pub struct NetIntFilterParameterXML {
|
|||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "filterref")]
|
#[serde(rename = "filterref")]
|
||||||
pub struct NetIntfilterRefXML {
|
pub struct NetIntfilterRefXML {
|
||||||
#[serde(rename = "@filter")]
|
#[serde(rename = "@filter")]
|
||||||
@ -81,7 +99,7 @@ pub struct NetIntfilterRefXML {
|
|||||||
pub parameters: Vec<NetIntFilterParameterXML>,
|
pub parameters: Vec<NetIntFilterParameterXML>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "interface")]
|
#[serde(rename = "interface")]
|
||||||
pub struct DomainNetInterfaceXML {
|
pub struct DomainNetInterfaceXML {
|
||||||
#[serde(rename = "@type")]
|
#[serde(rename = "@type")]
|
||||||
@ -95,14 +113,14 @@ pub struct DomainNetInterfaceXML {
|
|||||||
pub filterref: Option<NetIntfilterRefXML>,
|
pub filterref: Option<NetIntfilterRefXML>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "input")]
|
#[serde(rename = "input")]
|
||||||
pub struct DomainInputXML {
|
pub struct DomainInputXML {
|
||||||
#[serde(rename = "@type")]
|
#[serde(rename = "@type")]
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "backend")]
|
#[serde(rename = "backend")]
|
||||||
pub struct TPMBackendXML {
|
pub struct TPMBackendXML {
|
||||||
#[serde(rename = "@type")]
|
#[serde(rename = "@type")]
|
||||||
@ -112,7 +130,7 @@ pub struct TPMBackendXML {
|
|||||||
pub r#version: String,
|
pub r#version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "tpm")]
|
#[serde(rename = "tpm")]
|
||||||
pub struct TPMDeviceXML {
|
pub struct TPMDeviceXML {
|
||||||
#[serde(rename = "@model")]
|
#[serde(rename = "@model")]
|
||||||
@ -121,7 +139,7 @@ pub struct TPMDeviceXML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Devices information
|
/// Devices information
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "devices")]
|
#[serde(rename = "devices")]
|
||||||
pub struct DevicesXML {
|
pub struct DevicesXML {
|
||||||
/// Graphics (used for VNC)
|
/// Graphics (used for VNC)
|
||||||
@ -150,7 +168,7 @@ pub struct DevicesXML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Graphics information
|
/// Graphics information
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "graphics")]
|
#[serde(rename = "graphics")]
|
||||||
pub struct GraphicsXML {
|
pub struct GraphicsXML {
|
||||||
#[serde(rename = "@type")]
|
#[serde(rename = "@type")]
|
||||||
@ -160,14 +178,14 @@ pub struct GraphicsXML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Video device information
|
/// Video device information
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "video")]
|
#[serde(rename = "video")]
|
||||||
pub struct VideoXML {
|
pub struct VideoXML {
|
||||||
pub model: VideoModelXML,
|
pub model: VideoModelXML,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Video model device information
|
/// Video model device information
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "model")]
|
#[serde(rename = "model")]
|
||||||
pub struct VideoModelXML {
|
pub struct VideoModelXML {
|
||||||
#[serde(rename = "@type")]
|
#[serde(rename = "@type")]
|
||||||
@ -175,7 +193,7 @@ pub struct VideoModelXML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Disk information
|
/// Disk information
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "disk")]
|
#[serde(rename = "disk")]
|
||||||
pub struct DiskXML {
|
pub struct DiskXML {
|
||||||
#[serde(rename = "@type")]
|
#[serde(rename = "@type")]
|
||||||
@ -193,7 +211,7 @@ pub struct DiskXML {
|
|||||||
pub address: Option<DiskAddressXML>,
|
pub address: Option<DiskAddressXML>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "driver")]
|
#[serde(rename = "driver")]
|
||||||
pub struct DiskDriverXML {
|
pub struct DiskDriverXML {
|
||||||
#[serde(rename = "@name")]
|
#[serde(rename = "@name")]
|
||||||
@ -204,14 +222,14 @@ pub struct DiskDriverXML {
|
|||||||
pub r#cache: String,
|
pub r#cache: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "source")]
|
#[serde(rename = "source")]
|
||||||
pub struct DiskSourceXML {
|
pub struct DiskSourceXML {
|
||||||
#[serde(rename = "@file")]
|
#[serde(rename = "@file")]
|
||||||
pub file: String,
|
pub file: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "target")]
|
#[serde(rename = "target")]
|
||||||
pub struct DiskTargetXML {
|
pub struct DiskTargetXML {
|
||||||
#[serde(rename = "@dev")]
|
#[serde(rename = "@dev")]
|
||||||
@ -220,18 +238,18 @@ pub struct DiskTargetXML {
|
|||||||
pub bus: String,
|
pub bus: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "readonly")]
|
#[serde(rename = "readonly")]
|
||||||
pub struct DiskReadOnlyXML {}
|
pub struct DiskReadOnlyXML {}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "boot")]
|
#[serde(rename = "boot")]
|
||||||
pub struct DiskBootXML {
|
pub struct DiskBootXML {
|
||||||
#[serde(rename = "@order")]
|
#[serde(rename = "@order")]
|
||||||
pub order: String,
|
pub order: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "address")]
|
#[serde(rename = "address")]
|
||||||
pub struct DiskAddressXML {
|
pub struct DiskAddressXML {
|
||||||
#[serde(rename = "@type")]
|
#[serde(rename = "@type")]
|
||||||
@ -251,7 +269,7 @@ pub struct DiskAddressXML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Domain RAM information
|
/// Domain RAM information
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "memory")]
|
#[serde(rename = "memory")]
|
||||||
pub struct DomainMemoryXML {
|
pub struct DomainMemoryXML {
|
||||||
#[serde(rename = "@unit")]
|
#[serde(rename = "@unit")]
|
||||||
@ -261,7 +279,7 @@ pub struct DomainMemoryXML {
|
|||||||
pub memory: usize,
|
pub memory: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "topology")]
|
#[serde(rename = "topology")]
|
||||||
pub struct DomainCPUTopology {
|
pub struct DomainCPUTopology {
|
||||||
#[serde(rename = "@sockets")]
|
#[serde(rename = "@sockets")]
|
||||||
@ -272,14 +290,14 @@ pub struct DomainCPUTopology {
|
|||||||
pub threads: usize,
|
pub threads: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "cpu")]
|
#[serde(rename = "cpu")]
|
||||||
pub struct DomainVCPUXML {
|
pub struct DomainVCPUXML {
|
||||||
#[serde(rename = "$value")]
|
#[serde(rename = "$value")]
|
||||||
pub body: usize,
|
pub body: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "cpu")]
|
#[serde(rename = "cpu")]
|
||||||
pub struct DomainCPUXML {
|
pub struct DomainCPUXML {
|
||||||
#[serde(rename = "@mode")]
|
#[serde(rename = "@mode")]
|
||||||
@ -288,7 +306,7 @@ pub struct DomainCPUXML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Domain information, see https://libvirt.org/formatdomain.html
|
/// Domain information, see https://libvirt.org/formatdomain.html
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename = "domain")]
|
#[serde(rename = "domain")]
|
||||||
pub struct DomainXML {
|
pub struct DomainXML {
|
||||||
/// Domain type (kvm)
|
/// Domain type (kvm)
|
||||||
@ -300,6 +318,9 @@ pub struct DomainXML {
|
|||||||
pub genid: Option<uuid::Uuid>,
|
pub genid: Option<uuid::Uuid>,
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub metadata: Option<DomainMetadataXML>,
|
||||||
|
|
||||||
pub os: OSXML,
|
pub os: OSXML,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub features: FeaturesXML,
|
pub features: FeaturesXML,
|
||||||
@ -319,10 +340,32 @@ pub struct DomainXML {
|
|||||||
pub on_crash: String,
|
pub on_crash: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const METADATA_START_MARKER: &str =
|
||||||
|
"<virtweb:metadata xmlns:virtweb=\"https://virtweb.communiquons.org\">";
|
||||||
|
const METADATA_END_MARKER: &str = "</virtweb:metadata>";
|
||||||
|
|
||||||
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(quick_xml::de::from_str(xml)?)
|
let mut res: Self = quick_xml::de::from_str(xml)?;
|
||||||
|
|
||||||
|
// Handle custom metadata parsing issue
|
||||||
|
//
|
||||||
|
// https://github.com/tafia/quick-xml/pull/797
|
||||||
|
if xml.contains(METADATA_START_MARKER) && xml.contains(METADATA_END_MARKER) {
|
||||||
|
let s = xml
|
||||||
|
.split_once(METADATA_START_MARKER)
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
.split_once(METADATA_END_MARKER)
|
||||||
|
.unwrap()
|
||||||
|
.0;
|
||||||
|
let s = format!("<virtweb>{s}</virtweb>");
|
||||||
|
let metadata: DomainMetadataVirtWebXML = quick_xml::de::from_str(&s)?;
|
||||||
|
res.metadata = Some(DomainMetadataXML { virtweb: metadata });
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turn this domain into its XML definition
|
/// Turn this domain into its XML definition
|
||||||
|
@ -59,6 +59,9 @@ pub struct VMInfo {
|
|||||||
pub genid: Option<XMLUuid>,
|
pub genid: Option<XMLUuid>,
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
/// Group associated with the VM (VirtWeb specific field)
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub group: Option<String>,
|
||||||
pub boot_type: BootType,
|
pub boot_type: BootType,
|
||||||
pub architecture: VMArchitecture,
|
pub architecture: VMArchitecture,
|
||||||
/// VM allocated memory, in megabytes
|
/// VM allocated memory, in megabytes
|
||||||
@ -79,7 +82,7 @@ pub struct VMInfo {
|
|||||||
|
|
||||||
impl VMInfo {
|
impl VMInfo {
|
||||||
/// Turn this VM into a domain
|
/// Turn this VM into a domain
|
||||||
pub fn as_tomain(&self) -> anyhow::Result<DomainXML> {
|
pub fn as_domain(&self) -> anyhow::Result<DomainXML> {
|
||||||
if !regex!("^[a-zA-Z0-9]+$").is_match(&self.name) {
|
if !regex!("^[a-zA-Z0-9]+$").is_match(&self.name) {
|
||||||
return Err(StructureExtraction("VM name is invalid!").into());
|
return Err(StructureExtraction("VM name is invalid!").into());
|
||||||
}
|
}
|
||||||
@ -105,6 +108,12 @@ impl VMInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(group) = &self.group {
|
||||||
|
if !regex!("^[a-zA-Z0-9]+$").is_match(group) {
|
||||||
|
return Err(StructureExtraction("VM group name is invalid!").into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.memory < constants::MIN_VM_MEMORY || self.memory > constants::MAX_VM_MEMORY {
|
if self.memory < constants::MIN_VM_MEMORY || self.memory > constants::MAX_VM_MEMORY {
|
||||||
return Err(StructureExtraction("VM memory is invalid!").into());
|
return Err(StructureExtraction("VM memory is invalid!").into());
|
||||||
}
|
}
|
||||||
@ -282,6 +291,12 @@ impl VMInfo {
|
|||||||
title: self.title.clone(),
|
title: self.title.clone(),
|
||||||
description: self.description.clone(),
|
description: self.description.clone(),
|
||||||
|
|
||||||
|
metadata: Some(DomainMetadataXML {
|
||||||
|
virtweb: DomainMetadataVirtWebXML {
|
||||||
|
ns: "https://virtweb.communiquons.org".to_string(),
|
||||||
|
group: self.group.clone(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
os: OSXML {
|
os: OSXML {
|
||||||
r#type: OSTypeXML {
|
r#type: OSTypeXML {
|
||||||
arch: match self.architecture {
|
arch: match self.architecture {
|
||||||
@ -369,6 +384,7 @@ impl VMInfo {
|
|||||||
genid: domain.genid.map(XMLUuid),
|
genid: domain.genid.map(XMLUuid),
|
||||||
title: domain.title,
|
title: domain.title,
|
||||||
description: domain.description,
|
description: domain.description,
|
||||||
|
group: domain.metadata.clone().unwrap_or_default().virtweb.group,
|
||||||
boot_type: match domain.os.loader {
|
boot_type: match domain.os.loader {
|
||||||
None => BootType::UEFI,
|
None => BootType::UEFI,
|
||||||
Some(l) => match l.secure.as_str() {
|
Some(l) => match l.secure.as_str() {
|
||||||
|
@ -79,8 +79,6 @@ function VMListWidget(p: {
|
|||||||
setRunningVMs(new Set([...runningVMs]));
|
setRunningVMs(new Set([...runningVMs]));
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(runningVMs);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableContainer component={Paper}>
|
<TableContainer component={Paper}>
|
||||||
<Table>
|
<Table>
|
||||||
|
Loading…
Reference in New Issue
Block a user