Add qcow2.xz file format support
This commit is contained in:
@ -137,6 +137,9 @@ pub const PROGRAM_COPY: &str = "/bin/cp";
|
|||||||
/// Gzip program path
|
/// Gzip program path
|
||||||
pub const PROGRAM_GZIP: &str = "/usr/bin/gzip";
|
pub const PROGRAM_GZIP: &str = "/usr/bin/gzip";
|
||||||
|
|
||||||
|
/// XZ program path
|
||||||
|
pub const PROGRAM_XZ: &str = "/usr/bin/xz";
|
||||||
|
|
||||||
/// Bash program
|
/// Bash program
|
||||||
pub const PROGRAM_BASH: &str = "/usr/bin/bash";
|
pub const PROGRAM_BASH: &str = "/usr/bin/bash";
|
||||||
|
|
||||||
|
@ -28,8 +28,10 @@ pub enum DiskFileFormat {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
virtual_size: FileSize,
|
virtual_size: FileSize,
|
||||||
},
|
},
|
||||||
CompressedRaw,
|
GzCompressedRaw,
|
||||||
CompressedQCow2,
|
GzCompressedQCow2,
|
||||||
|
XzCompressedRaw,
|
||||||
|
XzCompressedQCow2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiskFileFormat {
|
impl DiskFileFormat {
|
||||||
@ -37,8 +39,10 @@ impl DiskFileFormat {
|
|||||||
match self {
|
match self {
|
||||||
DiskFileFormat::Raw { .. } => &["raw", ""],
|
DiskFileFormat::Raw { .. } => &["raw", ""],
|
||||||
DiskFileFormat::QCow2 { .. } => &["qcow2"],
|
DiskFileFormat::QCow2 { .. } => &["qcow2"],
|
||||||
DiskFileFormat::CompressedRaw => &["raw.gz"],
|
DiskFileFormat::GzCompressedRaw => &["raw.gz"],
|
||||||
DiskFileFormat::CompressedQCow2 => &["qcow2.gz"],
|
DiskFileFormat::GzCompressedQCow2 => &["qcow2.gz"],
|
||||||
|
DiskFileFormat::XzCompressedRaw => &["raw.xz"],
|
||||||
|
DiskFileFormat::XzCompressedQCow2 => &["qcow2.xz"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,9 +85,14 @@ impl DiskFileInfo {
|
|||||||
},
|
},
|
||||||
"gz" if name.ends_with(".qcow2") => {
|
"gz" if name.ends_with(".qcow2") => {
|
||||||
name = name.strip_suffix(".qcow2").unwrap_or(&name).to_string();
|
name = name.strip_suffix(".qcow2").unwrap_or(&name).to_string();
|
||||||
DiskFileFormat::CompressedQCow2
|
DiskFileFormat::GzCompressedQCow2
|
||||||
}
|
}
|
||||||
"gz" => DiskFileFormat::CompressedRaw,
|
"gz" => DiskFileFormat::GzCompressedRaw,
|
||||||
|
"xz" if name.ends_with(".qcow2") => {
|
||||||
|
name = name.strip_suffix(".qcow2").unwrap_or(&name).to_string();
|
||||||
|
DiskFileFormat::XzCompressedQCow2
|
||||||
|
}
|
||||||
|
"xz" => DiskFileFormat::XzCompressedRaw,
|
||||||
_ => anyhow::bail!("Unsupported disk extension: {ext}!"),
|
_ => anyhow::bail!("Unsupported disk extension: {ext}!"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,8 +168,8 @@ impl DiskFileInfo {
|
|||||||
|
|
||||||
// Prepare the conversion
|
// Prepare the conversion
|
||||||
let mut cmd = match (self.format, dest_format) {
|
let mut cmd = match (self.format, dest_format) {
|
||||||
// Decompress QCow2
|
// Decompress QCow2 (GZIP)
|
||||||
(DiskFileFormat::CompressedQCow2, DiskFileFormat::QCow2 { .. }) => {
|
(DiskFileFormat::GzCompressedQCow2, DiskFileFormat::QCow2 { .. }) => {
|
||||||
let mut cmd = Command::new(constants::PROGRAM_GZIP);
|
let mut cmd = Command::new(constants::PROGRAM_GZIP);
|
||||||
cmd.arg("--keep")
|
cmd.arg("--keep")
|
||||||
.arg("--decompress")
|
.arg("--decompress")
|
||||||
@ -170,8 +179,19 @@ impl DiskFileInfo {
|
|||||||
cmd
|
cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress QCow2
|
// Decompress QCow2 (XZ)
|
||||||
(DiskFileFormat::QCow2 { .. }, DiskFileFormat::CompressedQCow2) => {
|
(DiskFileFormat::XzCompressedQCow2, DiskFileFormat::QCow2 { .. }) => {
|
||||||
|
let mut cmd = Command::new(constants::PROGRAM_XZ);
|
||||||
|
cmd.arg("--stdout")
|
||||||
|
.arg("--keep")
|
||||||
|
.arg("--decompress")
|
||||||
|
.arg(&self.file_path)
|
||||||
|
.stdout(File::create(&temp_file)?);
|
||||||
|
cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compress QCow2 (Gzip)
|
||||||
|
(DiskFileFormat::QCow2 { .. }, DiskFileFormat::GzCompressedQCow2) => {
|
||||||
let mut cmd = Command::new(constants::PROGRAM_GZIP);
|
let mut cmd = Command::new(constants::PROGRAM_GZIP);
|
||||||
cmd.arg("--keep")
|
cmd.arg("--keep")
|
||||||
.arg("--to-stdout")
|
.arg("--to-stdout")
|
||||||
@ -180,6 +200,16 @@ impl DiskFileInfo {
|
|||||||
cmd
|
cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compress QCow2 (Xz)
|
||||||
|
(DiskFileFormat::QCow2 { .. }, DiskFileFormat::XzCompressedQCow2) => {
|
||||||
|
let mut cmd = Command::new(constants::PROGRAM_XZ);
|
||||||
|
cmd.arg("--keep")
|
||||||
|
.arg("--to-stdout")
|
||||||
|
.arg(&self.file_path)
|
||||||
|
.stdout(File::create(&temp_file)?);
|
||||||
|
cmd
|
||||||
|
}
|
||||||
|
|
||||||
// Convert QCow2 to Raw file
|
// Convert QCow2 to Raw file
|
||||||
(DiskFileFormat::QCow2 { .. }, DiskFileFormat::Raw { is_sparse }) => {
|
(DiskFileFormat::QCow2 { .. }, DiskFileFormat::Raw { is_sparse }) => {
|
||||||
let mut cmd = Command::new(constants::PROGRAM_QEMU_IMAGE);
|
let mut cmd = Command::new(constants::PROGRAM_QEMU_IMAGE);
|
||||||
@ -245,7 +275,7 @@ impl DiskFileInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compress Raw
|
// Compress Raw
|
||||||
(DiskFileFormat::Raw { .. }, DiskFileFormat::CompressedRaw) => {
|
(DiskFileFormat::Raw { .. }, DiskFileFormat::GzCompressedRaw) => {
|
||||||
let mut cmd = Command::new(constants::PROGRAM_GZIP);
|
let mut cmd = Command::new(constants::PROGRAM_GZIP);
|
||||||
cmd.arg("--keep")
|
cmd.arg("--keep")
|
||||||
.arg("--to-stdout")
|
.arg("--to-stdout")
|
||||||
@ -255,7 +285,7 @@ impl DiskFileInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decompress Raw to not sparse file
|
// Decompress Raw to not sparse file
|
||||||
(DiskFileFormat::CompressedRaw, DiskFileFormat::Raw { is_sparse: false }) => {
|
(DiskFileFormat::GzCompressedRaw, DiskFileFormat::Raw { is_sparse: false }) => {
|
||||||
let mut cmd = Command::new(constants::PROGRAM_GZIP);
|
let mut cmd = Command::new(constants::PROGRAM_GZIP);
|
||||||
cmd.arg("--keep")
|
cmd.arg("--keep")
|
||||||
.arg("--decompress")
|
.arg("--decompress")
|
||||||
@ -267,7 +297,7 @@ impl DiskFileInfo {
|
|||||||
|
|
||||||
// Decompress Raw to sparse file
|
// Decompress Raw to sparse file
|
||||||
// https://benou.fr/www/ben/decompressing-sparse-files.html
|
// https://benou.fr/www/ben/decompressing-sparse-files.html
|
||||||
(DiskFileFormat::CompressedRaw, DiskFileFormat::Raw { is_sparse: true }) => {
|
(DiskFileFormat::GzCompressedRaw, DiskFileFormat::Raw { is_sparse: true }) => {
|
||||||
let mut cmd = Command::new(constants::PROGRAM_BASH);
|
let mut cmd = Command::new(constants::PROGRAM_BASH);
|
||||||
cmd.arg("-c").arg(format!(
|
cmd.arg("-c").arg(format!(
|
||||||
"{} -d -c {} | {} conv=sparse of={}",
|
"{} -d -c {} | {} conv=sparse of={}",
|
||||||
|
@ -4,8 +4,8 @@ import { VMFileDisk, VMInfo } from "./VMApi";
|
|||||||
export type DiskImageFormat =
|
export type DiskImageFormat =
|
||||||
| { format: "Raw"; is_sparse: boolean }
|
| { format: "Raw"; is_sparse: boolean }
|
||||||
| { format: "QCow2"; virtual_size?: number }
|
| { format: "QCow2"; virtual_size?: number }
|
||||||
| { format: "CompressedQCow2" }
|
| { format: "GzCompressedQCow2" }
|
||||||
| { format: "CompressedRaw" };
|
| { format: "GzCompressedRaw" };
|
||||||
|
|
||||||
export type DiskImage = {
|
export type DiskImage = {
|
||||||
file_size: number;
|
file_size: number;
|
||||||
|
@ -42,13 +42,15 @@ export function ConvertDiskImageDialog(
|
|||||||
setFormat({ format: value ?? ("QCow2" as any) });
|
setFormat({ format: value ?? ("QCow2" as any) });
|
||||||
|
|
||||||
if (value === "QCow2") setFilename(`${origFilename}.qcow2`);
|
if (value === "QCow2") setFilename(`${origFilename}.qcow2`);
|
||||||
if (value === "CompressedQCow2") setFilename(`${origFilename}.qcow2.gz`);
|
if (value === "GzCompressedQCow2") setFilename(`${origFilename}.qcow2.gz`);
|
||||||
|
if (value === "XzCompressedQCow2") setFilename(`${origFilename}.qcow2.xz`);
|
||||||
if (value === "Raw") {
|
if (value === "Raw") {
|
||||||
setFilename(`${origFilename}.raw`);
|
setFilename(`${origFilename}.raw`);
|
||||||
// Check sparse checkbox by default
|
// Check sparse checkbox by default
|
||||||
setFormat({ format: "Raw", is_sparse: true });
|
setFormat({ format: "Raw", is_sparse: true });
|
||||||
}
|
}
|
||||||
if (value === "CompressedRaw") setFilename(`${origFilename}.raw.gz`);
|
if (value === "GzCompressedRaw") setFilename(`${origFilename}.raw.gz`);
|
||||||
|
if (value === "XzCompressedRaw") setFilename(`${origFilename}.raw.xz`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
@ -104,8 +106,10 @@ export function ConvertDiskImageDialog(
|
|||||||
options={[
|
options={[
|
||||||
{ value: "QCow2" },
|
{ value: "QCow2" },
|
||||||
{ value: "Raw" },
|
{ value: "Raw" },
|
||||||
{ value: "CompressedRaw" },
|
{ value: "GzCompressedRaw" },
|
||||||
{ value: "CompressedQCow2" },
|
{ value: "XzCompressedRaw" },
|
||||||
|
{ value: "GzCompressedQCow2" },
|
||||||
|
{ value: "XzCompressedQCow2" },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user