* [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore @ 2021-09-28 10:05 Hannes Laimer 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 1/5] pbs-api-types: add maintenance type and msg to ds config Hannes Laimer ` (6 more replies) 0 siblings, 7 replies; 13+ messages in thread From: Hannes Laimer @ 2021-09-28 10:05 UTC (permalink / raw) To: pbs-devel Adds a maintenance mode for datatsores. If a datastore is in maintenance mode it has a maintenance-type and a maintenance-msg. The type specifies what is still allowed on the ds and what is not. Currently there are two types: read only and offline. 'read only' prevents everything that would write something to the ds, but allows to read from it. 'offline' prevents everything on the datastore, neither operation that write nor operations that read form the datastore are allowed. The message is optional and is a short string that describes the reason for the maintenance, it is shown whenever an operation is prevented due to the maintenance. Here 'read only' is less restrictive than 'offline'. In order to check if some operation is allowed in the current maintenance mode a function has to be called before every operation that would be effected by a maintenance. This function recieves an upper bound for 'restrictiveness', so if we want to get the list of available snapshots we have to read from the ds, everything that is less restrictive than 'offline' is fine. Here that means maintenance has to either be off or 'read only'. Already running jobs and operations are not affected. Neither are the modification or creation of jobs, since they just modify a config file that is stored on the host system. (It might make sense to add a possibility to shut down running jobs when maintenance is turned on.) Hannes Laimer (5): pbs-api-types: add maintenance type and msg to ds config pbs-datastore: add check_maintenence function api2: make maintenance type and msg updatable/deletable jobs/api2: add checks for maintenance ui: add maintenance to datastore options pbs-api-types/src/datastore.rs | 33 +++++++++++++++++ pbs-datastore/src/datastore.rs | 18 ++++++++- src/api2/admin/datastore.rs | 48 +++++++++++++++++++++--- src/api2/config/datastore.rs | 8 ++++ src/api2/pull.rs | 5 ++- src/server/gc_job.rs | 5 ++- src/server/prune_job.rs | 4 +- src/server/verify_job.rs | 5 ++- www/Makefile | 1 + www/datastore/OptionView.js | 10 +++++ www/window/MaintenanceOptions.js | 63 ++++++++++++++++++++++++++++++++ 11 files changed, 188 insertions(+), 12 deletions(-) create mode 100644 www/window/MaintenanceOptions.js -- 2.30.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 1/5] pbs-api-types: add maintenance type and msg to ds config 2021-09-28 10:05 [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Hannes Laimer @ 2021-09-28 10:05 ` Hannes Laimer 2021-10-01 8:23 ` Dominik Csapak 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 2/5] pbs-datastore: add check_maintenence function Hannes Laimer ` (5 subsequent siblings) 6 siblings, 1 reply; 13+ messages in thread From: Hannes Laimer @ 2021-09-28 10:05 UTC (permalink / raw) To: pbs-devel --- pbs-api-types/src/datastore.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/pbs-api-types/src/datastore.rs b/pbs-api-types/src/datastore.rs index 75f82ea4..80ae77f2 100644 --- a/pbs-api-types/src/datastore.rs +++ b/pbs-api-types/src/datastore.rs @@ -165,6 +165,26 @@ pub struct PruneOptions { pub keep_yearly: Option<u64>, } +#[api()] +#[derive(PartialOrd, Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +/// Different maintenance types. +pub enum MaintenanceType { + /// Only reading operations are allowed. + ReadOnly, + /// Neither reading nor writing is allowed on the datastore. + Offline, +} + +impl std::fmt::Display for MaintenanceType { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match *self { + MaintenanceType::ReadOnly => write!(f, "read only"), + MaintenanceType::Offline => write!(f, "offline"), + } + } +} + #[api( properties: { name: { @@ -222,6 +242,15 @@ pub struct PruneOptions { optional: true, type: bool, }, + "maintenance-type": { + optional: true, + type: MaintenanceType, + }, + "maintenance-msg": { + description: "Text that will be shown as a description for the maintenance.", + optional: true, + type: String, + }, } )] #[derive(Serialize,Deserialize,Updater)] @@ -259,6 +288,10 @@ pub struct DataStoreConfig { /// Send notification only for job errors #[serde(skip_serializing_if="Option::is_none")] pub notify: Option<String>, + #[serde(skip_serializing_if="Option::is_none")] + pub maintenance_type: Option<MaintenanceType>, + #[serde(skip_serializing_if="Option::is_none")] + pub maintenance_msg: Option<String>, } #[api( -- 2.30.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 1/5] pbs-api-types: add maintenance type and msg to ds config 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 1/5] pbs-api-types: add maintenance type and msg to ds config Hannes Laimer @ 2021-10-01 8:23 ` Dominik Csapak 2021-10-01 12:00 ` Wolfgang Bumiller 0 siblings, 1 reply; 13+ messages in thread From: Dominik Csapak @ 2021-10-01 8:23 UTC (permalink / raw) To: Proxmox Backup Server development discussion, Hannes Laimer On 9/28/21 12:05, Hannes Laimer wrote: > --- > pbs-api-types/src/datastore.rs | 33 +++++++++++++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/pbs-api-types/src/datastore.rs b/pbs-api-types/src/datastore.rs > index 75f82ea4..80ae77f2 100644 > --- a/pbs-api-types/src/datastore.rs > +++ b/pbs-api-types/src/datastore.rs > @@ -165,6 +165,26 @@ pub struct PruneOptions { > pub keep_yearly: Option<u64>, > } > > +#[api()] > +#[derive(PartialOrd, Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] > +#[serde(rename_all = "lowercase")] > +/// Different maintenance types. > +pub enum MaintenanceType { > + /// Only reading operations are allowed. > + ReadOnly, > + /// Neither reading nor writing is allowed on the datastore. > + Offline, > +} > + > +impl std::fmt::Display for MaintenanceType { > + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { > + match *self { > + MaintenanceType::ReadOnly => write!(f, "read only"), since that goes into the config and api (AFAICS), i'd not use spaces in the value. we could use 'read-only' for example, but maybe check other parts of the api/configs where we may have values similar to this > + MaintenanceType::Offline => write!(f, "offline"), > + } > + } > +} > + > #[api( > properties: { > name: { > @@ -222,6 +242,15 @@ pub struct PruneOptions { > optional: true, > type: bool, > }, > + "maintenance-type": { > + optional: true, > + type: MaintenanceType, > + }, > + "maintenance-msg": { > + description: "Text that will be shown as a description for the maintenance.", > + optional: true, > + type: String, > + }, i think we could combine the message + type in the enum, we just have to manually to the deserialization (look for example how we do the media-location for tapes, there we can have a named 'vault' which gets (de)serialized as/from "vault-NAME" we could to the same here with "read-only-foo' and 'offline-foo' this would make for a nicer api maybe? (any other opinions @thomas @wolfgang @dietmar?) also i think the way it is now, i could update the maintenance message without setting a mode... > } > )] > #[derive(Serialize,Deserialize,Updater)] > @@ -259,6 +288,10 @@ pub struct DataStoreConfig { > /// Send notification only for job errors > #[serde(skip_serializing_if="Option::is_none")] > pub notify: Option<String>, > + #[serde(skip_serializing_if="Option::is_none")] > + pub maintenance_type: Option<MaintenanceType>, > + #[serde(skip_serializing_if="Option::is_none")] > + pub maintenance_msg: Option<String>, > } > > #[api( > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 1/5] pbs-api-types: add maintenance type and msg to ds config 2021-10-01 8:23 ` Dominik Csapak @ 2021-10-01 12:00 ` Wolfgang Bumiller 0 siblings, 0 replies; 13+ messages in thread From: Wolfgang Bumiller @ 2021-10-01 12:00 UTC (permalink / raw) To: Dominik Csapak Cc: Proxmox Backup Server development discussion, Hannes Laimer On Fri, Oct 01, 2021 at 10:23:08AM +0200, Dominik Csapak wrote: > On 9/28/21 12:05, Hannes Laimer wrote: > > --- > > pbs-api-types/src/datastore.rs | 33 +++++++++++++++++++++++++++++++++ > > 1 file changed, 33 insertions(+) > > > > diff --git a/pbs-api-types/src/datastore.rs b/pbs-api-types/src/datastore.rs > > index 75f82ea4..80ae77f2 100644 > > --- a/pbs-api-types/src/datastore.rs > > +++ b/pbs-api-types/src/datastore.rs > > @@ -165,6 +165,26 @@ pub struct PruneOptions { > > pub keep_yearly: Option<u64>, > > } > > +#[api()] > > +#[derive(PartialOrd, Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] > > +#[serde(rename_all = "lowercase")] > > +/// Different maintenance types. > > +pub enum MaintenanceType { > > + /// Only reading operations are allowed. > > + ReadOnly, > > + /// Neither reading nor writing is allowed on the datastore. > > + Offline, > > +} > > + > > +impl std::fmt::Display for MaintenanceType { > > + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { > > + match *self { > > + MaintenanceType::ReadOnly => write!(f, "read only"), > > since that goes into the config and api (AFAICS), i'd not use spaces in the > value. we could use 'read-only' for example, but maybe check other > parts of the api/configs where we may have values similar to this I'm actually kind of leaning towards using `serde_plain::forward_display_to_serde!()` for such cases. We have some of serde_plain's functionality int he proxmox crate and since the plan is to split things up further for the sake of compile time, `serde_plain` seems like a perfectly fine additional dependency (it's tiny and only uses serde) > > > + MaintenanceType::Offline => write!(f, "offline"), > > + } > > + } > > +} > > + > > #[api( > > properties: { > > name: { > > @@ -222,6 +242,15 @@ pub struct PruneOptions { > > optional: true, > > type: bool, > > }, > > + "maintenance-type": { > > + optional: true, > > + type: MaintenanceType, > > + }, > > + "maintenance-msg": { > > + description: "Text that will be shown as a description for the maintenance.", > > + optional: true, > > + type: String, > > + }, > > i think we could combine the message + type in the enum, we just have > to manually to the deserialization (look for example how we > do the media-location for tapes, there we can have a named 'vault' > which gets (de)serialized as/from "vault-NAME" > > we could to the same here with "read-only-foo' and 'offline-foo' > > this would make for a nicer api maybe? (any other opinions @thomas @wolfgang > @dietmar?) > > also i think the way it is now, i could update the maintenance message > without setting a mode... I suppose it's a tuple type, which, unfortunately, the schema cannot represent. On a side note, OpenAPI 3.1 & JSON Schema 2020-12 seem to have settled on a way to represent this though, in case we want to try and add support for that... Or you know, a string with custom deserialization works fine ;-) If there's supposed to be a text though and the enum uses dashes, maybe use a colon to separate the text? `"offline: Holding your data hostage until you pay up."` `"read-only: Raid resilvering, stop slowing it down to a crawl."` ^ permalink raw reply [flat|nested] 13+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 2/5] pbs-datastore: add check_maintenence function 2021-09-28 10:05 [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Hannes Laimer 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 1/5] pbs-api-types: add maintenance type and msg to ds config Hannes Laimer @ 2021-09-28 10:05 ` Hannes Laimer 2021-10-01 12:06 ` Wolfgang Bumiller 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 3/5] api2: make maintenance type and msg updatable/deletable Hannes Laimer ` (4 subsequent siblings) 6 siblings, 1 reply; 13+ messages in thread From: Hannes Laimer @ 2021-09-28 10:05 UTC (permalink / raw) To: pbs-devel This function checks if something is allowed in a specific maintenance type, it has to be called whenever something depends on maintenance to be off or less rescrictive than a specific type. --- pbs-datastore/src/datastore.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pbs-datastore/src/datastore.rs b/pbs-datastore/src/datastore.rs index b068a9c9..1014b357 100644 --- a/pbs-datastore/src/datastore.rs +++ b/pbs-datastore/src/datastore.rs @@ -11,7 +11,7 @@ use lazy_static::lazy_static; use proxmox::tools::fs::{replace_file, file_read_optional_string, CreateOptions}; -use pbs_api_types::{UPID, DataStoreConfig, Authid, GarbageCollectionStatus}; +use pbs_api_types::{UPID, DataStoreConfig, Authid, GarbageCollectionStatus, MaintenanceType}; use pbs_tools::format::HumanByte; use pbs_tools::fs::{lock_dir_noblock, DirLockGuard}; use pbs_tools::process_locker::ProcessLockSharedGuard; @@ -98,6 +98,22 @@ impl DataStore { Ok(()) } + /// checks if the current maintenace mode of the datastore allows something + pub fn check_maintenance(&self, need_less_than: MaintenanceType) -> Result<(), Error> { + let (config, _digest) = pbs_config::datastore::config()?; + let config: DataStoreConfig = config.lookup("datastore", &self.name())?; + if let Some(maintenance_type) = config.maintenance_type { + if maintenance_type >= need_less_than { + bail!("Datastore '{}' is in maintenance {} mode: {}", + &self.name(), + maintenance_type, + config.maintenance_msg.unwrap_or(String::from("no description")) + ); + } + } + Ok(()) + } + fn open_with_path(store_name: &str, path: &Path, config: DataStoreConfig) -> Result<Self, Error> { let chunk_store = ChunkStore::open(store_name, path)?; -- 2.30.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 2/5] pbs-datastore: add check_maintenence function 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 2/5] pbs-datastore: add check_maintenence function Hannes Laimer @ 2021-10-01 12:06 ` Wolfgang Bumiller 0 siblings, 0 replies; 13+ messages in thread From: Wolfgang Bumiller @ 2021-10-01 12:06 UTC (permalink / raw) To: Hannes Laimer; +Cc: pbs-devel, Dominik Csapak On Tue, Sep 28, 2021 at 12:05:45PM +0200, Hannes Laimer wrote: > This function checks if something is allowed in a specific maintenance > type, it has to be called whenever something depends on maintenance to > be off or less rescrictive than a specific type. > --- > pbs-datastore/src/datastore.rs | 18 +++++++++++++++++- > 1 file changed, 17 insertions(+), 1 deletion(-) > > diff --git a/pbs-datastore/src/datastore.rs b/pbs-datastore/src/datastore.rs > index b068a9c9..1014b357 100644 > --- a/pbs-datastore/src/datastore.rs > +++ b/pbs-datastore/src/datastore.rs > @@ -11,7 +11,7 @@ use lazy_static::lazy_static; > > use proxmox::tools::fs::{replace_file, file_read_optional_string, CreateOptions}; > > -use pbs_api_types::{UPID, DataStoreConfig, Authid, GarbageCollectionStatus}; > +use pbs_api_types::{UPID, DataStoreConfig, Authid, GarbageCollectionStatus, MaintenanceType}; > use pbs_tools::format::HumanByte; > use pbs_tools::fs::{lock_dir_noblock, DirLockGuard}; > use pbs_tools::process_locker::ProcessLockSharedGuard; > @@ -98,6 +98,22 @@ impl DataStore { > Ok(()) > } > > + /// checks if the current maintenace mode of the datastore allows something > + pub fn check_maintenance(&self, need_less_than: MaintenanceType) -> Result<(), Error> { I'd very much like the method name itself to suggest the direction of such a check, rather than have only the parameter name tell you this, not even the doc comment ;-) When you read `datastore.check_maintenance(foo)` the parameter name isn't actually visible in code, but the code should speak for itself. And like Dominik said, it's a confusing interface. Plus, I can't think if a really good name for the method that fixes my remark above. So maybe the public facing interface should just be: pub fn can_read(&self) -> bool; pub fn can_write(&self) -> bool; and/or pub fn check_read(&self) -> Result<(), Error>; pub fn check_write(&self) -> Result<(), Error>; with the error including the maintenance message > + let (config, _digest) = pbs_config::datastore::config()?; > + let config: DataStoreConfig = config.lookup("datastore", &self.name())?; > + if let Some(maintenance_type) = config.maintenance_type { > + if maintenance_type >= need_less_than { > + bail!("Datastore '{}' is in maintenance {} mode: {}", > + &self.name(), > + maintenance_type, > + config.maintenance_msg.unwrap_or(String::from("no description")) > + ); > + } > + } > + Ok(()) > + } > + > fn open_with_path(store_name: &str, path: &Path, config: DataStoreConfig) -> Result<Self, Error> { > let chunk_store = ChunkStore::open(store_name, path)?; > > -- > 2.30.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 3/5] api2: make maintenance type and msg updatable/deletable 2021-09-28 10:05 [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Hannes Laimer 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 1/5] pbs-api-types: add maintenance type and msg to ds config Hannes Laimer 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 2/5] pbs-datastore: add check_maintenence function Hannes Laimer @ 2021-09-28 10:05 ` Hannes Laimer 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 4/5] jobs/api2: add checks for maintenance Hannes Laimer ` (3 subsequent siblings) 6 siblings, 0 replies; 13+ messages in thread From: Hannes Laimer @ 2021-09-28 10:05 UTC (permalink / raw) To: pbs-devel --- src/api2/config/datastore.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs index 0819d5ec..1f1bb9c1 100644 --- a/src/api2/config/datastore.rs +++ b/src/api2/config/datastore.rs @@ -183,6 +183,10 @@ pub enum DeletableProperty { notify_user, /// Delete the notify property notify, + /// Delete the maintenance_type property + maintenance_type, + /// Delete the maintenance_msg property + maintenance_msg, } #[api( @@ -249,6 +253,8 @@ pub fn update_datastore( DeletableProperty::verify_new => { data.verify_new = None; }, DeletableProperty::notify => { data.notify = None; }, DeletableProperty::notify_user => { data.notify_user = None; }, + DeletableProperty::maintenance_type => { data.maintenance_type = None; }, + DeletableProperty::maintenance_msg => { data.maintenance_msg = None; }, } } } @@ -291,6 +297,8 @@ pub fn update_datastore( } } if update.verify_new.is_some() { data.verify_new = update.verify_new; } + if update.maintenance_type.is_some() { data.maintenance_type = update.maintenance_type; } + if update.maintenance_msg.is_some() { data.maintenance_msg = update.maintenance_msg; } if update.notify_user.is_some() { data.notify_user = update.notify_user; } -- 2.30.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 4/5] jobs/api2: add checks for maintenance 2021-09-28 10:05 [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Hannes Laimer ` (2 preceding siblings ...) 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 3/5] api2: make maintenance type and msg updatable/deletable Hannes Laimer @ 2021-09-28 10:05 ` Hannes Laimer 2021-10-01 8:28 ` Dominik Csapak 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 5/5] ui: add maintenance to datastore options Hannes Laimer ` (2 subsequent siblings) 6 siblings, 1 reply; 13+ messages in thread From: Hannes Laimer @ 2021-09-28 10:05 UTC (permalink / raw) To: pbs-devel --- src/api2/admin/datastore.rs | 48 +++++++++++++++++++++++++++++++++---- src/api2/pull.rs | 5 +++- src/server/gc_job.rs | 5 ++-- src/server/prune_job.rs | 4 +++- src/server/verify_job.rs | 5 ++-- 5 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs index 7e9a0ee0..f5ed6603 100644 --- a/src/api2/admin/datastore.rs +++ b/src/api2/admin/datastore.rs @@ -29,7 +29,7 @@ use pxar::EntryKind; use pbs_api_types::{ Authid, BackupContent, Counts, CryptMode, DataStoreListItem, GarbageCollectionStatus, GroupListItem, SnapshotListItem, SnapshotVerifyState, PruneOptions, - DataStoreStatus, RRDMode, RRDTimeFrameResolution, + DataStoreStatus, RRDMode, RRDTimeFrameResolution, MaintenanceType, BACKUP_ARCHIVE_NAME_SCHEMA, BACKUP_ID_SCHEMA, BACKUP_TIME_SCHEMA, BACKUP_TYPE_SCHEMA, DATASTORE_SCHEMA, IGNORE_VERIFIED_BACKUPS_SCHEMA, UPID_SCHEMA, @@ -83,6 +83,7 @@ fn check_priv_or_backup_owner( auth_id: &Authid, required_privs: u64, ) -> Result<(), Error> { + store.check_maintenance(MaintenanceType::Offline)?; let user_info = CachedUserInfo::new()?; let privs = user_info.lookup_privs(&auth_id, &["datastore", store.name()]); @@ -97,7 +98,7 @@ fn read_backup_index( store: &DataStore, backup_dir: &BackupDir, ) -> Result<(BackupManifest, Vec<BackupContent>), Error> { - + store.check_maintenance(MaintenanceType::Offline)?; let (manifest, index_size) = store.load_manifest(backup_dir)?; let mut result = Vec::new(); @@ -125,7 +126,7 @@ fn get_all_snapshot_files( store: &DataStore, info: &BackupInfo, ) -> Result<(BackupManifest, Vec<BackupContent>), Error> { - + store.check_maintenance(MaintenanceType::Offline)?; let (manifest, mut files) = read_backup_index(&store, &info.backup_dir)?; let file_set = files.iter().fold(HashSet::new(), |mut acc, item| { @@ -172,6 +173,9 @@ pub fn list_groups( let user_privs = user_info.lookup_privs(&auth_id, &["datastore", &store]); let datastore = DataStore::lookup_datastore(&store)?; + + datastore.check_maintenance(MaintenanceType::Offline)?; + let list_all = (user_privs & PRIV_DATASTORE_AUDIT) != 0; let backup_groups = BackupInfo::list_backup_groups(&datastore.base_path())?; @@ -267,9 +271,11 @@ pub fn delete_group( ) -> Result<Value, Error> { let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; + let datastore = DataStore::lookup_datastore(&store)?; + + datastore.check_maintenance(MaintenanceType::ReadOnly)?; let group = BackupGroup::new(backup_type, backup_id); - let datastore = DataStore::lookup_datastore(&store)?; check_priv_or_backup_owner(&datastore, &group, &auth_id, PRIV_DATASTORE_MODIFY)?; @@ -316,6 +322,8 @@ pub fn list_snapshot_files( let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::Offline)?; + let snapshot = BackupDir::new(backup_type, backup_id, backup_time)?; check_priv_or_backup_owner(&datastore, snapshot.group(), &auth_id, PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_READ)?; @@ -362,9 +370,12 @@ pub fn delete_snapshot( ) -> Result<Value, Error> { let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; + + let datastore = DataStore::lookup_datastore(&store)?; + + datastore.check_maintenance(MaintenanceType::ReadOnly)?; let snapshot = BackupDir::new(backup_type, backup_id, backup_time)?; - let datastore = DataStore::lookup_datastore(&store)?; check_priv_or_backup_owner(&datastore, snapshot.group(), &auth_id, PRIV_DATASTORE_MODIFY)?; @@ -415,6 +426,8 @@ pub fn list_snapshots ( let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::Offline)?; + let base_path = datastore.base_path(); let groups = match (backup_type, backup_id) { @@ -686,6 +699,9 @@ pub fn verify( rpcenv: &mut dyn RpcEnvironment, ) -> Result<Value, Error> { let datastore = DataStore::lookup_datastore(&store)?; + + datastore.check_maintenance(MaintenanceType::Offline)?; + let ignore_verified = ignore_verified.unwrap_or(true); let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; @@ -832,6 +848,8 @@ pub fn prune( let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::ReadOnly)?; + check_priv_or_backup_owner(&datastore, &group, &auth_id, PRIV_DATASTORE_MODIFY)?; let worker_id = format!("{}:{}/{}", store, &backup_type, &backup_id); @@ -1035,6 +1053,8 @@ pub fn garbage_collection_status( let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::Offline)?; + let status = datastore.last_gc_status(); Ok(status) @@ -1111,6 +1131,8 @@ pub fn download_file( let store = required_string_param(¶m, "store")?; let datastore = DataStore::lookup_datastore(store)?; + datastore.check_maintenance(MaintenanceType::Offline)?; + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let file_name = required_string_param(¶m, "file-name")?.to_owned(); @@ -1181,6 +1203,8 @@ pub fn download_file_decoded( let store = required_string_param(¶m, "store")?; let datastore = DataStore::lookup_datastore(store)?; + datastore.check_maintenance(MaintenanceType::Offline)?; + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let file_name = required_string_param(¶m, "file-name")?.to_owned(); @@ -1372,6 +1396,8 @@ pub fn catalog( ) -> Result<Vec<ArchiveEntry>, Error> { let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::Offline)?; + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?; @@ -1442,6 +1468,8 @@ pub fn pxar_file_download( let store = required_string_param(¶m, "store")?; let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::Offline)?; + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let filepath = required_string_param(¶m, "filepath")?.to_owned(); @@ -1597,6 +1625,8 @@ pub fn get_group_notes( ) -> Result<String, Error> { let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::Offline)?; + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let backup_group = BackupGroup::new(backup_type, backup_id); @@ -1639,6 +1669,8 @@ pub fn set_group_notes( ) -> Result<(), Error> { let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::ReadOnly)?; + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let backup_group = BackupGroup::new(backup_type, backup_id); @@ -1681,6 +1713,8 @@ pub fn get_notes( ) -> Result<String, Error> { let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::Offline)?; + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?; @@ -1732,6 +1766,8 @@ pub fn set_notes( ) -> Result<(), Error> { let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::ReadOnly)?; + let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?; @@ -1777,6 +1813,8 @@ pub fn set_backup_owner( let datastore = DataStore::lookup_datastore(&store)?; + datastore.check_maintenance(MaintenanceType::ReadOnly)?; + let backup_group = BackupGroup::new(backup_type, backup_id); let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; diff --git a/src/api2/pull.rs b/src/api2/pull.rs index ea8faab8..b1669288 100644 --- a/src/api2/pull.rs +++ b/src/api2/pull.rs @@ -9,7 +9,7 @@ use proxmox::api::{ApiMethod, Router, RpcEnvironment, Permission}; use pbs_client::{HttpClient, BackupRepository}; use pbs_api_types::{ - Remote, Authid, SyncJobConfig, + Remote, Authid, SyncJobConfig, MaintenanceType, DATASTORE_SCHEMA, REMOTE_ID_SCHEMA, REMOVE_VANISHED_BACKUPS_SCHEMA, PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_PRUNE, PRIV_REMOTE_READ, }; @@ -71,6 +71,9 @@ pub fn do_sync_job( to_stdout: bool, ) -> Result<String, Error> { + let datastore = DataStore::lookup_datastore(&sync_job.store)?; + datastore.check_maintenance(MaintenanceType::ReadOnly)?; + let job_id = format!("{}:{}:{}:{}", sync_job.remote, sync_job.remote_store, diff --git a/src/server/gc_job.rs b/src/server/gc_job.rs index 794fe146..be04b635 100644 --- a/src/server/gc_job.rs +++ b/src/server/gc_job.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use anyhow::Error; -use pbs_api_types::Authid; +use pbs_api_types::{Authid, MaintenanceType}; use pbs_tools::task_log; use pbs_datastore::DataStore; use proxmox_rest_server::WorkerTask; @@ -16,7 +16,8 @@ pub fn do_garbage_collection_job( schedule: Option<String>, to_stdout: bool, ) -> Result<String, Error> { - + datastore.check_maintenance(MaintenanceType::ReadOnly)?; + let store = datastore.name().to_string(); let (email, notify) = crate::server::lookup_datastore_notify_settings(&store); diff --git a/src/server/prune_job.rs b/src/server/prune_job.rs index fc6443e9..84131634 100644 --- a/src/server/prune_job.rs +++ b/src/server/prune_job.rs @@ -5,7 +5,7 @@ use anyhow::Error; use pbs_datastore::backup_info::BackupInfo; use pbs_datastore::prune::compute_prune_info; use pbs_datastore::DataStore; -use pbs_api_types::{Authid, PRIV_DATASTORE_MODIFY, PruneOptions}; +use pbs_api_types::{Authid, MaintenanceType, PRIV_DATASTORE_MODIFY, PruneOptions}; use pbs_config::CachedUserInfo; use pbs_tools::{task_log, task_warn}; use proxmox_rest_server::WorkerTask; @@ -20,6 +20,8 @@ pub fn prune_datastore( datastore: Arc<DataStore>, dry_run: bool, ) -> Result<(), Error> { + datastore.check_maintenance(MaintenanceType::ReadOnly)?; + task_log!(worker, "Starting datastore prune on store \"{}\"", store); if dry_run { diff --git a/src/server/verify_job.rs b/src/server/verify_job.rs index 6aba97c9..3b2b1472 100644 --- a/src/server/verify_job.rs +++ b/src/server/verify_job.rs @@ -1,7 +1,7 @@ use anyhow::{format_err, Error}; use pbs_tools::task_log; -use pbs_api_types::{Authid, VerificationJobConfig}; +use pbs_api_types::{Authid, VerificationJobConfig, MaintenanceType}; use proxmox_rest_server::WorkerTask; use pbs_datastore::DataStore; @@ -21,9 +21,10 @@ pub fn do_verification_job( schedule: Option<String>, to_stdout: bool, ) -> Result<String, Error> { - let datastore = DataStore::lookup_datastore(&verification_job.store)?; + datastore.check_maintenance(MaintenanceType::ReadOnly)?; + let outdated_after = verification_job.outdated_after; let ignore_verified_snapshots = verification_job.ignore_verified.unwrap_or(true); -- 2.30.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 4/5] jobs/api2: add checks for maintenance 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 4/5] jobs/api2: add checks for maintenance Hannes Laimer @ 2021-10-01 8:28 ` Dominik Csapak 0 siblings, 0 replies; 13+ messages in thread From: Dominik Csapak @ 2021-10-01 8:28 UTC (permalink / raw) To: Proxmox Backup Server development discussion, Hannes Laimer On 9/28/21 12:05, Hannes Laimer wrote: > --- > src/api2/admin/datastore.rs | 48 +++++++++++++++++++++++++++++++++---- > src/api2/pull.rs | 5 +++- > src/server/gc_job.rs | 5 ++-- > src/server/prune_job.rs | 4 +++- > src/server/verify_job.rs | 5 ++-- > 5 files changed, 56 insertions(+), 11 deletions(-) > > diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs > index 7e9a0ee0..f5ed6603 100644 > --- a/src/api2/admin/datastore.rs > +++ b/src/api2/admin/datastore.rs > @@ -29,7 +29,7 @@ use pxar::EntryKind; > use pbs_api_types::{ Authid, BackupContent, Counts, CryptMode, > DataStoreListItem, GarbageCollectionStatus, GroupListItem, > SnapshotListItem, SnapshotVerifyState, PruneOptions, > - DataStoreStatus, RRDMode, RRDTimeFrameResolution, > + DataStoreStatus, RRDMode, RRDTimeFrameResolution, MaintenanceType, > BACKUP_ARCHIVE_NAME_SCHEMA, BACKUP_ID_SCHEMA, BACKUP_TIME_SCHEMA, > BACKUP_TYPE_SCHEMA, DATASTORE_SCHEMA, > IGNORE_VERIFIED_BACKUPS_SCHEMA, UPID_SCHEMA, > @@ -83,6 +83,7 @@ fn check_priv_or_backup_owner( > auth_id: &Authid, > required_privs: u64, > ) -> Result<(), Error> { > + store.check_maintenance(MaintenanceType::Offline)?; > let user_info = CachedUserInfo::new()?; > let privs = user_info.lookup_privs(&auth_id, &["datastore", store.name()]); > > @@ -97,7 +98,7 @@ fn read_backup_index( > store: &DataStore, > backup_dir: &BackupDir, > ) -> Result<(BackupManifest, Vec<BackupContent>), Error> { > - > + store.check_maintenance(MaintenanceType::Offline)?; > let (manifest, index_size) = store.load_manifest(backup_dir)?; > > let mut result = Vec::new(); > @@ -125,7 +126,7 @@ fn get_all_snapshot_files( > store: &DataStore, > info: &BackupInfo, > ) -> Result<(BackupManifest, Vec<BackupContent>), Error> { > - > + store.check_maintenance(MaintenanceType::Offline)?; > let (manifest, mut files) = read_backup_index(&store, &info.backup_dir)?; > > let file_set = files.iter().fold(HashSet::new(), |mut acc, item| { > @@ -172,6 +173,9 @@ pub fn list_groups( > let user_privs = user_info.lookup_privs(&auth_id, &["datastore", &store]); > > let datastore = DataStore::lookup_datastore(&store)?; > + > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let list_all = (user_privs & PRIV_DATASTORE_AUDIT) != 0; > > let backup_groups = BackupInfo::list_backup_groups(&datastore.base_path())?; > @@ -267,9 +271,11 @@ pub fn delete_group( > ) -> Result<Value, Error> { > > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > + let datastore = DataStore::lookup_datastore(&store)?; > + > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > > let group = BackupGroup::new(backup_type, backup_id); > - let datastore = DataStore::lookup_datastore(&store)?; > > check_priv_or_backup_owner(&datastore, &group, &auth_id, PRIV_DATASTORE_MODIFY)?; > > @@ -316,6 +322,8 @@ pub fn list_snapshot_files( > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let snapshot = BackupDir::new(backup_type, backup_id, backup_time)?; > > check_priv_or_backup_owner(&datastore, snapshot.group(), &auth_id, PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_READ)?; > @@ -362,9 +370,12 @@ pub fn delete_snapshot( > ) -> Result<Value, Error> { > > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > + > + let datastore = DataStore::lookup_datastore(&store)?; > + > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > > let snapshot = BackupDir::new(backup_type, backup_id, backup_time)?; > - let datastore = DataStore::lookup_datastore(&store)?; > > check_priv_or_backup_owner(&datastore, snapshot.group(), &auth_id, PRIV_DATASTORE_MODIFY)?; > > @@ -415,6 +426,8 @@ pub fn list_snapshots ( > > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let base_path = datastore.base_path(); > > let groups = match (backup_type, backup_id) { > @@ -686,6 +699,9 @@ pub fn verify( > rpcenv: &mut dyn RpcEnvironment, > ) -> Result<Value, Error> { > let datastore = DataStore::lookup_datastore(&store)?; > + > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let ignore_verified = ignore_verified.unwrap_or(true); > > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > @@ -832,6 +848,8 @@ pub fn prune( > > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > + > check_priv_or_backup_owner(&datastore, &group, &auth_id, PRIV_DATASTORE_MODIFY)?; > > let worker_id = format!("{}:{}/{}", store, &backup_type, &backup_id); > @@ -1035,6 +1053,8 @@ pub fn garbage_collection_status( > > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::Offline)?; > + i was confused here at first, why garbage collect why garbage collect needs only read access, then noticed it's the status. but the status is not really a 'read' operation on the datastore? its more like the config or a task log since it only shows the status of the last gc > let status = datastore.last_gc_status(); > > Ok(status) > @@ -1111,6 +1131,8 @@ pub fn download_file( > let store = required_string_param(¶m, "store")?; > let datastore = DataStore::lookup_datastore(store)?; > > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > > let file_name = required_string_param(¶m, "file-name")?.to_owned(); > @@ -1181,6 +1203,8 @@ pub fn download_file_decoded( > let store = required_string_param(¶m, "store")?; > let datastore = DataStore::lookup_datastore(store)?; > > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > > let file_name = required_string_param(¶m, "file-name")?.to_owned(); > @@ -1372,6 +1396,8 @@ pub fn catalog( > ) -> Result<Vec<ArchiveEntry>, Error> { > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > > let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?; > @@ -1442,6 +1468,8 @@ pub fn pxar_file_download( > let store = required_string_param(¶m, "store")?; > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > > let filepath = required_string_param(¶m, "filepath")?.to_owned(); > @@ -1597,6 +1625,8 @@ pub fn get_group_notes( > ) -> Result<String, Error> { > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > let backup_group = BackupGroup::new(backup_type, backup_id); > > @@ -1639,6 +1669,8 @@ pub fn set_group_notes( > ) -> Result<(), Error> { > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > + > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > let backup_group = BackupGroup::new(backup_type, backup_id); > > @@ -1681,6 +1713,8 @@ pub fn get_notes( > ) -> Result<String, Error> { > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::Offline)?; > + > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?; > > @@ -1732,6 +1766,8 @@ pub fn set_notes( > ) -> Result<(), Error> { > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > + > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?; > > @@ -1777,6 +1813,8 @@ pub fn set_backup_owner( > > let datastore = DataStore::lookup_datastore(&store)?; > > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > + > let backup_group = BackupGroup::new(backup_type, backup_id); > > let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; > diff --git a/src/api2/pull.rs b/src/api2/pull.rs > index ea8faab8..b1669288 100644 > --- a/src/api2/pull.rs > +++ b/src/api2/pull.rs > @@ -9,7 +9,7 @@ use proxmox::api::{ApiMethod, Router, RpcEnvironment, Permission}; > > use pbs_client::{HttpClient, BackupRepository}; > use pbs_api_types::{ > - Remote, Authid, SyncJobConfig, > + Remote, Authid, SyncJobConfig, MaintenanceType, > DATASTORE_SCHEMA, REMOTE_ID_SCHEMA, REMOVE_VANISHED_BACKUPS_SCHEMA, > PRIV_DATASTORE_BACKUP, PRIV_DATASTORE_PRUNE, PRIV_REMOTE_READ, > }; > @@ -71,6 +71,9 @@ pub fn do_sync_job( > to_stdout: bool, > ) -> Result<String, Error> { > > + let datastore = DataStore::lookup_datastore(&sync_job.store)?; > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > + > let job_id = format!("{}:{}:{}:{}", > sync_job.remote, > sync_job.remote_store, > diff --git a/src/server/gc_job.rs b/src/server/gc_job.rs > index 794fe146..be04b635 100644 > --- a/src/server/gc_job.rs > +++ b/src/server/gc_job.rs > @@ -1,7 +1,7 @@ > use std::sync::Arc; > use anyhow::Error; > > -use pbs_api_types::Authid; > +use pbs_api_types::{Authid, MaintenanceType}; > use pbs_tools::task_log; > use pbs_datastore::DataStore; > use proxmox_rest_server::WorkerTask; > @@ -16,7 +16,8 @@ pub fn do_garbage_collection_job( > schedule: Option<String>, > to_stdout: bool, > ) -> Result<String, Error> { > - > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > + > let store = datastore.name().to_string(); > > let (email, notify) = crate::server::lookup_datastore_notify_settings(&store); > diff --git a/src/server/prune_job.rs b/src/server/prune_job.rs > index fc6443e9..84131634 100644 > --- a/src/server/prune_job.rs > +++ b/src/server/prune_job.rs > @@ -5,7 +5,7 @@ use anyhow::Error; > use pbs_datastore::backup_info::BackupInfo; > use pbs_datastore::prune::compute_prune_info; > use pbs_datastore::DataStore; > -use pbs_api_types::{Authid, PRIV_DATASTORE_MODIFY, PruneOptions}; > +use pbs_api_types::{Authid, MaintenanceType, PRIV_DATASTORE_MODIFY, PruneOptions}; > use pbs_config::CachedUserInfo; > use pbs_tools::{task_log, task_warn}; > use proxmox_rest_server::WorkerTask; > @@ -20,6 +20,8 @@ pub fn prune_datastore( > datastore: Arc<DataStore>, > dry_run: bool, > ) -> Result<(), Error> { > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > + > task_log!(worker, "Starting datastore prune on store \"{}\"", store); > > if dry_run { > diff --git a/src/server/verify_job.rs b/src/server/verify_job.rs > index 6aba97c9..3b2b1472 100644 > --- a/src/server/verify_job.rs > +++ b/src/server/verify_job.rs > @@ -1,7 +1,7 @@ > use anyhow::{format_err, Error}; > > use pbs_tools::task_log; > -use pbs_api_types::{Authid, VerificationJobConfig}; > +use pbs_api_types::{Authid, VerificationJobConfig, MaintenanceType}; > use proxmox_rest_server::WorkerTask; > use pbs_datastore::DataStore; > > @@ -21,9 +21,10 @@ pub fn do_verification_job( > schedule: Option<String>, > to_stdout: bool, > ) -> Result<String, Error> { > - > let datastore = DataStore::lookup_datastore(&verification_job.store)?; > > + datastore.check_maintenance(MaintenanceType::ReadOnly)?; > + why does a verification write access? because of the verify status in the manifest? imho that reason would be good to have in a comment > let outdated_after = verification_job.outdated_after; > let ignore_verified_snapshots = verification_job.ignore_verified.unwrap_or(true); > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 5/5] ui: add maintenance to datastore options 2021-09-28 10:05 [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Hannes Laimer ` (3 preceding siblings ...) 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 4/5] jobs/api2: add checks for maintenance Hannes Laimer @ 2021-09-28 10:05 ` Hannes Laimer 2021-10-01 8:36 ` Dominik Csapak 2021-10-01 8:18 ` [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Dominik Csapak 2021-10-01 9:36 ` Dominik Csapak 6 siblings, 1 reply; 13+ messages in thread From: Hannes Laimer @ 2021-09-28 10:05 UTC (permalink / raw) To: pbs-devel --- www/Makefile | 1 + www/datastore/OptionView.js | 10 +++++ www/window/MaintenanceOptions.js | 63 ++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 www/window/MaintenanceOptions.js diff --git a/www/Makefile b/www/Makefile index 4aec6e2c..8f6b17ed 100644 --- a/www/Makefile +++ b/www/Makefile @@ -63,6 +63,7 @@ JSSRC= \ window/BackupGroupChangeOwner.js \ window/CreateDirectory.js \ window/DataStoreEdit.js \ + window/MaintenanceOptions.js \ window/NotesEdit.js \ window/RemoteEdit.js \ window/NotifyOptions.js \ diff --git a/www/datastore/OptionView.js b/www/datastore/OptionView.js index 5a5e85be..1e0c3357 100644 --- a/www/datastore/OptionView.js +++ b/www/datastore/OptionView.js @@ -1,3 +1,4 @@ + Ext.define('PBS.Datastore.Options', { extend: 'Proxmox.grid.ObjectGrid', xtype: 'pbsDatastoreOptionView', @@ -111,5 +112,14 @@ Ext.define('PBS.Datastore.Options', { }, }, }, + "maintenance-type": { + required: true, + header: gettext('Maintenance mode'), + defaultValue: 'Off', + renderer: (value) => Ext.String.capitalize(value) || 'Off', + editor: { + xtype: 'pbsMaintenanceOptionEdit', + }, + }, }, }); diff --git a/www/window/MaintenanceOptions.js b/www/window/MaintenanceOptions.js new file mode 100644 index 00000000..8ff5ccf9 --- /dev/null +++ b/www/window/MaintenanceOptions.js @@ -0,0 +1,63 @@ +Ext.define('PBS.form.MaintenanceType', { + extend: 'Proxmox.form.KVComboBox', + alias: 'widget.pbsMaintenanceType', + + comboItems: [ + ['__default__', gettext('Off')], + ['readonly', gettext('Read Only')], + ['offline', gettext('Offline')], + ], +}); + +Ext.define('PBS.window.MaintenanceOptions', { + extend: 'Proxmox.window.Edit', + xtype: 'pbsMaintenanceOptionEdit', + mixins: ['Proxmox.Mixin.CBind'], + + subject: gettext('Maintenance mode'), + + width: 450, + fieldDefaults: { + labelWidth: 120, + }, + + items: { + xtype: 'inputpanel', + onGetValues: function(values) { + PBS.Utils.delete_if_default(values, 'maintenance-type', ''); + PBS.Utils.delete_if_default(values, 'maintenance-msg', ''); + if (values.delete) { + values.delete = values.delete.split(','); + } + + return values; + }, + items: [ + { + xtype: 'pbsMaintenanceType', + name: 'maintenance-type', + fieldLabel: gettext('Maintenance Type'), + value: '__default__', + deleteEmpty: true, + }, + { + xtype: 'textfield', + emptyText: 'none', + name: 'maintenance-msg', + fieldLabel: gettext('Description'), + value: '__default__', + deleteEmpty: true, + }, + ], + }, + setValues: function(values) { + let me = this; + + const options = { + 'maintenance-type': values['maintenance-type'] || '__default__', + 'maintenance-msg': values['maintenance-msg'], + }; + + me.callParent([options]); + }, +}); -- 2.30.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 5/5] ui: add maintenance to datastore options 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 5/5] ui: add maintenance to datastore options Hannes Laimer @ 2021-10-01 8:36 ` Dominik Csapak 0 siblings, 0 replies; 13+ messages in thread From: Dominik Csapak @ 2021-10-01 8:36 UTC (permalink / raw) To: Proxmox Backup Server development discussion, Hannes Laimer On 9/28/21 12:05, Hannes Laimer wrote: > --- > www/Makefile | 1 + > www/datastore/OptionView.js | 10 +++++ > www/window/MaintenanceOptions.js | 63 ++++++++++++++++++++++++++++++++ > 3 files changed, 74 insertions(+) > create mode 100644 www/window/MaintenanceOptions.js > > diff --git a/www/Makefile b/www/Makefile > index 4aec6e2c..8f6b17ed 100644 > --- a/www/Makefile > +++ b/www/Makefile > @@ -63,6 +63,7 @@ JSSRC= \ > window/BackupGroupChangeOwner.js \ > window/CreateDirectory.js \ > window/DataStoreEdit.js \ > + window/MaintenanceOptions.js \ > window/NotesEdit.js \ > window/RemoteEdit.js \ > window/NotifyOptions.js \ > diff --git a/www/datastore/OptionView.js b/www/datastore/OptionView.js > index 5a5e85be..1e0c3357 100644 > --- a/www/datastore/OptionView.js > +++ b/www/datastore/OptionView.js > @@ -1,3 +1,4 @@ > + > Ext.define('PBS.Datastore.Options', { > extend: 'Proxmox.grid.ObjectGrid', > xtype: 'pbsDatastoreOptionView', > @@ -111,5 +112,14 @@ Ext.define('PBS.Datastore.Options', { > }, > }, > }, > + "maintenance-type": { > + required: true, > + header: gettext('Maintenance mode'), > + defaultValue: 'Off', the default should probably be empty, no? Off should be handled by the renderer anyway > + renderer: (value) => Ext.String.capitalize(value) || 'Off', i would use that, but refactor the gettexts into e.g. Utils and write a renderer that maps it. that way we show the localized values here too > + editor: { > + xtype: 'pbsMaintenanceOptionEdit', > + }, > + }, > }, > }); > diff --git a/www/window/MaintenanceOptions.js b/www/window/MaintenanceOptions.js > new file mode 100644 > index 00000000..8ff5ccf9 > --- /dev/null > +++ b/www/window/MaintenanceOptions.js > @@ -0,0 +1,63 @@ > +Ext.define('PBS.form.MaintenanceType', { > + extend: 'Proxmox.form.KVComboBox', > + alias: 'widget.pbsMaintenanceType', > + > + comboItems: [ > + ['__default__', gettext('Off')], i think having 'Off' as no maintenance mode while also having 'Offline' will be confusing to some users. instead i'd use something like 'no maintenance' (at least as rendered value) > + ['readonly', gettext('Read Only')], > + ['offline', gettext('Offline')], > + ], > +}); > + > +Ext.define('PBS.window.MaintenanceOptions', { > + extend: 'Proxmox.window.Edit', > + xtype: 'pbsMaintenanceOptionEdit', > + mixins: ['Proxmox.Mixin.CBind'], > + > + subject: gettext('Maintenance mode'), > + > + width: 450, > + fieldDefaults: { > + labelWidth: 120, > + }, > + > + items: { > + xtype: 'inputpanel', > + onGetValues: function(values) { > + PBS.Utils.delete_if_default(values, 'maintenance-type', ''); > + PBS.Utils.delete_if_default(values, 'maintenance-msg', ''); > + if (values.delete) { > + values.delete = values.delete.split(','); > + } this is unnecessary, since the 'delete_if_default' should already make this an array if necessary it even blocked me from submitting the form, since 'split' is not a function of an array... > + > + return values; > + }, > + items: [ > + { > + xtype: 'pbsMaintenanceType', > + name: 'maintenance-type', > + fieldLabel: gettext('Maintenance Type'), > + value: '__default__', > + deleteEmpty: true, > + }, > + { > + xtype: 'textfield', > + emptyText: 'none', i'd leave that out, since we don't do it with comments either > + name: 'maintenance-msg', > + fieldLabel: gettext('Description'), > + value: '__default__', that should be empty? then you also don't need the 'delete_if_default' for the message since you set deleteEmpty also i think we should disable that field for the 'Off' variant since it does not make sense to have a maintenance message for no maintenance mode... > + deleteEmpty: true > + }, > + ], > + }, > + setValues: function(values) { > + let me = this; > + > + const options = { > + 'maintenance-type': values['maintenance-type'] || '__default__', > + 'maintenance-msg': values['maintenance-msg'], > + }; > + > + me.callParent([options]); > + }, > +}); > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore 2021-09-28 10:05 [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Hannes Laimer ` (4 preceding siblings ...) 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 5/5] ui: add maintenance to datastore options Hannes Laimer @ 2021-10-01 8:18 ` Dominik Csapak 2021-10-01 9:36 ` Dominik Csapak 6 siblings, 0 replies; 13+ messages in thread From: Dominik Csapak @ 2021-10-01 8:18 UTC (permalink / raw) To: Proxmox Backup Server development discussion, Hannes Laimer high level comment here, rest in the individual patches following i like the idea, but i find some things a bit clunky: * what gets saved is the maintenance mode (which is okay) but the interface to check it is confusing since the user has to give the mode that is *not* enough. IMHO it would be better if the check would require the least mode it requires instead. this could either be a "none" (or "writable") mode of the enum, or making the parameter an Option where None represents needing write access. * the check requiring an addition call to the storage seems like a thing one can easily forget. instead we could make our intent clear on the lookup part, which could do the check for us. if we then need elevated access, we can still have the check function. this way we cannot even request a datastore if its in offline mode anywhere in the code. i know this would require more code changes possibly, but i think this would provide a safer interface for this feature ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore 2021-09-28 10:05 [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Hannes Laimer ` (5 preceding siblings ...) 2021-10-01 8:18 ` [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Dominik Csapak @ 2021-10-01 9:36 ` Dominik Csapak 6 siblings, 0 replies; 13+ messages in thread From: Dominik Csapak @ 2021-10-01 9:36 UTC (permalink / raw) To: Proxmox Backup Server development discussion, Hannes Laimer i just noticed something that is a good example why the current approach regarding checking the mode is not optimal. setting the mode to 'offline' still lets me backup to tape and even restore from tape to it ;) ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2021-10-01 12:07 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-09-28 10:05 [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Hannes Laimer 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 1/5] pbs-api-types: add maintenance type and msg to ds config Hannes Laimer 2021-10-01 8:23 ` Dominik Csapak 2021-10-01 12:00 ` Wolfgang Bumiller 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 2/5] pbs-datastore: add check_maintenence function Hannes Laimer 2021-10-01 12:06 ` Wolfgang Bumiller 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 3/5] api2: make maintenance type and msg updatable/deletable Hannes Laimer 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 4/5] jobs/api2: add checks for maintenance Hannes Laimer 2021-10-01 8:28 ` Dominik Csapak 2021-09-28 10:05 ` [pbs-devel] [PATCH proxmox-backup 5/5] ui: add maintenance to datastore options Hannes Laimer 2021-10-01 8:36 ` Dominik Csapak 2021-10-01 8:18 ` [pbs-devel] [PATCH proxmox-backup 0/5] maintenance mode for datastore Dominik Csapak 2021-10-01 9:36 ` Dominik Csapak
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox