| 1 |
package Resmon::Module::ZPOOLERRS; |
|---|
| 2 |
use Resmon::ExtComm qw/cache_command/; |
|---|
| 3 |
use Resmon::Module; |
|---|
| 4 |
use vars qw/@ISA/; |
|---|
| 5 |
@ISA = qw/Resmon::Module/; |
|---|
| 6 |
|
|---|
| 7 |
# Checks for zpool read write errors by using zpool status -x |
|---|
| 8 |
# Will also notify if a zpool is degraded or not, similar to the basic zpool |
|---|
| 9 |
# check. |
|---|
| 10 |
|
|---|
| 11 |
# Sample configuration: |
|---|
| 12 |
# ZPOOLERRS { |
|---|
| 13 |
# zpools : warn_on_upgrade => yes |
|---|
| 14 |
# } |
|---|
| 15 |
|
|---|
| 16 |
# Another sample configuration, which ignores zpool upgrade requests |
|---|
| 17 |
# ZPOOLERRS { |
|---|
| 18 |
# zpools : noop |
|---|
| 19 |
# } |
|---|
| 20 |
|
|---|
| 21 |
sub handler { |
|---|
| 22 |
my $arg = shift; |
|---|
| 23 |
my $unit = $arg->{'object'}; |
|---|
| 24 |
# Do we warn on 'zpool needs an upgrade', or just leave it OK? |
|---|
| 25 |
my $warn_on_upgrade = $arg->{'warn_on_upgrade'} || "no"; |
|---|
| 26 |
my $output = cache_command( |
|---|
| 27 |
"zpool status -x", 600); |
|---|
| 28 |
if($output) { |
|---|
| 29 |
my %errs = (); |
|---|
| 30 |
my $currpool = ""; |
|---|
| 31 |
my $status = "OK"; |
|---|
| 32 |
foreach my $line (split(/\n/, $output)) { |
|---|
| 33 |
if ($line =~ /(all pools are healthy)/) { |
|---|
| 34 |
# If everything is OK, we don't need to go any further |
|---|
| 35 |
return "OK", $1; |
|---|
| 36 |
} |
|---|
| 37 |
if ($line =~ /pool: (.+)$/) { |
|---|
| 38 |
# Pool name |
|---|
| 39 |
$currpool = $1; |
|---|
| 40 |
} elsif ($line =~ /state: (.+)$/) { |
|---|
| 41 |
# Pool state |
|---|
| 42 |
$errs{$currpool} = "$1 "; |
|---|
| 43 |
if ($1 ne 'ONLINE') { |
|---|
| 44 |
$status = "BAD"; |
|---|
| 45 |
} |
|---|
| 46 |
} elsif ($line =~ |
|---|
| 47 |
/The pool is formatted using an older on-disk format/) { |
|---|
| 48 |
# Detect if the error is just that a pool needs upgrading. |
|---|
| 49 |
$errs{$currpool} .= "- needs upgrade "; |
|---|
| 50 |
if ($warn_on_upgrade eq "yes" && $status != "BAD") { |
|---|
| 51 |
$status = "WARNING"; |
|---|
| 52 |
} |
|---|
| 53 |
} elsif ($line =~ |
|---|
| 54 |
/([a-z0-9]+)\s+([A-Z]+)\s+(\d+)\s+(\d+)\s+(\d+)/) { |
|---|
| 55 |
# Pool errors |
|---|
| 56 |
if ($3 != 0 || $4 != 0 || $5 != 0) { |
|---|
| 57 |
$errs{$currpool} .= |
|---|
| 58 |
"- $1:$2 w/Errs: R:$3 W:$4 Chk:$5 "; |
|---|
| 59 |
$status = "BAD"; |
|---|
| 60 |
} |
|---|
| 61 |
} |
|---|
| 62 |
} |
|---|
| 63 |
# Generate the status |
|---|
| 64 |
my $errstring = ""; |
|---|
| 65 |
while (my ($k, $v) = each %errs) { |
|---|
| 66 |
# $v should always contain a trailing space |
|---|
| 67 |
chop($v); |
|---|
| 68 |
$errstring .= "$k: $v"; |
|---|
| 69 |
$errstring .= ", "; |
|---|
| 70 |
} |
|---|
| 71 |
# Remove the trailing comma and space |
|---|
| 72 |
chop($errstring); |
|---|
| 73 |
chop($errstring); |
|---|
| 74 |
return $status, $errstring; |
|---|
| 75 |
} |
|---|
| 76 |
return "BAD", "no data" |
|---|
| 77 |
}; |
|---|
| 78 |
1; |
|---|