file-restore: add 'extract' command for VM file restore
The data on the restore daemon is either encoded into a pxar archive, to provide the most accurate data for local restore, or encoded directly into a zip file (or written out unprocessed for files), depending on the 'pxar' argument to the 'extract' API call. Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
This commit is contained in:
committed by
Thomas Lamprecht
parent
1f03196c0b
commit
b13089cdf5
@ -41,6 +41,19 @@ pub trait BlockRestoreDriver {
|
||||
path: Vec<u8>,
|
||||
) -> Async<Result<Vec<ArchiveEntry>, Error>>;
|
||||
|
||||
/// pxar=true:
|
||||
/// Attempt to create a pxar archive of the given file path and return a reader instance for it
|
||||
/// pxar=false:
|
||||
/// Attempt to read the file or folder at the given path and return the file content or a zip
|
||||
/// file as a stream
|
||||
fn data_extract(
|
||||
&self,
|
||||
details: SnapRestoreDetails,
|
||||
img_file: String,
|
||||
path: Vec<u8>,
|
||||
pxar: bool,
|
||||
) -> Async<Result<Box<dyn tokio::io::AsyncRead + Unpin + Send>, Error>>;
|
||||
|
||||
/// Return status of all running/mapped images, result value is (id, extra data), where id must
|
||||
/// match with the ones returned from list()
|
||||
fn status(&self) -> Async<Result<Vec<DriverStatus>, Error>>;
|
||||
@ -79,6 +92,17 @@ pub async fn data_list(
|
||||
driver.data_list(details, img_file, path).await
|
||||
}
|
||||
|
||||
pub async fn data_extract(
|
||||
driver: Option<BlockDriverType>,
|
||||
details: SnapRestoreDetails,
|
||||
img_file: String,
|
||||
path: Vec<u8>,
|
||||
pxar: bool,
|
||||
) -> Result<Box<dyn tokio::io::AsyncRead + Send + Unpin>, Error> {
|
||||
let driver = driver.unwrap_or(DEFAULT_DRIVER).resolve();
|
||||
driver.data_extract(details, img_file, path, pxar).await
|
||||
}
|
||||
|
||||
#[api(
|
||||
input: {
|
||||
properties: {
|
||||
|
@ -204,6 +204,38 @@ impl BlockRestoreDriver for QemuBlockDriver {
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn data_extract(
|
||||
&self,
|
||||
details: SnapRestoreDetails,
|
||||
img_file: String,
|
||||
mut path: Vec<u8>,
|
||||
pxar: bool,
|
||||
) -> Async<Result<Box<dyn tokio::io::AsyncRead + Unpin + Send>, Error>> {
|
||||
async move {
|
||||
let client = ensure_running(&details).await?;
|
||||
if !path.is_empty() && path[0] != b'/' {
|
||||
path.insert(0, b'/');
|
||||
}
|
||||
let path = base64::encode(img_file.bytes().chain(path).collect::<Vec<u8>>());
|
||||
let (mut tx, rx) = tokio::io::duplex(1024 * 4096);
|
||||
tokio::spawn(async move {
|
||||
if let Err(err) = client
|
||||
.download(
|
||||
"api2/json/extract",
|
||||
Some(json!({ "path": path, "pxar": pxar })),
|
||||
&mut tx,
|
||||
)
|
||||
.await
|
||||
{
|
||||
eprintln!("reading file extraction stream failed - {}", err);
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Box::new(rx) as Box<dyn tokio::io::AsyncRead + Unpin + Send>)
|
||||
}
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn status(&self) -> Async<Result<Vec<DriverStatus>, Error>> {
|
||||
async move {
|
||||
let mut state_map = VMStateMap::load()?;
|
||||
|
Reference in New Issue
Block a user