move more api types for the client

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller
2021-07-09 14:26:42 +02:00
parent ba0ccc5991
commit ea584a7510
10 changed files with 319 additions and 305 deletions

View File

@ -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.

View File

@ -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::*;

View File

@ -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,
)
}
}
}

View File

@ -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,
};