#!/usr/bin/perl -w

# ---

=head1 NAME

check_programmingmode.pl - Nagios plugin for checking programmingmode of eib/knx nodes

=head1 SYNOPSIS

=over 4

=item check_programmingmode.pl -U url -E EIB/KNX-address [-v] [-w warning_threshold] [-c critical_threshold]

=item check_programmingmode.pl [-h|-V]

=back

=head1 OPTIONS

=over 4

=item -E|--eibraddr=expression

Physical EIB/KNX address e.g. 1.1.1

=item -U|--url=expression

BCU-Connection to EIB/KNX-Bus, e.g. ip:127.0.0.1

=item -w|--warning=threshold

threshold can be max (warn if < 0 or > max), min:max (warn if < min or >
max), min: (warn if < min), or @min:max (warn if >= min and <= max). All
values must be integer.

=item -c|--critical=threshold

see --warning for explanation of threshold format

=item -t|--timeout=seconds

timeout after check_programmingmode exits.

=item -v|--verbose

increases verbosity, specify twice to see the original output.

=item -V|--version

print version an exit

=item -h|--help

print help message and exit

=back

=cut
use strict;                             # strict syntax usage, predeclared Vars
use warnings;                           # for perl versions lesser than 5.6
use FindBin;                            # find path from this plugin
use lib "$FindBin::Bin/../perl/lib";
use Nagios::Plugin;                     # with const, vars and functions
use Getopt::Long qw(:config no_ignore_case bundling);   # Get options 
                                                        # case-sensitive
                                                        # bundled options
use Pod::Usage;                         # Perl Online Dokumentation (POD)
#use Test::More tests => 6;             # Testing Module for development

### Variables ################################################################
my $np = Nagios::Plugin->new(shortname => "PROGRAMMINGMODE");  # Crea Nag. Obj.
my $warn_threshold = '0:';
my $crit_threshold = '0:';
my $what = '';
my $result = UNKNOWN;
my $version = 'V1.0/2010-07-01';
my $printversion = 0;
my $verbose = 0;
my $help = 0;
my $timeout = 10;  # 10s by default
my $debug = 0;
my $progmode = '';
my $url = '';
my $progmodestatus = 2;
##############################################################################

GetOptions(
   "E|eibaddr=s"	=> \$what,		# =s string type
   "w|warnings=s"	=> \$warn_threshold,
   "c|critical=s"	=> \$crit_threshold,
   "t|timeout=s"	=> \$timeout,
   "h|help"		=> \$help,
   "V|version"		=> \$printversion,
   "v|verbose+"		=> \$verbose,		# Option can set multiple
   "d|debug:+"		=> \$debug,
   "U|url=s"		=> \$url		# e.g ip:127.0.0.1
) or pod2usage({ -exitval => UNKNOWN,
                 -verbose => 0,
                 -msg     => "*** unknown argument found ***" });

pod2usage(-verbose => 2,
          -exitval => UNKNOWN,
	  -output  => \*STDOUT,
         ) if ( $help );

pod2usage(-msg     => "\n$0 -- version: $version\n",
          -verbose => 0,
          -exitval => UNKNOWN,
         ) if ( $printversion );

pod2usage(-msg     => "*** no eibaddr and/or url specified ***",
          -verbose => 0,
          -exitval => UNKNOWN,
	) unless ($what && $url);

if ( $debug >= 2 ) {                               # Debug Information
        print "Plugin options:\n";
        printf "    %-23s %d\n", "verbose:", $verbose;
        printf "    %-23s %s\n", "warning:", $warn_threshold || '';
        printf "    %-23s %s\n", "critical:", $crit_threshold || '';
        printf "    %-23s %s\n", "timeout:", $timeout || '';
        printf "    %-23s %s\n", "eibaddr:", $what || '';
        printf "    %-23s %s\n", "debug:", $debug || '';
        printf "    %-23s %s\n", "url:", $url || '';
        printf "    %-23s %s\n", "version:", $version || '';
}

