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 248C31FF137 for ; Tue, 03 Mar 2026 16:23:47 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 61B6E1B8F0; Tue, 3 Mar 2026 16:24:17 +0100 (CET) From: Christian Ebner To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup v4 16/22] api: config: update notification thresholds for config and counters Date: Tue, 3 Mar 2026 16:23:11 +0100 Message-ID: <20260303152317.934256-30-c.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260303152317.934256-1-c.ebner@proxmox.com> References: <20260303152317.934256-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: 1772551387706 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.051 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: T7LYE522NDCAXA2GLOOJRXL6PT3ERDXJ X-Message-ID-Hash: T7LYE522NDCAXA2GLOOJRXL6PT3ERDXJ 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 dac92ce3d..957876376 100644 --- a/pbs-datastore/src/datastore.rs +++ b/pbs-datastore/src/datastore.rs @@ -18,8 +18,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; @@ -706,7 +706,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 { @@ -756,6 +759,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 f845fe2d0..d51c60f43 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; @@ -436,6 +437,8 @@ pub enum DeletableProperty { Tuning, /// Delete the maintenance-mode property MaintenanceMode, + /// Delete the notification-thresholds property + NotificationThresholds, } #[api( @@ -534,6 +537,10 @@ pub fn update_datastore( DeletableProperty::MaintenanceMode => { data.set_maintenance_mode(None)?; } + DeletableProperty::NotificationThresholds => { + data.notification_thresholds = None; + update_thresholds(&data)?; + } } } } @@ -619,6 +626,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)?; @@ -651,6 +663,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