datastore: move destroying group or dir into respective impl

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2022-04-24 18:49:09 +02:00
parent 5c9c23b6b2
commit f03649b8f3
2 changed files with 65 additions and 60 deletions

View File

@ -5,6 +5,8 @@ use std::sync::Arc;
use anyhow::{bail, format_err, Error}; use anyhow::{bail, format_err, Error};
use proxmox_sys::fs::lock_dir_noblock;
use pbs_api_types::{BackupType, GroupFilter, BACKUP_DATE_REGEX, BACKUP_FILE_REGEX}; use pbs_api_types::{BackupType, GroupFilter, BACKUP_DATE_REGEX, BACKUP_FILE_REGEX};
use pbs_config::{open_backup_lockfile, BackupLockGuard}; use pbs_config::{open_backup_lockfile, BackupLockGuard};
@ -166,6 +168,34 @@ impl BackupGroup {
pub fn iter_snapshots(&self) -> Result<crate::ListSnapshots, Error> { pub fn iter_snapshots(&self) -> Result<crate::ListSnapshots, Error> {
crate::ListSnapshots::new(self.clone()) crate::ListSnapshots::new(self.clone())
} }
/// Destroy the group inclusive all its backup snapshots (BackupDir's)
///
/// Returns true if all snapshots were removed, and false if some were protected
pub fn destroy(&self) -> Result<bool, Error> {
let path = self.full_group_path();
let _guard =
proxmox_sys::fs::lock_dir_noblock(&path, "backup group", "possible running backup")?;
log::info!("removing backup group {:?}", path);
let mut removed_all_snaps = true;
for snap in self.iter_snapshots()? {
let snap = snap?;
if snap.is_protected() {
removed_all_snaps = false;
continue;
}
snap.destroy(false)?;
}
if removed_all_snaps {
std::fs::remove_dir_all(&path).map_err(|err| {
format_err!("removing group directory {:?} failed - {}", path, err)
})?;
}
Ok(removed_all_snaps)
}
} }
impl AsRef<pbs_api_types::BackupGroup> for BackupGroup { impl AsRef<pbs_api_types::BackupGroup> for BackupGroup {
@ -319,7 +349,7 @@ impl BackupDir {
/// ///
/// Also creates the basedir. The lockfile is located in /// Also creates the basedir. The lockfile is located in
/// '/run/proxmox-backup/locks/{datastore}/{type}/{id}/{timestamp}.index.json.lck' /// '/run/proxmox-backup/locks/{datastore}/{type}/{id}/{timestamp}.index.json.lck'
pub(crate) fn manifest_lock_path(&self) -> Result<String, Error> { fn manifest_lock_path(&self) -> Result<String, Error> {
let mut path = format!("/run/proxmox-backup/locks/{}/{self}", self.store.name()); let mut path = format!("/run/proxmox-backup/locks/{}/{self}", self.store.name());
std::fs::create_dir_all(&path)?; std::fs::create_dir_all(&path)?;
use std::fmt::Write; use std::fmt::Write;
@ -337,6 +367,35 @@ impl BackupDir {
open_backup_lockfile(&path, Some(std::time::Duration::from_secs(5)), true) open_backup_lockfile(&path, Some(std::time::Duration::from_secs(5)), true)
.map_err(|err| format_err!("unable to acquire manifest lock {:?} - {}", &path, err)) .map_err(|err| format_err!("unable to acquire manifest lock {:?} - {}", &path, err))
} }
/// Destroy the whole snapshot, bails if it's protected
///
/// Setting `force` to true skips locking and thus ignores if the backup is currently in use.
pub fn destroy(&self, force: bool) -> Result<(), Error> {
let full_path = self.full_path();
let (_guard, _manifest_guard);
if !force {
_guard = lock_dir_noblock(&full_path, "snapshot", "possibly running or in use")?;
_manifest_guard = self.lock_manifest()?;
}
if self.is_protected() {
bail!("cannot remove protected snapshot"); // use special error type?
}
log::info!("removing backup snapshot {:?}", full_path);
std::fs::remove_dir_all(&full_path).map_err(|err| {
format_err!("removing backup snapshot {:?} failed - {}", full_path, err,)
})?;
// the manifest doesn't exist anymore, no need to keep the lock (already done by guard?)
if let Ok(path) = self.manifest_lock_path() {
let _ = std::fs::remove_file(path); // ignore errors
}
Ok(())
}
} }
impl AsRef<pbs_api_types::BackupDir> for BackupDir { impl AsRef<pbs_api_types::BackupDir> for BackupDir {

View File

@ -411,47 +411,16 @@ impl DataStore {
full_path full_path
} }
/// Remove a complete backup group including all snapshots, returns true /// Remove a complete backup group including all snapshots.
/// if all snapshots were removed, and false if some were protected ///
/// Returns true if all snapshots were removed, and false if some were protected
pub fn remove_backup_group( pub fn remove_backup_group(
self: &Arc<Self>, self: &Arc<Self>,
backup_group: &pbs_api_types::BackupGroup, backup_group: &pbs_api_types::BackupGroup,
) -> Result<bool, Error> { ) -> Result<bool, Error> {
let backup_group = self.backup_group(backup_group.clone()); let backup_group = self.backup_group(backup_group.clone());
let full_path = self.group_path(backup_group.as_ref()); backup_group.destroy()
let _guard = proxmox_sys::fs::lock_dir_noblock(
&full_path,
"backup group",
"possible running backup",
)?;
log::info!("removing backup group {:?}", full_path);
let mut removed_all = true;
// remove all individual backup dirs first to ensure nothing is using them
for snap in backup_group.list_backups()? {
if snap.backup_dir.is_protected() {
removed_all = false;
continue;
}
self.remove_backup_dir(snap.backup_dir.as_ref(), false)?;
}
if removed_all {
// no snapshots left, we can now safely remove the empty folder
std::fs::remove_dir_all(&full_path).map_err(|err| {
format_err!(
"removing backup group directory {:?} failed - {}",
full_path,
err,
)
})?;
}
Ok(removed_all)
} }
/// Remove a backup directory including all content /// Remove a backup directory including all content
@ -462,30 +431,7 @@ impl DataStore {
) -> Result<(), Error> { ) -> Result<(), Error> {
let backup_dir = self.backup_dir(backup_dir.clone())?; let backup_dir = self.backup_dir(backup_dir.clone())?;
let full_path = backup_dir.full_path(); backup_dir.destroy(force)
let (_guard, _manifest_guard);
if !force {
_guard = lock_dir_noblock(&full_path, "snapshot", "possibly running or in use")?;
_manifest_guard = backup_dir.lock_manifest()?;
}
if backup_dir.is_protected() {
bail!("cannot remove protected snapshot");
}
log::info!("removing backup snapshot {:?}", full_path);
std::fs::remove_dir_all(&full_path).map_err(|err| {
format_err!("removing backup snapshot {:?} failed - {}", full_path, err,)
})?;
// the manifest does not exists anymore, we do not need to keep the lock
if let Ok(path) = backup_dir.manifest_lock_path() {
// ignore errors
let _ = std::fs::remove_file(path);
}
Ok(())
} }
/// Returns the time of the last successful backup /// Returns the time of the last successful backup