You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.2 KiB
100 lines
3.2 KiB
#!/usr/bin/perl -w
|
|
|
|
use strict;
|
|
use warnings;
|
|
use JSON;
|
|
use File::Which;
|
|
use Getopt::Long;
|
|
|
|
my $json = {};
|
|
my $pool = undef;
|
|
my $what = undef;
|
|
|
|
GetOptions(
|
|
"zpool|pool=s" => \$pool,
|
|
"what=s" => \$what
|
|
);
|
|
|
|
my $zpool = which('zpool');
|
|
|
|
if ($what and !$pool){
|
|
print <<_EOF;
|
|
Usage:
|
|
$0 [--zpool=<name>] [--what=<item>]
|
|
|
|
<name> is an optional zpool name. If specified, will only output info for this zpool.
|
|
<item> is one of size, alloc, frag, cap, dedup, health and if specified, will only output the corresponding value
|
|
If --what is specified then --zpool is mandatory.
|
|
The default (with no option) is to output all the info of all the zpool in a JSON format
|
|
_EOF
|
|
exit 1;
|
|
}
|
|
|
|
if ($zpool){
|
|
my $cmd = "$zpool list -p -H" . ( ($pool) ? " $pool" : "");
|
|
foreach (qx($cmd)){
|
|
#NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
|
|
#rpool 464G 7.49G 457G - 2% 1% 1.00x ONLINE -
|
|
if (m/^(?<pool>\w+)\s+(?<size>\d+)\s+(?<alloc>\d+)\s+(?<free>\d+)\s+.+\s+(?<frag>\d+(\.\d+)?)\s+(?<cap>\d+(\.\d+)?)\s+(?<dedup>\d+(\.\d+)?)\s+(?<health>\w+)/){
|
|
$json->{$+{pool}}->{$_} = $+{$_} foreach (grep { $_ ne 'pool' } keys %+);
|
|
}
|
|
$json->{$+{pool}}->{errors} = get_zpool_errors($+{pool});
|
|
}
|
|
}
|
|
if ($what){
|
|
print ((defined $json->{$pool}->{$what}) ? $json->{$pool}->{$what} : 'ZBX_UNSUPORTED');
|
|
} elsif ($pool){
|
|
print ((defined $json->{$pool}) ? to_json($json->{$pool}) : 'ZBX_UNSUPORTED');
|
|
} else {
|
|
print to_json($json) . "\n";
|
|
}
|
|
exit 0;
|
|
|
|
sub get_zpool_errors {
|
|
my $pool = shift;
|
|
my $errors = {
|
|
read_errors => 0,
|
|
write_errors => 0,
|
|
cksum_errors => 0
|
|
};
|
|
my $i = 0;
|
|
my $index = {};
|
|
foreach my $line (qx($zpool status $pool)){
|
|
# Output looks like
|
|
# pool: rpool
|
|
# state: ONLINE
|
|
# status: One or more devices has experienced an unrecoverable error. An
|
|
# attempt was made to correct the error. Applications are unaffected.
|
|
# action: Determine if the device needs to be replaced, and clear the errors
|
|
# using 'zpool clear' or replace the device with 'zpool replace'.
|
|
# see: http://zfsonlinux.org/msg/ZFS-8000-9P
|
|
# scan: scrub repaired 0B in 0h5m with 0 errors on Tue May 29 10:04:31 2018
|
|
# config:
|
|
#
|
|
# NAME STATE READ WRITE CKSUM
|
|
# rpool ONLINE 0 0 0
|
|
# mirror-0 ONLINE 0 0 0
|
|
# sda2 ONLINE 0 0 0
|
|
# sdb2 ONLINE 0 0 474
|
|
#
|
|
# errors: No known data errors
|
|
|
|
# We want to save status, action, scan and errors
|
|
if ($line =~ m/^\s*(scan|action|status|errors):\s+(\w+.*)/){
|
|
$errors->{$1} = $2;
|
|
$index->{$i} = $1;
|
|
} elsif ($line !~ /:/ and defined $index->{$i-1}){
|
|
# Here, we reconstitute multiline values (like status and action)
|
|
chomp($line);
|
|
$line =~ s/\s+/ /g;
|
|
$errors->{$index->{$i-1}} .= $line;
|
|
} elsif ($line =~ m/\s+[a-zA-Z0-9_\-]+\s+[A-Z]+\s+(\d+)\s+(\d+)\s+(\d+)/){
|
|
# And here, we count the number of read, write and checksum errors
|
|
$errors->{read_errors} += $1;
|
|
$errors->{write_errors} += $2;
|
|
$errors->{cksum_errors} += $3;
|
|
}
|
|
$i++;
|
|
}
|
|
return $errors;
|
|
}
|
|
|