From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <d.csapak@proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by lists.proxmox.com (Postfix) with ESMTPS id 89BE674E18
 for <pve-devel@lists.proxmox.com>; Thu,  2 Jun 2022 09:42:39 +0200 (CEST)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id 442DA2BA
 for <pve-devel@lists.proxmox.com>; Thu,  2 Jun 2022 09:42:09 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com
 [94.136.29.106])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by firstgate.proxmox.com (Proxmox) with ESMTPS id BCA472A4
 for <pve-devel@lists.proxmox.com>; Thu,  2 Jun 2022 09:42:07 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 92E3D42895
 for <pve-devel@lists.proxmox.com>; Thu,  2 Jun 2022 09:42:07 +0200 (CEST)
From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Date: Thu,  2 Jun 2022 09:42:03 +0200
Message-Id: <20220602074206.814493-2-d.csapak@proxmox.com>
X-Mailer: git-send-email 2.30.2
In-Reply-To: <20220602074206.814493-1-d.csapak@proxmox.com>
References: <20220602074206.814493-1-d.csapak@proxmox.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.111 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 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
 T_SCC_BODY_TEXT_LINE    -0.01 -
 URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See
 http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more
 information. [jobs.pm, vzdump.pm, plugin.pm, pvescheduler.pm, backup.pm]
Subject: [pve-devel] [PATCH manager v2 1/3] fix #4026: add 'repeat-missed'
 option for jobs
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Thu, 02 Jun 2022 07:42:39 -0000

like systemd-timers 'persistent'. so that the user can configure it to not be
run after powering up when it was previously missed

this reverses the default behaviour to not run missed jobs after pvescheduler
was started, since most of the time that's not the desired behaviour

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 PVE/API2/Backup.pm          | 21 ++++++++++++++++++++-
 PVE/Jobs.pm                 |  5 +++++
 PVE/Jobs/Plugin.pm          |  7 +++++++
 PVE/Jobs/VZDump.pm          |  1 +
 PVE/Service/pvescheduler.pm |  6 +++++-
 5 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/PVE/API2/Backup.pm b/PVE/API2/Backup.pm
index 5d36789a..ced48977 100644
--- a/PVE/API2/Backup.pm
+++ b/PVE/API2/Backup.pm
@@ -180,6 +180,13 @@ __PACKAGE__->register_method({
 		description => "Enable or disable the job.",
 		default => '1',
 	    },
+	    'repeat-missed' => {
+		optional => 1,
+		type => 'boolean',
+		description => "If true, the job will be run as soon as possible if it was missed while".
+		" the scheduler was not running.",
+		default => 0,
+	    },
 	    comment => {
 		optional => 1,
 		type => 'string',
@@ -381,6 +388,13 @@ __PACKAGE__->register_method({
 		description => "Enable or disable the job.",
 		default => '1',
 	    },
+	    'repeat-missed' => {
+		optional => 1,
+		type => 'boolean',
+		description => "If true, the job will be run as soon as possible if it was missed while".
+		" the scheduler was not running.",
+		default => 0,
+	    },
 	    comment => {
 		optional => 1,
 		type => 'string',
@@ -440,8 +454,13 @@ __PACKAGE__->register_method({
 		die "no such vzdump job\n" if !$job || $job->{type} ne 'vzdump';
 	    }
 
+	    my $deletable = {
+		comment => 1,
+		'repeat-missed' => 1,
+	    };
+
 	    foreach my $k (@$delete) {
-		if (!PVE::VZDump::option_exists($k) && $k ne 'comment') {
+		if (!PVE::VZDump::option_exists($k) && !$deletable->{$k}) {
 		    raise_param_exc({ delete => "unknown option '$k'" });
 		}
 
diff --git a/PVE/Jobs.pm b/PVE/Jobs.pm
index da648630..ac44df00 100644
--- a/PVE/Jobs.pm
+++ b/PVE/Jobs.pm
@@ -209,6 +209,7 @@ sub get_last_runtime {
 }
 
 sub run_jobs {
+    my ($first_run) = @_;
     synchronize_job_states_with_config();
 
     my $jobs_cfg = cfs_read_file('jobs.cfg');
@@ -228,6 +229,10 @@ sub run_jobs {
 	    next;
 	}
 
+	# update last_run_time on the first run when 'repeat-missed' is 0, so that a missed job will not
+	# start immediately after boot
+	updated_job_schedule($id, $type) if $first_run && !$cfg->{'repeat-missed'};
+
 	next if defined($cfg->{enabled}) && !$cfg->{enabled}; # only schedule actually enabled jobs
 
 	my $last_run = get_last_runtime($id, $type);
diff --git a/PVE/Jobs/Plugin.pm b/PVE/Jobs/Plugin.pm
index 6098360b..b8cbef1e 100644
--- a/PVE/Jobs/Plugin.pm
+++ b/PVE/Jobs/Plugin.pm
@@ -39,6 +39,13 @@ my $defaultData = {
 	    description => "Description for the Job.",
 	    maxLength => 512,
 	},
+	'repeat-missed' => {
+	    optional => 1,
+	    type => 'boolean',
+	    description => "If true, the job will be run as soon as possible if it was missed while".
+		" the scheduler was not running.",
+	    default => 0,
+	},
     },
 };
 
diff --git a/PVE/Jobs/VZDump.pm b/PVE/Jobs/VZDump.pm
index 44fe33dc..7feb06a2 100644
--- a/PVE/Jobs/VZDump.pm
+++ b/PVE/Jobs/VZDump.pm
@@ -26,6 +26,7 @@ sub options {
 	enabled => { optional => 1 },
 	schedule => {},
 	comment => { optional => 1 },
+	'repeat-missed' => { optional => 1 },
     };
     foreach my $opt (keys %$props) {
 	if ($props->{$opt}->{optional}) {
diff --git a/PVE/Service/pvescheduler.pm b/PVE/Service/pvescheduler.pm
index f05f3bb9..40be5977 100755
--- a/PVE/Service/pvescheduler.pm
+++ b/PVE/Service/pvescheduler.pm
@@ -97,6 +97,8 @@ sub run {
 	$jobs->{$type}->{$child} = 1;
     };
 
+    my $first_run = 1;
+
     my $run_jobs = sub {
 	# TODO: actually integrate replication in PVE::Jobs and do not always fork here, we could
 	# do the state lookup and check if there's new work scheduled before doing so, e.g., by
@@ -109,8 +111,10 @@ sub run {
 	});
 
 	$fork->('jobs', sub {
-	    PVE::Jobs::run_jobs();
+	    PVE::Jobs::run_jobs($first_run);
 	});
+
+	$first_run = 0;
     };
 
     PVE::Jobs::setup_dirs();
-- 
2.30.2