summaryrefslogtreecommitdiff
path: root/scripts/check_bucardo_sync
blob: cbf7ed3984665d9a5b6cbc7daa7fddf40e799eb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#!/usr/bin/env perl
# -*-mode:cperl; indent-tabs-mode: nil-*-

## Check the status of Bucardo through the stats page
##
## Copyright 2007 Greg Sabino Mullane <greg@endpoint.com>

use strict;
use warnings;
use 5.8.0;
use Data::Dumper;
use Getopt::Long;
use File::Temp qw(tempfile);
File::Temp->safe_level( File::Temp::HIGH );
use lib "/usr/local/groundwork/nagios/libexec";
## Avoid the extraordinarily ill-named "utils.pm" from Nagios and do it ourself:
my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4);

my $USAGE =
qq{Usage: $0 --url <url> [-t timeout] \n};
## Plus -d debugfile

my $VERBOSE = 0;

my $VERSION = '1.2';
my $WGET = '/usr/bin/wget';
my %opt;

## Default combined timeout option in seconds for wget
$opt{timeout} = 25;
$opt{verbose} = 0;
GetOptions(\%opt,
           'version',
           'verbose',
           'help',
           'url=s',
           'timeout=i',
           'delta=i',
           'track=i',
           'debug=s',
);

$opt{version} and print qq{$0 Version $VERSION\n} and exit $ERRORS{'OK'};

$opt{help} and print $USAGE and exit $ERRORS{'OK'};

$opt{url} or print "ERROR: No URL was passed in\n$USAGE" and exit $ERRORS{'UNKNOWN'};

## Special url shortcuts
if ($opt{url} eq 'all') {
    $opt{url} = 'http://www.example.com/cgi-bin/bucardo-report?host=all';
}

my $MAX_DELTA = $opt{delta} || 50_000;
my $MAX_TRACK = $opt{track} || 50_000;

## If the url is not in a standard format, prepend 'http://'
my $url = $opt{url};
$url =~ m{^\w+://} or $url = qq{http://$url};

## Attempt to download the page
my ($tempfh, $tempfile);
if ($opt{debug}) {
  if (! open $tempfh, '<', $opt{debug}) {
    print qq{ERROR: Could not open debug file "$opt{debug}": $!\n};
    exit $ERRORS{'WARNING'};
  }
}
else {
  ($tempfh, $tempfile) = tempfile('/tmp/nagios_bucardocheck_XXXXXX', UNLINK => 1, SUFFIX => '.tmp');
  my ($errfh, $errfile) = tempfile('/tmp/nagios_bucardocheck_XXXXXX', UNLINK => 1, SUFFIX => '.tmp');

  my $COM = qq{$WGET --output-document=$tempfile --output-file=$errfile --timeout=$opt{timeout} "$opt{url}"};

  $VERBOSE and warn "Running $COM\n";

  system($COM);

  my $error = '';
  if (-s $errfile) {
    my $res = seek $errfh, 0, 0;
    { local $/; $error = <$errfh>; }
    if ($error =~ /Host not found/) {
      ## Mark as a warning because this is not our main job
      print qq{ERROR: Could not find the host for "$url"\n};
      exit $ERRORS{'WARNING'};
    }
    ## Other common errors?
  }
  close $errfh or die qq{Could not close temp file $errfile: $!\n};

  if (! -s $tempfile) {
    print qq{ERROR: Zero-length download for "$url"\n};
    exit $ERRORS{'UNKNOWN'};
  }
}

seek $tempfh, 0, 0;

## Look for nagios blocks
my $inner=0;
my (%bc,$host);
while (<$tempfh>) {
  if (!$inner) {
    /Begin Nagios/ and ++$inner;
    next;
  }
  if (/End Nagios/) {
    $inner=0;
    next;
  }
  if (/Host: (\w+)/) {
    $host=$1;
  }
  elsif (/(Expired|Overdue|Death): (\d+)/) {
    $bc{$host}{lc $1} = $2;
  }
  elsif (/bucardo_(delta|track) rows: (\d+)/) {
    $bc{$host}{$1} = $2;
  }
  elsif (/(Expired|Overdue|Death) (\w+) \| (\w+) \| (.+)/) {
    push @{$bc{$host}{lc$1.'detail'}}, {sync=>$2, target=>$3, time=>$4};
  }
}

#print Dumper \%bc;

if (!%bc) {
  print qq{ERROR: Nagios information not found\n};
}

my ($wmsg,$emsg,$wdetail,$edetail,$ddetail) = ('','','','','');
my $SEP=' ';
for my $host (sort keys %bc) {
  my $B = $bc{$host};
  ## Check for overdue
  if (exists $B->{overdue} and $B->{overdue} > 0) {
    $wmsg .= "$host overdue: $B->{overdue} ";
    $wdetail .= " $host overdue details: ";
    for my $host
      (
       sort {
    $a->{sync} cmp $b->{sync}
    or $a->{target} cmp $b->{target}
    }
    @{$B->{overduedetail}}) {
      $wdetail .= "$host->{sync}${SEP}$host->{target}${SEP}$host->{time} ";
    }
  }
  ## Check for expired
  if (exists $B->{expired} and $B->{expired} > 0) {
    $emsg .= "$host expired: $B->{expired} ";
    $edetail .= " $host expired details: ";
    for my $host
      (
       sort {
    $a->{sync} cmp $b->{sync}
    or $a->{target} cmp $b->{target}
    }
    @{$B->{expireddetail}}) {
      $edetail .= "$host->{sync}${SEP}$host->{target}${SEP}$host->{time} ";
    }
  }
  ## Check for syncs that are dying
  if (exists $B->{death} and $B->{death} > 0) {
    $wmsg .= "$host failed syncs: $B->{death} ";
    $ddetail .= " $host failure details: ";
    if ($B->{deathdetail}) {
      for my $host
        (
         sort {
           $a->{sync} cmp $b->{sync}
             or $a->{target} cmp $b->{target}
           }
         @{$B->{deathdetail}}) {
          $ddetail .= "$host->{sync}${SEP}$host->{target}${SEP}$host->{time} ";
        }
    }
    else {
      $ddetail .= '???';
    }
  }
  ## Check for bloat in the support tables
  if ($B->{delta} > $MAX_DELTA) {
    $wmsg .= "$host bucardo_delta bloat: $B->{delta} ";
  }
  if ($B->{track} > $MAX_TRACK) {
    $wmsg .= "$host bucardo_track bloat: $B->{track} ";
  }
}

if (!$wmsg and !$emsg) {
  print "All bucardo syncs are running normally\n";
  exit $ERRORS{'OK'};
}

print "ERROR: Bucardo $emsg$wmsg$edetail$wdetail$ddetail\n";

$emsg or exit $ERRORS{'WARNING'};

exit $ERRORS{'CRITICAL'};