5 use proxmox_sys
::{task_log, task_warn}
;
7 use pbs_datastore
::backup_info
::BackupInfo
;
8 use pbs_datastore
::prune
::compute_prune_info
;
9 use pbs_datastore
::DataStore
;
10 use pbs_api_types
::{Authid, Operation, PRIV_DATASTORE_MODIFY, PruneOptions}
;
11 use pbs_config
::CachedUserInfo
;
12 use proxmox_rest_server
::WorkerTask
;
14 use crate::server
::jobstate
::Job
;
16 pub fn prune_datastore(
17 worker
: Arc
<WorkerTask
>,
19 prune_options
: PruneOptions
,
21 datastore
: Arc
<DataStore
>,
23 ) -> Result
<(), Error
> {
24 task_log
!(worker
, "Starting datastore prune on store \"{}\"", store
);
27 task_log
!(worker
, "(dry test run)");
30 let keep_all
= !pbs_datastore
::prune
::keeps_something(&prune_options
);
33 task_log
!(worker
, "No prune selection - keeping all files.");
37 "retention options: {}",
38 pbs_datastore
::prune
::cli_options_string(&prune_options
)
42 let user_info
= CachedUserInfo
::new()?
;
43 let privs
= user_info
.lookup_privs(&auth_id
, &["datastore", store
]);
44 let has_privs
= privs
& PRIV_DATASTORE_MODIFY
!= 0;
46 let base_path
= datastore
.base_path();
48 let groups
= BackupInfo
::list_backup_groups(&base_path
)?
;
50 let list
= group
.list_backups(&base_path
)?
;
52 if !has_privs
&& !datastore
.owns_backup(&group
, &auth_id
)?
{
56 let mut prune_info
= compute_prune_info(list
, &prune_options
)?
;
57 prune_info
.reverse(); // delete older snapshots first
61 "Starting prune on store \"{}\" group \"{}/{}\"",
67 for (info
, mark
) in prune_info
{
68 let keep
= keep_all
|| mark
.keep();
75 info
.backup_dir
.backup_time_string()
77 if !keep
&& !dry_run
{
78 if let Err(err
) = datastore
.remove_backup_dir(&info
.backup_dir
, false) {
81 "failed to remove dir {:?}: {}",
82 info
.backup_dir
.relative_path(),
95 prune_options
: PruneOptions
,
98 schedule
: Option
<String
>,
99 ) -> Result
<String
, Error
> {
100 let datastore
= DataStore
::lookup_datastore(&store
, Some(Operation
::Write
))?
;
102 let worker_type
= job
.jobtype().to_string();
103 let auth_id
= auth_id
.clone();
104 let upid_str
= WorkerTask
::new_thread(
106 Some(job
.jobname().to_string()),
110 job
.start(&worker
.upid().to_string())?
;
112 if let Some(event_str
) = schedule
{
113 task_log
!(worker
, "task triggered by schedule '{}'", event_str
);
116 let result
= prune_datastore(worker
.clone(), auth_id
, prune_options
, &store
, datastore
, false);
118 let status
= worker
.create_state(&result
);
120 if let Err(err
) = job
.finish(status
) {
122 "could not finish job state for {}: {}",
123 job
.jobtype().to_string(),