3 ####################################################
5 # by Brandon Lee Poyner bpoyner / CCAC.edu #
6 ####################################################
12 my $drbd_proc='/proc/drbd';
14 my ($drbd_expect, $drbd_role, $drbd_version, $debug_mode);
15 my (%options, %cs, %st, %ld, %ds, %check, %warning, %critical);
17 my $prog_name=basename($0);
18 my $prog_revision='0.5.3';
21 'OK' => { 'retvalue' => 0 },
22 'WARNING' => { 'retvalue' => 1 },
23 'CRITICAL' => { 'retvalue' => 2 },
24 'UNKNOWN' => { 'retvalue' => 3 }
28 # Define various states and default alarm values
31 'Primary' => { 'value' => 'OK', 'type' => 'st' },
32 'Secondary' => { 'value' => 'OK', 'type' => 'st' },
33 'Unknown' => { 'value' => 'CRITICAL', 'type' => 'st' },
34 'StandAlone' => { 'value' => 'WARNING', 'type' => 'cs' },
35 'Unconnected' => { 'value' => 'CRITICAL', 'type' => 'cs' },
36 'Timeout' => { 'value' => 'CRITICAL', 'type' => 'cs' },
37 'BrokenPipe' => { 'value' => 'CRITICAL', 'type' => 'cs' },
38 'WFConnection' => { 'value' => 'CRITICAL', 'type' => 'cs' },
39 'WFReportParams' => { 'value' => 'CRITICAL', 'type' => 'cs' },
40 'Connected' => { 'value' => 'OK', 'type' => 'cs' },
41 'Unconfigured' => { 'value' => 'OK', 'type' => 'cs' },
43 'SyncingAll' => { 'value' => 'WARNING', 'type' => 'cs' },
44 'SyncingQuick' => { 'value' => 'WARNING', 'type' => 'cs' },
45 'SyncPaused' => { 'value' => 'CRITICAL', 'type' => 'cs' },
47 'WFBitMapS' => { 'value' => 'CRITICAL', 'type' => 'cs' },
48 'WFBitMapT' => { 'value' => 'CRITICAL', 'type' => 'cs' },
49 'SyncSource' => { 'value' => 'WARNING', 'type' => 'cs' },
50 'SyncTarget' => { 'value' => 'WARNING', 'type' => 'cs' },
51 'PausedSyncS' => { 'value' => 'CRITICAL', 'type' => 'cs' },
52 'PausedSyncT' => { 'value' => 'CRITICAL', 'type' => 'cs' },
53 'NetworkFailure' => { 'value' => 'CRITICAL', 'type' => 'cs' },
54 'SkippedSyncS' => { 'value' => 'CRITICAL', 'type' => 'cs' },
55 'SkippedSyncT' => { 'value' => 'CRITICAL', 'type' => 'cs' },
56 'Consistent' => { 'value' => 'OK', 'type' => 'ld' },
57 'Inconsistent' => { 'value' => 'CRITICAL', 'type' => 'ld' },
59 'UpToDate' => { 'value' => 'OK', 'type' => 'ds' },
60 'Consistent' => { 'value' => 'OK', 'type' => 'ds' },
61 'Negotiating' => { 'value' => 'WARNING', 'type' => 'ds' },
62 'Attaching' => { 'value' => 'WARNING', 'type' => 'ds' },
63 'Diskless' => { 'value' => 'CRITICAL', 'type' => 'ds' },
64 'Failed' => { 'value' => 'CRITICAL', 'type' => 'ds' },
65 'Outdated' => { 'value' => 'CRITICAL', 'type' => 'ds' },
66 'Inconsistent' => { 'value' => 'CRITICAL', 'type' => 'ds' },
67 'DUnknown' => { 'value' => 'CRITICAL', 'type' => 'ds' },
69 'VerifyS' => { 'value' => 'WARNING', 'type' => 'cs' },
70 'VerifyT' => { 'value' => 'WARNING', 'type' => 'cs' },
72 'Disconnecting' => { 'value' => 'WARNING', 'type' => 'cs' },
73 'ProtocolError' => { 'value' => 'CRITICAL', 'type' => 'cs' },
74 'TearDown' => { 'value' => 'WARNING', 'type' => 'cs' },
75 'StartingSyncS' => { 'value' => 'WARNING', 'type' => 'cs' },
76 'StartingSyncT' => { 'value' => 'WARNING', 'type' => 'cs' },
77 'WFSyncUUID' => { 'value' => 'WARNING', 'type' => 'cs' }
85 &myexit('UNKNOWN',"$prog_name should never reach here");
89 Usage: $prog_name [-d <All|Configured|...>] [-e expect] [-p proc] [-r role] [-o states] [-w states] [-c states] [--debug]
91 -d STRING [default: $drbd_devices. Example: 0,1,2 ]
92 -p STRING [default: $drbd_proc. Use '-' for stdin]
93 -e STRING [Must be this connected state. Example: Connected]
94 -r STRING [Must be this node state. Example: Primary]
95 -o STRING [Change value to OK. Example: StandAlone]
96 -w STRING [Change value to WARNING. Example: SyncingAll]
97 -c STRING [Change value to CRITICAL. Example: Inconsistent,WFConnection]
103 $prog_name $prog_revision
105 The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute
106 copies of the plugins under the terms of the GNU General Public License.
107 For more information about these matters, see the file named COPYING.
118 Send email to nagios-users\@lists.sourceforge.net if you have questions
119 regarding use of this software. To submit patches or suggest improvements,
120 send email to bpoyner\@ccac.edu
122 exit $errorcodes{'UNKNOWN'}->{'retvalue'};
126 my ($help, $version, $debug, $ok_string, $warning_string,
129 # Get command line options
131 GetOptions("h|help" => \$help,
132 "V|version" => \$version,
133 "d|device|devices=s" => \$drbd_devices,
134 "e|expect=s" => \$drbd_expect,
135 "p|proc=s" => \$drbd_proc,
136 "r|role=s" => \$drbd_role,
137 "o|ok=s" => \$ok_string,
138 "w|warning=s" => \$warning_string,
139 "c|critical=s" => \$critical_string,
141 if (defined($help) && ($help ne "")) {
143 exit $errorcodes{'UNKNOWN'}->{'retvalue'};
145 if (defined($version) && ($version ne "")) {
147 exit $errorcodes{'UNKNOWN'}->{'retvalue'};
149 if (defined($drbd_expect) && ($drbd_expect ne "")) {
150 # User requested the connected state to be very specific
151 &change_values($drbd_expect,'cs','expect','connected state');
153 if (defined($drbd_role) && ($drbd_role ne "")) {
154 # User requested the node state to be very specific
155 &change_values($drbd_role,'st','role','node state');
157 if (defined($ok_string) && ($ok_string ne "")) {
158 # User requested certain values to be OK
159 &set_values($ok_string,'OK');
161 if (defined($warning_string) && ($warning_string ne "")) {
162 # User requested certain values to be WARNING
163 &set_values($warning_string,'WARNING');
165 if (defined($critical_string) && ($critical_string ne "")) {
166 # User requested certain values to be CRITICAL
167 &set_values($critical_string,'CRITICAL');
169 if (defined($debug) && ($debug ne "")) {
171 # Debugging information
174 print STDERR "<$prog_name settings>\n";
175 print STDERR "DRBD Devices: $drbd_devices\n";
176 printf STDERR "DRBD Proc: %s\n", defined($drbd_proc)?$drbd_proc:"";
177 printf STDERR "DRBD Expect: %s\n", defined($drbd_expect)?$drbd_expect:"";
178 printf STDERR "DRBD Role: %s\n", defined($drbd_role)?$drbd_role:"";
179 my (@ok, @critical, @warning);
180 for my $key ( keys %state ) {
181 if ($state{$key}->{'value'} eq 'OK') {
184 if ($state{$key}->{'value'} eq 'WARNING') {
187 if ($state{$key}->{'value'} eq 'CRITICAL') {
188 push(@critical,$key);
191 printf STDERR "DRBD OK: %s\n", join(" ",sort(@ok));
192 printf STDERR "DRBD WARNING: %s\n", join(" ",sort(@warning));
193 printf STDERR "DRBD CRITICAL: %s\n", join(" ",sort(@critical));
194 print STDERR "</$prog_name settings>\n";
200 # Read in contents of proc file, feed results into hashes
203 if ( $drbd_proc ne "-" ) {
205 if ( ! -e $drbd_proc ) {
206 &myexit('UNKNOWN',"No such file $drbd_proc");
208 open(DRBD, "$drbd_proc") ||
209 &myexit('UNKNOWN',"Could not open $drbd_proc");
214 if (/^version: (\d+).(\d+)/) {
215 $drbd_version = "$1.$2";
217 if (/^\s?(\d+):.* cs:(\w+)/) {
220 if (/^\s?(\d+):.* st:(\w+)\//) {
223 if (/^\s?(\d+):.* ld:(\w+)/) {
226 if (/^\s?(\d+):.* ds:(\w+)/) {
230 if ( $drbd_proc ne "-" ) {
233 if (defined($debug_mode) && ($debug_mode == 1)) {
235 # Debugging information
237 print STDERR "<$prog_name devices found>\n";
238 for my $key ( sort keys %cs ) {
239 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}":"";
241 print STDERR "</$prog_name devices found>\n";
245 sub parse_drbd_devices {
247 # Determine which DRBD devices to monitor
250 if ($drbd_devices =~ /^all$/i) {
251 for my $device ( keys %cs ) {
252 push(@devices,$device);
254 } elsif ($drbd_devices =~ /^configured$/i) {
255 for my $device ( keys %cs ) {
256 next if ($cs{$device} eq "Unconfigured");
257 push(@devices,$device);
260 @devices = split(/,/,$drbd_devices);
262 foreach my $device (@devices) {
263 if (!(defined($cs{$device}))) {
264 &myexit('OK',"Could not find device $device");
268 if (int(keys %check) == 0) {
269 &myexit('UNKNOWN',"No configured devices found");
271 if (defined($debug_mode) && ($debug_mode == 1)) {
273 # Debugging information
275 print STDERR "<$prog_name devices to check>\n";
276 for my $key ( sort keys %check ) {
277 printf STDERR "Checking enabled for device $key\n";
279 print STDERR "</$prog_name devices to check>\n";
283 sub check_drbd_state {
284 for my $drbd_device ( sort keys %check ) {
285 if ((defined($drbd_version)) && ($drbd_version >= '8.0')) {
287 # We're dealing with version 8.0 or greater
290 if ((defined($ds{$drbd_device})) &&
291 (defined($state{$ds{$drbd_device}}))) {
292 $state{$ds{$drbd_device}}->{$drbd_device}->{'level'} = 1;
293 } elsif (defined($ds{$drbd_device})) {
294 &myexit('CRITICAL',"Data state unknown value '$ds{$drbd_device}' for device $drbd_device");
297 if ((defined($drbd_version)) && ($drbd_version == '0.7')) {
299 # We're dealing with version 0.7
300 # Set local data consistency
302 if ((defined($ld{$drbd_device})) &&
303 (defined($state{$ld{$drbd_device}}))) {
304 $state{$ld{$drbd_device}}->{$drbd_device}->{'level'} = 1;
305 } elsif (defined($ld{$drbd_device})) {
306 &myexit('CRITICAL',"Local data consistency unknown value '$ld{$drbd_device}' for device $drbd_device");
310 # Check for a state value (Primary, Secondary, etc)
312 if ((defined($st{$drbd_device})) &&
313 (defined($state{$st{$drbd_device}}))) {
314 $state{$st{$drbd_device}}->{$drbd_device}->{'level'} = 1;
315 } elsif (defined($st{$drbd_device})) {
316 &myexit('CRITICAL',"Node state unknown value '$st{$drbd_device}' for device $drbd_device");
319 # Check for a connected state value (Connected, StandAlone, etc)
321 if (defined($state{$cs{$drbd_device}})) {
322 $state{$cs{$drbd_device}}->{$drbd_device}->{'level'} = 1;
324 &myexit('CRITICAL',"Connection state unknown value '$cs{$drbd_device}' for device $drbd_device");
327 # Debugging information
329 if (defined($debug_mode) && ($debug_mode == 1)) {
330 print STDERR "<$prog_name device $drbd_device status>\n";
331 for my $key ( keys %state ) {
332 if (defined($state{$key}->{$drbd_device}->{'level'})) {
333 print STDERR "$key $state{$key}->{'value'}\n";
336 print STDERR "</$prog_name device $drbd_device status>\n";
339 # Determine if any values are CRITICAL or WARNING
341 for my $key ( keys %state ) {
342 if (defined($state{$key}->{$drbd_device}->{'level'})) {
343 if ($state{$key}->{'value'} eq "CRITICAL") {
344 $critical{$drbd_device} = 1;
346 if ($state{$key}->{'value'} eq "WARNING") {
347 $warning{$drbd_device} = 1;
356 my $critical_count=int(keys %critical);
357 my $warning_count=int(keys %warning);
358 if ($critical_count > 0) {
360 # We found a CRITICAL situation
363 for my $device (sort keys %critical) {
364 $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}":"");
366 if ($i != $critical_count) {
370 &myexit('CRITICAL',$message);
371 } elsif ($warning_count > 0) {
373 # We found a WARNING situation
376 for my $device (sort keys %warning) {
377 $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}":"");
379 if ($i != $warning_count) {
383 &myexit('WARNING',$message);
386 # Everything checks out OK
388 my $device_count=int(keys %check);
389 if ($device_count == 1) {
390 for my $device ( sort keys %check ) {
391 $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}":"");
395 for my $device ( sort keys %check ) {
396 $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}":"");
398 if ($i != $device_count) {
403 &myexit('OK',$message);
409 # Set item to value requested
411 my ($items,$value) = @_;
412 my @items = split(/,/,$items);
413 foreach my $item (@items) {
414 if (defined($state{$item})) {
415 $state{$item}->{'value'} = "$value";
417 print STDERR "State '$item' not found\n";
424 # Look for all values of a given type, set requested value to OK
425 # and all other values to CRITICAL
427 my ($argument,$type,$error1,$error2) = @_;
428 if ((defined($state{$argument})) &&
429 ($state{$argument}->{'type'} eq "$type")) {
430 for my $key ( keys %state ) {
431 if ($state{$key}->{'type'} eq "$type") {
432 if ($key eq $argument) {
433 &set_values($argument,'OK');
435 &set_values($key,'CRITICAL');
440 &myexit('UNKNOWN',"$error1 option only works for $error2");
446 # Print error message and exit
448 my ($error, $message) = @_;
449 if (!(defined($errorcodes{$error}))) {
450 printf STDERR "Error code $error not known\n";
451 print "DRBD UNKNOWN: $message\n";
452 exit $errorcodes{'UNKNOWN'}->{'retvalue'};
454 print "DRBD $error: $message\n";
455 exit $errorcodes{$error}->{'retvalue'};