Add the logic which will call disk image conversion from disk image route
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-05-29 11:37:11 +02:00
parent e7ac0198ab
commit e017fe96d5
10 changed files with 279 additions and 13 deletions

View File

@ -1,7 +1,7 @@
use crate::app_config::AppConfig;
use crate::constants;
use crate::controllers::HttpResult;
use crate::utils::file_disks_utils::DiskFileInfo;
use crate::utils::file_disks_utils::{DiskFileFormat, DiskFileInfo};
use crate::utils::files_utils;
use actix_files::NamedFile;
use actix_multipart::form::MultipartForm;
@ -91,6 +91,59 @@ pub async fn download(p: web::Path<DiskFilePath>, req: HttpRequest) -> HttpResul
Ok(NamedFile::open(file_path)?.into_response(&req))
}
#[derive(serde::Deserialize)]
pub struct ConvertDiskImageRequest {
dest_file_name: String,
#[serde(flatten)]
format: DiskFileFormat,
}
/// Convert disk image into a new format
pub async fn convert(
p: web::Path<DiskFilePath>,
req: web::Json<ConvertDiskImageRequest>,
) -> HttpResult {
if !files_utils::check_file_name(&p.filename) {
return Ok(HttpResponse::BadRequest().json("Invalid src file name!"));
}
if !files_utils::check_file_name(&req.dest_file_name) {
return Ok(HttpResponse::BadRequest().json("Invalid destination file name!"));
}
if !req
.format
.ext()
.iter()
.any(|e| req.dest_file_name.ends_with(e))
{
return Ok(HttpResponse::BadRequest().json("Invalid destination file extension!"));
}
let src_file_path = AppConfig::get()
.disk_images_storage_path()
.join(&p.filename);
let src = DiskFileInfo::load_file(&src_file_path)?;
let dst_file_path = AppConfig::get()
.disk_images_storage_path()
.join(&req.dest_file_name);
if dst_file_path.exists() {
return Ok(HttpResponse::Conflict().json("Specified destination file already exists!"));
}
// Perform conversion
if let Err(e) = src.convert(&dst_file_path, req.format) {
log::error!("Disk file conversion error: {e}");
return Ok(
HttpResponse::InternalServerError().json(format!("Disk file conversion error: {e}"))
);
}
Ok(HttpResponse::Ok().json(src))
}
/// Delete a disk image
pub async fn delete(p: web::Path<DiskFilePath>) -> HttpResult {
if !files_utils::check_file_name(&p.filename) {

View File

@ -46,6 +46,7 @@ struct ServerConstraints {
memory_size: LenConstraints,
disk_name_size: LenConstraints,
disk_size: LenConstraints,
disk_image_name_size: LenConstraints,
net_name_size: LenConstraints,
net_title_size: LenConstraints,
net_nat_comment_size: LenConstraints,
@ -91,6 +92,8 @@ pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
max: DISK_SIZE_MAX.as_bytes(),
},
disk_image_name_size: LenConstraints { min: 5, max: 220 },
net_name_size: LenConstraints { min: 2, max: 50 },
net_title_size: LenConstraints { min: 0, max: 50 },
net_nat_comment_size: LenConstraints {

View File

@ -349,6 +349,10 @@ async fn main() -> std::io::Result<()> {
"/api/disk_images/{filename}",
web::get().to(disk_images_controller::download),
)
.route(
"/api/disk_images/{filename}/convert",
web::post().to(disk_images_controller::convert),
)
.route(
"/api/disk_images/{filename}",
web::delete().to(disk_images_controller::delete),

View File

@ -13,15 +13,32 @@ enum DisksError {
Create,
}
#[derive(Debug, serde::Serialize)]
#[derive(Debug, serde::Serialize, serde::Deserialize, Copy, Clone)]
#[serde(tag = "format")]
pub enum DiskFileFormat {
Raw { is_sparse: bool },
QCow2 { virtual_size: FileSize },
Raw {
#[serde(default)]
is_sparse: bool,
},
QCow2 {
#[serde(default)]
virtual_size: FileSize,
},
CompressedRaw,
CompressedQCow2,
}
impl DiskFileFormat {
pub fn ext(&self) -> &'static [&'static str] {
match self {
DiskFileFormat::Raw { .. } => &["", "raw"],
DiskFileFormat::QCow2 { .. } => &["qcow2"],
DiskFileFormat::CompressedRaw => &["raw.gz"],
DiskFileFormat::CompressedQCow2 => &["qcow2.gz"],
}
}
}
/// Disk file information
#[derive(serde::Serialize)]
pub struct DiskFileInfo {
@ -125,6 +142,11 @@ impl DiskFileInfo {
Ok(())
}
/// Copy / convert file disk image into a new destination with optionally a new file format
pub fn convert(&self, dest_file: &Path, dest_format: DiskFileFormat) -> anyhow::Result<()> {
todo!()
}
}
#[derive(serde::Deserialize)]

View File

@ -1,5 +1,14 @@
#[derive(
serde::Serialize, serde::Deserialize, Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord,
serde::Serialize,
serde::Deserialize,
Copy,
Clone,
Debug,
Eq,
PartialEq,
PartialOrd,
Ord,
Default,
)]
pub struct FileSize(usize);