move more api types for the client
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
@ -9,12 +9,7 @@ use proxmox::const_regex;
|
||||
use pbs_datastore::catalog::CatalogEntryType;
|
||||
|
||||
use crate::{
|
||||
backup::{
|
||||
CryptMode,
|
||||
Fingerprint,
|
||||
DirEntryAttribute,
|
||||
},
|
||||
server::UPID,
|
||||
backup::DirEntryAttribute,
|
||||
config::acl::Role,
|
||||
};
|
||||
|
||||
@ -244,39 +239,10 @@ pub struct AclListItem {
|
||||
pub roleid: String,
|
||||
}
|
||||
|
||||
pub const BACKUP_ARCHIVE_NAME_SCHEMA: Schema =
|
||||
StringSchema::new("Backup archive name.")
|
||||
.format(&PROXMOX_SAFE_ID_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const BACKUP_TYPE_SCHEMA: Schema =
|
||||
StringSchema::new("Backup type.")
|
||||
.format(&ApiStringFormat::Enum(&[
|
||||
EnumEntry::new("vm", "Virtual Machine Backup"),
|
||||
EnumEntry::new("ct", "Container Backup"),
|
||||
EnumEntry::new("host", "Host Backup")]))
|
||||
.schema();
|
||||
|
||||
pub const BACKUP_ID_SCHEMA: Schema =
|
||||
StringSchema::new("Backup ID.")
|
||||
.format(&BACKUP_ID_FORMAT)
|
||||
.schema();
|
||||
|
||||
pub const BACKUP_TIME_SCHEMA: Schema =
|
||||
IntegerSchema::new("Backup time (Unix epoch.)")
|
||||
.minimum(1_547_797_308)
|
||||
.schema();
|
||||
|
||||
pub const UPID_SCHEMA: Schema = StringSchema::new("Unique Process/Task ID.")
|
||||
.max_length(256)
|
||||
.schema();
|
||||
|
||||
pub const DATASTORE_SCHEMA: Schema = StringSchema::new("Datastore name.")
|
||||
.format(&PROXMOX_SAFE_ID_FORMAT)
|
||||
.min_length(3)
|
||||
.max_length(32)
|
||||
.schema();
|
||||
|
||||
pub const DATASTORE_MAP_SCHEMA: Schema = StringSchema::new("Datastore mapping.")
|
||||
.format(&DATASTORE_MAP_FORMAT)
|
||||
.min_length(3)
|
||||
@ -391,180 +357,6 @@ pub const REALM_ID_SCHEMA: Schema = StringSchema::new("Realm name.")
|
||||
|
||||
// Complex type definitions
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
store: {
|
||||
schema: DATASTORE_SCHEMA,
|
||||
},
|
||||
comment: {
|
||||
optional: true,
|
||||
schema: SINGLE_LINE_COMMENT_SCHEMA,
|
||||
},
|
||||
},
|
||||
)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all="kebab-case")]
|
||||
/// Basic information about a datastore.
|
||||
pub struct DataStoreListItem {
|
||||
pub store: String,
|
||||
pub comment: Option<String>,
|
||||
}
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
"backup-type": {
|
||||
schema: BACKUP_TYPE_SCHEMA,
|
||||
},
|
||||
"backup-id": {
|
||||
schema: BACKUP_ID_SCHEMA,
|
||||
},
|
||||
"last-backup": {
|
||||
schema: BACKUP_TIME_SCHEMA,
|
||||
},
|
||||
"backup-count": {
|
||||
type: Integer,
|
||||
},
|
||||
files: {
|
||||
items: {
|
||||
schema: BACKUP_ARCHIVE_NAME_SCHEMA
|
||||
},
|
||||
},
|
||||
owner: {
|
||||
type: Authid,
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all="kebab-case")]
|
||||
/// Basic information about a backup group.
|
||||
pub struct GroupListItem {
|
||||
pub backup_type: String, // enum
|
||||
pub backup_id: String,
|
||||
pub last_backup: i64,
|
||||
/// Number of contained snapshots
|
||||
pub backup_count: u64,
|
||||
/// List of contained archive files.
|
||||
pub files: Vec<String>,
|
||||
/// The owner of group
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub owner: Option<Authid>,
|
||||
}
|
||||
|
||||
#[api()]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
/// Result of a verify operation.
|
||||
pub enum VerifyState {
|
||||
/// Verification was successful
|
||||
Ok,
|
||||
/// Verification reported one or more errors
|
||||
Failed,
|
||||
}
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
upid: {
|
||||
schema: UPID_SCHEMA
|
||||
},
|
||||
state: {
|
||||
type: VerifyState
|
||||
},
|
||||
},
|
||||
)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
/// Task properties.
|
||||
pub struct SnapshotVerifyState {
|
||||
/// UPID of the verify task
|
||||
pub upid: UPID,
|
||||
/// State of the verification. Enum.
|
||||
pub state: VerifyState,
|
||||
}
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
"backup-type": {
|
||||
schema: BACKUP_TYPE_SCHEMA,
|
||||
},
|
||||
"backup-id": {
|
||||
schema: BACKUP_ID_SCHEMA,
|
||||
},
|
||||
"backup-time": {
|
||||
schema: BACKUP_TIME_SCHEMA,
|
||||
},
|
||||
comment: {
|
||||
schema: SINGLE_LINE_COMMENT_SCHEMA,
|
||||
optional: true,
|
||||
},
|
||||
verification: {
|
||||
type: SnapshotVerifyState,
|
||||
optional: true,
|
||||
},
|
||||
fingerprint: {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
files: {
|
||||
items: {
|
||||
schema: BACKUP_ARCHIVE_NAME_SCHEMA
|
||||
},
|
||||
},
|
||||
owner: {
|
||||
type: Authid,
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all="kebab-case")]
|
||||
/// Basic information about backup snapshot.
|
||||
pub struct SnapshotListItem {
|
||||
pub backup_type: String, // enum
|
||||
pub backup_id: String,
|
||||
pub backup_time: i64,
|
||||
/// The first line from manifest "notes"
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub comment: Option<String>,
|
||||
/// The result of the last run verify task
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub verification: Option<SnapshotVerifyState>,
|
||||
/// Fingerprint of encryption key
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub fingerprint: Option<Fingerprint>,
|
||||
/// List of contained archive files.
|
||||
pub files: Vec<BackupContent>,
|
||||
/// Overall snapshot size (sum of all archive sizes).
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub size: Option<u64>,
|
||||
/// The owner of the snapshots group
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub owner: Option<Authid>,
|
||||
}
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
"backup-type": {
|
||||
schema: BACKUP_TYPE_SCHEMA,
|
||||
},
|
||||
"backup-id": {
|
||||
schema: BACKUP_ID_SCHEMA,
|
||||
},
|
||||
"backup-time": {
|
||||
schema: BACKUP_TIME_SCHEMA,
|
||||
},
|
||||
},
|
||||
)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all="kebab-case")]
|
||||
/// Prune result.
|
||||
pub struct PruneListItem {
|
||||
pub backup_type: String, // enum
|
||||
pub backup_id: String,
|
||||
pub backup_time: i64,
|
||||
/// Keep snapshot
|
||||
pub keep: bool,
|
||||
}
|
||||
|
||||
pub const PRUNE_SCHEMA_KEEP_DAILY: Schema = IntegerSchema::new(
|
||||
"Number of daily backups to keep.")
|
||||
.minimum(1)
|
||||
@ -595,30 +387,6 @@ pub const PRUNE_SCHEMA_KEEP_YEARLY: Schema = IntegerSchema::new(
|
||||
.minimum(1)
|
||||
.schema();
|
||||
|
||||
#[api(
|
||||
properties: {
|
||||
"filename": {
|
||||
schema: BACKUP_ARCHIVE_NAME_SCHEMA,
|
||||
},
|
||||
"crypt-mode": {
|
||||
type: CryptMode,
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all="kebab-case")]
|
||||
/// Basic information about archive files inside a backup snapshot.
|
||||
pub struct BackupContent {
|
||||
pub filename: String,
|
||||
/// Info if file is encrypted, signed, or neither.
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub crypt_mode: Option<CryptMode>,
|
||||
/// Archive size (from backup manifest).
|
||||
#[serde(skip_serializing_if="Option::is_none")]
|
||||
pub size: Option<u64>,
|
||||
}
|
||||
|
||||
#[api()]
|
||||
#[derive(Default, Serialize, Deserialize)]
|
||||
/// Storage space usage information.
|
||||
|
@ -77,6 +77,8 @@ pub use pbs_datastore::manifest::*;
|
||||
pub use pbs_datastore::prune;
|
||||
pub use pbs_datastore::prune::*;
|
||||
|
||||
pub use pbs_datastore::store_progress::StoreProgress;
|
||||
|
||||
pub use pbs_datastore::dynamic_index::*;
|
||||
pub use pbs_datastore::fixed_index;
|
||||
pub use pbs_datastore::fixed_index::*;
|
||||
@ -97,9 +99,6 @@ pub use dynamic_index::*;
|
||||
mod datastore;
|
||||
pub use datastore::*;
|
||||
|
||||
mod store_progress;
|
||||
pub use store_progress::*;
|
||||
|
||||
mod verify;
|
||||
pub use verify::*;
|
||||
|
||||
|
@ -1,79 +0,0 @@
|
||||
#[derive(Debug, Default)]
|
||||
/// Tracker for progress of operations iterating over `Datastore` contents.
|
||||
pub struct StoreProgress {
|
||||
/// Completed groups
|
||||
pub done_groups: u64,
|
||||
/// Total groups
|
||||
pub total_groups: u64,
|
||||
/// Completed snapshots within current group
|
||||
pub done_snapshots: u64,
|
||||
/// Total snapshots in current group
|
||||
pub group_snapshots: u64,
|
||||
}
|
||||
|
||||
impl StoreProgress {
|
||||
pub fn new(total_groups: u64) -> Self {
|
||||
StoreProgress {
|
||||
total_groups,
|
||||
.. Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates an interpolated relative progress based on current counters.
|
||||
pub fn percentage(&self) -> f64 {
|
||||
let per_groups = (self.done_groups as f64) / (self.total_groups as f64);
|
||||
if self.group_snapshots == 0 {
|
||||
per_groups
|
||||
} else {
|
||||
let per_snapshots = (self.done_snapshots as f64) / (self.group_snapshots as f64);
|
||||
per_groups + (1.0 / self.total_groups as f64) * per_snapshots
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for StoreProgress {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let current_group = if self.done_groups < self.total_groups {
|
||||
self.done_groups + 1
|
||||
} else {
|
||||
self.done_groups
|
||||
};
|
||||
|
||||
if self.group_snapshots == 0 {
|
||||
write!(
|
||||
f,
|
||||
"{:.2}% ({}/{} groups)",
|
||||
self.percentage() * 100.0,
|
||||
self.done_groups,
|
||||
self.total_groups,
|
||||
)
|
||||
} else if self.total_groups == 1 {
|
||||
write!(
|
||||
f,
|
||||
"{:.2}% ({}/{} snapshots)",
|
||||
self.percentage() * 100.0,
|
||||
self.done_snapshots,
|
||||
self.group_snapshots,
|
||||
)
|
||||
} else if self.done_snapshots == self.group_snapshots {
|
||||
write!(
|
||||
f,
|
||||
"{:.2}% ({}/{} groups)",
|
||||
self.percentage() * 100.0,
|
||||
current_group,
|
||||
self.total_groups,
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"{:.2}% ({}/{} groups, {}/{} snapshots in group #{})",
|
||||
self.percentage() * 100.0,
|
||||
self.done_groups,
|
||||
self.total_groups,
|
||||
self.done_snapshots,
|
||||
self.group_snapshots,
|
||||
current_group,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -12,13 +12,20 @@ use serde_json::json;
|
||||
|
||||
use proxmox::api::error::{HttpError, StatusCode};
|
||||
|
||||
use pbs_datastore::task_log;
|
||||
use pbs_api_types::{Authid, SnapshotListItem, GroupListItem};
|
||||
use pbs_datastore::{task_log, BackupInfo, BackupDir, BackupGroup, StoreProgress};
|
||||
use pbs_datastore::data_blob::DataBlob;
|
||||
use pbs_datastore::dynamic_index::DynamicIndexReader;
|
||||
use pbs_datastore::fixed_index::FixedIndexReader;
|
||||
use pbs_datastore::index::IndexFile;
|
||||
use pbs_datastore::manifest::{
|
||||
CLIENT_LOG_BLOB_NAME, MANIFEST_BLOB_NAME, ArchiveType, BackupManifest, FileInfo, archive_type
|
||||
};
|
||||
use pbs_tools::sha::sha256;
|
||||
|
||||
use crate::{
|
||||
api2::types::*,
|
||||
backup::*,
|
||||
client::*,
|
||||
backup::DataStore,
|
||||
client::{BackupReader, BackupRepository, HttpClient, HttpClientOptions, RemoteChunkReader},
|
||||
server::WorkerTask,
|
||||
tools::ParallelHandler,
|
||||
};
|
||||
|
Reference in New Issue
Block a user