3 ####################################################
5 # by Brandon Lee Poyner bpoyner / CCAC.edu #
6 ####################################################
7 ## 20151221 Peter Palfrader: add --ok-no-devices
13 my $drbd_proc='/proc/drbd';
15 my ($drbd_expect, $drbd_role, $drbd_version, $debug_mode);
16 my (%options, %cs, %st, %ld, %ds, %check, %warning, %critical);
17 my $ok_no_devices = 0;
19 my $prog_name=basename($0);
20 my $prog_revision='0.5.3';
23 'OK' => { 'retvalue' => 0 },
24 'WARNING' => { 'retvalue' => 1 },
25 'CRITICAL' => { 'retvalue' => 2 },
26 'UNKNOWN' => { 'retvalue' => 3 }
30 # Define various states and default alarm values
33 'Primary' => { 'value' => 'OK', 'type' => 'st' },
34 'Secondary' => { 'value' => 'OK', 'type' => 'st' },
35 'Unknown' => { 'value' => 'CRITICAL', 'type' => 'st' },
36 'StandAlone' => { 'value' => 'WARNING', 'type' => 'cs' },
37 'Unconnected' => { 'value' => 'CRITICAL', 'type' => 'cs' },
38 'Timeout' => { 'value' => 'CRITICAL', 'type' => 'cs' },
39 'BrokenPipe' => { 'value' => 'CRITICAL', 'type' => 'cs' },
40 'WFConnection' => { 'value' => 'CRITICAL', 'type' => 'cs' },
41 'WFReportParams' => { 'value' => 'CRITICAL', 'type' => 'cs' },
42 'Connected' => { 'value' => 'OK', 'type' => 'cs' },
43 'Unconfigured' => { 'value' => 'OK', 'type' => 'cs' },
45 'SyncingAll' => { 'value' => 'WARNING', 'type' => 'cs' },
46 'SyncingQuick' => { 'value' => 'WARNING', 'type' => 'cs' },
47 'SyncPaused' => { 'value' => 'CRITICAL', 'type' => 'cs' },
49 'WFBitMapS' => { 'value' => 'CRITICAL', 'type' => 'cs' },
50 'WFBitMapT' => { 'value' => 'CRITICAL', 'type' => 'cs' },
51 'SyncSource' => { 'value' => 'WARNING', 'type' => 'cs' },
52 'SyncTarget' => { 'value' => 'WARNING', 'type' => 'cs' },
53 'PausedSyncS' => { 'value' => 'CRITICAL', 'type' => 'cs' },
54 'PausedSyncT' => { 'value' => 'CRITICAL', 'type' => 'cs' },
55 'NetworkFailure' => { 'value' => 'CRITICAL', 'type' => 'cs' },
56 'SkippedSyncS' => { 'value' => 'CRITICAL', 'type' => 'cs' },
57 'SkippedSyncT' => { 'value' => 'CRITICAL', 'type' => 'cs' },
58 'Consistent' => { 'value' => 'OK', 'type' => 'ld' },
59 'Inconsistent' => { 'value' => 'CRITICAL', 'type' => 'ld' },
61 'UpToDate' => { 'value' => 'OK', 'type' => 'ds' },
62 'Consistent' => { 'value' => 'OK', 'type' => 'ds' },
63 'Negotiating' => { 'value' => 'WARNING', 'type' => 'ds' },
64 'Attaching' => { 'value' => 'WARNING', 'type' => 'ds' },
65 'Diskless' => { 'value' => 'CRITICAL', 'type' => 'ds' },
66 'Failed' => { 'value' => 'CRITICAL', 'type' => 'ds' },
67 'Outdated' => { 'value' => 'CRITICAL', 'type' => 'ds' },
68 'Inconsistent' => { 'value' => 'CRITICAL', 'type' => 'ds' },
69 'DUnknown' => { 'value' => 'CRITICAL', 'type' => 'ds' },
71 'VerifyS' => { 'value' => 'WARNING', 'type' => 'cs' },
72 'VerifyT' => { 'value' => 'WARNING', 'type' => 'cs' },
74 'Disconnecting' => { 'value' => 'WARNING', 'type' => 'cs' },
75 'ProtocolError' => { 'value' => 'CRITICAL', 'type' => 'cs' },
76 'TearDown' => { 'value' => 'WARNING', 'type' => 'cs' },
77 'StartingSyncS' => { 'value' => 'WARNING', 'type' => 'cs' },
78 'StartingSyncT' => { 'value' => 'WARNING', 'type' => 'cs' },
79 'WFSyncUUID' => { 'value' => 'WARNING', 'type' => 'cs' }
87 &myexit('UNKNOWN',"$prog_name should never reach here");
91 Usage: $prog_name [-d <All|Configured|...>] [-e expect] [-p proc] [-r role] [-o states] [-w states] [-c states] [--debug] [--ok-no-devices]
93 -d STRING [default: $drbd_devices. Example: 0,1,2 ]
94 -p STRING [default: $drbd_proc. Use '-' for stdin]
95 -e STRING [Must be this connected state. Example: Connected]
96 -r STRING [Must be this node state. Example: Primary]
97 -o STRING [Change value to OK. Example: StandAlone]
98 -w STRING [Change value to WARNING. Example: SyncingAll]
99 -c STRING [Change value to CRITICAL. Example: Inconsistent,WFConnection]
105 $prog_name $prog_revision
107 The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute
108 copies of the plugins under the terms of the GNU General Public License.
109 For more information about these matters, see the file named COPYING.
120 Send email to nagios-users\@lists.sourceforge.net if you have questions
121 regarding use of this software. To submit patches or suggest improvements,
122 send email to bpoyner\@ccac.edu
124 exit $errorcodes{'UNKNOWN'}->{'retvalue'};
128 my ($help, $version, $debug, $ok_string, $warning_string,
131 # Get command line options
133 GetOptions("h|help" => \$help,
134 "V|version" => \$version,
135 "d|device|devices=s" => \$drbd_devices,
136 "e|expect=s" => \$drbd_expect,
137 "p|proc=s" => \$drbd_proc,
138 "r|role=s" => \$drbd_role,
139 "o|ok=s" => \$ok_string,
140 "w|warning=s" => \$warning_string,
141 "c|critical=s" => \$critical_string,
142 "ok-no-devices" => \$ok_no_devices,
144 if (defined($help) && ($help ne "")) {
146 exit $errorcodes{'UNKNOWN'}->{'retvalue'};
148 if (defined($version) && ($version ne "")) {
150 exit $errorcodes{'UNKNOWN'}->{'retvalue'};
152 if (defined($drbd_expect) && ($drbd_expect ne "")) {
153 # User requested the connected state to be very specific
154 &change_values($drbd_expect,'cs','expect','connected state');
156 if (defined($drbd_role) && ($drbd_role ne "")) {
157 # User requested the node state to be very specific
158 &change_values($drbd_role,'st','role','node state');
160 if (defined($ok_string) && ($ok_string ne "")) {
161 # User requested certain values to be OK
162 &set_values($ok_string,'OK');
164 if (defined($warning_string) && ($warning_string ne "")) {
165 # User requested certain values to be WARNING
166 &set_values($warning_string,'WARNING');
168 if (defined($critical_string) && ($critical_string ne "")) {
169 # User requested certain values to be CRITICAL
170 &set_values($critical_string,'CRITICAL');
172 if (defined($debug) && ($debug ne "")) {
174 # Debugging information
177 print STDERR "<$prog_name settings>\n";
178 print STDERR "DRBD Devices: $drbd_devices\n";
179 printf STDERR "DRBD Proc: %s\n", defined($drbd_proc)?$drbd_proc:"";
180 printf STDERR "DRBD Expect: %s\n", defined($drbd_expect)?$drbd_expect:"";
181 printf STDERR "DRBD Role: %s\n", defined($drbd_role)?$drbd_role:"";
182 my (@ok, @critical, @warning);
183 for my $key ( keys %state ) {
184 if ($state{$key}->{'value'} eq 'OK') {
187 if ($state{$key}->{'value'} eq 'WARNING') {
190 if ($state{$key}->{'value'} eq 'CRITICAL') {
191 push(@critical,$key);
194 printf STDERR "DRBD OK: %s\n", join(" ",sort(@ok));
195 printf STDERR "DRBD WARNING: %s\n", join(" ",sort(@warning));
196 printf STDERR "DRBD CRITICAL: %s\n", join(" ",sort(@critical));
197 print STDERR "</$prog_name settings>\n";
203 # Read in contents of proc file, feed results into hashes
206 if ( $drbd_proc ne "-" ) {
208 if ( ! -e $drbd_proc ) {
209 &myexit('UNKNOWN',"No such file $drbd_proc");
211 open(DRBD, "$drbd_proc") ||
212 &myexit('UNKNOWN',"Could not open $drbd_proc");
217 if (/^version: (\d+).(\d+)/) {
218 $drbd_version = "$1.$2";
220 if (/^\s?(\d+):.* cs:(\w+)/) {
223 if (/^\s?(\d+):.* st:(\w+)\//) {
226 if (/^\s?(\d+):.* ld:(\w+)/) {
229 if (/^\s?(\d+):.* ds:(\w+)/) {
233 if ( $drbd_proc ne "-" ) {
236 if (defined($debug_mode) && ($debug_mode == 1)) {
238 # Debugging information
240 print STDERR "<$prog_name devices found>\n";
241 for my $key ( sort keys %cs ) {
242 printf STDERR "Found Device $key $cs{$key}%s%s%s\n", defined($st{$key})?" $st{$key}":"", defined($ld{$key})?" $ld{$key}":"", defined($ds{$key})?" $ds{$key}":"";
244 print STDERR "</$prog_name devices found>\n";
248 sub parse_drbd_devices {
250 # Determine which DRBD devices to monitor
253 if ($drbd_devices =~ /^all$/i) {
254 for my $device ( keys %cs ) {
255 push(@devices,$device);
257 } elsif ($drbd_devices =~ /^configured$/i) {
258 for my $device ( keys %cs ) {
259 next if ($cs{$device} eq "Unconfigured");
260 push(@devices,$device);
263 @devices = split(/,/,$drbd_devices);
265 foreach my $device (@devices) {
266 if (!(defined($cs{$device}))) {
267 &myexit('OK',"Could not find device $device");
271 if (int(keys %check) == 0) {
272 &myexit($ok_no_devices ? 'OK' : 'UNKNOWN',"No configured devices found");
274 if (defined($debug_mode) && ($debug_mode == 1)) {
276 # Debugging information
278 print STDERR "<$prog_name devices to check>\n";
279 for my $key ( sort keys %check ) {
280 printf STDERR "Checking enabled for device $key\n";
282 print STDERR "</$prog_name devices to check>\n";
286 sub check_drbd_state {
287 for my $drbd_device ( sort keys %check ) {
288 if ((defined($drbd_version)) && ($drbd_version >= '8.0')) {
290 # We're dealing with version 8.0 or greater
293 if ((defined($ds{$drbd_device})) &&
294 (defined($state{$ds{$drbd_device}}))) {
295 $state{$ds{$drbd_device}}->{$drbd_device}->{'level'} = 1;
296 } elsif (defined($ds{$drbd_device})) {
297 &myexit('CRITICAL',"Data state unknown value '$ds{$drbd_device}' for device $drbd_device");
300 if ((defined($drbd_version)) && ($drbd_version == '0.7')) {
302 # We're dealing with version 0.7
303 # Set local data consistency
305 if ((defined($ld{$drbd_device})) &&
306 (defined($state{$ld{$drbd_device}}))) {
307 $state{$ld{$drbd_device}}->{$drbd_device}->{'level'} = 1;
308 } elsif (defined($ld{$drbd_device})) {
309 &myexit('CRITICAL',"Local data consistency unknown value '$ld{$drbd_device}' for device $drbd_device");
313 # Check for a state value (Primary, Secondary, etc)
315 if ((defined($st{$drbd_device})) &&
316 (defined($state{$st{$drbd_device}}))) {
317 $state{$st{$drbd_device}}->{$drbd_device}->{'level'} = 1;
318 } elsif (defined($st{$drbd_device})) {
319 &myexit('CRITICAL',"Node state unknown value '$st{$drbd_device}' for device $drbd_device");
322 # Check for a connected state value (Connected, StandAlone, etc)
324 if (defined($state{$cs{$drbd_device}})) {
325 $state{$cs{$drbd_device}}->{$drbd_device}->{'level'} = 1;
327 &myexit('CRITICAL',"Connection state unknown value '$cs{$drbd_device}' for device $drbd_device");
330 # Debugging information
332 if (defined($debug_mode) && ($debug_mode == 1)) {
333 print STDERR "<$prog_name device $drbd_device status>\n";
334 for my $key ( keys %state ) {
335 if (defined($state{$key}->{$drbd_device}->{'level'})) {
336 print STDERR "$key $state{$key}->{'value'}\n";
339 print STDERR "</$prog_name device $drbd_device status>\n";
342 # Determine if any values are CRITICAL or WARNING
344 for my $key ( keys %state ) {
345 if (defined($state{$key}->{$drbd_device}->{'level'})) {
346 if ($state{$key}->{'value'} eq "CRITICAL") {
347 $critical{$drbd_device} = 1;
349 if ($state{$key}->{'value'} eq "WARNING") {
350 $warning{$drbd_device} = 1;
359 my $critical_count=int(keys %critical);
360 my $warning_count=int(keys %warning);
361 if ($critical_count > 0) {
363 # We found a CRITICAL situation
366 for my $device (sort keys %critical) {
367 $message.=sprintf("Device %d%s $cs{$device}%s%s", $device,defined($st{$device})?" $st{$device}":"",defined($ld{$device})?" $ld{$device}":"",defined($ds{$device})?" $ds{$device}":"");
369 if ($i != $critical_count) {
373 &myexit('CRITICAL',$message);
374 } elsif ($warning_count > 0) {
376 # We found a WARNING situation
379 for my $device (sort keys %warning) {
380 $message.=sprintf("Device %d%s $cs{$device}%s%s", $device,defined($st{$device})?" $st{$device}":"",defined($ld{$device})?" $ld{$device}":"",defined($ds{$device})?" $ds{$device}":"");
382 if ($i != $warning_count) {
386 &myexit('WARNING',$message);
389 # Everything checks out OK
391 my $device_count=int(keys %check);
392 if ($device_count == 1) {
393 for my $device ( sort keys %check ) {
394 $message=sprintf("Device %d%s $cs{$device}%s%s", $device,defined($st{$device})?" $st{$device}":"",defined($ld{$device})?" $ld{$device}":"",defined($ds{$device})?" $ds{$device}":"");
398 for my $device ( sort keys %check ) {
399 $message.=sprintf("Dev %d %0.3s%0.3s%0.3s%0.3s", $device,defined($st{$device})?"$st{$device}":"",$cs{$device},defined($ld{$device})?"$ld{$device}":"",defined($ds{$device})?"$ds{$device}":"");
401 if ($i != $device_count) {
406 &myexit('OK',$message);
412 # Set item to value requested
414 my ($items,$value) = @_;
415 my @items = split(/,/,$items);
416 foreach my $item (@items) {
417 if (defined($state{$item})) {
418 $state{$item}->{'value'} = "$value";
420 print STDERR "State '$item' not found\n";
427 # Look for all values of a given type, set requested value to OK
428 # and all other values to CRITICAL
430 my ($argument,$type,$error1,$error2) = @_;
431 if ((defined($state{$argument})) &&
432 ($state{$argument}->{'type'} eq "$type")) {
433 for my $key ( keys %state ) {
434 if ($state{$key}->{'type'} eq "$type") {
435 if ($key eq $argument) {
436 &set_values($argument,'OK');
438 &set_values($key,'CRITICAL');
443 &myexit('UNKNOWN',"$error1 option only works for $error2");
449 # Print error message and exit
451 my ($error, $message) = @_;
452 if (!(defined($errorcodes{$error}))) {
453 printf STDERR "Error code $error not known\n";
454 print "DRBD UNKNOWN: $message\n";
455 exit $errorcodes{'UNKNOWN'}->{'retvalue'};
457 print "DRBD $error: $message\n";
458 exit $errorcodes{$error}->{'retvalue'};