From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id BF2701FF0DD for ; Thu, 22 Oct 2026 18:43:59 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id E8B6F21635; Thu, 22 Oct 2026 18:43:58 +0200 (CEST) From: Jonas Theisen To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox v4 1/9] pbs-api-types: add 'disable' to {sync,verify,tape,gc} job schema and datastore config Date: Thu, 22 Oct 2026 18:43:16 +0200 Message-ID: <20261022164343.353831-2-j.theisen@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261022164343.353831-1-j.theisen@proxmox.com> References: <20261022164343.353831-1-j.theisen@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1792687435631 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.122 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust 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: 42TJGS56OOFCJWNBOFTOFJXXACC4QGX6 X-Message-ID-Hash: 42TJGS56OOFCJWNBOFTOFJXXACC4QGX6 X-MailFrom: j.theisen@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: To be able to en-/disable the respective jobs this patch adds the "disable" field to the job config and the needed schema. This also adds the "gc_disable" parameter to the datastore config to allow this type of job to be disabled. "disable" was chosen over "enable" to be consistent with the already existing config and API endpoints for prune jobs. This commit also aligns the prune job config to make use of the new schema but does not modify functionality. Signed-off-by: Jonas Theisen --- pbs-api-types/src/datastore.rs | 13 ++++++++++++ pbs-api-types/src/jobs.rs | 39 ++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/pbs-api-types/src/datastore.rs b/pbs-api-types/src/datastore.rs index 93ccaf07..cf661589 100644 --- a/pbs-api-types/src/datastore.rs +++ b/pbs-api-types/src/datastore.rs @@ -460,6 +460,11 @@ pub const COUNTER_RESET_SCHEDULE_SCHEMA: Schema = optional: true, schema: SINGLE_LINE_COMMENT_SCHEMA, }, + "gc-disable": { + description: "Disable scheduled execution of garbage collection.", + optional: true, + type: Boolean, + }, "gc-schedule": { optional: true, schema: GC_SCHEDULE_SCHEMA, @@ -524,6 +529,10 @@ pub struct DataStoreConfig { #[serde(skip_serializing_if = "Option::is_none")] pub comment: Option, + #[serde(default, skip_serializing_if = "crate::is_false")] + #[updater(serde(skip_serializing_if = "Option::is_none"))] + pub gc_disable: bool, + #[serde(skip_serializing_if = "Option::is_none")] pub gc_schedule: Option, @@ -605,6 +614,7 @@ impl DataStoreConfig { name, path, comment: None, + gc_disable: Default::default(), gc_schedule: None, gc_on_unmount: None, prune_schedule: None, @@ -1704,6 +1714,9 @@ pub struct GarbageCollectionJobStatus { pub store: String, #[serde(flatten)] pub status: GarbageCollectionStatus, + /// Disable state of the gc job + #[serde(default)] + pub disable: bool, /// Schedule of the gc job #[serde(skip_serializing_if = "Option::is_none")] pub schedule: Option, diff --git a/pbs-api-types/src/jobs.rs b/pbs-api-types/src/jobs.rs index 9a5d2b77..6b725b75 100644 --- a/pbs-api-types/src/jobs.rs +++ b/pbs-api-types/src/jobs.rs @@ -32,6 +32,12 @@ pub const JOB_ID_SCHEMA: Schema = StringSchema::new("Job ID.") .max_length(32) .schema(); +pub const DISABLE_JOB_SCHEMA: Schema = BooleanSchema::new( + "Disable the scheduled execution of this task.", + ) + .default(false) + .schema(); + pub const SYNC_SCHEDULE_SCHEMA: Schema = StringSchema::new("Run sync job at specified schedule.") .format(&ApiStringFormat::VerifyFn( proxmox_time::verify_calendar_event, @@ -228,6 +234,10 @@ pub const VERIFICATION_OUTDATED_AFTER_SCHEMA: Schema = optional: true, schema: VERIFICATION_SCHEDULE_SCHEMA, }, + disable: { + optional: true, + schema: DISABLE_JOB_SCHEMA, + }, ns: { optional: true, schema: BACKUP_NAMESPACE_SCHEMA, @@ -267,6 +277,10 @@ pub struct VerificationJobConfig { #[serde(skip_serializing_if = "Option::is_none")] /// when to schedule this job in calendar event notation pub schedule: Option, + /// Disable this job. + #[serde(default, skip_serializing_if = "crate::is_false")] + #[updater(serde(skip_serializing_if = "Option::is_none"))] + pub disable: bool, #[serde(skip_serializing_if = "Option::is_none", default)] /// on which backup namespace to run the verification recursively pub ns: Option, @@ -403,6 +417,10 @@ pub struct TapeBackupJobSetup { optional: true, schema: SYNC_SCHEDULE_SCHEMA, }, + disable: { + optional: true, + schema: DISABLE_JOB_SCHEMA, + }, } )] #[derive(Serialize, Deserialize, Clone, Updater, PartialEq)] @@ -417,6 +435,10 @@ pub struct TapeBackupJobConfig { pub comment: Option, #[serde(skip_serializing_if = "Option::is_none")] pub schedule: Option, + /// Disable this job. + #[serde(default, skip_serializing_if = "crate::is_false")] + #[updater(serde(skip_serializing_if = "Option::is_none"))] + pub disable: bool, } #[api( @@ -642,6 +664,10 @@ pub const UNMOUNT_ON_SYNC_DONE_SCHEMA: Schema = optional: true, schema: SYNC_SCHEDULE_SCHEMA, }, + disable: { + optional: true, + schema: DISABLE_JOB_SCHEMA, + }, "group-filter": { schema: GROUP_FILTER_LIST_SCHEMA, optional: true, @@ -717,6 +743,10 @@ pub struct SyncJobConfig { pub comment: Option, #[serde(skip_serializing_if = "Option::is_none")] pub schedule: Option, + /// Disable this job. + #[serde(default, skip_serializing_if = "crate::is_false")] + #[updater(serde(skip_serializing_if = "Option::is_none"))] + pub disable: bool, #[serde(skip_serializing_if = "Option::is_none")] pub group_filter: Option>, #[serde(flatten)] @@ -886,9 +916,8 @@ impl PruneJobOptions { #[api( properties: { disable: { - type: Boolean, optional: true, - default: false, + schema: DISABLE_JOB_SCHEMA, }, id: { schema: JOB_ID_SCHEMA, @@ -919,7 +948,7 @@ pub struct PruneJobConfig { pub store: String, /// Disable this job. - #[serde(default, skip_serializing_if = "is_false")] + #[serde(default, skip_serializing_if = "crate::is_false")] #[updater(serde(skip_serializing_if = "Option::is_none"))] pub disable: bool, @@ -938,10 +967,6 @@ impl PruneJobConfig { } } -fn is_false(b: &bool) -> bool { - !b -} - #[api( properties: { config: { -- 2.47.3