#!/usr/bin/perl -w

# Author: Timo Laine
# Quite a lot copied from check_bacula.pl which is GPL.

# Change the database parameters, create a DB user which has select privilege to Bacula catalod DB and you're ready to go.

# This is best used with check_bacula.pl, use that to monitor that you dont miss too many subsequent runs of a client and this
# that the full jobs are succesfully run at decent intervals. For example I have some clients which run full monthly, diff weekly and inc daily. 
# I use check_bacula.pl to monitor that I have 2 succesful jobs within last 72 hours and this to monitor that the newest full is not older than 35 days.

# There are probably some leftovers from other scripts.
# This script doesn't need any access to the bacula daemons, only tcp connection and select privilege to the catalog database.

##    This program is free software: you can redistribute it and/or modify
##    it under the terms of the GNU General Public License as published by
##    the Free Software Foundation, either version 3 of the License, or
##    (at your option) any later version.
##
##    This program is distributed in the hope that it will be useful,
##    but WITHOUT ANY WARRANTY; without even the implied warranty of
##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##    GNU General Public License for more details.
##
##    You should have received a copy of the GNU General Public License
##    along with check_bacula.pl.  If not, see <http://www.gnu.org/licenses/>.


use strict;
use POSIX;
use File::Basename;
use DBI;
use Switch;
use Getopt::Long;
use vars qw(
       $opt_help
           $opt_job
           $opt_critical
           $opt_warning
           $opt_level
           $opt_usage
           $opt_version
           $out
           $sql
           $date_start
           $date_stop
           $state
           $count
           );
           
sub print_help();
sub print_usage();
sub get_now();
sub get_date;

my $sql;
my $days;
my $end;
my $level;
my $progname = basename($0);
my $progVers = "0.9";
my $sqlDB = "bacula-DB";
my $sqlUsername = "bacula-select-only-user";
my $sqlPassword = "randomlongpassword";
my $sqlHost = "catalog-mysql-host here";

my %ERRORS = (  'UNKNOWN'       =>      '3',
                'OK'            =>      '0',
                'WARNING'       =>      '1',
                'CRITICAL'      =>      '2');
                
Getopt::Long::Configure('bundling');
GetOptions
        (
        "c=s"   =>      \$opt_critical, "critical=s"    =>      \$opt_critical,
        "w=s"   =>      \$opt_warning,  "warning=s"     =>      \$opt_warning,
        "L=s"   =>      \$opt_level,    "level=s"       =>      \$opt_level,
        "j=s"   =>      \$opt_job,      "job=s"         =>      \$opt_job,
        "h"     =>      \$opt_help,     "help"          =>      \$opt_help,
                                        "usage"         =>      \$opt_usage,
        "V"     =>      \$opt_version,  "version"       =>      \$opt_version
        ) || die "Try '$progname --help' for more information.\n";

sub print_help() {
 print "\n";
 print "If Bacula holds its MySQL-data behind password, you have to manually enter the password into the script as variable \$sqlPassword.\n";
 print "And be sure to prevent everybody from reading it!\n";
 print "\n";
 print "Options:\n";
 print "L       check backup level F for full, D for differential, I for incremential\n";
 print "c       max days since successful job for not returning critical\n";
 print "w       max days since successful job for not returning warning\n";
 print "j       name of the job to check (case-sensitive)\n";
 print "h       show this help\n";
 print "V       print script version\n";
}

sub print_usage() {
 print "Usage: $progname -L <level> -c <critical> -w <warning> -j <job-name> [ -h ] [ -V ]\n";
}

if ($opt_help) {
 print_usage();
 print_help();
 exit $ERRORS{'UNKNOWN'};
}

if ($opt_usage) {
 print_usage();
 exit $ERRORS{'UNKNOWN'};
}

if ($opt_version) {
 print "$progname $progVers\n";
 exit $ERRORS{'UNKNOWN'};
}

switch ($opt_level) {

		case "F"	{ $level = "full";}
		case "D"	{ $level = "differential";}
		case "I"	{ $level = "incremental";}
		else		{ print_usage(); exit $ERRORS{'UNKNOWN'}; }
}

if ($opt_job && $opt_warning && $opt_critical) {
 my $dsn = "DBI:mysql:database=$sqlDB;host=$sqlHost";
 my $dbh = DBI->connect( $dsn,$sqlUsername,$sqlPassword ) or die "Error connecting to: '$dsn': $DBI::errstr\n";

$sql = "SELECT  Datediff(NOW(), EndTime) as \'days\', EndTime AS \'end\' FROM `Job` WHERE Name = \"$opt_job\" and JobStatus='T' AND Level = \"$opt_level\" ORDER BY Datediff(NOW(), EndTime) ASC LIMIT 1;";

my $sth = $dbh->prepare($sql) or die "Error preparing statement",$dbh->errstr;
$sth->execute;

my @row;
while ( @row = $sth->fetchrow_array()) {
($days,$end) = @row;
}
$sth->finish;
$dbh->disconnect();

if (! $end) { print "Bacula UNKNOWN: Successful $level job for $opt_job not found.\n"; exit $ERRORS{'UNKNOWN'}; }

$state = 'OK';
if ($days > $opt_warning) { $state='WARNING' }
if ($days > $opt_critical) { $state='CRITICAL' }
if ($days < 0) { $state='UNKNOWN';} ;

print "Bacula $state: $days days since last successful $level backup\n";
exit $ERRORS{$state};

}
else
{
print_help();
exit $ERRORS{'UNKNOWN'};
}
