From 02db72678ffbbf6a68c4eedee0c14a2e0c96449a Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Wed, 27 Oct 2021 13:22:28 +0200 Subject: [PATCH] add protected info of snapshots to api and task logs adds the info that a snapshot is protected to: * snapshot list * manual pruning (also dry-run) * prune jobs Signed-off-by: Dominik Csapak Signed-off-by: Wolfgang Bumiller --- pbs-api-types/src/datastore.rs | 2 ++ pbs-datastore/src/prune.rs | 40 +++++++++++++++++++++++++++------- src/api2/admin/datastore.rs | 15 ++++++++----- src/server/prune_job.rs | 6 ++--- tests/prune.rs | 4 ++-- 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/pbs-api-types/src/datastore.rs b/pbs-api-types/src/datastore.rs index 462081e4..77c1258f 100644 --- a/pbs-api-types/src/datastore.rs +++ b/pbs-api-types/src/datastore.rs @@ -390,6 +390,8 @@ pub struct SnapshotListItem { /// The owner of the snapshots group #[serde(skip_serializing_if = "Option::is_none")] pub owner: Option, + /// Protection from prunes + pub protected: bool, } #[api( diff --git a/pbs-datastore/src/prune.rs b/pbs-datastore/src/prune.rs index 0eaa8acd..e66ed408 100644 --- a/pbs-datastore/src/prune.rs +++ b/pbs-datastore/src/prune.rs @@ -7,7 +7,30 @@ use pbs_api_types::PruneOptions; use super::BackupInfo; -enum PruneMark { Protected, Keep, KeepPartial, Remove } +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum PruneMark { Protected, Keep, KeepPartial, Remove } + +impl PruneMark { + pub fn keep(&self) -> bool { + *self != PruneMark::Remove + } + + pub fn protected(&self) -> bool { + *self == PruneMark::Protected + } +} + +impl std::fmt::Display for PruneMark { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let txt = match self { + PruneMark::Protected => "protected", + PruneMark::Keep => "keep", + PruneMark::KeepPartial => "keep-partial", + PruneMark::Remove => "remove", + }; + write!(f, "{}", txt) + } +} fn mark_selections Result> ( mark: &mut HashMap, @@ -125,7 +148,7 @@ pub fn cli_options_string(options: &PruneOptions) -> String { pub fn compute_prune_info( mut list: Vec, options: &PruneOptions, -) -> Result, Error> { +) -> Result, Error> { let mut mark = HashMap::new(); @@ -173,15 +196,16 @@ pub fn compute_prune_info( })?; } - let prune_info: Vec<(BackupInfo, bool)> = list.into_iter() + let prune_info: Vec<(BackupInfo, PruneMark)> = list.into_iter() .map(|info| { let backup_id = info.backup_dir.relative_path(); - let keep = match mark.get(&backup_id) { - Some(PruneMark::Keep) => true, - Some(PruneMark::KeepPartial) => true, - _ => false, + let mark = if info.protected { + PruneMark::Protected + } else { + *mark.get(&backup_id).unwrap_or(&PruneMark::Remove) }; - (info, keep) + + (info, mark) }) .collect(); diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs index 3bf8e104..b739d430 100644 --- a/src/api2/admin/datastore.rs +++ b/src/api2/admin/datastore.rs @@ -441,6 +441,7 @@ pub fn list_snapshots ( let backup_type = group.backup_type().to_string(); let backup_id = group.backup_id().to_string(); let backup_time = info.backup_dir.backup_time(); + let protected = info.backup_dir.is_protected(base_path.clone()); match get_all_snapshot_files(&datastore, &info) { Ok((manifest, files)) => { @@ -479,6 +480,7 @@ pub fn list_snapshots ( files, size, owner, + protected, } }, Err(err) => { @@ -503,6 +505,7 @@ pub fn list_snapshots ( files, size: None, owner, + protected, } }, } @@ -846,8 +849,8 @@ pub fn prune( let keep_all = !pbs_datastore::prune::keeps_something(&prune_options); if dry_run { - for (info, mut keep) in prune_info { - if keep_all { keep = true; } + for (info, mark) in prune_info { + let keep = keep_all || mark.keep(); let backup_time = info.backup_dir.backup_time(); let group = info.backup_dir.group(); @@ -857,6 +860,7 @@ pub fn prune( "backup-id": group.backup_id(), "backup-time": backup_time, "keep": keep, + "protected": mark.protected(), })); } return Ok(json!(prune_result)); @@ -874,8 +878,8 @@ pub fn prune( store, backup_type, backup_id); } - for (info, mut keep) in prune_info { - if keep_all { keep = true; } + for (info, mark) in prune_info { + let keep = keep_all || mark.keep(); let backup_time = info.backup_dir.backup_time(); let timestamp = info.backup_dir.backup_time_string(); @@ -887,7 +891,7 @@ pub fn prune( group.backup_type(), group.backup_id(), timestamp, - if keep { "keep" } else { "remove" }, + mark, ); task_log!(worker, "{}", msg); @@ -897,6 +901,7 @@ pub fn prune( "backup-id": group.backup_id(), "backup-time": backup_time, "keep": keep, + "protected": mark.protected(), })); if !(dry_run || keep) { diff --git a/src/server/prune_job.rs b/src/server/prune_job.rs index fc6443e9..0fc68118 100644 --- a/src/server/prune_job.rs +++ b/src/server/prune_job.rs @@ -63,12 +63,12 @@ pub fn prune_datastore( group.backup_id() ); - for (info, mut keep) in prune_info { - if keep_all { keep = true; } + for (info, mark) in prune_info { + let keep = keep_all || mark.keep(); task_log!( worker, "{} {}/{}/{}", - if keep { "keep" } else { "remove" }, + mark, group.backup_type(), group.backup_id(), info.backup_dir.backup_time_string() diff --git a/tests/prune.rs b/tests/prune.rs index 96c29f4a..448588b6 100644 --- a/tests/prune.rs +++ b/tests/prune.rs @@ -19,8 +19,8 @@ fn get_prune_list( prune_info .iter() - .filter_map(|(info, keep)| { - if *keep != return_kept { + .filter_map(|(info, mark)| { + if mark.keep() != return_kept { None } else { Some(info.backup_dir.relative_path())