[Pkg-nagios-changes] [pkg-nagios-plugins-contrib] 01/01: check_multipath: Update to latest version 0.4.7

Jan Wagner waja at moszumanska.debian.org
Sat Sep 10 16:42:32 UTC 2016


This is an automated email from the git hooks/post-receive script.

waja pushed a commit to branch master
in repository pkg-nagios-plugins-contrib.

commit fa1684b0e6ac70656f7a2656d8ffacca9111212e
Author: Jan Wagner <waja at cyconet.org>
Date:   Sat Sep 10 18:36:46 2016 +0200

    check_multipath: Update to latest version 0.4.7
---
 check_multipath/check-multipath.pl | 559 +++++++++++++++++++++++++++++--------
 check_multipath/control            |   2 +-
 2 files changed, 449 insertions(+), 112 deletions(-)

diff --git a/check_multipath/check-multipath.pl b/check_multipath/check-multipath.pl
index bd1440c..7ae3c0c 100644
--- a/check_multipath/check-multipath.pl
+++ b/check_multipath/check-multipath.pl
@@ -21,7 +21,7 @@
 #-------------------------------------------------------------
 #
 #
-# Copyright (C) 2011-2015
+# Copyright (C) 2011-2016
 # Hinnerk Rümenapf, Trond H. Amundsen, Gunther Schlegel, Matija Nalis, 
 # Bernd Zeimetz, Sven Anders, Ben Evans
 #
@@ -53,7 +53,7 @@
 #      0.1.5    add debian testcases and patch by Bernd Zeimetz
 #      0.1.6    Added checklunline test for "-" character, thanks to Sven Anders <s.anders at digitec.de> also for test data (testcase 22)
 #      0.1.7    Added test option
-#      0.1.8    Added Support for LUN names without HEX-ID (e.g. iSCSI LUNs)
+#      0.1.8    Added Support for LUN names without WWID (e.g. iSCSI LUNs)
 #      0.1.9    Added extraconfig option
 #
 #      0.2.0    Improved flexibility, more testcases. Thanks to Benjamin von Mossner and Ben Evans
@@ -64,17 +64,22 @@
 #      
 #      0.3.0    Added Option --ll, added handling of checker messages. Thanks to Andreas Steinel <Andreas.Steinel at exirius.de>
 #
-#      0.4.0    Added check if multipathd is running (suggested by Dmitry Sakoun)   11. Dec. 2015
+#      0.4.0    Added check if multipathd is running (suggested by Dmitry Sakoun)            11. Dec. 2015
 #               Added --group option (based on comments by Robert Towster and Tom Schier)
-#      0.4.1    minor changes 14. Dec 2015
+#      0.4.1    minor changes                                                                14. Dec. 2015
 #
+#      0.4.5    distinguish between different attributes identifying a LUN (OPTIONAL) (based on suggestions by Séverin Launiau)
+#               for output and extraconfig LUN-selector (see usage message)
+#               Added ability to check counts of policies per LUN  (suggested by Jim Clark)
+#               Added ability to check counts of scsi-hosts and scsi-ids per LUN              3. Aug. 2016
+#      0.4.6    Bugfix (output)
+#      0.4.7    Compatibility with CentOS/RHEL 5-7: no "switch", check second directory for multipath binary   (thanks to Christian Zettel) 25. Aug. 2016
 #
 
 
-
 use strict;
 use warnings;
-use Switch;
+#use Switch; ## causes compatibility issues (perl version)
 use POSIX qw(isatty);
 use Getopt::Long qw(:config no_ignore_case);
 
@@ -93,7 +98,7 @@ use vars qw( $NAME $VERSION $AUTHOR $CONTACT $E_OK $E_WARNING $E_CRITICAL
 
 # === Version and similar info ===
 $NAME    = 'check-multipath.pl';
-$VERSION = '0.4.1   14. DEC 2015';
+$VERSION = '0.4.7   25. AUG 2016';
 $AUTHOR  = 'Hinnerk Rümenapf';
 $CONTACT = 'hinnerk [DOT] ruemenapf [AT] uni-hamburg [DOT] de   (hinnerk [DOT] ruemenapf [AT] gmx [DOT] de)';
 
@@ -381,14 +386,14 @@ $SIG{__WARN__} = sub { push @perl_warnings, [@_]; };
 ." \\_ 2:0:1:3 sds 65:32 [active][undef]\n"
 ." \\_ 7:0:1:3 sdr 65:16 [active][undef]\n",
 
-#23. LUN without HEX-ID (iSCSI) thanks to Ernest Beinrohr <Ernest.Beinrohr at axonpro.sk>
+#23. LUN without WWID (iSCSI) thanks to Ernest Beinrohr <Ernest.Beinrohr at axonpro.sk>
 "1STORAGE_server_target2 dm-2 IET,VIRTUAL-DISK\n"
 ."size=1.0T features='0' hwhandler='0' wp=rw\n"
 ."`-+- policy='round-robin 0' prio=0 status=active\n"
 ."  |- 9:0:0:1  sdc 8:32 active undef running\n"
 ."  `- 10:0:0:1 sdd 8:48 active undef running\n",
 
-#24. LUN without HEX-ID (iSCSI) thanks to Ernest Beinrohr <Ernest.Beinrohr at axonpro.sk>
+#24. LUN without WWID (iSCSI) thanks to Ernest Beinrohr <Ernest.Beinrohr at axonpro.sk>
 "1STORAGE_server_target2 dm-2 IET,VIRTUAL-DISK\n"
 ."size=1.0T features='0' hwhandler='0' wp=rw\n"
 ."`-+- policy='round-robin 0' prio=1 status=active\n"
@@ -473,14 +478,49 @@ $SIG{__WARN__} = sub { push @perl_warnings, [@_]; };
 ."| `- 1:0:2:11 sdau 66:224 active ready running\n"
 ."`-+- policy='round-robin 0' prio=10 status=enabled\n"
 ."  |- 0:0:3:11 sdz  65:144 active ready running\n"
-."  `- 1:0:3:11 sdba 67:64  active ready running\n"
+."  `- 1:0:3:11 sdba 67:64  active ready running\n",
+
+#32. thanks to Séverin Launiau
+"3600a098038303039492b473242384661 dm-19 NETAPP  ,LUN C-Mode\n"
+."size=5.0T features='4 queue_if_no_path pg_init_retries 50 retain_attached_hw_handle' hwhandler='1 alua' wp=rw\n"
+."|-+- policy='service-time 0' prio=50 status=active\n"
+."| `- 7:0:0:0  sdb 8:16  active ready running\n"
+."`-+- policy='service-time 0' prio=10 status=enabled\n"
+."  `- 11:0:0:0 sdg 8:96  active ready running\n"
+."360a98000375432714a3f336733636843 dm-3 NETAPP  ,LUN\n"
+."size=10T features='4 queue_if_no_path pg_init_retries 50 retain_attached_hw_handle' hwhandler='0' wp=rw\n"
+."`-+- policy='service-time 0' prio=2 status=active\n"
+."  |- 8:0:0:0  sdd 8:48  active ready running\n"
+."  |- 9:0:0:0  sde 8:64  active ready running\n"
+."  |- 10:0:0:0 sdf 8:80  active ready running\n"
+."  `- 12:0:0:0 sdi 8:128 active ready running\n"
+."3600a098038303039365d4671616a756e dm-2 NETAPP  ,LUN C-Mode\n"
+."size=150G features='4 queue_if_no_path pg_init_retries 50 retain_attached_hw_handle' hwhandler='1 alua' wp=rw\n"
+."|-+- policy='service-time 0' prio=50 status=active\n"
+."| `- 11:0:0:1 sdh 8:112 active ready running\n"
+."`-+- policy='service-time 0' prio=10 status=enabled\n"
+."  `- 7:0:0:1  sdc 8:32  active ready running\n"
     );
 
