diff --git a/src/api2/types/file_restore.rs b/pbs-api-types/src/file_restore.rs similarity index 98% rename from src/api2/types/file_restore.rs rename to pbs-api-types/src/file_restore.rs index 29085c31..eedb172b 100644 --- a/src/api2/types/file_restore.rs +++ b/pbs-api-types/src/file_restore.rs @@ -1,7 +1,8 @@ use serde::{Deserialize, Serialize}; + use proxmox::api::api; -#[api()] +#[api] #[derive(Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] /// General status information about a running VM file-restore daemon @@ -12,4 +13,3 @@ pub struct RestoreDaemonStatus { /// not set, as then the status call will have reset the timer before returning the value pub timeout: i64, } - diff --git a/pbs-api-types/src/lib.rs b/pbs-api-types/src/lib.rs index 1c9063bf..024181ee 100644 --- a/pbs-api-types/src/lib.rs +++ b/pbs-api-types/src/lib.rs @@ -56,6 +56,8 @@ pub use upid::UPID; mod crypto; pub use crypto::{CryptMode, Fingerprint}; +pub mod file_restore; + #[rustfmt::skip] #[macro_use] mod local_macros { diff --git a/pbs-datastore/src/catalog.rs b/pbs-datastore/src/catalog.rs index 26003bf8..7a65e8d1 100644 --- a/pbs-datastore/src/catalog.rs +++ b/pbs-datastore/src/catalog.rs @@ -5,8 +5,10 @@ use std::io::{Read, Write, Seek, SeekFrom}; use std::os::unix::ffi::OsStrExt; use anyhow::{bail, format_err, Error}; +use serde::{Deserialize, Serialize}; use pathpatterns::{MatchList, MatchType}; +use proxmox::api::api; use proxmox::tools::io::ReadExt; use crate::file_formats::PROXMOX_CATALOG_FILE_MAGIC_1_0; @@ -808,3 +810,56 @@ fn test_catalog_i64_compatibility() { test_encode_decode((1<<50)-1); test_encode_decode(u64::MAX); } + +/// An entry in a hierarchy of files for restore and listing. +#[api] +#[derive(Serialize, Deserialize)] +pub struct ArchiveEntry { + /// Base64-encoded full path to the file, including the filename + pub filepath: String, + /// Displayable filename text for UIs + pub text: String, + /// File or directory type of this entry + #[serde(rename = "type")] + pub entry_type: String, + /// Is this entry a leaf node, or does it have children (i.e. a directory)? + pub leaf: bool, + /// The file size, if entry_type is 'f' (file) + #[serde(skip_serializing_if="Option::is_none")] + pub size: Option, + /// The file "last modified" time stamp, if entry_type is 'f' (file) + #[serde(skip_serializing_if="Option::is_none")] + pub mtime: Option, +} + +impl ArchiveEntry { + pub fn new(filepath: &[u8], entry_type: Option<&DirEntryAttribute>) -> Self { + let size = match entry_type { + Some(DirEntryAttribute::File { size, .. }) => Some(*size), + _ => None, + }; + Self::new_with_size(filepath, entry_type, size) + } + + pub fn new_with_size( + filepath: &[u8], + entry_type: Option<&DirEntryAttribute>, + size: Option, + ) -> Self { + Self { + filepath: base64::encode(filepath), + text: String::from_utf8_lossy(filepath.split(|x| *x == b'/').last().unwrap()) + .to_string(), + entry_type: match entry_type { + Some(entry_type) => CatalogEntryType::from(entry_type).to_string(), + None => "v".to_owned(), + }, + leaf: !matches!(entry_type, None | Some(DirEntryAttribute::Directory { .. })), + size, + mtime: match entry_type { + Some(DirEntryAttribute::File { mtime, .. }) => Some(*mtime), + _ => None, + }, + } + } +} diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs index b979fd19..c181a84c 100644 --- a/src/api2/admin/datastore.rs +++ b/src/api2/admin/datastore.rs @@ -35,7 +35,7 @@ use pbs_client::pxar::create_zip; use pbs_datastore::{BackupDir, BackupGroup, StoreProgress, CATALOG_NAME}; use pbs_datastore::backup_info::BackupInfo; use pbs_datastore::cached_chunk_reader::CachedChunkReader; -use pbs_datastore::catalog::CatalogReader; +use pbs_datastore::catalog::{ArchiveEntry, CatalogReader}; use pbs_datastore::data_blob::DataBlob; use pbs_datastore::data_blob_reader::DataBlobReader; use pbs_datastore::dynamic_index::{BufferedDynamicReader, DynamicIndexReader, LocalDynamicReadAt}; @@ -48,8 +48,8 @@ use pbs_tools::stream::{AsyncReaderStream, AsyncChannelWriter}; use pbs_tools::json::{required_integer_param, required_string_param}; use crate::api2::types::{ - ArchiveEntry, DataStoreStatus, RRDMode, RRDTimeFrameResolution, - IGNORE_VERIFIED_BACKUPS_SCHEMA, UPID_SCHEMA, VERIFICATION_OUTDATED_AFTER_SCHEMA + DataStoreStatus, RRDMode, RRDTimeFrameResolution, IGNORE_VERIFIED_BACKUPS_SCHEMA, UPID_SCHEMA, + VERIFICATION_OUTDATED_AFTER_SCHEMA }; use crate::api2::node::rrd::create_value_from_rrd; use crate::api2::helpers; diff --git a/src/api2/helpers.rs b/src/api2/helpers.rs index 2d3d23e2..8f43cacf 100644 --- a/src/api2/helpers.rs +++ b/src/api2/helpers.rs @@ -7,9 +7,7 @@ use hyper::{Body, Response, StatusCode, header}; use proxmox::http_bail; -use pbs_datastore::catalog::{CatalogReader, DirEntryAttribute}; - -use crate::api2::types::ArchiveEntry; +use pbs_datastore::catalog::{ArchiveEntry, CatalogReader, DirEntryAttribute}; pub async fn create_download_response(path: PathBuf) -> Result, Error> { let file = match tokio::fs::File::open(path.clone()).await { diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs index 7f12cf60..2d9d0d39 100644 --- a/src/api2/types/mod.rs +++ b/src/api2/types/mod.rs @@ -6,16 +6,11 @@ use serde::{Deserialize, Serialize}; use proxmox::api::{api, schema::*}; use proxmox::const_regex; -use pbs_datastore::catalog::{CatalogEntryType, DirEntryAttribute}; - use crate::config::acl::Role; mod tape; pub use tape::*; -mod file_restore; -pub use file_restore::*; - mod acme; pub use acme::*; @@ -818,59 +813,6 @@ pub struct DatastoreNotify { pub sync: Option, } -/// An entry in a hierarchy of files for restore and listing. -#[api()] -#[derive(Serialize, Deserialize)] -pub struct ArchiveEntry { - /// Base64-encoded full path to the file, including the filename - pub filepath: String, - /// Displayable filename text for UIs - pub text: String, - /// File or directory type of this entry - #[serde(rename = "type")] - pub entry_type: String, - /// Is this entry a leaf node, or does it have children (i.e. a directory)? - pub leaf: bool, - /// The file size, if entry_type is 'f' (file) - #[serde(skip_serializing_if="Option::is_none")] - pub size: Option, - /// The file "last modified" time stamp, if entry_type is 'f' (file) - #[serde(skip_serializing_if="Option::is_none")] - pub mtime: Option, -} - -impl ArchiveEntry { - pub fn new(filepath: &[u8], entry_type: Option<&DirEntryAttribute>) -> Self { - let size = match entry_type { - Some(DirEntryAttribute::File { size, .. }) => Some(*size), - _ => None, - }; - Self::new_with_size(filepath, entry_type, size) - } - - pub fn new_with_size( - filepath: &[u8], - entry_type: Option<&DirEntryAttribute>, - size: Option, - ) -> Self { - Self { - filepath: base64::encode(filepath), - text: String::from_utf8_lossy(filepath.split(|x| *x == b'/').last().unwrap()) - .to_string(), - entry_type: match entry_type { - Some(entry_type) => CatalogEntryType::from(entry_type).to_string(), - None => "v".to_owned(), - }, - leaf: !matches!(entry_type, None | Some(DirEntryAttribute::Directory { .. })), - size, - mtime: match entry_type { - Some(DirEntryAttribute::File { mtime, .. }) => Some(*mtime), - _ => None, - }, - } - } -} - pub const DATASTORE_NOTIFY_STRING_SCHEMA: Schema = StringSchema::new( "Datastore notification setting") .format(&ApiStringFormat::PropertyString(&DatastoreNotify::API_SCHEMA)) diff --git a/src/bin/proxmox-file-restore.rs b/src/bin/proxmox-file-restore.rs index d024069c..fa852f51 100644 --- a/src/bin/proxmox-file-restore.rs +++ b/src/bin/proxmox-file-restore.rs @@ -19,7 +19,7 @@ use pxar::decoder::aio::Decoder; use pbs_api_types::CryptMode; use pbs_datastore::{CryptConfig, CATALOG_NAME}; use pbs_datastore::backup_info::BackupDir; -use pbs_datastore::catalog::{CatalogReader, DirEntryAttribute}; +use pbs_datastore::catalog::{ArchiveEntry, CatalogReader, DirEntryAttribute}; use pbs_datastore::dynamic_index::{BufferedDynamicReader, LocalDynamicReadAt}; use pbs_datastore::index::IndexFile; use pbs_datastore::key_derivation::decrypt_key; @@ -34,7 +34,7 @@ use pbs_client::tools::{ REPO_URL_SCHEMA, }; -use proxmox_backup::api2::{helpers, types::ArchiveEntry}; +use proxmox_backup::api2::helpers; use proxmox_backup::tools; mod proxmox_file_restore; diff --git a/src/bin/proxmox_file_restore/block_driver.rs b/src/bin/proxmox_file_restore/block_driver.rs index 60f30abb..14c572fb 100644 --- a/src/bin/proxmox_file_restore/block_driver.rs +++ b/src/bin/proxmox_file_restore/block_driver.rs @@ -12,10 +12,9 @@ use proxmox::api::{api, cli::*}; use pbs_client::BackupRepository; use pbs_datastore::backup_info::BackupDir; +use pbs_datastore::catalog::ArchiveEntry; use pbs_datastore::manifest::BackupManifest; -use proxmox_backup::api2::types::ArchiveEntry; - use super::block_driver_qemu::QemuBlockDriver; /// Contains details about a snapshot that is to be accessed by block file restore diff --git a/src/bin/proxmox_file_restore/block_driver_qemu.rs b/src/bin/proxmox_file_restore/block_driver_qemu.rs index e3a90b91..7fc6331f 100644 --- a/src/bin/proxmox_file_restore/block_driver_qemu.rs +++ b/src/bin/proxmox_file_restore/block_driver_qemu.rs @@ -12,8 +12,8 @@ use proxmox::tools::fs::lock_file; use pbs_client::{DEFAULT_VSOCK_PORT, BackupRepository, VsockClient}; use pbs_datastore::backup_info::BackupDir; +use pbs_datastore::catalog::ArchiveEntry; -use proxmox_backup::api2::types::ArchiveEntry; use proxmox_backup::tools; use super::block_driver::*; diff --git a/src/bin/proxmox_restore_daemon/api.rs b/src/bin/proxmox_restore_daemon/api.rs index 8e0bd029..b835bb2a 100644 --- a/src/bin/proxmox_restore_daemon/api.rs +++ b/src/bin/proxmox_restore_daemon/api.rs @@ -19,14 +19,13 @@ use proxmox::api::{ }; use proxmox::{identity, list_subdirs_api_method, sortable}; +use pbs_api_types::file_restore::RestoreDaemonStatus; use pbs_client::pxar::{create_archive, Flags, PxarCreateOptions, ENCODER_MAX_ENTRIES}; -use pbs_datastore::catalog::DirEntryAttribute; +use pbs_datastore::catalog::{ArchiveEntry, DirEntryAttribute}; use pbs_tools::fs::read_subdir; use pbs_tools::json::required_string_param; use pbs_tools::zip::zip_directory; -use proxmox_backup::api2::types::*; - use pxar::encoder::aio::TokioWriter; use super::{disk::ResolveResult, watchdog_remaining, watchdog_inhibit, watchdog_ping};