# set timeout alarm
$SIG{ALRM} = sub { $np->nagios_die("Timeout reached"); }; # Return: UNKNOWN
alarm($timeout);

# allocate thresholds
$np->set_thresholds(
   warning  => $warn_threshold,         # Option -w to warn_threshold
   critical => $crit_threshold          # Option -c to crit_threshold
);

# Debug-Information about threshold values
print "DEBUG: warn= $warn_threshold, crit= $crit_threshold\n" if ($debug);

# The core programm call
open ( OUT, "LANG=C /usr/bin/progmodestatus $url $what 2>&1 |" ) # open output
   or $np->nagios_die( "can't start /usr/bin/progmodestatus");	# LANG=C for Eng	
while (<OUT>) {				# While output is there
   print "$_" if ($verbose);		# if verbose, print current line
   chomp $_;				# cut current textline
   
   $progmode = $_;

   if ($_ eq "in programming mode") 	# if "in programming mode"
   {
      $progmodestatus = 1;
      last;
   }
   elsif ($_ eq "not in programming mode") # if "not in programming mode"
   {
      $progmodestatus = 0;
      last; 
   }
   else
   {
      $np->nagios_exit( CRITICAL, "cannot read programming mode value");
      last;
   }
}
close (OUT);

# Debug-Messages
if ($debug >= 2)
{
        printf "    %-23s %d\n", "progmodestatus:", $progmodestatus;
}


# Performance-Data
$np->add_perfdata( label => "progmode", value => $progmodestatus, 
                   uom => "", threshold => $np->threshold() # No Unit
);

# Compare the actual value with the threshold
$result = $np->check_threshold(  $progmodestatus );

# Reset alarm
alarm(0);

# Return exit-code
$np->nagios_exit( $result, "$progmode ($progmodestatus)"); 

=head1 EXAMPLES

=head2 Command line example

Check the programming mode of the EIB/KNX-Bus at an EIB/KNX-Device over IP-Gateway:

$ check_voltage.pl -E 1.1.1 -U ip:127.0.0.1 

PROGRAMMINGMODE OK - not in programmingmode (0)

=head2 Nagios configuration example

 define command {
   command_name   check_programmingmode
   command_line   $USER1$/check_programmingmode.pl --eibaddr $HOSTADDRESS$ --url                  $ARG1$ -w $ARG2$ -c $ARG3$
 }

 define service {
   host_name            1.1.1:_Switch
   service_description  ProgrammingMode
   check_command        check_programmingmode!ip:127.0.0.1!@1:!~:1
   use                  generic-service
}

Warning will be set, if the programming mode is on (1), otherwise the programmingmode is off (0), which means ok. All other values are critical. 

 define host {
   use                   generic-node            ; Name of host template
   host_name             1.1.1:_Switch
   alias                 Switch 1.1.1
   address               1.1.1
 }

The pysical Address of the EIB/KNX-Device is defined as regular address.

=head1 NAGIOS PLUGIN NOTES

Nagios plugin reference: http://nagiosplug.sourceforge.net/developer-guidelines.html

This plugin does NOT use Nagios DEFAULT_SOCKET_TIMEOUT (provided by utils.pm as $TIMEOUT) because the path to utils.pm must be specified completely in this program and forces users to edit the source code if their install location is different (if they realize this is the problem). The utils.pm will be deprecated soon and using the Nagios::Plugin from CPAN is recommanded. You can view the default timeout for this module by using the -vv option. 

Other than that, it attempts to follow published guidelines for Nagios plugins.


=head1 AUTHOR

Sebastian Renker, <sebastian.renker@stud.fh-erfurt.de>

=head1 KNOWN ISSUES

none

=head1 BUGS

none

=head1 LICENSE

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License (and no
later version).

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

=head1 HISTORY

V1.1/2010-07-01 following nagios plugin development guidelines
V1.0/2010-05-07 inital version for bachelor thesis

=cut