+
 # Commands with full path
 $SUDO                = '/usr/bin/sudo';
-$MULTIPATH_LIST_LONG = '/sbin/multipath -ll';
-$MULTIPATH_LIST      = '/sbin/multipath -l';
-$MULTIPATH_RELOAD    = '/sbin/multipath -r';
+
+
+# check path for multipath command
+my $multipathCmd = '/usr/sbin/multipath';
+if (! -e $multipathCmd ) {
+    $multipathCmd = '/sbin/multipath';
+    if ( ! -e $multipathCmd ) {
+	$multipathCmd = '';
+    } # if
+} # if
+
+# commands with options
+$MULTIPATH_LIST_LONG = $multipathCmd.' -ll';
+$MULTIPATH_LIST      = $multipathCmd.' -l';
+$MULTIPATH_RELOAD    = $multipathCmd.' -r';
+
 
 # Exit codes
 $E_OK       = 0;
@@ -521,6 +561,9 @@ see:
  http://exchange.nagios.org/directory/Plugins/Operating-Systems/Linux/check-2Dmultipath-2Epl/details
  http://www.nagios.org/documentation
 
+The number of parameters and options has increased over the time, as a result of feature requests by users. 
+You might not need most of them.
+
 A configuration for a specific LUN name via --extraconfig has highest priority and overrides group and global config.
 If a regex defined in --group matches a LUN line the specified group values are used. (First regex in List, checked from left to right)
 Otherwise the global defaults are used (--min-paths, --ok-paths).
@@ -531,6 +574,17 @@ OPTIONS:
   -n, --no-multipath  Exitcode for no LUNs, no multipath driver and multipathd not running  [warning]
   -M, --mdskip        Skip extra check if multipathd is running (check uses '--no-multipath' returncode)
 
+  -a, --addchecks     define low/high marks for additional checks
+                        number of policies   per LUN   p,<LOW>,<HIGH>  DEFAULT: p,0,0
+                        number of scsi-hosts per LUN  sh,<LOW>,<HIGH>  DEFAULT: sh,0,0
+                        number of scsi-ids,  per LUN  si,<LOW>,<HIGH>  DEFAULT: si,0,0
+                      e.g. 'p,1,2,sh,1,2';  'si,1,2,p,1,2,sh,2,4';  'p,1,2'
+                      See documentation of multipath output. If the HIGH value is 0, the check is skipped.
+                      A typical standard-configuration uses 2 scsi-hosts and 2 scsi-ids, resulting in four paths
+                      representing all possible combinations: h0-i0, h0-i1, h1-i0, h1-i1. 
+
+ --scsi-all           Count all scsi-hosts and scsi-ids, even from paths that report an error state. 
+
   -r, --reload        force devmap reload if status is WARNING or CRITICAL
                       (multipath -r)
                       Can help to pick up LUNs coming back to life.
@@ -548,19 +602,42 @@ OPTIONS:
   -g, --group         Specify perl-regex to identify groups of LUNs with other default-thresholds.
                       Overrides global config for LUNs with LUN lines that math a group regex.
                       In most cases a simple String should be sufficient. NOTE: special regex characters must be escaped!
-                      "<LUN_LINE_REGEX>,<LOW>,<HIGH>:"  for each group with deviant thresholds
-                      e.g.  "IBM,ServeRAID,1,1:HAL,ChpRAID,1,2:"
+                      "<LUN_LINE_REGEX>,<LOW>,<HIGH>[@#,<ADDCHECKS>]:"  for each group with deviant thresholds (see explanation of --addchecks)
+                      e.g.  "IBM,ServeRAID,1,1:HAL,ChpRAID,1,2:"  or "IBM,ServeRAID,1,1@#,p,1,2:HAL,ChpRAID,1,2@#,sh,1,2,si,1,2:"
                       Use command multipath -l to see the LUN lines and to identify groups.
 
   -e, --extraconfig   Specify different low/high thresholds for LUNs.
                       Overrides group and global config for the specified LUNs.
-                      optional: specify return code if no data for LUN name was found 
+                      optional: specify return code if no data for LUN selector was found 
                                 (ok, warning, critical), default is warning
-                      "<LUN>,<LOW>,<HIGH>[,<RETURNCODE>]:"  for each LUN with deviant thresholds
+                                the return code MAY be followed by definitions of additional check, see explanation of --addchecks above
+                      "<LUN-selector>,<LOW>,<HIGH>[,<RETURNCODE>[,<ADDCHECKS>]]:"  for each LUN with deviant thresholds
                       e.g.  "iscsi_lun_01,2,2:dummyLun,1,1,ok:paranoid_lun,8,16,critical:"
-                            "oddLun,3,5,critical:"
-                            "default,2,4,warning:DonalLunny,6,8:"
-                      Use option -v to see LUN names used by this plugin. 
+                            "oddLun,3,5:"
+                            "paranoidOddLun,5,11,critical,p,3,5,sh,5,9,si,3,7:"
+                            "default,2,4,warning:DonalLunny,6,8,warning,sh,1,4,si,1,4:" 
+
+                      <LUN-selector> is by default checked against the "generic Name", as used in older plugin versions. 
+                      You can specify a prefix to select a LUN attribute as identifier. 
+                      Not all attributes may be available, depending on the specific multipath configuration.
+                      Use command multipath -l to see the complete LUN lines.
+                        "G!" generic name, as used in older versions. Exists always. Content depends on the specific configuration. DEFAULT
+                        "W!" WWID as reported by the multipath command
+                        "D!" dm Identifier (dm-3 or similar)
+                        "N!" user-firendly name 
+                      e.g. 'W!36000d774000045f655ea91cb4ea41d6f,4,8,critical:DonalLunny,6,8:D!dm-3,1,2,warning,sh,1,2,si,1,2:'
+                      NOTE: enclose parameter value in SINGLE-quotes for this notation!
+
+  -p, --print         List to determine which attribute of the LUN should be printed as identifier in the output
+                      The letters in the list are checked from left to right, the first coresponding attribute that exists is printed. 
+                      The letter G is always appended to the list.
+                      Avalible are:
+                        G: generic name, as used in older versions. Exists always. Content depends on the specific configuration.
+                        W: WWID as reported by the multipath command
+                        D: dm Identifier (dm-3 or similar)
+                        N: user-firendly name 
+                      e.g. "DN":  print dm-identifier (if present), else user friendly name (if present) else generic name (as G is always appended to the list) 
+                           "WDN": print WWID (if present), else print dm-identifier (if present), else user friendly name (if present) else generic name (as G ist always appended to the list)  
 
   -s, --state         Prefix alerts with alert state
   -S, --short-state   Prefix alerts with alert state abbreviated
@@ -586,7 +663,7 @@ $LICENSE = <<"END_LICENSE";
 
 $NAME   $VERSION
 
-Copyright (C) 2011-2014 $AUTHOR
+Copyright (C) 2011-2016 $AUTHOR
 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 This is free software: you are free to change and redistribute it.
 There is NO WARRANTY, to the extent permitted by law.
@@ -623,8 +700,30 @@ END_LICENSE
       'll'            => 0, 
       'mdskip'        => 0,
       'group'         => '',
+      'print'         => '',
+      'scsi-all'      => 0,
+      'addchecks'     => '',
+    );
+
+
+# the hash keys define the valid check identifiers. only  \w  characters for IDs!
+# Initialize the hash with defaults (no checks)
+my %addChecks 
+ = (
+    'sh' => [0,0],      # scsi-hosts
+    'si' => [0,0],      # scsi-ids
+    'p'  => [0,0],      # policies
     );
 
