From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 416A01FF13B for ; Wed, 11 Mar 2026 14:09:53 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 164221B378; Wed, 11 Mar 2026 14:09:28 +0100 (CET) From: Christian Ebner To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup v5 14/20] api: config: update notification thresholds for config and counters Date: Wed, 11 Mar 2026 14:08:17 +0100 Message-ID: <20260311130823.724888-28-c.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260311130823.724888-1-c.ebner@proxmox.com> References: <20260311130823.724888-1-c.ebner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1773234485990 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.057 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: P75KAQSDOTSXDKGTPNRWYDCF2G4HXZPZ X-Message-ID-Hash: P75KAQSDOTSXDKGTPNRWYDCF2G4HXZPZ X-MailFrom: c.ebner@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Allow users to update or clear notification threshold values stored in the datastore configuration via api or cli. At the same time, also load and update the threshold values for the shared request counters so they are applied immediately. To achieve this without duplicating code, move the request counter loading and updating of the thresholds into dedicated helpers. Signed-off-by: Christian Ebner --- pbs-datastore/src/datastore.rs | 27 ++++++++++++++++++++++++--- src/api2/config/datastore.rs | 33 +++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/pbs-datastore/src/datastore.rs b/pbs-datastore/src/datastore.rs index a2b2f182b..d60609124 100644 --- a/pbs-datastore/src/datastore.rs +++ b/pbs-datastore/src/datastore.rs @@ -19,8 +19,8 @@ use tracing::{info, warn}; use proxmox_human_byte::HumanByte; use proxmox_s3_client::{ - S3Client, S3ClientConf, S3ClientOptions, S3ObjectKey, S3PathPrefix, S3RateLimiterOptions, - S3RequestCounterOptions, SharedRequestCounters, + RequestCounterThresholds, S3Client, S3ClientConf, S3ClientOptions, S3ObjectKey, S3PathPrefix, + S3RateLimiterOptions, S3RequestCounterOptions, SharedRequestCounters, }; use proxmox_schema::ApiType; @@ -729,7 +729,10 @@ impl DataStore { ); let cache = LocalDatastoreLruCache::new(cache_capacity, chunk_store.clone()); - let request_counters = Self::request_counters(&config, &backend_config)?; + + let mut request_counters = Self::request_counters(&config, &backend_config)?; + + Self::update_notification_thresholds(&mut request_counters, &config)?; (Some(cache), Some(Arc::new(request_counters))) } else { @@ -779,6 +782,24 @@ impl DataStore { Ok(request_counters) } + /// Update the notification threshold values on the counters by given config + pub fn update_notification_thresholds( + counters: &mut SharedRequestCounters, + config: &DataStoreConfig, + ) -> Result<(), Error> { + let thresholds: RequestCounterThresholds = + if let Some(thresholds) = &config.notification_thresholds { + serde_json::from_value( + RequestCounterThresholds::API_SCHEMA.parse_property_string(thresholds)?, + )? + } else { + RequestCounterThresholds::default() + }; + + counters.update_thresholds(&thresholds); + Ok(()) + } + // Requires obtaining a shared chunk store lock beforehand pub fn create_fixed_writer>( &self, diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs index 45a251851..6f9920714 100644 --- a/src/api2/config/datastore.rs +++ b/src/api2/config/datastore.rs @@ -14,10 +14,11 @@ use proxmox_section_config::SectionConfigData; use proxmox_uuid::Uuid; use pbs_api_types::{ - Authid, DataStoreConfig, DataStoreConfigUpdater, DatastoreBackendType, DatastoreNotify, - DatastoreTuning, KeepOptions, MaintenanceMode, MaintenanceType, PruneJobConfig, - PruneJobOptions, DATASTORE_SCHEMA, PRIV_DATASTORE_ALLOCATE, PRIV_DATASTORE_AUDIT, - PRIV_DATASTORE_MODIFY, PRIV_SYS_MODIFY, PROXMOX_CONFIG_DIGEST_SCHEMA, UPID_SCHEMA, + Authid, DataStoreConfig, DataStoreConfigUpdater, DatastoreBackendConfig, DatastoreBackendType, + DatastoreNotify, DatastoreTuning, KeepOptions, MaintenanceMode, MaintenanceType, + PruneJobConfig, PruneJobOptions, DATASTORE_SCHEMA, PRIV_DATASTORE_ALLOCATE, + PRIV_DATASTORE_AUDIT, PRIV_DATASTORE_MODIFY, PRIV_SYS_MODIFY, PROXMOX_CONFIG_DIGEST_SCHEMA, + UPID_SCHEMA, }; use pbs_config::BackupLockGuard; use pbs_datastore::chunk_store::ChunkStore; @@ -442,6 +443,8 @@ pub enum DeletableProperty { Tuning, /// Delete the maintenance-mode property MaintenanceMode, + /// Delete the notification-thresholds property + NotificationThresholds, } #[api( @@ -540,6 +543,10 @@ pub fn update_datastore( DeletableProperty::MaintenanceMode => { data.set_maintenance_mode(None)?; } + DeletableProperty::NotificationThresholds => { + data.notification_thresholds = None; + update_thresholds(&data)?; + } } } } @@ -625,6 +632,11 @@ pub fn update_datastore( data.set_maintenance_mode(maintenance_mode)?; } + if update.notification_thresholds.is_some() { + data.notification_thresholds = update.notification_thresholds; + update_thresholds(&data)?; + } + config.set_data(&name, "datastore", &data)?; pbs_config::datastore::save_config(&config)?; @@ -657,6 +669,19 @@ pub fn update_datastore( Ok(()) } +fn update_thresholds(config: &DataStoreConfig) -> Result<(), Error> { + let backend_config: DatastoreBackendConfig = serde_json::from_value( + DatastoreBackendConfig::API_SCHEMA + .parse_property_string(config.backend.as_deref().unwrap_or(""))?, + )?; + if backend_config.ty.unwrap_or_default() == DatastoreBackendType::S3 { + let mut request_counters = + pbs_datastore::DataStore::request_counters(config, &backend_config)?; + pbs_datastore::DataStore::update_notification_thresholds(&mut request_counters, config)?; + } + Ok(()) +} + #[api( protected: true, input: { -- 2.47.3