[pve-devel] [PATCH proxmox-backup 1/2] restore-daemon: add 'format' parameter to the 'extract' handler
Dominik Csapak
d.csapak at proxmox.com
Tue May 31 13:17:22 CEST 2022
this can be 'plain', 'pxar', 'zip' or 'tar.zst', and it returns the
content in the given format (with fallback to the old behaviour if not
given)
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
note: needs a bumped 'proxmox-compression' in the Cargo.toml to build
.../src/proxmox_restore_daemon/api.rs | 49 ++++++++++++++++---
1 file changed, 43 insertions(+), 6 deletions(-)
diff --git a/proxmox-restore-daemon/src/proxmox_restore_daemon/api.rs b/proxmox-restore-daemon/src/proxmox_restore_daemon/api.rs
index aeb5a71d..c4977ce6 100644
--- a/proxmox-restore-daemon/src/proxmox_restore_daemon/api.rs
+++ b/proxmox-restore-daemon/src/proxmox_restore_daemon/api.rs
@@ -13,7 +13,7 @@ use serde_json::Value;
use tokio::sync::Semaphore;
use pathpatterns::{MatchEntry, MatchPattern, MatchType, Pattern};
-use proxmox_compression::zip::zip_directory;
+use proxmox_compression::{tar::tar_directory, zip::zip_directory, zstd::ZstdEncoder};
use proxmox_router::{
list_subdirs_api_method, ApiHandler, ApiMethod, ApiResponseFuture, Permission, Router,
RpcEnvironment, SubdirMap,
@@ -236,11 +236,24 @@ pub const API_METHOD_EXTRACT: ApiMethod = ApiMethod::new(
true,
&BooleanSchema::new(concat!(
"if true, return a pxar archive, otherwise either the ",
- "file content or the directory as a zip file"
+ "file content or the directory as a zip file. DEPRECATED: use 'format' instead."
))
.default(true)
.schema()
- )
+ ),
+ (
+ "format",
+ true,
+ &StringSchema::new("The desired format of the result.")
+ .format(&ApiStringFormat::Enum(&[
+ EnumEntry::new("plain", "Plain file (only works for single files)"),
+ EnumEntry::new("pxar", "PXAR archive"),
+ EnumEntry::new("zip", "ZIP archive"),
+ EnumEntry::new("tar.zst", "Zstd compressed TAR archive"),
+ ]))
+ .default("pxar")
+ .schema()
+ ),
]),
),
)
@@ -271,6 +284,11 @@ fn extract(
let path = Path::new(OsStr::from_bytes(&path[..]));
let pxar = param["pxar"].as_bool().unwrap_or(true);
+ let format = match param["format"].as_str() {
+ Some(format) => format.to_string(),
+ // FIXME: old default was plain or zip, remove that with 3.0
+ None => if pxar { "pxar".to_string() } else { String::new() }
+ };
let query_result = proxmox_async::runtime::block_in_place(move || {
let mut disk_state = crate::DISK_STATE.lock().unwrap();
@@ -290,7 +308,9 @@ fn extract(
let (mut writer, reader) = tokio::io::duplex(1024 * 64);
- if pxar {
+ let mut zstd = false;
+
+ if format == "pxar" {
tokio::spawn(async move {
let _inhibitor = _inhibitor;
let _permit = _permit;
@@ -349,12 +369,24 @@ fn extract(
error!("pxar streaming task failed - {}", err);
}
});
+ } else if format == "tar.zst" {
+ zstd = true;
+ tokio::spawn(async move {
+ let _inhibitor = _inhibitor;
+ let _permit = _permit;
+ if let Err(err) = tar_directory(&mut writer, &vm_path).await {
+ error!("file or dir streaming task failed - {}", err);
+ }
+ });
} else {
+ if format == "plain" && vm_path.is_dir() {
+ bail!("cannot stream dir with format 'plain'");
+ }
tokio::spawn(async move {
let _inhibitor = _inhibitor;
let _permit = _permit;
let result = async move {
- if vm_path.is_dir() {
+ if vm_path.is_dir() || format == "zip" {
zip_directory(&mut writer, &vm_path).await?;
Ok(())
} else if vm_path.is_file() {
@@ -377,7 +409,12 @@ fn extract(
let stream = tokio_util::io::ReaderStream::new(reader);
- let body = Body::wrap_stream(stream);
+ let body = if zstd {
+ let stream = ZstdEncoder::new(stream)?;
+ Body::wrap_stream(stream)
+ } else {
+ Body::wrap_stream(stream)
+ };
Ok(Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "application/octet-stream")
--
2.30.2
More information about the pve-devel
mailing list