+# short human readable description
+my %addCheckNames
+ = (
+    'sh' => 'scsi-hosts',
+    'si' => 'scsi-ids',
+    'p'  => 'policies',
+    );
+
+
 # Get options
 GetOptions(#'t|timeout=i'      => \$opt{timeout},
 	   'h|help'           => \$opt{'help'},
@@ -643,6 +742,9 @@ GetOptions(#'t|timeout=i'      => \$opt{timeout},
 	   'L|ll'             => \$opt{'ll'},
 	   'M|mdskip'         => \$opt{'mdskip'},
 	   'g|group=s'        => \$opt{'group'},
+	   'p|print=s'        => \$opt{'print'},
+	   'scsi-all'         => \$opt{'scsi-all'},
+	   'a|addchecks=s'    => \$opt{'addchecks'},
 	  ) or do { print $USAGE; exit $E_UNKNOWN };
 
 # If user requested help
@@ -671,6 +773,66 @@ if ($opt{'version'}) {
 #alarm $opt{timeout};
 
 
+
+#---------------------------------------
+#
+# Initialise a hash with current addcheck defaults
+# copy the arrays, not just the references!
+#
+sub getNewAddCheckHash {
+    my %h;
+
+    foreach my $k (keys %addChecks) {
+	#print "getNewAddCheckHash : '$k'\n";
+	my @arr = @{$addChecks{$k}};
+	$h{$k}= \@arr;
+    } # foreach
+
+    return \%h;
+} # sub
+
+
+#---------------------------------------
+#
+# analyse definition of additional checks, write check-values to referenced hash
+#
+sub getAddChecks {
+    my ($inString, $rOuthash, $errPrefix) = @_;
+    
+    if ( !defined($inString) ) {         # undefined or empty means no change
+	return;
+    } elsif ($inString eq '') { 
+	return;
+    } # if
+
+    if ( !defined($errPrefix) ) {        # errorPrefix should give information about the call context
+	$errPrefix = '';
+    } # if
+
+    if ($inString !~ m!^\w+,\d+,\d+(,\w+,\d+,\d+)*$! ) {
+	unknown_error($errPrefix."invalid addcheck definition: '$inString', syntax error. See help information.");
+    } # if
+    
+    while ($inString =~ m!(\w+),(\d+),(\d+)!g) {
+	my ( $id, $low, $high ) = ($1, $2, $3); 
+	#print "AddCheck: id='$id', low='$low', high='$high', errprefix='$errPrefix'\n";
+
+	if ( defined($$rOuthash{$id}) ) {            # hash keys define valid ids
+	    if ( $low <= $high ) {                   # make sure low and high value are in the right order
+		@{$$rOuthash{$id}} = ($low, $high);  # only set values found in input string, leave the others untouched
+	    } else {
+		unknown_error($errPrefix."invalid addcheck definition for id '$id', low value bigger than high value. See help information.");
+	    } # if
+	} else {
+	    unknown_error($errPrefix."invalid addcheck identifier '$id' in '$inString', syntax error. See help information.");
+	} # if
+    } # while
+} # sub
+
+#---------------------------------------
+
+
+
 # Default line break
 $linebreak = isatty(*STDOUT) ? "\n" : '<br/>';
 
@@ -688,23 +850,31 @@ if (defined $opt{linebreak}) {
     }
 } # if
 
+# Analyse additional check definitions. Parameter sets defaults
+# exit on Error
+getAddChecks( $opt{'addchecks'}, \%addChecks, "Parameter '--addchecks'; " );
+
 
 # group option
 my @group = ();
 
-#print "--group='".$opt{'group'}.$opt{'group'}."'\n";
+#print "--group='".$opt{'group'}."'\n";
 if ($opt{'group'} ne '') {
-    if ( $opt{'group'} !~ m!^(.+?,\d+,\d+:)+$! ) {
+    if ( $opt{'group'} !~ m!^(.+?,\d+,\d+(?:@#(,\w+,\d+,\d+)*)?:)+$! ) {
 	unknown_error("Wrong usage of '--group' option: '"
 		      . $opt{'group'}
 		      . "' syntax error. See help information.");
     } # if
 
-    while ( $opt{'group'} =~ m!(.+?),(\d+),(\d+):!g ) {
-	my $regex =$1;
-	my $crit =$2;
-	my $warn =$3;
-	#print "GROUP: Regex='$regex', c=$crit, w=$warn\n";
+    while ( $opt{'group'} =~ m/(.+?),(\d+),(\d+)(?:@#,([\w\d,]+))?:/g ) {
+	my $regex     = $1;
+	my $crit      = $2;
+	my $warn      = $3;
+	my $addchecks = $4;
+	if ( !defined($addchecks) ) {
+	    $addchecks = '';
+	} # if
+	#print "GROUP: Regex='$regex', c=$crit, w=$warn, addchecks='$addchecks'\n";
 
 	if ($crit > $warn) {
 	    unknown_error("Error in '--group' option '"
@@ -712,40 +882,63 @@ if ($opt{'group'} ne '') {
 			  . "' for group rule '$regex': critical threshold ($crit) must not be higher than warning threshold ($warn).");
 	} # if
 
-	push ( @group, { 'regex' => $regex, 'warn' => $warn, 'crit' => $crit } );
+	my $rHash = getNewAddCheckHash();              # initialise with default
+	getAddChecks( $addchecks, $rHash, "Parameter '--group'; " );
+	push ( @group, { 'regex' => $regex, 'warn' => $warn, 'crit' => $crit, 'addchecks' => $rHash } );
     } # while 
 } # if
 
 
+# print option
+$opt{'print'} .= 'G';                  # last resort: "generic name" (always present) als default
+if  ($opt{'print'} !~ m!^[GWND]+$!) {
+    unknown_error("Error in '--print' option: invalid character in value '". $opt{'print'} ."'. Please check usage.");
+} # if
+
+
 # extraconfig option
-my %extraconfig = ();
+my @extraconfig = ();
 
 if ($opt{extraconfig} ne '') {
-    if ( $opt{extraconfig} !~ m!^([\w\-]+,\d+,\d+(?:,(?:ok|warning|critical))?:)+$! ) {
+    if ( $opt{extraconfig} !~ m/^([GWDN]!)?([\w\-]+,\d+,\d+(?:,(?:ok|warning|critical)(?:,\w+,\d+,\d+)*)?:)+$/ ) {
 	unknown_error("Wrong usage of '--extraconfig' option: '"
 		      . $opt{extraconfig}
 		      . "' syntax error. See help information.");
     } # if
 
-    while ( $opt{extraconfig} =~ m!([\w\-]+),(\d+),(\d+)(?:,(ok|warning|critical))?:+!g ) {
-	my $name =$1;
-	my $crit =$2;
-	my $warn =$3;
-	my $ret = $4;
-        my $missingRet=$E_WARNING;
+    #print "EXTRA-Param '$opt{extraconfig}'\n";
+    while ( $opt{extraconfig} =~ m/(?:([GWDN])!)?([\w\-]+),(\d+),(\d+)(?:,(ok|warning|critical)(?:,([\w\d,]+))?)?:+/g ) {
+        my $attribute   = $1;
+	my $attribValue = $2;
+	my $crit        = $3;
+	my $warn        = $4;
+	my $ret         = $5;
+	my $addchecks   = $6;
+        my $missingRet  = $E_WARNING;                          # set default
 	
-	if ( defined($ret) ) {
+	if ( defined($ret) ) {                                 # if retcode is given: convert and store
 	    $missingRet=$text2exit{$ret};
-	}
-	#print "EXTRA: $name, c=$crit, w=$warn, m=$missingRet, '$ret'\n";
+	} else {
+	    $ret = '#UNDEF#';
+	} # if
+	if ( !defined($addchecks) ) {
+	    $addchecks = '';
+	} # if
+	if ( !defined($attribute) ) {
+	    $attribute = 'G';                                  # DEFAULT: generic Name
+	} # if
+
+	#print "EXTRA: attrib='$attribute', val='$attribValue', c=$crit, w=$warn, m=$missingRet, '$ret', addchecks='$addchecks'\n";
 
 	if ($crit > $warn) {
 	    unknown_error("Error in '--extraconfig' option '"
 			  . $opt{extraconfig}
-			  . "' for LUN '$name': critical threshold ($crit) must not be higher than warning threshold ($warn).");
+			  . "' for LUN selector '".$attribute.'!'.$attribValue."': critical threshold ($crit) must not be higher than warning threshold ($warn).");
 	} # if
 
-	$extraconfig{$name} = {'warn' => $warn, 'crit' => $crit, 'missingRet' => $missingRet, 'found' => 0 };
+	my $rHash = getNewAddCheckHash ();             # initialise with default
+	getAddChecks( $addchecks, $rHash, "Parameter '--extraconfig'; " );
+	push ( @extraconfig, {'attrib' => $attribute, 'val' =>$attribValue, 'warn' => $warn, 'crit' => $crit, 'missingRet' => $missingRet, 'addchecks' => $rHash, 'found' => 0 });
     } # while 
 } # if
 
@@ -804,11 +997,11 @@ sub report {
 sub unknown_error {
     my $msg = shift;
 		
-    my $hostname = qx('hostname');           # add hostname to error message
-    chomp $hostname;
     if ($opt{"test"}) {
 	print "ERROR: $msg |TESTCASE|\n";
     } else {
+	my $hostname = qx('hostname');           # add hostname to error message
+	chomp $hostname;
 	print "ERROR: $msg |Host: $hostname|\n";
     }
     exit $E_UNKNOWN;
@@ -816,6 +1009,29 @@ sub unknown_error {
 
 #---------------------------------------
 #
+# get attribute to print from LUN data
+#
+sub getLunPrintName {
+    my ( $rLunDef ) = @_;
+
+    my $lunPrintName = 'UNDEF';
+    my $displayPrio   = $opt{'print'};
+    for(my $i = 0; $i < length($displayPrio); $i++) {  # all characters in prio-string
+	my $c = substr ($displayPrio, $i, 1);
+	#print "i=$i, c='$c'\n";
+	if ($$rLunDef{$c}) {                          # first non-empty attribute wins
+	    $lunPrintName = $$rLunDef{$c};
+	    #print "FOUND: $lunPrintName i=$i, c='$c'\n";
+	    last;
+	} # if
+    } # for
+
+    return $lunPrintName;
+} # sub
+
+
+#---------------------------------------
+#
 # get output of multipath -l
 # or debug input (testcase)
 #
@@ -885,38 +1101,70 @@ sub checkLunLine {
     my ($textLine, $rCurrentLun, $rLunData) = @_;
     #print "checkLunLine: '$textLine'\n";
 
+    my $idGeneric = '';
+    my $idWWID    = '';
+    my $idDm      = '';
+    my $idName    = '';
+
     # mpathb (36000d774000045f655ea91cb4ea41d6f) dm-1 FALCON,IPSTOR DISK
     # mpathb (36000d774000045f655ea91cb4ea41d6f) dm-1 
     # MYVOLUME (36005076801810523100000000000006f)
     # tex-lun4 (3600000e00d0000000002161200120000) dm-7 FUJITSU ,ETERNUS_DXL
     # fc-p6-vicepb (1Proware_FF010000333001EC) dm-1 Proware,R_laila            thanks to Michal Svamberg
-    if ($textLine =~ m/^([\w\-]+) \s+ \([\w\-]+\)/x) {
+    #if ($textLine =~ m/^([\w\-]+) \s+ \([\w\-]+\)/x) {
+    if ($textLine =~ m/^([\w\-]+) \s+ \(([\w\-]+)\) (?: \s+ ([\w\-]+))?/x) {
 	$$rCurrentLun = $1;
-	#report("named LUN $$rCurrentLun found", $E_OK);
+	$idGeneric    = $1;
+	$idName       = $1;
+	$idWWID       = $2;
+	$idDm         = $3;
+	
+	if ( !defined($idDm) ) {
+	    $idDm ='';
+	}
+	#report("named LUN $$rCurrentLun found, G='$idGeneric', W='$idWWID', D='$idDm', N='$idName'", $E_OK);
     } 
     # 36006016019e02a00d009495ddbf3e011 dm-2 DGC,VRAID
-    elsif ($textLine =~ m/^[0-9a-fA-F]+ \s+ ([\w\-\_]+)/x) {
-	$$rCurrentLun = $1;
-	#report("simple (1) LUN $$rCurrentLun found", $E_OK);
+    # 360a98000503361754b5a58724f6f7a59 dm-2 NETAPP  ,LUN
+    # 360a98000503361754b5a58724f6f7a59 dm-2 NETAPP  ,LUN C-Mode
+    #elsif ($textLine =~ m/^[0-9a-fA-F]+ \s+ ([\w\-\_]+)/x) {
+    elsif ($textLine =~ m/^([0-9a-fA-F]+) \s+ ([\w\-\_]+)/x) {
+	$$rCurrentLun = $2;
+	$idGeneric    = $2;
+	$idWWID       = $1;
+	$idDm         = $2;
+	#report("simple (1) LUN $$rCurrentLun found, G='$idGeneric', W='$idWWID', D='$idDm', N='$idName'", $E_OK);
     } 
     # 360a98000503361754b5a58724f6f7a59dm-2 NETAPP  ,LUN
-    elsif ($textLine =~ m/^[0-9a-fA-F]{3,33} \s* ([\w\-\_]+) \s+/x) {
-	$$rCurrentLun = $1;
-	#report("simple (2) LUN $$rCurrentLun found", $E_OK);
+    #elsif ($textLine =~ m/^[0-9a-fA-F]{3,33} \s* ([\w\-\_]+) \s+/x) {    
+    elsif ($textLine =~ m/^([0-9a-fA-F]{33}) ([\w\-]+) \s+ ([\w\-\_]+)/x) {
+	$$rCurrentLun = $2;
+	$idGeneric    = $2;
+	$idWWID       = $1;
+	$idDm         = $2;
+	#report("simple (2) LUN $$rCurrentLun found, G='$idGeneric', W='$idWWID', D='$idDm', N='$idName'", $E_OK);
     } 
     # iscsi-LUN example
     # 1STORAGE_server_target2 dm-2 IET,VIRTUAL-DISK
-    #elsif ($textLine =~ m/^([\w\-]+) \s+ [a-z]+\-\d+/x) {
-    elsif ($textLine =~ m/^([\w\-]+) \s+ [a-z]+\-\d+ \s+ [\w\-\,]+/x) {
+    #elsif ($textLine =~ m/^([\w\-]+) \s+ [a-z]+\-\d+ \s+ [\w\-\,]+/x) {
+    elsif ($textLine =~ m/^([\w\-_]+) \s+ ([\w\-]+) \s+ [\w\-\_]+/x) {
 	$$rCurrentLun = $1;
-	#report("LUN without HEX-ID $$rCurrentLun found", $E_OK);
+	$idGeneric    = $1;
+	$idName       = $1;
+	$idDm         = $2;
+	
+	#report("LUN without WWID $$rCurrentLun found, G='$idGeneric', W='$idWWID', D='$idDm', N='$idName'", $E_OK);
     }
     else {
 	return 0;   ## Not a LUN line, stop here and return zero
     } # if
 
     # initialise data of found LUN
-    ${$rLunData}{$$rCurrentLun} = { 'paths' => 0, 'lunline' => $textLine };
+    ${$rLunData}{$$rCurrentLun} = { 'paths' => 0, 'policies' => 0,
+				    'lunline' => $textLine, 
+				    'G' => $idGeneric, 'W' => $idWWID, 'D' => $idDm, 'N' => $idName, 
+				    'sh-hash' => {}, 'si-hash' => {}
+    };
     return 1;
 } # sub
 
@@ -926,7 +1174,7 @@ sub checkLunLine {
 # check if text is a policy description line
 #
 sub checkPolicyLine {
-    my ($textLine) = @_;
+    my ($textLine, $currentLun, $rLunData) = @_;
     #print "checkPolicyLine: '$textLine'\n";
 
     # `-+- policy='round-robin 0' prio=-1 status=active
@@ -937,6 +1185,8 @@ sub checkPolicyLine {
     # _ round-robin 0  active 
     #if ( $textLine =~ m/^[|\`\-\+_\s]+ \s+ (?:policy=\')?[\w\.\-\_]+ \s \d(?:\')? \s+ prio=/x ) {
     if ( $textLine =~ m/^[|\`\-\+_\s]+ \s+ (?:policy=\')?[\w\.\-\_]+ \s \d(?:\')? \s+ \w+/x ) {
+	${$$rLunData{$currentLun}}{'policies'}++;
+      #print "checkPolicyLine: found policy no. ".${$$rLunData{$currentLun}}{'policies'}."\n";
 	return 1;
     } else {
 	return 0;
@@ -960,10 +1210,8 @@ sub checkMultipathText {
     foreach my $textLine (@$rTextArray) {
 	$i++;
 	#print "$i:\n";
-	switch($state) {
-                                                                 # initial state: look for path state, new LUN Name, policy
-	    case "pathDesc"
-	    { 	                                                 # check for path status line
+	if ($state eq 'pathDesc') {                              # initial state: look for path state, new LUN Name, policy
+	     	                                                 # check for path status line
 		#  |- 3:0:0:1 sdf 8:80  active undef running 
                 ## \_ 3:0:1:1 sde 8:64  [active][undef]
                 ##  _ 3:0:1:1 sde 8:64   active  undef 
@@ -976,47 +1224,65 @@ sub checkMultipathText {
 		#  (thanks to Ben Evans)
                 #  `- #:#:#:# - #:#  active undef running
 
-	        #if ( $textLine =~ m/^[\s_\|\-\`\\\+]+ [\d\:]+ \s+ (\w+) \s+ [\d\:]+ \s+ \w+ \s+ \w+/xi ) {
-                if ( $textLine =~ m/^[\s_\|\-\`\\\+]+ [#\d\:]+ \s+ ([\w\-]+) \s+ [#\d\:]+ \s+ \w+/xi ) { 
-		    my $pathName   = $1;
-		    #print "'$textLine', ";
-		    #print "LUN '$currentLun', path '$pathName'\n";
+               #if ( $textLine =~ m/^[\s_\|\-\`\\\+]+ [#\d\:]+ \s+ ([\w\-]+) \s+ [#\d\:]+ \s+ \w+/xi ) { 
+                if ( $textLine =~ m/^[\s_\|\-\`\\\+]+ ([#\d]+):[#\d]+:([#\d]+):[#\d]+ \s+ ([\w\-]+) \s+ [#\d\:]+ \s+ \w+/xi ) { 
+		    my $sh         = $1;
+		    my $si         = $2;
+		    my $pathName   = $3;
+		    my $ok         = 0;
+		    
+		    my $rLunData   = $lunData{$currentLun};
+
+		    #print "pathDesc: [$textLine], ";
+		    #print "LUN '$currentLun', path '$pathName', sh='$sh', si='$si'\n";
 
 		    if ($textLine =~ m/fail|fault|offline|shaky/) {     # fail or fault, offline or shaky?
 			#print "ERROR: $textLine\n";
-			report("LUN $currentLun, path $pathName: ERROR.", $E_WARNING);
+			report("LUN ".getLunPrintName ($rLunData).", path $pathName: ERROR.", $E_WARNING);
 		    } 
 		    elsif ($textLine !~ m/\sactive\s/) {         # path is active?
 			#print "NOT active: $textLine\n";
-			report("LUN $currentLun, path $pathName: NOT active.", $E_WARNING);
+			report("LUN ".getLunPrintName ($rLunData).", path $pathName: NOT active.", $E_WARNING);
 		    }
 		    elsif ($pathName eq "-") {                   # empty path name => path is missing (thanks to Ben Evans)
-			report("LUN $currentLun: missing path (empty path name)", $E_WARNING);
+			report("LUN ".getLunPrintName ($rLunData).": missing path (empty path name)", $E_WARNING);
 		    }
 		    else {
 			if ( $currentLun eq "") {                # YES => check logic, increase path count for LUN
 			     unknown_error ("Path info before LUN name. Line $i:\n'$textLine'")
 			}
-			${$lunData{$currentLun}}{'paths'}++;
+			$$rLunData{'paths'}++;
+			$ok =1;
 		    } # if
-		}                                               # check for new LUN name
+
+		    
+		    if ( $ok || $opt{'scsi-all'}) {              # if path is OK or ALL paths are to be counted
+			if ($sh =~ m!^\d+$! ) {
+			    ${$$rLunData{'sh-hash'}}{$sh}=1;     # store scsi-host as hash key
+			} # if
+
+			if ($si =~ m!^\d+$! ) {
+			    ${$$rLunData{'si-hash'}}{$si}=1;     # store scsi-id as hash key
+			} # if
+		    } # if
+		}                                                # check for new LUN name
 		elsif ( checkLunLine ($textLine, \$currentLun, \%lunData) ) {
 		    $state="lunInfo";
-		}                                               # check for new LUN name
-		elsif ( ($currentLun ne "") && checkPolicyLine ($textLine) ) {
+		}                                                # check for new LUN name
+		elsif ( ($currentLun ne "") && checkPolicyLine ($textLine, $currentLun, \%lunData) ) {
 		   ; # SKIP NESTED POLICY 
 		} 
 		elsif ( $textLine =~ m/checker msg is /) {
 		    ; # SKIP tur message stuff
 		}
-		else {                                        # error: unknown line format
+		else {                                           # error: unknown line format
 		    unknown_error ("Line $i not recognised. Expected path info, new LUN or nested policy:\n'$textLine'")
 		}
             } # case
 
 	    # after new LUN was found skip the INFO-Line (nothing else...)
-	    case "lunInfo" {
-		if ( $currentLun eq "" ) {                      # check logic
+	    elsif ($state eq 'lunInfo') {
+		if ( $currentLun eq "" ) {                       # check logic
 		    unknown_error ("No current LUN while looking for LUN info. Line $i:\n'$textLine'")
 		}
 		# size=2.0T features='1 queue_if_no_path' hwhandler='0' wp=rw
@@ -1028,19 +1294,19 @@ sub checkMultipathText {
                #if ($textLine =~ m/^\s*size=[\w\.]+\s+features=/x) {
                 if ($textLine =~ m/^\s*size=[\w\.]+\s+ ([a-zA-Z]+\s+)? features=/x) {
 		    $state = "pathPolicy";
-		} else {                                        # error: unknown line format
+		} else {                                         # error: unknown line format
 		    unknown_error ("Line $i not recognised. Expected LUN info:\n'$textLine'")
 		}
 	    } # case
 
 	    # after LUN info was found skip the path policy (nothing else...)
             # or handle new LUN if no paths available
-	    case "pathPolicy" {
+	    elsif ($state eq 'pathPolicy') {
 		if ( $currentLun eq "") {                       # check logic
 		    unknown_error ("No current LUN while looking for path policy. Line $i:\'$textLine'")
 		}
 
-                if ( checkPolicyLine ($textLine) ) {
+                if ( checkPolicyLine ($textLine, $currentLun, \%lunData)) {
 		    $state = "pathDesc";
 		}                                               # new LUN found
 		elsif ( checkLunLine ($textLine, \$currentLun, \%lunData) ) {
@@ -1048,13 +1314,59 @@ sub checkMultipathText {
 		} else {                                        # error: unknown line format
 		    unknown_error ("Line $i not recognised. Expected path policy or new LUN:\n'$textLine'")
 		}
-	    } # case
-	} # switch
+	    }
+	    else {
+		unknown_error ("Internal error: unknown state '$state' of parser")
+	    } # if
     } # foreach
 
     return \%lunData
 } # sub
 
+
+
+#---------------------------------------
+#
+# test value
+#
+sub testValue {
+    my ($val, $low, $high, $lunPrintName, $txtErr, $txtOk) = @_;
+    
+    if ( !defined($txtOk) ) {
+	$txtOk = '';
+    } elsif ($txtOk ne '')  {
+	$txtOk .= ' ';
+    } #if
+
+    #print "TEST val='$val', low='$low', high='$high', LUN='$lunPrintName', txtErr='$txtErr', txtOk='$txtOk'\n";
+
+    if ($val < $low){
+	report("LUN $lunPrintName: less than $low $txtErr ($val/$high)!", $E_CRITICAL);
+    } elsif ($val < $high){
+	report("LUN $lunPrintName: less than $high $txtErr ($val/$high).", $E_WARNING);
+    } else {
+	report("LUN $lunPrintName: $txtOk$val/$high.", $E_OK);
+    } # if 
+} # sub
+
+#---------------------------------------
+#
+# test additional checks
+#
+sub testAddChecks {
+    my ($rDefHash, $rValueHash, $lunPrintName) = @_;
+
+    foreach my $id (sort keys %{$rDefHash} ) {
+	my $rDefArr = $$rDefHash{$id};
+
+	if ($$rDefArr[1] > 0 ) {                                  # high mark 0 => NO check
+	    testValue ($$rValueHash{$id}, $$rDefArr[0], $$rDefArr[1], $lunPrintName, $addCheckNames{$id}, $addCheckNames{$id});
+	} else {
+	   #print "SKIP $$rValueHash{$id}, $$rDefArr[0], $$rDefArr[1], $lunPrintName, $addCheckNames{$id}, $addCheckNames{$id} \n"  
+	}# if
+    } # foreach
+} # sub
+
 #=====================================================================
 # Main program
 #=====================================================================
@@ -1079,6 +1391,12 @@ if ( !$opt{'mdskip'} ) {                                         # check is not
 } # if
 
 
+if ( ($opt{'di'} == 0) && ($multipathCmd eq '') ) {
+    # No testcase called and no multipath binary found
+    unknown_error ("No multipath binary found. Unable to perform check.");
+} # if
+
+
 my $mpListCmd = $MULTIPATH_LIST;
 if ($opt{'ll'}) {
     $mpListCmd = $MULTIPATH_LIST_LONG;
@@ -1099,48 +1417,67 @@ if (scalar keys %lunData == 0) {
 # Check path count for each LUN
 #
 foreach my $lunName ( sort {$a cmp $b} keys %lunData) {
-    my $rLunDef   = $lunData{$lunName};
-    my $pathCount = $$rLunDef{'paths'};
-    my $lunLine   = $$rLunDef{'lunline'};
-
-    my $warn = $opt{'ok-paths'};
-    my $crit = $opt{'min-paths'};
-
-    # 	$extraconfig{$name} = {'warn' => $warn, 'crit' => $crit};
-    if (defined ($extraconfig{$lunName}) ) {       # deviant thresholds for THIS LUN from options?
-	$warn = ${$extraconfig{$lunName}}{'warn'};
-	$crit = ${$extraconfig{$lunName}}{'crit'};
-	#print "$lunName: $pathCount  EXTRA: crit=$crit, warn=$warn\n";
-	${$extraconfig{$lunName}}{'found'} = 1;
-    } else {	                                   # LUN-Line matches a group definition?
-	foreach my $rGroupDef ( @group ) {
+    my $rLunDef        = $lunData{$lunName};
+    my $pathCount      = $$rLunDef{'paths'};
+    my $policiesCount  = $$rLunDef{'policies'};
+    my $lunLine        = $$rLunDef{'lunline'};
+
+    my $warn           = $opt{'ok-paths'};
+    my $crit           = $opt{'min-paths'};
+
+    my $rAddChecks     = \%addChecks;  # initialise with default
+
+    # Get the LUN-ID to be displayed, a 'G' in appended to the option-string at parameter check
+    my $lunPrintName = getLunPrintName ($rLunDef);
+
+    # check if an extraconfig entry matches
+    my $extraconfigMatched = 0;
+    foreach my $rExtraConf( @extraconfig ) {
+	if ( $$rExtraConf{'val'} eq $$rLunDef{$$rExtraConf{'attrib'}}) {
+	    $warn    = $$rExtraConf{'warn'};
+	    $crit    = $$rExtraConf{'crit'};
+
+	    $rAddChecks = $$rExtraConf{'addchecks'};
+	    $$rExtraConf{'found'} = 1;
+	    $extraconfigMatched   = 1;
+	    #print "EXTRA: ".$$rExtraConf{'attrib'}."!".$$rExtraConf{'val'}." c=$crit w=$warn \n";
+	    last;
+	} # if
+    } # foreach
+
+    if ( !$extraconfigMatched ) {                  # NO extaconfig entry matched
+	foreach my $rGroupDef ( @group ) {         # LUN-Line matches a group definition?
 	    my $regex = ${$rGroupDef}{'regex'};
 	    #print "GRP: '$regex'\n";
 	    if ($lunLine =~ m!$regex! ) {
-		$warn = ${$rGroupDef}{'warn'};
-		$crit = ${$rGroupDef}{'crit'};
-		#print "GRP: '$regex' MATCH: c=$crit w=$warn \n";
+		$warn    = ${$rGroupDef}{'warn'};
+		$crit    = ${$rGroupDef}{'crit'};
+		$rAddChecks = ${$rGroupDef}{'addchecks'};
+		#print "GRP: '$regex' MATCH: c=$crit w=$warn\n";
 		last;
-	    }
+	    } # if
 	} # foreach
     }# if
+
+    #print "LUN '$lunPrintName'\n";
     
-    if ($pathCount < $crit){
-	report("LUN $lunName: less than $crit paths ($pathCount/$warn)!", $E_CRITICAL);
-    } elsif ($pathCount < $warn){
-	report("LUN $lunName: less than $warn paths ($pathCount/$warn).", $E_WARNING);
-    } else {
-	report("LUN $lunName: $pathCount/$warn.", $E_OK);
-    }
+    testValue ($pathCount, $crit, $warn, $lunPrintName, 'paths', '' );
+
+    my %addCheckValues = ( 
+	'sh' => scalar( keys %{$$rLunDef{'sh-hash'}}), 
+	'si' => scalar( keys %{$$rLunDef{'si-hash'}}), 
+	'p' => $policiesCount 
+	);
+    testAddChecks ( $rAddChecks, \%addCheckValues, $lunPrintName);
 } # foreach
 
 
 #
 # Check if all LUNs in extraconfig were found
 #
-foreach my $lunName ( keys %extraconfig ) {
-    if (! ${$extraconfig{$lunName}}{'found'} ) {
-	report("LUN '$lunName' in extraconfig, but NO DATA found.",${$extraconfig{$lunName}}{'missingRet'} );
+foreach my $rExtraConf ( @extraconfig ) {
+    if (! $$rExtraConf{'found'} ) {
+	report("NO DATA found for extra-config LUN selector '". $$rExtraConf{'attrib'}.'!'.$$rExtraConf{'val'}."'", $$rExtraConf{'missingRet'} );
     }
 } # foreach
 
@@ -1216,4 +1553,4 @@ if ( ($exit_code != $E_OK) && $opt{'reload'}  ){
 print $linebreak;
 #print "$exit_code\n";
 # Exit with proper exit code
-exit $exit_code; 
+exit $exit_code;
diff --git a/check_multipath/control b/check_multipath/control
index 1986c04..264d554 100644
--- a/check_multipath/control
+++ b/check_multipath/control
@@ -1,5 +1,5 @@
 Watch: http://exchange.nagios.org/directory/Plugins/Operating-Systems/Linux/check-2Dmultipath-2Epl/details Current Version</div><div class="data">([0-9.]+)</div>
-Version: 0.4.1
+Version: 0.4.7
 Homepage: http://exchange.nagios.org/directory/Plugins/Operating-Systems/Linux/check-2Dmultipath-2Epl/details
 Uploaders: Bernd Zeimetz <bzed at debian.org>
 Description: plugin to monitor the number of available and

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-nagios/pkg-nagios-plugins-contrib.git



More information about the Pkg-nagios-changes mailing list