vn-ansible/roles/pve/files/nrpe/check_zfs.pl

121 lines
3.1 KiB
Perl
Executable File

#!/usr/bin/perl
use strict;
use warnings;
use English;
$ENV{'PATH'} = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
use constant N_OK => 0;
use constant N_WARNING => 1;
use constant N_CRITICAL => 2;
use constant N_MSG => [ "OK", "WARNING", "CRITICAL" ];
my @zpool = ();
sub get_pools() {
local *P;
my $zpool_cmd = $EUID == 0 ? "zpool" : "sudo zpool";
open(P, $zpool_cmd . " list -H 2>&1 |") or &nagios_response("Could not find zpool command", N_CRITICAL);
while (<P>) {
chomp;
my @ret = split(/\s+/, $_);
push(@zpool, {
'name' => $ret[0],
'health' => $ret[-2],
'size' => $ret[1],
'alloc' => $ret[2],
'free' => $ret[3]
});
}
close(P);
my $rc = $?;
if ($rc != 0) {
&nagios_response("zpool list command failed (rc=$rc)", N_CRITICAL);
}
}
sub get_status()
{
my $storage = shift || "unknown";
my $cat = 0;
my $res = {};
local *P;
my $zpool_cmd = $EUID == 0 ? "zpool" : "sudo zpool";
open(P, $zpool_cmd . " status $storage 2>&1 |") or &nagios_response("Could not find zpool command", N_CRITICAL);
while (<P>) {
chomp;
if ($_ =~ /^\s*([^\s]+):\s*(.*)$/) {
$cat = $1;
$res->{"$cat"} = ();
if ($2) {
push(@{$res->{"$cat"}}, $2);
}
} elsif ($cat && $_ =~ /^\s+(.+)$/) {
push(@{$res->{"$cat"}}, $1);
}
}
close(P);
my $rc = $?;
if ($rc != 0) {
&nagios_response("zpool status command failed (rc=$rc)", N_CRITICAL);
}
return $res;
}
sub nagios_response()
{
my $msg = shift || "Unknown";
my $exit_status = shift;
if (!defined($exit_status)) {
$exit_status = N_CRITICAL;
}
printf("%s %s\n", N_MSG->[$exit_status], $msg);
exit($exit_status);
}
sub main() {
&get_pools();
my $exit_status = N_OK;
my @out = ();
foreach my $pool (@zpool) {
if ($pool->{'health'} eq 'DEGRADED') {
$exit_status = N_WARNING;
my $extinfo = &get_status($pool->{'name'});
my $scanned = 0;
my $total = 0;
my $speed = 0;
my $left = 0;
my $percent = 0;
my $resilvered = 0;
if (defined($extinfo->{'scan'})) {
foreach my $line (@{$extinfo->{'scan'}}) {
if ($line =~ /^\s*([^\s]+)\s+scanned out of\s+([^\s]+)\s+at\s+([^\s]+),\s*([^\s]+)\s+to go/) {
$scanned = $1;
$total = $2;
$speed = $3;
$left = $4;
} elsif ($line =~ /^\s*([^\s]+)\s+resilvered,\s*([^\s]+)\s+done/) {
$resilvered = $1;
$percent = $2;
}
}
}
if ($scanned && length($scanned) > 2) {
push(@out, sprintf("%s(RESILVER %s,%s,%s)", $pool->{'name'}, $percent, $speed, $left));
} else {
push(@out, sprintf("%s(%s %s/%s)", $pool->{'name'}, $pool->{'health'}, $pool->{'alloc'}, $pool->{'size'}));
}
} elsif ($pool->{'health'} ne 'ONLINE') {
$exit_status = N_WARNING;
push(@out, sprintf("%s(%s %s/%s)", $pool->{'name'}, $pool->{'health'}, $pool->{'alloc'}, $pool->{'size'}));
} else {
push(@out, sprintf("%s(%s %s/%s)", $pool->{'name'}, $pool->{'health'}, $pool->{'alloc'}, $pool->{'size'}));
}
}
&nagios_response(join(",", @out), $exit_status);
}
&main();