#!/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 (

) { 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 (

) { 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();