diff --git a/zabbix_conf/mpath.conf b/zabbix_conf/mpath.conf new file mode 100644 index 0000000..9a136b2 --- /dev/null +++ b/zabbix_conf/mpath.conf @@ -0,0 +1,6 @@ +# Discover multipath devices +# $1 not used for now +UserParameter=vfs.mpath.discovery[*],sudo /var/lib/zabbix/bin/disco_mpath_sudo --$1 + +# Check multipath device +UserParameter=vfs.mpath.info[*],sudo /var/lib/zabbix/bin/check_mpath_sudo --mpath=$1 diff --git a/zabbix_scripts/check_mpath_sudo b/zabbix_scripts/check_mpath_sudo new file mode 100644 index 0000000..e1fb48c --- /dev/null +++ b/zabbix_scripts/check_mpath_sudo @@ -0,0 +1,125 @@ +#!/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= [--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; diff --git a/zabbix_scripts/disco_mpath_sudo b/zabbix_scripts/disco_mpath_sudo new file mode 100644 index 0000000..0622d6b --- /dev/null +++ b/zabbix_scripts/disco_mpath_sudo @@ -0,0 +1,31 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use JSON; +use Getopt::Long; +use File::Which; + +my $mpath = 1; +my $pretty = 0; +my $json = []; + +GetOptions( + "mpath" => \$mpath, + "pretty" => \$pretty +); + +my $multipath = which('multipath'); + +if (not defined $multipath){ + print to_json($json, { pretty => $pretty }); + exit 0; +} + +foreach (qx($multipath -l -v1)){ + chomp; + push @{$json}, { '{#MPATH_DEV}' => $_ }; +} + +print to_json($json, { pretty => $pretty }); +exit 0;