diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs index 79ab97e7..60941501 100644 --- a/src/api2/admin/datastore.rs +++ b/src/api2/admin/datastore.rs @@ -820,7 +820,7 @@ pub fn verify( permission: &Permission::Privilege(&["datastore", "{store}"], PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_PRUNE, true), }, )] -/// Prune the datastore +/// Prune a group on the datastore pub fn prune( backup_id: String, backup_type: String, @@ -922,6 +922,62 @@ pub fn prune( Ok(json!(prune_result)) } +#[api( + input: { + properties: { + "dry-run": { + optional: true, + type: bool, + default: false, + description: "Just show what prune would do, but do not delete anything.", + }, + "prune-options": { + type: PruneOptions, + flatten: true, + }, + store: { + schema: DATASTORE_SCHEMA, + }, + }, + }, + returns: { + schema: UPID_SCHEMA, + }, + access: { + permission: &Permission::Privilege(&["datastore", "{store}"], PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_PRUNE, true), + }, +)] +/// Prune the datastore +pub fn prune_datastore( + dry_run: bool, + prune_options: PruneOptions, + store: String, + _param: Value, + rpcenv: &mut dyn RpcEnvironment, +) -> Result { + + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; + + let datastore = DataStore::lookup_datastore(&store)?; + + let upid_str = WorkerTask::new_thread( + "prune", + Some(store.clone()), + auth_id.clone(), + false, + move |worker| crate::server::prune_datastore( + worker.clone(), + auth_id, + prune_options, + &store, + datastore, + dry_run + ), + )?; + + Ok(upid_str) +} + #[api( input: { properties: { @@ -1844,6 +1900,11 @@ const DATASTORE_INFO_SUBDIRS: SubdirMap = &[ &Router::new() .post(&API_METHOD_PRUNE) ), + ( + "prune-datastore", + &Router::new() + .post(&API_METHOD_PRUNE_DATASTORE) + ), ( "pxar-file-download", &Router::new() diff --git a/src/server/prune_job.rs b/src/server/prune_job.rs index bbf53ade..255e21ce 100644 --- a/src/server/prune_job.rs +++ b/src/server/prune_job.rs @@ -19,9 +19,14 @@ pub fn prune_datastore( prune_options: PruneOptions, store: &str, datastore: Arc, + dry_run: bool, ) -> Result<(), Error> { task_log!(worker, "Starting datastore prune on store \"{}\"", store); + if dry_run { + task_log!(worker, "(dry test run)"); + } + let keep_all = !prune_options.keeps_something(); if keep_all { @@ -69,7 +74,7 @@ pub fn prune_datastore( group.backup_id(), info.backup_dir.backup_time_string() ); - if !keep { + if !keep && !dry_run { if let Err(err) = datastore.remove_backup_dir(&info.backup_dir, false) { task_warn!( worker, @@ -108,7 +113,7 @@ pub fn do_prune_job( task_log!(worker, "task triggered by schedule '{}'", event_str); } - let result = prune_datastore(worker.clone(), auth_id, prune_options, &store, datastore); + let result = prune_datastore(worker.clone(), auth_id, prune_options, &store, datastore, false); let status = worker.create_state(&result);