From ab9da87eb0e29f492889b5c238f688fe29d8eb4d Mon Sep 17 00:00:00 2001 From: Christopher Schenk Date: Wed, 20 Jun 2018 12:41:49 +0200 Subject: [PATCH 1/5] Add commandline option to check if a certain amount of spares are present --- .../Plugin/CheckRaid/Plugins/mdstat.pm | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm b/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm index 7de18d2f..559e1b00 100644 --- a/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm +++ b/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm @@ -171,6 +171,26 @@ sub check { # failed disks my @fd = map { $_->{dev} } grep { $_->{flags} =~ /F/ } @{$md{disks}}; + # spare disks + my @sd = map { $_->{dev} } grep { $_->{flags} =~ /S/ } @{$md{disks}}; + + my $spare_count = 0; + if (exists $this->{options}{'mdstat_spare_count'}) + { + my @spare_options = (); + @spare_options = split(/\|/, $this->{options}{'mdstat_spare_count'}); + foreach my $val (@spare_options) + { + my ($disk, $value) = split(/:/, $val); + for(@md) + { + if ($md{dev} eq $disk) + { + $spare_count = $value; + } + } + } + } # raid0 is just there or its not. raid0 can't degrade. # same for linear, no $md_status available @@ -194,6 +214,10 @@ sub check { # FIXME: this is same as above? $this->warning; $s .= "hot-spare failure:". join(",", @fd) .":$md{status}"; + } elsif (@sd < $spare_count) + { + $this->warning; + $s .= "Array ".$md{dev}." should have ".$spare_count." spares, but has only ".(0+@sd)." spares"; } else { $s .= "$md{status}"; } From 3ca261f519828b8a43a6ebd5f71645c558c1e6ec Mon Sep 17 00:00:00 2001 From: Christopher Schenk Date: Wed, 20 Jun 2018 15:15:30 +0200 Subject: [PATCH 2/5] We should rather use a comma instead of a pipe as seperator --- lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm b/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm index 559e1b00..966f4296 100644 --- a/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm +++ b/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm @@ -178,7 +178,7 @@ sub check { if (exists $this->{options}{'mdstat_spare_count'}) { my @spare_options = (); - @spare_options = split(/\|/, $this->{options}{'mdstat_spare_count'}); + @spare_options = split(/\,/, $this->{options}{'mdstat_spare_count'}); foreach my $val (@spare_options) { my ($disk, $value) = split(/:/, $val); From 1274aa19182e42991ca1c5e44635c86b6ed16620 Mon Sep 17 00:00:00 2001 From: Christopher Schenk Date: Fri, 23 Nov 2018 12:04:22 +0100 Subject: [PATCH 3/5] Return crititcal if there is an spare_count option for an non exsisting array --- .../Plugin/CheckRaid/Plugins/mdstat.pm | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm b/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm index 966f4296..a89269af 100644 --- a/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm +++ b/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm @@ -161,6 +161,11 @@ sub check { my (@status); my @md = $this->parse; + my @spare_options = (); + + @spare_options = split(/\,/, $this->{options}{'mdstat_spare_count'}) + if (exists $this->{options}{'mdstat_spare_count'}); + foreach (@md) { my %md = %$_; @@ -175,18 +180,18 @@ sub check { my @sd = map { $_->{dev} } grep { $_->{flags} =~ /S/ } @{$md{disks}}; my $spare_count = 0; - if (exists $this->{options}{'mdstat_spare_count'}) + OPTION_LOOP: { - my @spare_options = (); - @spare_options = split(/\,/, $this->{options}{'mdstat_spare_count'}); - foreach my $val (@spare_options) + foreach my $i (0 .. $#spare_options) { - my ($disk, $value) = split(/:/, $val); + my ($disk, $value) = split(/:/, $spare_options[$i]); for(@md) { if ($md{dev} eq $disk) { $spare_count = $value; + splice(@spare_options, $i, 1); + last OPTION_LOOP; } } } @@ -224,6 +229,17 @@ sub check { push(@status, $s); } + if ($#spare_options > 0) + { + $this->critical; + foreach (@spare_options) + { + my ($disk, $value) = split(/:/, $_); + my $s = "$disk is defined in spare_count option but could not be found!"; + push(@status, $s); + } + } + return unless @status; # denote this plugin as ran ok From 0a25f36484e60037213c8bf57f366f40712a2bfb Mon Sep 17 00:00:00 2001 From: Christopher Schenk Date: Fri, 30 Nov 2018 10:01:46 +0100 Subject: [PATCH 4/5] Use scalar keyword instead of $# --- lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm b/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm index a89269af..98af1e96 100644 --- a/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm +++ b/lib/App/Monitoring/Plugin/CheckRaid/Plugins/mdstat.pm @@ -163,8 +163,8 @@ sub check { my @spare_options = (); - @spare_options = split(/\,/, $this->{options}{'mdstat_spare_count'}) - if (exists $this->{options}{'mdstat_spare_count'}); + @spare_options = split(/\,/, $this->{options}{mdstat_spare_count}) + if (exists $this->{options}{mdstat_spare_count}); foreach (@md) { my %md = %$_; @@ -229,7 +229,7 @@ sub check { push(@status, $s); } - if ($#spare_options > 0) + if (scalar @spare_options > 0) { $this->critical; foreach (@spare_options) From 43d47be8272ee8ae6c21e10ab88bd2d390e61da2 Mon Sep 17 00:00:00 2001 From: Christopher Schenk Date: Fri, 30 Nov 2018 10:03:25 +0100 Subject: [PATCH 5/5] Add tests for mdstat_spare_count option --- t/check_mdstat.t | 42 +++++++++++++++++++++++++++++++++++++++++- t/data/mdstat/pr185_0 | 6 ++++++ t/data/mdstat/pr185_1 | 10 ++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 t/data/mdstat/pr185_0 create mode 100644 t/data/mdstat/pr185_1 diff --git a/t/check_mdstat.t b/t/check_mdstat.t index e040f4e9..2cbb8282 100755 --- a/t/check_mdstat.t +++ b/t/check_mdstat.t @@ -7,7 +7,7 @@ BEGIN { use strict; use warnings; use constant INACTIVE_TESTS => 2; -use constant ACTIVE_TESTS => 19; +use constant ACTIVE_TESTS => 26; use Test::More tests => 1 + ACTIVE_TESTS * 6 + INACTIVE_TESTS * 2; use test; @@ -95,6 +95,42 @@ my @tests = ( active => 1, message => 'md1(1.82 TiB raid1):hot-spare failure:sdh1:UUUUU, md0(119.18 GiB raid1):UU', }, + { input => 'pr185_0', status => OK, + mdstat_spare_count => 'md1:1', + active => 1, + message => 'md1(3.49 TiB raid5):UUUUU', + }, + { input => 'pr185_0', status => WARNING, + mdstat_spare_count => 'md1:2', + active => 1, + message => 'md1(3.49 TiB raid5):Array md1 should have 2 spares, but has only 1 spares', + }, + { input => 'pr185_0', status => CRITICAL, + mdstat_spare_count => 'md2:2', + active => 1, + message => 'md1(3.49 TiB raid5):UUUUU, md2 is defined in spare_count option but could not be found!', + }, + { input => 'pr185_1', status => OK, + mdstat_spare_count => 'md1:1,md2:2', + active => 1, + message => 'md1(3.49 TiB raid5):UUUUU, md2(3.49 TiB raid5):UUUUU', + }, + { input => 'pr185_1', status => WARNING, + mdstat_spare_count => 'md1:1,md2:3', + active => 1, + message => 'md1(3.49 TiB raid5):UUUUU, md2(3.49 TiB raid5):Array md2 should have 3 spares, but has only 2 spares', + }, + { input => 'pr185_1', status => WARNING, + mdstat_spare_count => 'md1:2,md2:3', + active => 1, + message => 'md1(3.49 TiB raid5):Array md1 should have 2 spares, but has only 1 spares, md2(3.49 TiB raid5):Array md2 should have 3 spares, but has only 2 spares', + }, + { input => 'pr185_1', status => CRITICAL, + mdstat_spare_count => 'md1:1,md2:2,md3:1', + active => 1, + message => 'md1(3.49 TiB raid5):UUUUU, md2(3.49 TiB raid5):UUUUU, md3 is defined in spare_count option but could not be found!', + }, + ); # test that plugin can be created @@ -108,6 +144,10 @@ foreach my $test (@tests) { if (defined $test->{check_status}) { $options{check_status} = $test->{check_status}; } + if (defined $test->{mdstat_spare_count}) { + $options{mdstat_spare_count} = $test->{mdstat_spare_count}; + } + my $plugin = mdstat->new( commands => { 'mdstat' => ['<', TESTDIR . '/data/mdstat/' . $test->{input}], diff --git a/t/data/mdstat/pr185_0 b/t/data/mdstat/pr185_0 new file mode 100644 index 00000000..2e0a47be --- /dev/null +++ b/t/data/mdstat/pr185_0 @@ -0,0 +1,6 @@ +Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] +md1 : active raid5 sdh[3] sdg[2] sdj[6] sde[1] sdk[5](S) sdd[0] + 3750244352 blocks super 1.2 level 5, 512k chunk, algorithm 2 [5/5] [UUUUU] + bitmap: 4/7 pages [16KB], 65536KB chunk + +unused devices: diff --git a/t/data/mdstat/pr185_1 b/t/data/mdstat/pr185_1 new file mode 100644 index 00000000..19e91545 --- /dev/null +++ b/t/data/mdstat/pr185_1 @@ -0,0 +1,10 @@ +Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] +md1 : active raid5 sdh[3] sdg[2] sdj[6] sde[1] sdk[5](S) sdd[0] + 3750244352 blocks super 1.2 level 5, 512k chunk, algorithm 2 [5/5] [UUUUU] + bitmap: 4/7 pages [16KB], 65536KB chunk + +md2 : active raid5 sda[3] sdb[2] sdc[6] sdf[1] sdi[5](S) sdl[0](S) sdm[7] + 3750244352 blocks super 1.2 level 5, 512k chunk, algorithm 2 [5/5] [UUUUU] + bitmap: 4/7 pages [16KB], 65536KB chunk + +unused devices: