]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Add MaximumConcurrentJobPerLevel script for RunScript Job Queue control example
authorEric Bollengier <eric@baculasystems.com>
Wed, 15 Feb 2023 11:05:12 +0000 (12:05 +0100)
committerEric Bollengier <eric@baculasystems.com>
Thu, 14 Sep 2023 11:57:01 +0000 (13:57 +0200)
bacula/scripts/MaximumConcurrentJobPerLevel [new file with mode: 0755]

diff --git a/bacula/scripts/MaximumConcurrentJobPerLevel b/bacula/scripts/MaximumConcurrentJobPerLevel
new file mode 100755 (executable)
index 0000000..2954135
--- /dev/null
@@ -0,0 +1,117 @@
+#!/usr/bin/perl -w
+# Copyright (C) 2000-2023 Bacula Systems SA
+# License: BSD 2-Clause; see file LICENSE-FOSS
+
+use strict;
+
+################################################################
+# Installation
+################################################################
+#
+# Copy the script into /opt/bacula/scripts
+# - Configure the variables at the top of the script (bconsole, limits)
+# - Use the following runscript
+# Job {
+#   RunScript {
+#     RunsWhen = Queued
+#     Command = "/opt/bacula/scripts/MaximumConcurrentJobPerLevel '%c' %l"
+#     Fail On Error = no
+#     RunsOnClient = no
+#   }
+#  ...
+# }
+
+
+################################################################
+# Custom
+my $bconsole = "/tmp/regress/bin/bconsole -u10";
+my $client = shift or usage();
+my $level = shift or usage();
+my $verbose = $ENV{VERBOSE} || 0;
+
+my %MaximumConcurrentJob = (
+    'Full' => 1,
+    'Differental' => 1,
+    'Incremental' => 1
+    );
+
+################################################################
+# The Job intend to use a separate file-daemon for each of our clusters.
+# The schedule calls for Full, Incremental, and Differential backups to
+# occasionally run simultaneously but I want to make sure that a slot is always
+# open for one job of each level to run against the cluster.  
+
+# The behavior might be summarized by:
+# Maximum Concurrent Full Jobs = 1
+# Maximum Concurrent Differential Jobs = 1
+# Maximum Concurrent Incremental Jobs = 1
+
+sub usage
+{
+    print "ERROR: Incorrect usage: $0 client level\n";
+    exit -1;
+}
+
+use File::Temp;
+# The JSON package must be installed libjson-perl or perl-JSON
+eval "use JSON;";
+if ($@) {
+    print "ERROR: Perl JSON module not found. Job control disabled.\n$@";
+    exit -1;
+}
+
+my $l;
+# Get the list of running jobs for the same level and the same client
+if ($level =~ /^([FDI])/) {
+    $l = $1;
+} else {
+    print "Level $level not handled by Job control procedure\n";
+    exit -1;
+}
+
+my ($fh, $filename) = File::Temp::tempfile();
+if (!open(FP, "|$bconsole> $filename")) {
+    print "ERROR: Unable to execute bconsole. Job control disabled.\n$!";
+    unlink($filename);
+    exit -1;
+}
+
+print FP ".api 2 api_opts=j\n";
+print FP ".status dir running client=\"$client\"\nquit\n";
+close(FP);
+unlink($filename);
+
+my $running;
+while (my $line = <$fh>) {
+    if ($verbose) {
+        print "DEBUG: $line";
+    }
+    if ($line =~ /^\{/) {
+        $running = $line;
+        last;
+    } 
+}
+
+if (!$running) {
+    print "ERROR: Unable to get running job list. Job control disabled.\n";
+    exit -1;
+}
+
+my $json = JSON::decode_json($running);
+if (!$json) {
+    print "ERROR: Unable to decode JSON output from Director. Job control disabled.\n";
+    exit -1;
+}
+
+my @jobs = grep {
+    $_->{level} eq $l && $_->{jobstatus} eq 'R'
+   } @{ $json->{running} };
+
+my $nb = scalar(@jobs);
+print "Found $nb Job(s) running at level $level for $client\n";
+if ($nb <= $MaximumConcurrentJob{$level}) {
+    exit 0;
+} else {
+    exit 1;
+}
+