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.
126 lines
3.2 KiB
126 lines
3.2 KiB
4 years ago
|
#!/usr/bin/perl
|
||
|
|
||
|
use strict;
|
||
|
use warnings;
|
||
|
use JSON;
|
||
|
use Getopt::Long;
|
||
|
use File::Which;
|
||
|
|
||
|
my $json = {};
|
||
|
my $mpath = undef;
|
||
|
my $help = 0;
|
||
|
my $pretty = 0;
|
||
|
|
||
|
GetOptions(
|
||
|
"mpath=s" => \$mpath,
|
||
|
"help" => \$help,
|
||
|
"pretty" => \$pretty
|
||
|
);
|
||
|
|
||
|
my $multipathd = which('multipathd');
|
||
|
|
||
|
if (not defined $multipathd){
|
||
|
print 'ZBX_NOTSUPPORTED';
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
if ($help or not defined $mpath){
|
||
|
print <<_EOF;
|
||
|
Usage : $0 --mpath=<name of the mpath device> [--pretty]
|
||
|
|
||
|
* --mpath : the name of the device to check
|
||
|
* --pretty : output pretty JSON, easier to read for humans
|
||
|
* --help : display this help
|
||
|
|
||
|
_EOF
|
||
|
exit 2;
|
||
|
}
|
||
|
|
||
|
$json = {
|
||
|
mpath => $mpath,
|
||
|
size => 0,
|
||
|
dm_st => 'unknown',
|
||
|
features => '',
|
||
|
failures => 0,
|
||
|
path_failures => 0,
|
||
|
paths_num_total => 0,
|
||
|
paths_num_ko => 0,
|
||
|
paths_num_active => 0,
|
||
|
paths_num_inactive => 0,
|
||
|
paths_details => [],
|
||
|
paths_with_issue => [],
|
||
|
errors => []
|
||
|
};
|
||
|
my @res = qx($multipathd show maps raw format "%n|%N|%S|%f|%t|%x|%0");
|
||
|
if ($? != 0){
|
||
|
push @{$json->{errors}}, "Failed to run multipathd show maps raw format";
|
||
|
}
|
||
|
foreach (@res){
|
||
|
chomp;
|
||
|
next if $_ !~ /^$mpath\|/;
|
||
|
(undef, $json->{paths_num_total}, $json->{size}, $json->{features},
|
||
|
$json->{dm_st}, $json->{failures}, $json->{path_failures}) = split(/\s*\|\s*/, $_);
|
||
|
# Cast to int
|
||
|
foreach (qw(failures path_failures paths_num_total)){
|
||
|
$json->{$_} = 0 + $json->{$_};
|
||
|
}
|
||
|
# Convert size to bytes
|
||
|
my $unit = chop $json->{size};
|
||
|
if ($unit eq 'K'){
|
||
|
$json->{size} *= 1024;
|
||
|
} elsif ($unit eq 'M'){
|
||
|
$json->{size} *= 1024 * 1024;
|
||
|
} elsif ($unit eq 'G'){
|
||
|
$json->{size} *= 1024 * 1024 * 1024;
|
||
|
} elsif ($unit eq 'T'){
|
||
|
$json->{size} *= 1024 * 1024 * 1024 * 1024;
|
||
|
} elsif ($unit eq 'P'){
|
||
|
$json->{size} *= 1024 * 1024 * 1024 * 1024 * 1024;
|
||
|
}
|
||
|
# No need to process the other mpath here
|
||
|
last;
|
||
|
}
|
||
|
|
||
|
# Now check status of every path
|
||
|
@res = qx($multipathd show paths format "%m|%d|%t|%o|%T|%0|%z");
|
||
|
if ($? != 0){
|
||
|
push @{$json->{errors}}, "Failed to run multipathd show paths format";
|
||
|
}
|
||
|
# Skip header line
|
||
|
shift @res;
|
||
|
foreach (@res){
|
||
|
chomp;
|
||
|
next if $_ !~ /^$mpath\|/;
|
||
|
my (undef, $dev, $dm_st, $dev_st, $chk_st, $failures, $serial) = split(/\s*\|\s*/, $_);
|
||
|
push @{$json->{paths_details}}, {
|
||
|
dev => $dev,
|
||
|
dm_st => $dm_st,
|
||
|
dev_st => $dev_st,
|
||
|
chk_st => $chk_st,
|
||
|
failures => $failures + 0,
|
||
|
serial => $serial
|
||
|
};
|
||
|
if ($dm_st eq 'active'){
|
||
|
$json->{paths_num_active} += 1;
|
||
|
if ($dev_st ne 'running'){
|
||
|
$json->{paths_num_ko} += 1;
|
||
|
push @{$json->{paths_with_issue}}, $dev;
|
||
|
push @{$json->{errors}}, "dev $dev is not running";
|
||
|
} elsif ($chk_st ne 'ready' or $failures > 0){
|
||
|
$json->{paths_num_ko} += 1;
|
||
|
push @{$json->{paths_with_issue}}, $dev;
|
||
|
push @{$json->{errors}}, "dev $dev is not active";
|
||
|
} else {
|
||
|
$json->{paths_num_ok} += 1;
|
||
|
}
|
||
|
} else {
|
||
|
$json->{paths_num_inactive} += 1;
|
||
|
}
|
||
|
}
|
||
|
# We want easy usage from zabbix, so turn thos ones to strings
|
||
|
$json->{paths_with_issue} = join(',', @{$json->{paths_with_issue}});
|
||
|
$json->{errors} = join(',', @{$json->{errors}});
|
||
|
|
||
|
print to_json($json, { pretty => $pretty });
|
||
|
exit 0;
|