diff --git a/virtweb_backend/src/actors/libvirt_actor.rs b/virtweb_backend/src/actors/libvirt_actor.rs index 37bfe47..b3883fc 100644 --- a/virtweb_backend/src/actors/libvirt_actor.rs +++ b/virtweb_backend/src/actors/libvirt_actor.rs @@ -1,9 +1,10 @@ use crate::app_config::AppConfig; -use crate::libvirt_lib_structures::{DomainXML, DomainXMLUuid}; +use crate::libvirt_lib_structures::{DomainState, DomainXML, DomainXMLUuid}; use crate::libvirt_rest_structures::*; use actix::{Actor, Context, Handler, Message}; use virt::connect::Connect; use virt::domain::Domain; +use virt::sys; use virt::sys::VIR_DOMAIN_XML_SECURE; pub struct LibVirtActor { @@ -88,3 +89,29 @@ impl Handler for LibVirtActor { DomainXMLUuid::parse_from_str(&domain.get_uuid_string()?) } } + +#[derive(Message)] +#[rtype(result = "anyhow::Result")] +pub struct GetDomainStateReq(pub DomainXMLUuid); + +impl Handler for LibVirtActor { + type Result = anyhow::Result; + + fn handle(&mut self, msg: GetDomainStateReq, _ctx: &mut Self::Context) -> Self::Result { + log::debug!("Get domain state:\n{}", msg.0.as_string()); + let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?; + let (state, _) = domain.get_state()?; + Ok(match state { + sys::VIR_DOMAIN_NOSTATE => DomainState::NoState, + sys::VIR_DOMAIN_RUNNING => DomainState::Running, + sys::VIR_DOMAIN_BLOCKED => DomainState::Blocked, + sys::VIR_DOMAIN_PAUSED => DomainState::Paused, + sys::VIR_DOMAIN_SHUTDOWN => DomainState::Shutdown, + sys::VIR_DOMAIN_SHUTOFF => DomainState::Shutoff, + sys::VIR_DOMAIN_CRASHED => DomainState::Crashed, + sys::VIR_DOMAIN_PMSUSPENDED => DomainState::PowerManagementSuspended, + + _ => DomainState::Other, + }) + } +} diff --git a/virtweb_backend/src/controllers/vm_controller.rs b/virtweb_backend/src/controllers/vm_controller.rs index a63bf91..c094425 100644 --- a/virtweb_backend/src/controllers/vm_controller.rs +++ b/virtweb_backend/src/controllers/vm_controller.rs @@ -1,8 +1,15 @@ use crate::controllers::{HttpResult, LibVirtReq}; -use crate::libvirt_lib_structures::DomainXMLUuid; +use crate::libvirt_lib_structures::{DomainState, DomainXMLUuid}; use crate::libvirt_rest_structures::VMInfo; use actix_web::{web, HttpResponse}; +#[derive(serde::Serialize)] +struct VMInfoAndState { + #[serde(flatten)] + info: VMInfo, + state: DomainState, +} + /// Create a new VM pub async fn create(client: LibVirtReq, req: web::Json) -> HttpResult { let domain = match req.0.to_domain() { @@ -32,5 +39,10 @@ pub async fn get_single(client: LibVirtReq, id: web::Path) -> H } }; - Ok(HttpResponse::Ok().json(VMInfo::from_domain(info)?)) + let state = client.get_domain_state(id.uid).await?; + + Ok(HttpResponse::Ok().json(VMInfoAndState { + info: VMInfo::from_domain(info)?, + state, + })) } diff --git a/virtweb_backend/src/libvirt_client.rs b/virtweb_backend/src/libvirt_client.rs index 8a9d0ef..e3f55c8 100644 --- a/virtweb_backend/src/libvirt_client.rs +++ b/virtweb_backend/src/libvirt_client.rs @@ -1,6 +1,6 @@ use crate::actors::libvirt_actor; use crate::actors::libvirt_actor::LibVirtActor; -use crate::libvirt_lib_structures::{DomainXML, DomainXMLUuid}; +use crate::libvirt_lib_structures::{DomainState, DomainXML, DomainXMLUuid}; use crate::libvirt_rest_structures::HypervisorInfo; use actix::Addr; @@ -22,4 +22,9 @@ impl LibVirtClient { pub async fn update_domain(&self, xml: DomainXML) -> anyhow::Result { self.0.send(libvirt_actor::DefineDomainReq(xml)).await? } + + /// Get the state of a domain + pub async fn get_domain_state(&self, id: DomainXMLUuid) -> anyhow::Result { + self.0.send(libvirt_actor::GetDomainStateReq(id)).await? + } } diff --git a/virtweb_backend/src/libvirt_lib_structures.rs b/virtweb_backend/src/libvirt_lib_structures.rs index 7802fa0..e283d5b 100644 --- a/virtweb_backend/src/libvirt_lib_structures.rs +++ b/virtweb_backend/src/libvirt_lib_structures.rs @@ -73,3 +73,17 @@ pub struct DomainXML { pub on_reboot: String, pub on_crash: String, } + +/// Domain state +#[derive(serde::Serialize, Debug, Copy, Clone)] +pub enum DomainState { + NoState, + Running, + Blocked, + Paused, + Shutdown, + Shutoff, + Crashed, + PowerManagementSuspended, + Other, +}