api2/admin/datastore: add get/set_protection
for gettin/setting the protected flag for snapshots (akin to notes) Signed-off-by: Dominik Csapak <d.csapak@proxmox.com> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
5cc7d89139
commit
8292d3d20e
|
@ -858,6 +858,30 @@ impl DataStore {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the protection status of the specified snapshot.
|
||||||
|
pub fn update_protection(
|
||||||
|
&self,
|
||||||
|
backup_dir: &BackupDir,
|
||||||
|
protection: bool
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let full_path = self.snapshot_path(backup_dir);
|
||||||
|
|
||||||
|
let _guard = lock_dir_noblock(&full_path, "snapshot", "possibly running or in use")?;
|
||||||
|
|
||||||
|
let protected_path = backup_dir.protected_file(self.base_path());
|
||||||
|
if protection {
|
||||||
|
std::fs::File::create(protected_path)
|
||||||
|
.map_err(|err| format_err!("could not create protection file: {}", err))?;
|
||||||
|
} else if let Err(err) = std::fs::remove_file(protected_path) {
|
||||||
|
// ignore error for non-existing file
|
||||||
|
if err.kind() != std::io::ErrorKind::NotFound {
|
||||||
|
bail!("could not remove protection file: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn verify_new(&self) -> bool {
|
pub fn verify_new(&self) -> bool {
|
||||||
self.verify_new
|
self.verify_new
|
||||||
}
|
}
|
||||||
|
|
|
@ -1750,6 +1750,92 @@ pub fn set_notes(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
store: {
|
||||||
|
schema: DATASTORE_SCHEMA,
|
||||||
|
},
|
||||||
|
"backup-type": {
|
||||||
|
schema: BACKUP_TYPE_SCHEMA,
|
||||||
|
},
|
||||||
|
"backup-id": {
|
||||||
|
schema: BACKUP_ID_SCHEMA,
|
||||||
|
},
|
||||||
|
"backup-time": {
|
||||||
|
schema: BACKUP_TIME_SCHEMA,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
permission: &Permission::Privilege(&["datastore", "{store}"], PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_BACKUP, true),
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Query protection for a specific backup
|
||||||
|
pub fn get_protection(
|
||||||
|
store: String,
|
||||||
|
backup_type: String,
|
||||||
|
backup_id: String,
|
||||||
|
backup_time: i64,
|
||||||
|
rpcenv: &mut dyn RpcEnvironment,
|
||||||
|
) -> Result<bool, Error> {
|
||||||
|
let datastore = DataStore::lookup_datastore(&store)?;
|
||||||
|
|
||||||
|
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
|
||||||
|
let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
|
||||||
|
|
||||||
|
check_priv_or_backup_owner(&datastore, backup_dir.group(), &auth_id, PRIV_DATASTORE_AUDIT)?;
|
||||||
|
|
||||||
|
let protected_path = backup_dir.protected_file(datastore.base_path());
|
||||||
|
|
||||||
|
Ok(protected_path.exists())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
store: {
|
||||||
|
schema: DATASTORE_SCHEMA,
|
||||||
|
},
|
||||||
|
"backup-type": {
|
||||||
|
schema: BACKUP_TYPE_SCHEMA,
|
||||||
|
},
|
||||||
|
"backup-id": {
|
||||||
|
schema: BACKUP_ID_SCHEMA,
|
||||||
|
},
|
||||||
|
"backup-time": {
|
||||||
|
schema: BACKUP_TIME_SCHEMA,
|
||||||
|
},
|
||||||
|
protected: {
|
||||||
|
description: "Enable/disable protection.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
permission: &Permission::Privilege(&["datastore", "{store}"],
|
||||||
|
PRIV_DATASTORE_MODIFY | PRIV_DATASTORE_BACKUP,
|
||||||
|
true),
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// En- or disable protection for a specific backup
|
||||||
|
pub fn set_protection(
|
||||||
|
store: String,
|
||||||
|
backup_type: String,
|
||||||
|
backup_id: String,
|
||||||
|
backup_time: i64,
|
||||||
|
protected: bool,
|
||||||
|
rpcenv: &mut dyn RpcEnvironment,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let datastore = DataStore::lookup_datastore(&store)?;
|
||||||
|
|
||||||
|
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
|
||||||
|
let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
|
||||||
|
|
||||||
|
check_priv_or_backup_owner(&datastore, backup_dir.group(), &auth_id, PRIV_DATASTORE_MODIFY)?;
|
||||||
|
|
||||||
|
datastore.update_protection(&backup_dir, protected)
|
||||||
|
}
|
||||||
|
|
||||||
#[api(
|
#[api(
|
||||||
input: {
|
input: {
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -1898,6 +1984,12 @@ const DATASTORE_INFO_SUBDIRS: SubdirMap = &[
|
||||||
.get(&API_METHOD_GET_NOTES)
|
.get(&API_METHOD_GET_NOTES)
|
||||||
.put(&API_METHOD_SET_NOTES)
|
.put(&API_METHOD_SET_NOTES)
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"protected",
|
||||||
|
&Router::new()
|
||||||
|
.get(&API_METHOD_GET_PROTECTION)
|
||||||
|
.put(&API_METHOD_SET_PROTECTION)
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"prune",
|
"prune",
|
||||||
&Router::new()
|
&Router::new()
|
||||||
|
|
Loading…
Reference in New Issue