diff --git a/virtweb_backend/src/controllers/groups_controller.rs b/virtweb_backend/src/controllers/groups_controller.rs new file mode 100644 index 0000000..b9b6c12 --- /dev/null +++ b/virtweb_backend/src/controllers/groups_controller.rs @@ -0,0 +1,16 @@ +use crate::controllers::{HttpResult, LibVirtReq}; +use actix_web::HttpResponse; + +/// Get the list of groups +pub async fn list(client: LibVirtReq) -> HttpResult { + let groups = match client.get_full_groups_list().await { + Err(e) => { + log::error!("Failed to get the list of groups! {e}"); + return Ok(HttpResponse::InternalServerError() + .json(format!("Failed to get the list of groups! {e}"))); + } + Ok(l) => l, + }; + + Ok(HttpResponse::Ok().json(groups)) +} diff --git a/virtweb_backend/src/controllers/mod.rs b/virtweb_backend/src/controllers/mod.rs index 7c41010..1a68d56 100644 --- a/virtweb_backend/src/controllers/mod.rs +++ b/virtweb_backend/src/controllers/mod.rs @@ -8,6 +8,7 @@ use std::io::ErrorKind; pub mod api_tokens_controller; pub mod auth_controller; +pub mod groups_controller; pub mod iso_controller; pub mod network_controller; pub mod nwfilter_controller; diff --git a/virtweb_backend/src/libvirt_client.rs b/virtweb_backend/src/libvirt_client.rs index 640a74f..7adefdb 100644 --- a/virtweb_backend/src/libvirt_client.rs +++ b/virtweb_backend/src/libvirt_client.rs @@ -7,8 +7,9 @@ use crate::libvirt_lib_structures::XMLUuid; use crate::libvirt_rest_structures::hypervisor::HypervisorInfo; use crate::libvirt_rest_structures::net::NetworkInfo; use crate::libvirt_rest_structures::nw_filter::NetworkFilter; -use crate::libvirt_rest_structures::vm::VMInfo; +use crate::libvirt_rest_structures::vm::{VMGroupId, VMInfo}; use actix::Addr; +use std::collections::HashSet; #[derive(Clone)] pub struct LibVirtClient(pub Addr); @@ -107,6 +108,18 @@ impl LibVirtClient { .await? } + /// Get the full list of groups + pub async fn get_full_groups_list(&self) -> anyhow::Result> { + let domains = self.get_full_domains_list().await?; + let mut out = HashSet::new(); + for d in domains { + if let Some(g) = VMInfo::from_domain(d)?.group { + out.insert(g); + } + } + Ok(out.into_iter().collect()) + } + /// Update a network configuration pub async fn update_network( &self, diff --git a/virtweb_backend/src/libvirt_rest_structures/vm.rs b/virtweb_backend/src/libvirt_rest_structures/vm.rs index 195b853..4ce4118 100644 --- a/virtweb_backend/src/libvirt_rest_structures/vm.rs +++ b/virtweb_backend/src/libvirt_rest_structures/vm.rs @@ -10,6 +10,9 @@ use crate::utils::files_utils::convert_size_unit_to_mb; use lazy_regex::regex; use num::Integer; +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash)] +pub struct VMGroupId(pub String); + #[derive(serde::Serialize, serde::Deserialize)] pub enum BootType { UEFI, @@ -61,7 +64,7 @@ pub struct VMInfo { pub description: Option, /// Group associated with the VM (VirtWeb specific field) #[serde(skip_serializing_if = "Option::is_none")] - pub group: Option, + pub group: Option, pub boot_type: BootType, pub architecture: VMArchitecture, /// VM allocated memory, in megabytes @@ -109,7 +112,7 @@ impl VMInfo { } if let Some(group) = &self.group { - if !regex!("^[a-zA-Z0-9]+$").is_match(group) { + if !regex!("^[a-zA-Z0-9]+$").is_match(&group.0) { return Err(StructureExtraction("VM group name is invalid!").into()); } } @@ -294,7 +297,7 @@ impl VMInfo { metadata: Some(DomainMetadataXML { virtweb: DomainMetadataVirtWebXML { ns: "https://virtweb.communiquons.org".to_string(), - group: self.group.clone(), + group: self.group.clone().map(|g| g.0), }, }), os: OSXML { @@ -384,7 +387,13 @@ impl VMInfo { genid: domain.genid.map(XMLUuid), title: domain.title, description: domain.description, - group: domain.metadata.clone().unwrap_or_default().virtweb.group, + group: domain + .metadata + .clone() + .unwrap_or_default() + .virtweb + .group + .map(VMGroupId), boot_type: match domain.os.loader { None => BootType::UEFI, Some(l) => match l.secure.as_str() { diff --git a/virtweb_backend/src/main.rs b/virtweb_backend/src/main.rs index 81ffae9..b6431c0 100644 --- a/virtweb_backend/src/main.rs +++ b/virtweb_backend/src/main.rs @@ -22,7 +22,7 @@ use virtweb_backend::constants::{ MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, SESSION_COOKIE_NAME, }; use virtweb_backend::controllers::{ - api_tokens_controller, auth_controller, iso_controller, network_controller, + api_tokens_controller, auth_controller, groups_controller, iso_controller, network_controller, nwfilter_controller, server_controller, static_controller, vm_controller, }; use virtweb_backend::libvirt_client::LibVirtClient; @@ -210,6 +210,8 @@ async fn main() -> std::io::Result<()> { web::get().to(vm_controller::vnc_token), ) .route("/api/vnc", web::get().to(vm_controller::vnc)) + // Groups controller + .route("/api/groups/list", web::get().to(groups_controller::list)) // Network controller .route( "/api/network/create",