Can get domains screenshots
This commit is contained in:
@ -2,8 +2,11 @@ use crate::app_config::AppConfig;
|
||||
use crate::libvirt_lib_structures::{DomainState, DomainXML, DomainXMLUuid};
|
||||
use crate::libvirt_rest_structures::*;
|
||||
use actix::{Actor, Context, Handler, Message};
|
||||
use image::ImageOutputFormat;
|
||||
use std::io::Cursor;
|
||||
use virt::connect::Connect;
|
||||
use virt::domain::Domain;
|
||||
use virt::stream::Stream;
|
||||
use virt::sys;
|
||||
use virt::sys::VIR_DOMAIN_XML_SECURE;
|
||||
|
||||
@ -225,3 +228,36 @@ impl Handler<ResumeDomainReq> for LibVirtActor {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "anyhow::Result<Vec<u8>>")]
|
||||
pub struct ScreenshotDomainReq(pub DomainXMLUuid);
|
||||
|
||||
impl Handler<ScreenshotDomainReq> for LibVirtActor {
|
||||
type Result = anyhow::Result<Vec<u8>>;
|
||||
|
||||
fn handle(&mut self, msg: ScreenshotDomainReq, _ctx: &mut Self::Context) -> Self::Result {
|
||||
log::debug!("Take screenshot of domain:\n{}", msg.0.as_string());
|
||||
let domain = Domain::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
||||
|
||||
let stream = Stream::new(&self.m, 0)?;
|
||||
domain.screenshot(&stream, 0, 0)?;
|
||||
|
||||
let mut screen_out = Vec::with_capacity(1000000);
|
||||
let mut buff = [0u8; 1000];
|
||||
loop {
|
||||
let size = stream.recv(&mut buff)?;
|
||||
|
||||
if size == 0 {
|
||||
break;
|
||||
}
|
||||
screen_out.extend_from_slice(&buff[0..size]);
|
||||
}
|
||||
|
||||
let image = image::load_from_memory(&screen_out)?;
|
||||
let mut png_out = Cursor::new(Vec::new());
|
||||
image.write_to(&mut png_out, ImageOutputFormat::Png)?;
|
||||
|
||||
Ok(png_out.into_inner())
|
||||
}
|
||||
}
|
||||
|
@ -130,3 +130,17 @@ pub async fn resume(client: LibVirtReq, id: web::Path<SingleVMUUidReq>) -> HttpR
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Take a screenshot of a VM
|
||||
pub async fn screenshot(client: LibVirtReq, id: web::Path<SingleVMUUidReq>) -> HttpResult {
|
||||
Ok(match client.screenshot_domain(id.uid).await {
|
||||
Ok(b) => HttpResponse::Ok().content_type("image/png").body(b),
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
"Failed to take the screenshot of a domain {:?} ! {e}",
|
||||
id.uid
|
||||
);
|
||||
HttpResponse::InternalServerError().json("Failed to take the screenshot of the domain!")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -67,4 +67,9 @@ impl LibVirtClient {
|
||||
pub async fn resume_domain(&self, id: DomainXMLUuid) -> anyhow::Result<()> {
|
||||
self.0.send(libvirt_actor::ResumeDomainReq(id)).await?
|
||||
}
|
||||
|
||||
/// Take a screenshot of the domain
|
||||
pub async fn screenshot_domain(&self, id: DomainXMLUuid) -> anyhow::Result<Vec<u8>> {
|
||||
self.0.send(libvirt_actor::ScreenshotDomainReq(id)).await?
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +150,10 @@ async fn main() -> std::io::Result<()> {
|
||||
web::get().to(vm_controller::suspend),
|
||||
)
|
||||
.route("/api/vm/{uid}/resume", web::get().to(vm_controller::resume))
|
||||
.route(
|
||||
"/api/vm/{uid}/screenshot",
|
||||
web::get().to(vm_controller::screenshot),
|
||||
)
|
||||
})
|
||||
.bind(&AppConfig::get().listen_address)?
|
||||
.run()
|
||||
|
Reference in New Issue
Block a user