From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id EAACC1FF0B6 for ; Wed, 30 Sep 2026 17:22:14 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id BA513215F9; Wed, 30 Sep 2026 17:22:14 +0200 (CEST) From: Jonas Theisen To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup 05/14] fix #7904: Implement "Enable" checkbox for Sync jobs Date: Wed, 30 Sep 2026 17:18:03 +0200 Message-ID: <20260930152131.317493-6-j.theisen@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260930152131.317493-1-j.theisen@proxmox.com> References: <20260930152131.317493-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: 1790781730036 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.234 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: RA2S4TQ4Q2JS2TF3FUELGNQ7SGTI3KGR X-Message-ID-Hash: RA2S4TQ4Q2JS2TF3FUELGNQ7SGTI3KGR 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 allow users to disable a sync job without having to remove the schedule this patch introduces an "Enable" checkbox. The value is inserted into the job config and honored by the scheduler by skipping disabled jobs altogether. If the value is not present in a job config it is assumed the job is to be enabled for backwards compatibility. If the job is disabled the schedule input box in the UI is also disabled and such is configured to not allow empty inputs anymore. Signed-off-by: Jonas Theisen --- src/api2/admin/sync.rs | 10 +++++++++- src/api2/config/sync.rs | 4 ++++ src/bin/proxmox-backup-proxy.rs | 8 ++++++++ www/window/SyncJobEdit.js | 26 ++++++++++++++++++++++++-- 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/api2/admin/sync.rs b/src/api2/admin/sync.rs index 1799f51c0..39fe7c648 100644 --- a/src/api2/admin/sync.rs +++ b/src/api2/admin/sync.rs @@ -112,7 +112,15 @@ pub fn list_config_sync_jobs( continue; } - let status = compute_schedule_status("syncjob", &job.id, job.schedule.as_deref())?; + let mut status = compute_schedule_status("syncjob", &job.id, job.schedule.as_deref())?; + + let enabled = match job.enable { + Some(c) => c, + None => true, + }; + if !enabled { + status.next_run = Some(0); + } list.push(SyncJobStatus { config: job, diff --git a/src/api2/config/sync.rs b/src/api2/config/sync.rs index 068e2619c..f23a66df0 100644 --- a/src/api2/config/sync.rs +++ b/src/api2/config/sync.rs @@ -674,6 +674,9 @@ pub fn update_sync_job( if update.schedule.is_some() { data.schedule = update.schedule; } + if let Some(enable) = update.enable { + data.enable = Some(enable); + } if update.remove_vanished.is_some() { data.remove_vanished = update.remove_vanished; } @@ -819,6 +822,7 @@ acl:1:/remote/remote1/remotestore1:write@pbs:RemoteSyncOperator max_depth: None, group_filter: None, schedule: None, + enable: None, limit: pbs_api_types::RateLimitConfig::default(), // no limit transfer_last: None, encrypted_only: None, diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs index 22abfdbdb..ddeeff721 100644 --- a/src/bin/proxmox-backup-proxy.rs +++ b/src/bin/proxmox-backup-proxy.rs @@ -684,6 +684,14 @@ async fn schedule_datastore_sync_jobs() { None => continue, }; + let job_enabled = match job_config.enable { + Some(c) => c, + None => true, //if not defined assume enabled for backwards compatibility + }; + if !job_enabled { + continue; + } + let worker_type = "syncjob"; if check_schedule(worker_type, &event_str, &job_id) { let job = match Job::new(worker_type, &job_id) { diff --git a/www/window/SyncJobEdit.js b/www/window/SyncJobEdit.js index 961ce2951..9ff949b22 100644 --- a/www/window/SyncJobEdit.js +++ b/www/window/SyncJobEdit.js @@ -97,6 +97,10 @@ Ext.define('PBS.window.SyncJobEdit', { } else { values.location = 'remote'; } + + if (!values.schedule || values.schedule === '') { + values.enable = false; + } me.callParent([values]); }, @@ -203,13 +207,31 @@ Ext.define('PBS.window.SyncJobEdit', { deleteEmpty: '{!isCreate}', }, }, + { + xtype: 'proxmoxcheckbox', + fieldLabel: gettext('Enable'), + name: 'enable', + autoEl: { + tag: 'div', + 'data-qtip': gettext('Enable scheduled execution of this task.'), + }, + listeners: { + change: function (field, enabled) { + let me = this; + let view = me.up('pbsSyncJobEdit'); + let schedule = view.down('field[name=schedule]'); + schedule.setDisabled(!enabled); + }, + }, + uncheckedValue: false, + value: true, + }, { xtype: 'pbsCalendarEvent', name: 'schedule', fieldLabel: gettext('Sync Schedule'), - emptyText: gettext('none'), + allowBlank: false, cbind: { - deleteEmpty: '{!isCreate}', value: '{scheduleValue}', }, }, -- 2.47.3