Compare commits
3 Commits
50600e4e56
...
9407d8f0a8
| Author | SHA1 | Date | |
|---|---|---|---|
| 9407d8f0a8 | |||
| 2fefdb97be | |||
| 14c95ac4f7 |
@@ -7,6 +7,7 @@ use std::io::ErrorKind;
|
|||||||
|
|
||||||
pub mod auth_controller;
|
pub mod auth_controller;
|
||||||
pub mod server_controller;
|
pub mod server_controller;
|
||||||
|
pub mod sys_info_controller;
|
||||||
pub mod vm_controller;
|
pub mod vm_controller;
|
||||||
|
|
||||||
/// Custom error to ease controller writing
|
/// Custom error to ease controller writing
|
||||||
|
|||||||
22
remote_backend/src/controllers/sys_info_controller.rs
Normal file
22
remote_backend/src/controllers/sys_info_controller.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
use crate::controllers::HttpResult;
|
||||||
|
use crate::virtweb_client;
|
||||||
|
use actix_web::HttpResponse;
|
||||||
|
|
||||||
|
#[derive(serde::Serialize)]
|
||||||
|
struct SysInfoStatus {
|
||||||
|
allowed: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if system info can be retrieved
|
||||||
|
pub async fn config() -> HttpResult {
|
||||||
|
let info = virtweb_client::get_token_info().await?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json(SysInfoStatus {
|
||||||
|
allowed: info.can_retrieve_system_info(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get current system status
|
||||||
|
pub async fn status() -> HttpResult {
|
||||||
|
Ok(HttpResponse::Ok().json(virtweb_client::get_server_info().await?))
|
||||||
|
}
|
||||||
@@ -3,13 +3,16 @@
|
|||||||
use crate::controllers::HttpResult;
|
use crate::controllers::HttpResult;
|
||||||
use crate::virtweb_client;
|
use crate::virtweb_client;
|
||||||
use crate::virtweb_client::VMUuid;
|
use crate::virtweb_client::VMUuid;
|
||||||
use actix_web::HttpResponse;
|
use actix_web::{web, HttpResponse};
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize)]
|
#[derive(Debug, serde::Serialize)]
|
||||||
pub struct VMInfoAndCaps {
|
pub struct VMInfoAndCaps {
|
||||||
uiid: VMUuid,
|
uiid: VMUuid,
|
||||||
name: String,
|
name: String,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
|
architecture: String,
|
||||||
|
memory: usize,
|
||||||
|
number_vcpu: usize,
|
||||||
can_get_state: bool,
|
can_get_state: bool,
|
||||||
can_start: bool,
|
can_start: bool,
|
||||||
can_shutdown: bool,
|
can_shutdown: bool,
|
||||||
@@ -27,12 +30,15 @@ pub async fn list() -> HttpResult {
|
|||||||
let mut res = vec![];
|
let mut res = vec![];
|
||||||
|
|
||||||
for v in rights.list_vm() {
|
for v in rights.list_vm() {
|
||||||
let vm_info = virtweb_client::get_vm_info(v).await?;
|
let vm_info = virtweb_client::vm_info(v).await?;
|
||||||
|
|
||||||
res.push(VMInfoAndCaps {
|
res.push(VMInfoAndCaps {
|
||||||
uiid: vm_info.uuid,
|
uiid: vm_info.uuid,
|
||||||
name: vm_info.name,
|
name: vm_info.name,
|
||||||
description: vm_info.description.clone(),
|
description: vm_info.description.clone(),
|
||||||
|
architecture: vm_info.architecture.to_string(),
|
||||||
|
memory: vm_info.memory,
|
||||||
|
number_vcpu: vm_info.number_vcpu,
|
||||||
can_get_state: rights.is_route_allowed("GET", &v.route_state()),
|
can_get_state: rights.is_route_allowed("GET", &v.route_state()),
|
||||||
can_start: rights.is_route_allowed("GET", &v.route_start()),
|
can_start: rights.is_route_allowed("GET", &v.route_start()),
|
||||||
can_shutdown: rights.is_route_allowed("GET", &v.route_shutdown()),
|
can_shutdown: rights.is_route_allowed("GET", &v.route_shutdown()),
|
||||||
@@ -46,3 +52,57 @@ pub async fn list() -> HttpResult {
|
|||||||
|
|
||||||
Ok(HttpResponse::Ok().json(res))
|
Ok(HttpResponse::Ok().json(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct ReqPath {
|
||||||
|
uid: VMUuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the state of a VM
|
||||||
|
pub async fn state(path: web::Path<ReqPath>) -> HttpResult {
|
||||||
|
Ok(HttpResponse::Ok().json(virtweb_client::vm_state(path.uid).await?))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start a VM
|
||||||
|
pub async fn start(path: web::Path<ReqPath>) -> HttpResult {
|
||||||
|
virtweb_client::vm_start(path.uid).await?;
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shutdown a VM
|
||||||
|
pub async fn shutdown(path: web::Path<ReqPath>) -> HttpResult {
|
||||||
|
virtweb_client::vm_shutdown(path.uid).await?;
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Kill a VM
|
||||||
|
pub async fn kill(path: web::Path<ReqPath>) -> HttpResult {
|
||||||
|
virtweb_client::vm_kill(path.uid).await?;
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reset a VM
|
||||||
|
pub async fn reset(path: web::Path<ReqPath>) -> HttpResult {
|
||||||
|
virtweb_client::vm_reset(path.uid).await?;
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Suspend a VM
|
||||||
|
pub async fn suspend(path: web::Path<ReqPath>) -> HttpResult {
|
||||||
|
virtweb_client::vm_suspend(path.uid).await?;
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resume a VM
|
||||||
|
pub async fn resume(path: web::Path<ReqPath>) -> HttpResult {
|
||||||
|
virtweb_client::vm_resume(path.uid).await?;
|
||||||
|
Ok(HttpResponse::Ok().finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Take the screenshot of a VM
|
||||||
|
pub async fn screenshot(path: web::Path<ReqPath>) -> HttpResult {
|
||||||
|
let screenshot = virtweb_client::vm_screenshot(path.uid).await?;
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.insert_header(("content-type", "image/png"))
|
||||||
|
.body(screenshot))
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ use actix_web::{web, App, HttpServer};
|
|||||||
use light_openid::basic_state_manager::BasicStateManager;
|
use light_openid::basic_state_manager::BasicStateManager;
|
||||||
use remote_backend::app_config::AppConfig;
|
use remote_backend::app_config::AppConfig;
|
||||||
use remote_backend::constants;
|
use remote_backend::constants;
|
||||||
use remote_backend::controllers::{auth_controller, server_controller, vm_controller};
|
use remote_backend::controllers::{
|
||||||
|
auth_controller, server_controller, sys_info_controller, vm_controller,
|
||||||
|
};
|
||||||
use remote_backend::middlewares::auth_middleware::AuthChecker;
|
use remote_backend::middlewares::auth_middleware::AuthChecker;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -80,6 +82,31 @@ async fn main() -> std::io::Result<()> {
|
|||||||
web::get().to(auth_controller::sign_out),
|
web::get().to(auth_controller::sign_out),
|
||||||
)
|
)
|
||||||
.route("/api/vm/list", web::get().to(vm_controller::list))
|
.route("/api/vm/list", web::get().to(vm_controller::list))
|
||||||
|
.route("/api/vm/{uid}/state", web::get().to(vm_controller::state))
|
||||||
|
.route("/api/vm/{uid}/start", web::get().to(vm_controller::start))
|
||||||
|
.route(
|
||||||
|
"/api/vm/{uid}/shutdown",
|
||||||
|
web::get().to(vm_controller::shutdown),
|
||||||
|
)
|
||||||
|
.route("/api/vm/{uid}/kill", web::get().to(vm_controller::kill))
|
||||||
|
.route("/api/vm/{uid}/reset", web::get().to(vm_controller::reset))
|
||||||
|
.route(
|
||||||
|
"/api/vm/{uid}/suspend",
|
||||||
|
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),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/api/sysinfo/config",
|
||||||
|
web::get().to(sys_info_controller::config),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/api/sysinfo/status",
|
||||||
|
web::get().to(sys_info_controller::status),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.bind(&AppConfig::get().listen_address)?
|
.bind(&AppConfig::get().listen_address)?
|
||||||
.run()
|
.run()
|
||||||
|
|||||||
@@ -74,6 +74,27 @@ pub struct VMInfo {
|
|||||||
pub uuid: VMUuid,
|
pub uuid: VMUuid,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
pub architecture: String,
|
||||||
|
pub memory: usize,
|
||||||
|
pub number_vcpu: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize, Debug)]
|
||||||
|
pub struct VMState {
|
||||||
|
pub state: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize, Debug)]
|
||||||
|
pub struct SystemSystemInfo {
|
||||||
|
physical_core_count: usize,
|
||||||
|
uptime: usize,
|
||||||
|
used_memory: usize,
|
||||||
|
available_memory: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize, Debug)]
|
||||||
|
pub struct SystemInfo {
|
||||||
|
system: SystemSystemInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
#[derive(serde::Deserialize, Debug)]
|
||||||
@@ -126,10 +147,15 @@ impl TokenInfo {
|
|||||||
.map(|r| VMUuid::from_str(r.path.rsplit_once('/').unwrap().1).unwrap())
|
.map(|r| VMUuid::from_str(r.path.rsplit_once('/').unwrap().1).unwrap())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if system info can be retrived
|
||||||
|
pub fn can_retrieve_system_info(&self) -> bool {
|
||||||
|
self.is_route_allowed("GET", "/api/server/info")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform a request on the API
|
/// Perform a request on the API
|
||||||
async fn request<D: Display, E: serde::de::DeserializeOwned>(uri: D) -> anyhow::Result<E> {
|
async fn request<D: Display>(uri: D) -> anyhow::Result<reqwest::Response> {
|
||||||
let url = format!("{}{}", AppConfig::get().virtweb_base_url, uri);
|
let url = format!("{}{}", AppConfig::get().virtweb_base_url, uri);
|
||||||
log::debug!("Will query {uri}...");
|
log::debug!("Will query {uri}...");
|
||||||
|
|
||||||
@@ -154,20 +180,78 @@ async fn request<D: Display, E: serde::de::DeserializeOwned>(uri: D) -> anyhow::
|
|||||||
return Err(VirtWebClientError::InvalidStatusCode(res.status().as_u16()).into());
|
return Err(VirtWebClientError::InvalidStatusCode(res.status().as_u16()).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(res.json().await?)
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform a request on the API
|
||||||
|
async fn json_request<D: Display, E: serde::de::DeserializeOwned>(uri: D) -> anyhow::Result<E> {
|
||||||
|
Ok(request(uri).await?.json().await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get current token information
|
/// Get current token information
|
||||||
pub async fn get_token_info() -> anyhow::Result<TokenInfo> {
|
pub async fn get_token_info() -> anyhow::Result<TokenInfo> {
|
||||||
let res: TokenInfo =
|
let res: TokenInfo =
|
||||||
request(format!("/api/token/{}", AppConfig::get().virtweb_token_id)).await?;
|
json_request(format!("/api/token/{}", AppConfig::get().virtweb_token_id)).await?;
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a vm information
|
/// Get a vm information
|
||||||
pub async fn get_vm_info(id: VMUuid) -> anyhow::Result<VMInfo> {
|
pub async fn vm_info(id: VMUuid) -> anyhow::Result<VMInfo> {
|
||||||
let res: VMInfo = request(format!("/api/vm/{}", id.0)).await?;
|
json_request(id.route_info()).await
|
||||||
|
}
|
||||||
Ok(res)
|
|
||||||
|
/// Get a vm information
|
||||||
|
pub async fn vm_state(id: VMUuid) -> anyhow::Result<VMState> {
|
||||||
|
json_request(id.route_state()).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start a vm
|
||||||
|
pub async fn vm_start(id: VMUuid) -> anyhow::Result<()> {
|
||||||
|
request(id.route_start()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shutdown a vm
|
||||||
|
pub async fn vm_shutdown(id: VMUuid) -> anyhow::Result<()> {
|
||||||
|
request(id.route_shutdown()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Kill a vm
|
||||||
|
pub async fn vm_kill(id: VMUuid) -> anyhow::Result<()> {
|
||||||
|
request(id.route_kill()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reset a vm
|
||||||
|
pub async fn vm_reset(id: VMUuid) -> anyhow::Result<()> {
|
||||||
|
request(id.route_reset()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Suspend a vm
|
||||||
|
pub async fn vm_suspend(id: VMUuid) -> anyhow::Result<()> {
|
||||||
|
request(id.route_suspend()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resume a vm
|
||||||
|
pub async fn vm_resume(id: VMUuid) -> anyhow::Result<()> {
|
||||||
|
request(id.route_resume()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Grab a screenshot of the VM
|
||||||
|
pub async fn vm_screenshot(id: VMUuid) -> anyhow::Result<Vec<u8>> {
|
||||||
|
Ok(request(id.route_screenshot())
|
||||||
|
.await?
|
||||||
|
.bytes()
|
||||||
|
.await?
|
||||||
|
.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get current server information
|
||||||
|
pub async fn get_server_info() -> anyhow::Result<SystemInfo> {
|
||||||
|
json_request("/api/server/info").await
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user