diff options
Diffstat (limited to 'puppet/modules/nagios/files')
38 files changed, 8454 insertions, 0 deletions
| diff --git a/puppet/modules/nagios/files/configs/CentOS/cgi.cfg b/puppet/modules/nagios/files/configs/CentOS/cgi.cfg new file mode 100644 index 00000000..cd625d4c --- /dev/null +++ b/puppet/modules/nagios/files/configs/CentOS/cgi.cfg @@ -0,0 +1,280 @@ +################################################################# +# +# CGI.CFG - Sample CGI Configuration File for Nagios 2.9 +# +# Last Modified: 11-21-2006 +# +################################################################# + + +# MAIN CONFIGURATION FILE +# This tells the CGIs where to find your main configuration file. +# The CGIs will read the main and host config files for any other +# data they might need. + +main_config_file=/etc/nagios/nagios.cfg + + + +# PHYSICAL HTML PATH +# This is the path where the HTML files for Nagios reside.  This +# value is used to locate the logo images needed by the statusmap +# and statuswrl CGIs. + +physical_html_path=/usr/share/nagios/share + + + +# URL HTML PATH +# This is the path portion of the URL that corresponds to the +# physical location of the Nagios HTML files (as defined above). +# This value is used by the CGIs to locate the online documentation +# and graphics.  If you access the Nagios pages with an URL like +# http://www.myhost.com/nagios, this value should be '/nagios' +# (without the quotes). + +url_html_path=/nagios + + + +# CONTEXT-SENSITIVE HELP +# This option determines whether or not a context-sensitive +# help icon will be displayed for most of the CGIs. +# Values: 0 = disables context-sensitive help +#         1 = enables context-sensitive help + +show_context_help=0 + + + +# NAGIOS PROCESS CHECK COMMAND +# This is the full path and filename of the program used to check +# the status of the Nagios process.  It is used only by the CGIs +# and is completely optional.  However, if you don't use it, you'll +# see warning messages in the CGIs about the Nagios process +# not running and you won't be able to execute any commands from +# the web interface.  The program should follow the same rules +# as plugins; the return codes are the same as for the plugins, +# it should have timeout protection, it should output something +# to STDIO, etc. +# +# Note: The command line for the check_nagios plugin below may +# have to be tweaked a bit, as different versions of the plugin +# use different command line arguments/syntaxes. + +#nagios_check_command=/usr/lib64/nagios/plugins/check_nagios /var/log/nagios/status.dat 5 '/usr/sbin/nagios' + + + +# AUTHENTICATION USAGE +# This option controls whether or not the CGIs will use any  +# authentication when displaying host and service information, as +# well as committing commands to Nagios for processing.   +# +# Read the HTML documentation to learn how the authorization works! +# +# NOTE: It is a really *bad* idea to disable authorization, unless +# you plan on removing the command CGI (cmd.cgi)!  Failure to do +# so will leave you wide open to kiddies messing with Nagios and +# possibly hitting you with a denial of service attack by filling up +# your drive by continuously writing to your command file! +# +# Setting this value to 0 will cause the CGIs to *not* use +# authentication (bad idea), while any other value will make them +# use the authentication functions (the default). + +use_authentication=1 + + + +# DEFAULT USER +# Setting this variable will define a default user name that can +# access pages without authentication.  This allows people within a +# secure domain (i.e., behind a firewall) to see the current status +# without authenticating.  You may want to use this to avoid basic +# authentication if you are not using a secure server since basic +# authentication transmits passwords in the clear. +# +# Important:  Do not define a default username unless you are +# running a secure web server and are sure that everyone who has +# access to the CGIs has been authenticated in some manner!  If you +# define this variable, anyone who has not authenticated to the web +# server will inherit all rights you assign to this user! +  +#default_user_name=guest + + + +# SYSTEM/PROCESS INFORMATION ACCESS +# This option is a comma-delimited list of all usernames that +# have access to viewing the Nagios process information as +# provided by the Extended Information CGI (extinfo.cgi).  By +# default, *no one* has access to this unless you choose to +# not use authorization.  You may use an asterisk (*) to +# authorize any user who has authenticated to the web server. + +#authorized_for_system_information=nagiosadmin,theboss,jdoe +authorized_for_system_information=admin + +# CONFIGURATION INFORMATION ACCESS +# This option is a comma-delimited list of all usernames that +# can view ALL configuration information (hosts, commands, etc). +# By default, users can only view configuration information +# for the hosts and services they are contacts for. You may use +# an asterisk (*) to authorize any user who has authenticated +# to the web server. + +#authorized_for_configuration_information=nagiosadmin,jdoe +authorized_for_configuration_information=admin + + + +# SYSTEM/PROCESS COMMAND ACCESS +# This option is a comma-delimited list of all usernames that +# can issue shutdown and restart commands to Nagios via the +# command CGI (cmd.cgi).  Users in this list can also change +# the program mode to active or standby. By default, *no one* +# has access to this unless you choose to not use authorization. +# You may use an asterisk (*) to authorize any user who has +# authenticated to the web server. + +#authorized_for_system_commands=nagiosadmin +authorized_for_system_commands=admin + + + +# GLOBAL HOST/SERVICE VIEW ACCESS +# These two options are comma-delimited lists of all usernames that +# can view information for all hosts and services that are being +# monitored.  By default, users can only view information +# for hosts or services that they are contacts for (unless you +# you choose to not use authorization). You may use an asterisk (*) +# to authorize any user who has authenticated to the web server. + + +#authorized_for_all_services=nagiosadmin,guest +authorized_for_all_services=admin +#authorized_for_all_hosts=nagiosadmin,guest +authorized_for_all_hosts=admin + + + +# GLOBAL HOST/SERVICE COMMAND ACCESS +# These two options are comma-delimited lists of all usernames that +# can issue host or service related commands via the command +# CGI (cmd.cgi) for all hosts and services that are being monitored.  +# By default, users can only issue commands for hosts or services  +# that they are contacts for (unless you you choose to not use  +# authorization).  You may use an asterisk (*) to authorize any +# user who has authenticated to the web server. + +#authorized_for_all_service_commands=nagiosadmin +authorized_for_all_service_commands=admin +#authorized_for_all_host_commands=nagiosadmin +authorized_for_all_host_commands=admin + + + + +# STATUSMAP BACKGROUND IMAGE +# This option allows you to specify an image to be used as a  +# background in the statusmap CGI.  It is assumed that the image +# resides in the HTML images path (i.e. /usr/local/nagios/share/images). +# This path is automatically determined by appending "/images" +# to the path specified by the 'physical_html_path' directive. +# Note:  The image file may be in GIF, PNG, JPEG, or GD2 format. +# However, I recommend that you convert your image to GD2 format +# (uncompressed), as this will cause less CPU load when the CGI +# generates the image. + +#statusmap_background_image=smbackground.gd2 + + + +# DEFAULT STATUSMAP LAYOUT METHOD +# This option allows you to specify the default layout method +# the statusmap CGI should use for drawing hosts.  If you do +# not use this option, the default is to use user-defined +# coordinates.  Valid options are as follows: +#	0 = User-defined coordinates +#	1 = Depth layers +#       2 = Collapsed tree +#       3 = Balanced tree +#       4 = Circular +#       5 = Circular (Marked Up) + +default_statusmap_layout=5 + + + +# DEFAULT STATUSWRL LAYOUT METHOD +# This option allows you to specify the default layout method +# the statuswrl (VRML) CGI should use for drawing hosts.  If you +# do not use this option, the default is to use user-defined +# coordinates.  Valid options are as follows: +#	0 = User-defined coordinates +#       2 = Collapsed tree +#       3 = Balanced tree +#       4 = Circular + +default_statuswrl_layout=4 + + + +# STATUSWRL INCLUDE +# This option allows you to include your own objects in the  +# generated VRML world.  It is assumed that the file +# resides in the HTML path (i.e. /usr/local/nagios/share). + +#statuswrl_include=myworld.wrl + + + +# PING SYNTAX +# This option determines what syntax should be used when +# attempting to ping a host from the WAP interface (using +# the statuswml CGI.  You must include the full path to +# the ping binary, along with all required options.  The +# $HOSTADDRESS$ macro is substituted with the address of +# the host before the command is executed. +# Please note that the syntax for the ping binary is +# notorious for being different on virtually ever *NIX +# OS and distribution, so you may have to tweak this to +# work on your system. + +ping_syntax=/bin/ping -n -U -c 5 $HOSTADDRESS$ + + + +# REFRESH RATE +# This option allows you to specify the refresh rate in seconds +# of various CGIs (status, statusmap, extinfo, and outages).   + +refresh_rate=90 + + + +# SOUND OPTIONS +# These options allow you to specify an optional audio file +# that should be played in your browser window when there are +# problems on the network.  The audio files are used only in +# the status CGI.  Only the sound for the most critical problem +# will be played.  Order of importance (higher to lower) is as +# follows: unreachable hosts, down hosts, critical services, +# warning services, and unknown services. If there are no +# visible problems, the sound file optionally specified by +# 'normal_sound' variable will be played. +# +# +# <varname>=<sound_file> +# +# Note: All audio files must be placed in the /media subdirectory +# under the HTML path (i.e. /usr/local/nagios/share/media/). + +#host_unreachable_sound=hostdown.wav +#host_down_sound=hostdown.wav +#service_critical_sound=critical.wav +#service_warning_sound=warning.wav +#service_unknown_sound=warning.wav +#normal_sound=noproblem.wav + diff --git a/puppet/modules/nagios/files/configs/CentOS/nagios.cfg b/puppet/modules/nagios/files/configs/CentOS/nagios.cfg new file mode 100644 index 00000000..b88e3db7 --- /dev/null +++ b/puppet/modules/nagios/files/configs/CentOS/nagios.cfg @@ -0,0 +1,949 @@ +############################################################################## +# +# NAGIOS.CFG - Sample Main Config File for Nagios 2.10 +# +# Read the documentation for more information on this configuration +# file.  I've provided some comments here, but things may not be so +# clear without further explanation. +# +# Last Modified: 12-21-2006 +# +############################################################################## + + +# LOG FILE +# This is the main log file where service and host events are logged +# for historical purposes.  This should be the first option specified  +# in the config file!!! + +log_file=/var/log/nagios/nagios.log + + + +# OBJECT CONFIGURATION FILE(S) +# This is the configuration file in which you define hosts, host +# groups, contacts, contact groups, services, etc.  I guess it would +# be better called an object definition file, but for historical +# reasons it isn't.  You can split object definitions into several +# different config files by using multiple cfg_file statements here. +# Nagios will read and process all the config files you define. +# This can be very useful if you want to keep command definitions  +# separate from host and contact definitions... + +# Puppet-managed configuration files +cfg_file=/etc/nagios/nagios_templates.cfg +cfg_file=/etc/nagios/nagios_command.cfg +cfg_file=/etc/nagios/nagios_contact.cfg +cfg_file=/etc/nagios/nagios_contactgroup.cfg +cfg_file=/etc/nagios/nagios_host.cfg +cfg_file=/etc/nagios/nagios_hostdependency.cfg +cfg_file=/etc/nagios/nagios_hostescalation.cfg +cfg_file=/etc/nagios/nagios_hostextinfo.cfg +cfg_file=/etc/nagios/nagios_hostgroup.cfg +cfg_file=/etc/nagios/nagios_hostgroupescalation.cfg +cfg_file=/etc/nagios/nagios_service.cfg +cfg_file=/etc/nagios/nagios_servicedependency.cfg +cfg_file=/etc/nagios/nagios_serviceescalation.cfg +cfg_file=/etc/nagios/nagios_serviceextinfo.cfg +cfg_file=/etc/nagios/nagios_servicegroup.cfg +cfg_file=/etc/nagios/nagios_timeperiod.cfg + +# OBJECT CACHE FILE +# This option determines where object definitions are cached when +# Nagios starts/restarts.  The CGIs read object definitions from  +# this cache file (rather than looking at the object config files +# directly) in order to prevent inconsistencies that can occur +# when the config files are modified after Nagios starts. + +object_cache_file=/var/log/nagios/objects.cache + + + +# RESOURCE FILE +# This is an optional resource file that contains $USERx$ macro +# definitions. Multiple resource files can be specified by using +# multiple resource_file definitions.  The CGIs will not attempt to +# read the contents of resource files, so information that is +# considered to be sensitive (usernames, passwords, etc) can be +# defined as macros in this file and restrictive permissions (600) +# can be placed on this file. + +resource_file=/etc/nagios/private/resource.cfg + + + +# STATUS FILE +# This is where the current status of all monitored services and +# hosts is stored.  Its contents are read and processed by the CGIs. +# The contents of the status file are deleted every time Nagios +#  restarts. + +status_file=/var/log/nagios/status.dat + + + +# NAGIOS USER +# This determines the effective user that Nagios should run as.   +# You can either supply a username or a UID. + +nagios_user=nagios + + + +# NAGIOS GROUP +# This determines the effective group that Nagios should run as.   +# You can either supply a group name or a GID. + +nagios_group=nagios + + + +# EXTERNAL COMMAND OPTION +# This option allows you to specify whether or not Nagios should check +# for external commands (in the command file defined below).  By default +# Nagios will *not* check for external commands, just to be on the +# cautious side.  If you want to be able to use the CGI command interface +# you will have to enable this.  Setting this value to 0 disables command +# checking (the default), other values enable it. + +check_external_commands=0 + + + +# EXTERNAL COMMAND CHECK INTERVAL +# This is the interval at which Nagios should check for external commands. +# This value works of the interval_length you specify later.  If you leave +# that at its default value of 60 (seconds), a value of 1 here will cause +# Nagios to check for external commands every minute.  If you specify a +# number followed by an "s" (i.e. 15s), this will be interpreted to mean +# actual seconds rather than a multiple of the interval_length variable. +# Note: In addition to reading the external command file at regularly  +# scheduled intervals, Nagios will also check for external commands after +# event handlers are executed. +# NOTE: Setting this value to -1 causes Nagios to check the external +# command file as often as possible. + +#command_check_interval=15s +command_check_interval=-1 + + + +# EXTERNAL COMMAND FILE +# This is the file that Nagios checks for external command requests. +# It is also where the command CGI will write commands that are submitted +# by users, so it must be writeable by the user that the web server +# is running as (usually 'nobody').  Permissions should be set at the  +# directory level instead of on the file, as the file is deleted every +# time its contents are processed. + +command_file=/var/spool/nagios/cmd/nagios.cmd + + + +# EXTERNAL COMMAND BUFFER SLOTS +# This settings is used to tweak the number of items or "slots" that +# the Nagios daemon should allocate to the buffer that holds incoming  +# external commands before they are processed.  As external commands  +# are processed by the daemon, they are removed from the buffer.   + +external_command_buffer_slots=4096 + + + +# COMMENT FILE +# This is the file that Nagios will use for storing host and service +# comments. + +comment_file=/var/log/nagios/comments.dat + + + +# DOWNTIME FILE +# This is the file that Nagios will use for storing host and service +# downtime data. + +downtime_file=/var/log/nagios/downtime.dat + + + +# LOCK FILE +# This is the lockfile that Nagios will use to store its PID number +# in when it is running in daemon mode. + +lock_file=/var/run/nagios.pid + + + +# TEMP FILE +# This is a temporary file that is used as scratch space when Nagios +# updates the status log, cleans the comment file, etc.  This file +# is created, used, and deleted throughout the time that Nagios is +# running. + +temp_file=/var/log/nagios/nagios.tmp + + + +# EVENT BROKER OPTIONS +# Controls what (if any) data gets sent to the event broker. +# Values:  0      = Broker nothing +#         -1      = Broker everything +#         <other> = See documentation + +event_broker_options=-1 + + + +# EVENT BROKER MODULE(S) +# This directive is used to specify an event broker module that should +# by loaded by Nagios at startup.  Use multiple directives if you want +# to load more than one module.  Arguments that should be passed to +# the module at startup are seperated from the module path by a space. +# +# Example: +# +#   broker_module=<modulepath> [moduleargs] + +#broker_module=/somewhere/module1.o +#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 + + + + +# LOG ROTATION METHOD +# This is the log rotation method that Nagios should use to rotate +# the main log file. Values are as follows.. +#	n	= None - don't rotate the log +#	h	= Hourly rotation (top of the hour) +#	d	= Daily rotation (midnight every day) +#	w	= Weekly rotation (midnight on Saturday evening) +#	m	= Monthly rotation (midnight last day of month) + +log_rotation_method=d + + + +# LOG ARCHIVE PATH +# This is the directory where archived (rotated) log files should be  +# placed (assuming you've chosen to do log rotation). + +log_archive_path=/var/log/nagios/archives + + + +# LOGGING OPTIONS +# If you want messages logged to the syslog facility, as well as the +# NetAlarm log file set this option to 1.  If not, set it to 0. + +use_syslog=1 + + + +# NOTIFICATION LOGGING OPTION +# If you don't want notifications to be logged, set this value to 0. +# If notifications should be logged, set the value to 1. + +log_notifications=1 + + + +# SERVICE RETRY LOGGING OPTION +# If you don't want service check retries to be logged, set this value +# to 0.  If retries should be logged, set the value to 1. + +log_service_retries=1 + + + +# HOST RETRY LOGGING OPTION +# If you don't want host check retries to be logged, set this value to +# 0.  If retries should be logged, set the value to 1. + +log_host_retries=1 + + + +# EVENT HANDLER LOGGING OPTION +# If you don't want host and service event handlers to be logged, set +# this value to 0.  If event handlers should be logged, set the value +# to 1. + +log_event_handlers=1 + + + +# INITIAL STATES LOGGING OPTION +# If you want Nagios to log all initial host and service states to +# the main log file (the first time the service or host is checked) +# you can enable this option by setting this value to 1.  If you +# are not using an external application that does long term state +# statistics reporting, you do not need to enable this option.  In +# this case, set the value to 0. + +log_initial_states=0 + + + +# EXTERNAL COMMANDS LOGGING OPTION +# If you don't want Nagios to log external commands, set this value +# to 0.  If external commands should be logged, set this value to 1. +# Note: This option does not include logging of passive service +# checks - see the option below for controlling whether or not +# passive checks are logged. + +log_external_commands=1 + + + +# PASSIVE CHECKS LOGGING OPTION +# If you don't want Nagios to log passive host and service checks, set +# this value to 0.  If passive checks should be logged, set +# this value to 1. + +log_passive_checks=1 + + + +# GLOBAL HOST AND SERVICE EVENT HANDLERS +# These options allow you to specify a host and service event handler +# command that is to be run for every host or service state change. +# The global event handler is executed immediately prior to the event +# handler that you have optionally specified in each host or +# service definition. The command argument is the short name of a +# command definition that you define in your host configuration file. +# Read the HTML docs for more information. + +#global_host_event_handler=somecommand +#global_service_event_handler=somecommand + + + +# SERVICE INTER-CHECK DELAY METHOD +# This is the method that Nagios should use when initially +# "spreading out" service checks when it starts monitoring.  The +# default is to use smart delay calculation, which will try to +# space all service checks out evenly to minimize CPU load. +# Using the dumb setting will cause all checks to be scheduled +# at the same time (with no delay between them)!  This is not a +# good thing for production, but is useful when testing the +# parallelization functionality. +#	n	= None - don't use any delay between checks +#	d	= Use a "dumb" delay of 1 second between checks +#	s	= Use "smart" inter-check delay calculation +#       x.xx    = Use an inter-check delay of x.xx seconds + +service_inter_check_delay_method=s + + + +# MAXIMUM SERVICE CHECK SPREAD +# This variable determines the timeframe (in minutes) from the +# program start time that an initial check of all services should +# be completed.  Default is 30 minutes. + +max_service_check_spread=30 + + + +# SERVICE CHECK INTERLEAVE FACTOR +# This variable determines how service checks are interleaved. +# Interleaving the service checks allows for a more even +# distribution of service checks and reduced load on remote +# hosts.  Setting this value to 1 is equivalent to how versions +# of Nagios previous to 0.0.5 did service checks.  Set this +# value to s (smart) for automatic calculation of the interleave +# factor unless you have a specific reason to change it. +#       s       = Use "smart" interleave factor calculation +#       x       = Use an interleave factor of x, where x is a +#                 number greater than or equal to 1. + +service_interleave_factor=s + + + +# HOST INTER-CHECK DELAY METHOD +# This is the method that Nagios should use when initially +# "spreading out" host checks when it starts monitoring.  The +# default is to use smart delay calculation, which will try to +# space all host checks out evenly to minimize CPU load. +# Using the dumb setting will cause all checks to be scheduled +# at the same time (with no delay between them)! +#	n	= None - don't use any delay between checks +#	d	= Use a "dumb" delay of 1 second between checks +#	s	= Use "smart" inter-check delay calculation +#       x.xx    = Use an inter-check delay of x.xx seconds + +host_inter_check_delay_method=s + + + +# MAXIMUM HOST CHECK SPREAD +# This variable determines the timeframe (in minutes) from the +# program start time that an initial check of all hosts should +# be completed.  Default is 30 minutes. + +max_host_check_spread=30 + + + +# MAXIMUM CONCURRENT SERVICE CHECKS +# This option allows you to specify the maximum number of  +# service checks that can be run in parallel at any given time. +# Specifying a value of 1 for this variable essentially prevents +# any service checks from being parallelized.  A value of 0 +# will not restrict the number of concurrent checks that are +# being executed. + +max_concurrent_checks=0 + + + +# SERVICE CHECK REAPER FREQUENCY +# This is the frequency (in seconds!) that Nagios will process +# the results of services that have been checked. + +service_reaper_frequency=10 + + + +# CHECK RESULT BUFFER SLOTS +# This settings is used to tweak the number of items or "slots" that +# the Nagios daemon should allocate to the buffer that holds  +# service check results before they are processed.  As check results +# are processed by the daemon, they are removed from the buffer.   + +check_result_buffer_slots=4096 + + + +# AUTO-RESCHEDULING OPTION +# This option determines whether or not Nagios will attempt to +# automatically reschedule active host and service checks to +# "smooth" them out over time.  This can help balance the load on +# the monitoring server.   +# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE +# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY + +auto_reschedule_checks=0 + + + +# AUTO-RESCHEDULING INTERVAL +# This option determines how often (in seconds) Nagios will +# attempt to automatically reschedule checks.  This option only +# has an effect if the auto_reschedule_checks option is enabled. +# Default is 30 seconds. +# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE +# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY + +auto_rescheduling_interval=30 + + + + +# AUTO-RESCHEDULING WINDOW +# This option determines the "window" of time (in seconds) that +# Nagios will look at when automatically rescheduling checks. +# Only host and service checks that occur in the next X seconds +# (determined by this variable) will be rescheduled. This option +# only has an effect if the auto_reschedule_checks option is +# enabled.  Default is 180 seconds (3 minutes). +# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE +# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY + +auto_rescheduling_window=180 + + + +# SLEEP TIME +# This is the number of seconds to sleep between checking for system +# events and service checks that need to be run. + +sleep_time=0.25 + + + +# TIMEOUT VALUES +# These options control how much time Nagios will allow various +# types of commands to execute before killing them off.  Options +# are available for controlling maximum time allotted for +# service checks, host checks, event handlers, notifications, the +# ocsp command, and performance data commands.  All values are in +# seconds. + +service_check_timeout=60 +host_check_timeout=30 +event_handler_timeout=30 +notification_timeout=30 +ocsp_timeout=5 +perfdata_timeout=5 + + + +# RETAIN STATE INFORMATION +# This setting determines whether or not Nagios will save state +# information for services and hosts before it shuts down.  Upon +# startup Nagios will reload all saved service and host state +# information before starting to monitor.  This is useful for  +# maintaining long-term data on state statistics, etc, but will +# slow Nagios down a bit when it (re)starts.  Since its only +# a one-time penalty, I think its well worth the additional +# startup delay. + +retain_state_information=1 + + + +# STATE RETENTION FILE +# This is the file that Nagios should use to store host and +# service state information before it shuts down.  The state  +# information in this file is also read immediately prior to +# starting to monitor the network when Nagios is restarted. +# This file is used only if the preserve_state_information +# variable is set to 1. + +state_retention_file=/var/log/nagios/retention.dat + + + +# RETENTION DATA UPDATE INTERVAL +# This setting determines how often (in minutes) that Nagios +# will automatically save retention data during normal operation. +# If you set this value to 0, Nagios will not save retention +# data at regular interval, but it will still save retention +# data before shutting down or restarting.  If you have disabled +# state retention, this option has no effect. + +retention_update_interval=60 + + + +# USE RETAINED PROGRAM STATE +# This setting determines whether or not Nagios will set  +# program status variables based on the values saved in the +# retention file.  If you want to use retained program status +# information, set this value to 1.  If not, set this value +# to 0. + +use_retained_program_state=1 + + + +# USE RETAINED SCHEDULING INFO +# This setting determines whether or not Nagios will retain +# the scheduling info (next check time) for hosts and services +# based on the values saved in the retention file.  If you +# If you want to use retained scheduling info, set this +# value to 1.  If not, set this value to 0. + +use_retained_scheduling_info=0 + + + +# INTERVAL LENGTH +# This is the seconds per unit interval as used in the +# host/contact/service configuration files.  Setting this to 60 means +# that each interval is one minute long (60 seconds).  Other settings +# have not been tested much, so your mileage is likely to vary... + +interval_length=60 + + + +# AGGRESSIVE HOST CHECKING OPTION +# If you don't want to turn on aggressive host checking features, set +# this value to 0 (the default).  Otherwise set this value to 1 to +# enable the aggressive check option.  Read the docs for more info +# on what aggressive host check is or check out the source code in +# base/checks.c + +use_aggressive_host_checking=0 + + + +# SERVICE CHECK EXECUTION OPTION +# This determines whether or not Nagios will actively execute +# service checks when it initially starts.  If this option is  +# disabled, checks are not actively made, but Nagios can still +# receive and process passive check results that come in.  Unless +# you're implementing redundant hosts or have a special need for +# disabling the execution of service checks, leave this enabled! +# Values: 1 = enable checks, 0 = disable checks + +execute_service_checks=1 + + + +# PASSIVE SERVICE CHECK ACCEPTANCE OPTION +# This determines whether or not Nagios will accept passive +# service checks results when it initially (re)starts. +# Values: 1 = accept passive checks, 0 = reject passive checks + +accept_passive_service_checks=1 + + + +# HOST CHECK EXECUTION OPTION +# This determines whether or not Nagios will actively execute +# host checks when it initially starts.  If this option is  +# disabled, checks are not actively made, but Nagios can still +# receive and process passive check results that come in.  Unless +# you're implementing redundant hosts or have a special need for +# disabling the execution of host checks, leave this enabled! +# Values: 1 = enable checks, 0 = disable checks + +execute_host_checks=1 + + + +# PASSIVE HOST CHECK ACCEPTANCE OPTION +# This determines whether or not Nagios will accept passive +# host checks results when it initially (re)starts. +# Values: 1 = accept passive checks, 0 = reject passive checks + +accept_passive_host_checks=1 + + + +# NOTIFICATIONS OPTION +# This determines whether or not Nagios will sent out any host or +# service notifications when it is initially (re)started. +# Values: 1 = enable notifications, 0 = disable notifications + +enable_notifications=1 + + + +# EVENT HANDLER USE OPTION +# This determines whether or not Nagios will run any host or +# service event handlers when it is initially (re)started.  Unless +# you're implementing redundant hosts, leave this option enabled. +# Values: 1 = enable event handlers, 0 = disable event handlers + +enable_event_handlers=1 + + + +# PROCESS PERFORMANCE DATA OPTION +# This determines whether or not Nagios will process performance +# data returned from service and host checks.  If this option is +# enabled, host performance data will be processed using the +# host_perfdata_command (defined below) and service performance +# data will be processed using the service_perfdata_command (also +# defined below).  Read the HTML docs for more information on +# performance data. +# Values: 1 = process performance data, 0 = do not process performance data + +process_performance_data=0 + + + +# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS +# These commands are run after every host and service check is +# performed.  These commands are executed only if the +# enable_performance_data option (above) is set to 1.  The command +# argument is the short name of a command definition that you  +# define in your host configuration file.  Read the HTML docs for +# more information on performance data. + +#host_perfdata_command=process-host-perfdata +#service_perfdata_command=process-service-perfdata + + + +# HOST AND SERVICE PERFORMANCE DATA FILES +# These files are used to store host and service performance data. +# Performance data is only written to these files if the +# enable_performance_data option (above) is set to 1. + +#host_perfdata_file=/tmp/host-perfdata +#service_perfdata_file=/tmp/service-perfdata + + + +# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES +# These options determine what data is written (and how) to the +# performance data files.  The templates may contain macros, special +# characters (\t for tab, \r for carriage return, \n for newline) +# and plain text.  A newline is automatically added after each write +# to the performance data file.  Some examples of what you can do are +# shown below. + +#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ +#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ + + + + +# HOST AND SERVICE PERFORMANCE DATA FILE MODES +# This option determines whether or not the host and service +# performance data files are opened in write ("w") or append ("a") +# mode.  Unless you are the files are named pipes, you will probably +# want to use the default mode of append ("a"). + +#host_perfdata_file_mode=a +#service_perfdata_file_mode=a + + + +# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL +# These options determine how often (in seconds) the host and service +# performance data files are processed using the commands defined +# below.  A value of 0 indicates the files should not be periodically +# processed. + +#host_perfdata_file_processing_interval=0 +#service_perfdata_file_processing_interval=0 + + + +# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS +# These commands are used to periodically process the host and +# service performance data files.  The interval at which the +# processing occurs is determined by the options above. + +#host_perfdata_file_processing_command=process-host-perfdata-file +#service_perfdata_file_processing_command=process-service-perfdata-file + + + +# OBSESS OVER SERVICE CHECKS OPTION +# This determines whether or not Nagios will obsess over service +# checks and run the ocsp_command defined below.  Unless you're +# planning on implementing distributed monitoring, do not enable +# this option.  Read the HTML docs for more information on +# implementing distributed monitoring. +# Values: 1 = obsess over services, 0 = do not obsess (default) + +obsess_over_services=0 + + + +# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND +# This is the command that is run for every service check that is +# processed by Nagios.  This command is executed only if the +# obsess_over_service option (above) is set to 1.  The command  +# argument is the short name of a command definition that you +# define in your host configuration file. Read the HTML docs for +# more information on implementing distributed monitoring. + +#ocsp_command=somecommand + + + +# ORPHANED SERVICE CHECK OPTION +# This determines whether or not Nagios will periodically  +# check for orphaned services.  Since service checks are not +# rescheduled until the results of their previous execution  +# instance are processed, there exists a possibility that some +# checks may never get rescheduled.  This seems to be a rare +# problem and should not happen under normal circumstances. +# If you have problems with service checks never getting +# rescheduled, you might want to try enabling this option. +# Values: 1 = enable checks, 0 = disable checks + +check_for_orphaned_services=1 + + + +# SERVICE FRESHNESS CHECK OPTION +# This option determines whether or not Nagios will periodically +# check the "freshness" of service results.  Enabling this option +# is useful for ensuring passive checks are received in a timely +# manner. +# Values: 1 = enabled freshness checking, 0 = disable freshness checking + +check_service_freshness=1 + + + +# SERVICE FRESHNESS CHECK INTERVAL +# This setting determines how often (in seconds) Nagios will +# check the "freshness" of service check results.  If you have +# disabled service freshness checking, this option has no effect. + +service_freshness_check_interval=60 + + + +# HOST FRESHNESS CHECK OPTION +# This option determines whether or not Nagios will periodically +# check the "freshness" of host results.  Enabling this option +# is useful for ensuring passive checks are received in a timely +# manner. +# Values: 1 = enabled freshness checking, 0 = disable freshness checking + +check_host_freshness=0 + + + +# HOST FRESHNESS CHECK INTERVAL +# This setting determines how often (in seconds) Nagios will +# check the "freshness" of host check results.  If you have +# disabled host freshness checking, this option has no effect. + +host_freshness_check_interval=60 + + + +# AGGREGATED STATUS UPDATES +# This option determines whether or not Nagios will  +# aggregate updates of host, service, and program status +# data.  Normally, status data is updated immediately when +# a change occurs.  This can result in high CPU loads if +# you are monitoring a lot of services.  If you want Nagios +# to only refresh status data every few seconds, disable +# this option. +# Values: 1 = enable aggregate updates, 0 = disable aggregate updates + +aggregate_status_updates=1 + + + +# AGGREGATED STATUS UPDATE INTERVAL +# Combined with the aggregate_status_updates option, +# this option determines the frequency (in seconds!) that +# Nagios will periodically dump program, host, and  +# service status data.  If you are not using aggregated +# status data updates, this option has no effect. + +status_update_interval=15 + + + +# FLAP DETECTION OPTION +# This option determines whether or not Nagios will try +# and detect hosts and services that are "flapping".   +# Flapping occurs when a host or service changes between +# states too frequently.  When Nagios detects that a  +# host or service is flapping, it will temporarily suppress +# notifications for that host/service until it stops +# flapping.  Flap detection is very experimental, so read +# the HTML documentation before enabling this feature! +# Values: 1 = enable flap detection +#         0 = disable flap detection (default) + +enable_flap_detection=0 + + + +# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES +# Read the HTML documentation on flap detection for +# an explanation of what this option does.  This option +# has no effect if flap detection is disabled. + +low_service_flap_threshold=5.0 +high_service_flap_threshold=20.0 +low_host_flap_threshold=5.0 +high_host_flap_threshold=20.0 + + + +# DATE FORMAT OPTION +# This option determines how short dates are displayed. Valid options +# include: +#	us		(MM-DD-YYYY HH:MM:SS) +#	euro    	(DD-MM-YYYY HH:MM:SS) +#	iso8601		(YYYY-MM-DD HH:MM:SS) +#	strict-iso8601	(YYYY-MM-DDTHH:MM:SS) +# + +date_format=us + + + +# P1.PL FILE LOCATION +# This value determines where the p1.pl perl script (used by the +# embedded Perl interpreter) is located.  If you didn't compile +# Nagios with embedded Perl support, this option has no effect. + +p1_file=/usr/sbin/p1.pl + + + +# ILLEGAL OBJECT NAME CHARACTERS +# This option allows you to specify illegal characters that cannot +# be used in host names, service descriptions, or names of other +# object types. + +illegal_object_name_chars=`~!$%^&*|'"<>?,()= + + + +# ILLEGAL MACRO OUTPUT CHARACTERS +# This option allows you to specify illegal characters that are +# stripped from macros before being used in notifications, event +# handlers, etc.  This DOES NOT affect macros used in service or +# host check commands. +# The following macros are stripped of the characters you specify: +#	$HOSTOUTPUT$ +#	$HOSTPERFDATA$ +#	$HOSTACKAUTHOR$ +#	$HOSTACKCOMMENT$ +#	$SERVICEOUTPUT$ +#	$SERVICEPERFDATA$ +#	$SERVICEACKAUTHOR$ +#	$SERVICEACKCOMMENT$ + +illegal_macro_output_chars=`~$&|'"<> + + + +# REGULAR EXPRESSION MATCHING +# This option controls whether or not regular expression matching +# takes place in the object config files.  Regular expression +# matching is used to match host, hostgroup, service, and service +# group names/descriptions in some fields of various object types. +# Values: 1 = enable regexp matching, 0 = disable regexp matching + +use_regexp_matching=0 + + + +# "TRUE" REGULAR EXPRESSION MATCHING +# This option controls whether or not "true" regular expression  +# matching takes place in the object config files.  This option +# only has an effect if regular expression matching is enabled +# (see above).  If this option is DISABLED, regular expression +# matching only occurs if a string contains wildcard characters +# (* and ?).  If the option is ENABLED, regexp matching occurs +# all the time (which can be annoying). +# Values: 1 = enable true matching, 0 = disable true matching + +use_true_regexp_matching=0 + + + + +# ADMINISTRATOR EMAIL ADDRESS +# The email address of the administrator of *this* machine (the one +# doing the monitoring).  Nagios never uses this value itself, but +# you can access this value by using the $ADMINEMAIL$ macro in your +# notification commands. + +admin_email=nagios + + + +# ADMINISTRATOR PAGER NUMBER/ADDRESS +# The pager number/address for the administrator of *this* machine. +# Nagios never uses this value itself, but you can access this +# value by using the $ADMINPAGER$ macro in your notification +# commands. + +admin_pager=pagenagios + + + +# DAEMON CORE DUMP OPTION +# This option determines whether or not Nagios is allowed to create +# a core dump when it runs as a daemon.  Note that it is generally +# considered bad form to allow this, but it may be useful for +# debugging purposes. +# Values: 1 - Allow core dumps +#         0 - Do not allow core dumps (default) + +daemon_dumps_core=0 + + + diff --git a/puppet/modules/nagios/files/configs/CentOS/private/resource.cfg.i386 b/puppet/modules/nagios/files/configs/CentOS/private/resource.cfg.i386 new file mode 100644 index 00000000..0ccf2e17 --- /dev/null +++ b/puppet/modules/nagios/files/configs/CentOS/private/resource.cfg.i386 @@ -0,0 +1,34 @@ +########################################################################### +# +# RESOURCE.CFG - Sample Resource File for Nagios 2.9 +# +# Last Modified: 09-10-2003 +# +# You can define $USERx$ macros in this file, which can in turn be used +# in command definitions in your host config file(s).  $USERx$ macros are +# useful for storing sensitive information such as usernames, passwords,  +# etc.  They are also handy for specifying the path to plugins and  +# event handlers - if you decide to move the plugins or event handlers to +# a different directory in the future, you can just update one or two +# $USERx$ macros, instead of modifying a lot of command definitions. +# +# The CGIs will not attempt to read the contents of resource files, so +# you can set restrictive permissions (600 or 660) on them. +# +# Nagios supports up to 32 $USERx$ macros ($USER1$ through $USER32$) +# +# Resource files may also be used to store configuration directives for +# external data sources like MySQL... +# +########################################################################### + +# Sets $USER1$ to be the path to the plugins +$USER1$=/usr/lib/nagios/plugins + +# Sets $USER2$ to be the path to event handlers +#$USER2$=/usr/lib64/nagios/plugins/eventhandlers + +# Store some usernames and passwords (hidden from the CGIs) +#$USER3$=someuser +#$USER4$=somepassword + diff --git a/puppet/modules/nagios/files/configs/CentOS/private/resource.cfg.x86_64 b/puppet/modules/nagios/files/configs/CentOS/private/resource.cfg.x86_64 new file mode 100644 index 00000000..b9f0841c --- /dev/null +++ b/puppet/modules/nagios/files/configs/CentOS/private/resource.cfg.x86_64 @@ -0,0 +1,34 @@ +########################################################################### +# +# RESOURCE.CFG - Sample Resource File for Nagios 2.9 +# +# Last Modified: 09-10-2003 +# +# You can define $USERx$ macros in this file, which can in turn be used +# in command definitions in your host config file(s).  $USERx$ macros are +# useful for storing sensitive information such as usernames, passwords,  +# etc.  They are also handy for specifying the path to plugins and  +# event handlers - if you decide to move the plugins or event handlers to +# a different directory in the future, you can just update one or two +# $USERx$ macros, instead of modifying a lot of command definitions. +# +# The CGIs will not attempt to read the contents of resource files, so +# you can set restrictive permissions (600 or 660) on them. +# +# Nagios supports up to 32 $USERx$ macros ($USER1$ through $USER32$) +# +# Resource files may also be used to store configuration directives for +# external data sources like MySQL... +# +########################################################################### + +# Sets $USER1$ to be the path to the plugins +$USER1$=/usr/lib64/nagios/plugins + +# Sets $USER2$ to be the path to event handlers +#$USER2$=/usr/lib64/nagios/plugins/eventhandlers + +# Store some usernames and passwords (hidden from the CGIs) +#$USER3$=someuser +#$USER4$=somepassword + diff --git a/puppet/modules/nagios/files/configs/Debian/cgi.cfg b/puppet/modules/nagios/files/configs/Debian/cgi.cfg new file mode 100644 index 00000000..103db8a1 --- /dev/null +++ b/puppet/modules/nagios/files/configs/Debian/cgi.cfg @@ -0,0 +1,330 @@ +################################################################# +# +# CGI.CFG - Sample CGI Configuration File for Nagios  +# +################################################################# + + +# MAIN CONFIGURATION FILE +# This tells the CGIs where to find your main configuration file. +# The CGIs will read the main and host config files for any other +# data they might need. + +main_config_file=/etc/nagios3/nagios.cfg + + + +# PHYSICAL HTML PATH +# This is the path where the HTML files for Nagios reside.  This +# value is used to locate the logo images needed by the statusmap +# and statuswrl CGIs. + +physical_html_path=/usr/share/nagios3/htdocs + + + +# URL HTML PATH +# This is the path portion of the URL that corresponds to the +# physical location of the Nagios HTML files (as defined above). +# This value is used by the CGIs to locate the online documentation +# and graphics.  If you access the Nagios pages with an URL like +# http://www.myhost.com/nagios, this value should be '/nagios' +# (without the quotes). + +url_html_path=/nagios3 + + + +# CONTEXT-SENSITIVE HELP +# This option determines whether or not a context-sensitive +# help icon will be displayed for most of the CGIs. +# Values: 0 = disables context-sensitive help +#         1 = enables context-sensitive help + +show_context_help=1 + + + +# PENDING STATES OPTION +# This option determines what states should be displayed in the web +# interface for hosts/services that have not yet been checked. +# Values: 0 = leave hosts/services that have not been check yet in their original state +#         1 = mark hosts/services that have not been checked yet as PENDING + +use_pending_states=1 + +nagios_check_command=/usr/lib/nagios/plugins/check_nagios /var/cache/nagios3/status.dat 5 '/usr/sbin/nagios3' + + +# AUTHENTICATION USAGE +# This option controls whether or not the CGIs will use any  +# authentication when displaying host and service information, as +# well as committing commands to Nagios for processing.   +# +# Read the HTML documentation to learn how the authorization works! +# +# NOTE: It is a really *bad* idea to disable authorization, unless +# you plan on removing the command CGI (cmd.cgi)!  Failure to do +# so will leave you wide open to kiddies messing with Nagios and +# possibly hitting you with a denial of service attack by filling up +# your drive by continuously writing to your command file! +# +# Setting this value to 0 will cause the CGIs to *not* use +# authentication (bad idea), while any other value will make them +# use the authentication functions (the default). + +use_authentication=1 + + + + +# x509 CERT AUTHENTICATION +# When enabled, this option allows you to use x509 cert (SSL) +# authentication in the CGIs.  This is an advanced option and should +# not be enabled unless you know what you're doing. + +use_ssl_authentication=0 + + + + +# DEFAULT USER +# Setting this variable will define a default user name that can +# access pages without authentication.  This allows people within a +# secure domain (i.e., behind a firewall) to see the current status +# without authenticating.  You may want to use this to avoid basic +# authentication if you are not using a secure server since basic +# authentication transmits passwords in the clear. +# +# Important:  Do not define a default username unless you are +# running a secure web server and are sure that everyone who has +# access to the CGIs has been authenticated in some manner!  If you +# define this variable, anyone who has not authenticated to the web +# server will inherit all rights you assign to this user! +  +#default_user_name=guest + + + +# SYSTEM/PROCESS INFORMATION ACCESS +# This option is a comma-delimited list of all usernames that +# have access to viewing the Nagios process information as +# provided by the Extended Information CGI (extinfo.cgi).  By +# default, *no one* has access to this unless you choose to +# not use authorization.  You may use an asterisk (*) to +# authorize any user who has authenticated to the web server. + +authorized_for_system_information=nagiosadmin + + + +# CONFIGURATION INFORMATION ACCESS +# This option is a comma-delimited list of all usernames that +# can view ALL configuration information (hosts, commands, etc). +# By default, users can only view configuration information +# for the hosts and services they are contacts for. You may use +# an asterisk (*) to authorize any user who has authenticated +# to the web server. + +authorized_for_configuration_information=nagiosadmin + + + +# SYSTEM/PROCESS COMMAND ACCESS +# This option is a comma-delimited list of all usernames that +# can issue shutdown and restart commands to Nagios via the +# command CGI (cmd.cgi).  Users in this list can also change +# the program mode to active or standby. By default, *no one* +# has access to this unless you choose to not use authorization. +# You may use an asterisk (*) to authorize any user who has +# authenticated to the web server. + +authorized_for_system_commands=nagiosadmin + + + +# GLOBAL HOST/SERVICE VIEW ACCESS +# These two options are comma-delimited lists of all usernames that +# can view information for all hosts and services that are being +# monitored.  By default, users can only view information +# for hosts or services that they are contacts for (unless you +# you choose to not use authorization). You may use an asterisk (*) +# to authorize any user who has authenticated to the web server. + + +authorized_for_all_services=nagiosadmin +authorized_for_all_hosts=nagiosadmin + + + +# GLOBAL HOST/SERVICE COMMAND ACCESS +# These two options are comma-delimited lists of all usernames that +# can issue host or service related commands via the command +# CGI (cmd.cgi) for all hosts and services that are being monitored.  +# By default, users can only issue commands for hosts or services  +# that they are contacts for (unless you you choose to not use  +# authorization).  You may use an asterisk (*) to authorize any +# user who has authenticated to the web server. + +authorized_for_all_service_commands=nagiosadmin +authorized_for_all_host_commands=nagiosadmin + + + + +# STATUSMAP BACKGROUND IMAGE +# This option allows you to specify an image to be used as a  +# background in the statusmap CGI.  It is assumed that the image +# resides in the HTML images path (i.e. /usr/local/nagios/share/images). +# This path is automatically determined by appending "/images" +# to the path specified by the 'physical_html_path' directive. +# Note:  The image file may be in GIF, PNG, JPEG, or GD2 format. +# However, I recommend that you convert your image to GD2 format +# (uncompressed), as this will cause less CPU load when the CGI +# generates the image. + +#statusmap_background_image=smbackground.gd2 + + + +# DEFAULT STATUSMAP LAYOUT METHOD +# This option allows you to specify the default layout method +# the statusmap CGI should use for drawing hosts.  If you do +# not use this option, the default is to use user-defined +# coordinates.  Valid options are as follows: +#	0 = User-defined coordinates +#	1 = Depth layers +#       2 = Collapsed tree +#       3 = Balanced tree +#       4 = Circular +#       5 = Circular (Marked Up) + +default_statusmap_layout=5 + + + +# DEFAULT STATUSWRL LAYOUT METHOD +# This option allows you to specify the default layout method +# the statuswrl (VRML) CGI should use for drawing hosts.  If you +# do not use this option, the default is to use user-defined +# coordinates.  Valid options are as follows: +#	0 = User-defined coordinates +#       2 = Collapsed tree +#       3 = Balanced tree +#       4 = Circular + +default_statuswrl_layout=4 + + + +# STATUSWRL INCLUDE +# This option allows you to include your own objects in the  +# generated VRML world.  It is assumed that the file +# resides in the HTML path (i.e. /usr/local/nagios/share). + +#statuswrl_include=myworld.wrl + + + +# PING SYNTAX +# This option determines what syntax should be used when +# attempting to ping a host from the WAP interface (using +# the statuswml CGI.  You must include the full path to +# the ping binary, along with all required options.  The +# $HOSTADDRESS$ macro is substituted with the address of +# the host before the command is executed. +# Please note that the syntax for the ping binary is +# notorious for being different on virtually ever *NIX +# OS and distribution, so you may have to tweak this to +# work on your system. + +ping_syntax=/bin/ping -n -U -c 5 $HOSTADDRESS$ + + + +# REFRESH RATE +# This option allows you to specify the refresh rate in seconds +# of various CGIs (status, statusmap, extinfo, and outages).   + +refresh_rate=90 + + + +# ESCAPE HTML TAGS +# This option determines whether HTML tags in host and service +# status output is escaped in the web interface.  If enabled, +# your plugin output will not be able to contain clickable links. + +escape_html_tags=1 + + + + +# SOUND OPTIONS +# These options allow you to specify an optional audio file +# that should be played in your browser window when there are +# problems on the network.  The audio files are used only in +# the status CGI.  Only the sound for the most critical problem +# will be played.  Order of importance (higher to lower) is as +# follows: unreachable hosts, down hosts, critical services, +# warning services, and unknown services. If there are no +# visible problems, the sound file optionally specified by +# 'normal_sound' variable will be played. +# +# +# <varname>=<sound_file> +# +# Note: All audio files must be placed in the /media subdirectory +# under the HTML path (i.e. /usr/local/nagios/share/media/). + +#host_unreachable_sound=hostdown.wav +#host_down_sound=hostdown.wav +#service_critical_sound=critical.wav +#service_warning_sound=warning.wav +#service_unknown_sound=warning.wav +#normal_sound=noproblem.wav + + + +# URL TARGET FRAMES +# These options determine the target frames in which notes and  +# action URLs will open. + +action_url_target=_blank +notes_url_target=_blank + + + + +# LOCK AUTHOR NAMES OPTION +# This option determines whether users can change the author name  +# when submitting comments, scheduling downtime.  If disabled, the  +# author names will be locked into their contact name, as defined in Nagios. +# Values: 0 = allow editing author names +#         1 = lock author names (disallow editing) + +lock_author_names=1 + + + + +# SPLUNK INTEGRATION OPTIONS +# These options allow you to enable integration with Splunk +# in the web interface.  If enabled, you'll be presented with +# "Splunk It" links in various places in the CGIs (log file, +# alert history, host/service detail, etc).  Useful if you're +# trying to research why a particular problem occurred. +# For more information on Splunk, visit http://www.splunk.com/ + +# This option determines whether the Splunk integration is enabled +# Values: 0 = disable Splunk integration +#         1 = enable Splunk integration + +#enable_splunk_integration=1 + + +# This option should be the URL used to access your instance of Splunk + +#splunk_url=http://127.0.0.1:8000/ + + diff --git a/puppet/modules/nagios/files/configs/Debian/nagios.cfg b/puppet/modules/nagios/files/configs/Debian/nagios.cfg new file mode 100644 index 00000000..291a4741 --- /dev/null +++ b/puppet/modules/nagios/files/configs/Debian/nagios.cfg @@ -0,0 +1,1288 @@ +############################################################################## +# +# NAGIOS.CFG - Sample Main Config File for Nagios  +# +# +############################################################################## + + +# LOG FILE +# This is the main log file where service and host events are logged +# for historical purposes.  This should be the first option specified  +# in the config file!!! + +log_file=/var/log/nagios3/nagios.log + + + +# OBJECT CONFIGURATION FILE(S) +# These are the object configuration files in which you define hosts, +# host groups, contacts, contact groups, services, etc. +# You can split your object definitions across several config files +# if you wish (as shown below), or keep them all in a single config file. +#cfg_file=/etc/nagios3/commands.cfg + +# Puppet-managed configuration files +cfg_file=/etc/nagios3/nagios_templates.cfg +cfg_file=/etc/nagios3/nagios_command.cfg +cfg_file=/etc/nagios3/nagios_contact.cfg +cfg_file=/etc/nagios3/nagios_contactgroup.cfg +cfg_file=/etc/nagios3/nagios_host.cfg +cfg_file=/etc/nagios3/nagios_hostdependency.cfg +cfg_file=/etc/nagios3/nagios_hostescalation.cfg +cfg_file=/etc/nagios3/nagios_hostextinfo.cfg +cfg_file=/etc/nagios3/nagios_hostgroup.cfg +cfg_file=/etc/nagios3/nagios_hostgroupescalation.cfg +cfg_file=/etc/nagios3/nagios_service.cfg +cfg_file=/etc/nagios3/nagios_servicedependency.cfg +cfg_file=/etc/nagios3/nagios_serviceescalation.cfg +cfg_file=/etc/nagios3/nagios_serviceextinfo.cfg +cfg_file=/etc/nagios3/nagios_servicegroup.cfg +cfg_file=/etc/nagios3/nagios_timeperiod.cfg + +# Debian also defaults to using the check commands defined by the debian +# nagios-plugins package +cfg_dir=/etc/nagios-plugins/config + + + +# OBJECT CACHE FILE +# This option determines where object definitions are cached when +# Nagios starts/restarts.  The CGIs read object definitions from  +# this cache file (rather than looking at the object config files +# directly) in order to prevent inconsistencies that can occur +# when the config files are modified after Nagios starts. + +object_cache_file=/var/cache/nagios3/objects.cache + + + +# PRE-CACHED OBJECT FILE +# This options determines the location of the precached object file. +# If you run Nagios with the -p command line option, it will preprocess +# your object configuration file(s) and write the cached config to this +# file.  You can then start Nagios with the -u option to have it read +# object definitions from this precached file, rather than the standard +# object configuration files (see the cfg_file and cfg_dir options above). +# Using a precached object file can speed up the time needed to (re)start  +# the Nagios process if you've got a large and/or complex configuration. +# Read the documentation section on optimizing Nagios to find our more +# about how this feature works. + +precached_object_file=/var/lib/nagios3/objects.precache + + + +# RESOURCE FILE +# This is an optional resource file that contains $USERx$ macro +# definitions. Multiple resource files can be specified by using +# multiple resource_file definitions.  The CGIs will not attempt to +# read the contents of resource files, so information that is +# considered to be sensitive (usernames, passwords, etc) can be +# defined as macros in this file and restrictive permissions (600) +# can be placed on this file. + +resource_file=/etc/nagios3/resource.cfg + + + +# STATUS FILE +# This is where the current status of all monitored services and +# hosts is stored.  Its contents are read and processed by the CGIs. +# The contents of the status file are deleted every time Nagios +#  restarts. + +status_file=/var/cache/nagios3/status.dat + + + +# STATUS FILE UPDATE INTERVAL +# This option determines the frequency (in seconds) that +# Nagios will periodically dump program, host, and  +# service status data. + +status_update_interval=10 + + + +# NAGIOS USER +# This determines the effective user that Nagios should run as.   +# You can either supply a username or a UID. + +nagios_user=nagios + + + +# NAGIOS GROUP +# This determines the effective group that Nagios should run as.   +# You can either supply a group name or a GID. + +nagios_group=nagios + + + +# EXTERNAL COMMAND OPTION +# This option allows you to specify whether or not Nagios should check +# for external commands (in the command file defined below).  By default +# Nagios will *not* check for external commands, just to be on the +# cautious side.  If you want to be able to use the CGI command interface +# you will have to enable this. +# Values: 0 = disable commands, 1 = enable commands + +check_external_commands=0 + + + +# EXTERNAL COMMAND CHECK INTERVAL +# This is the interval at which Nagios should check for external commands. +# This value works of the interval_length you specify later.  If you leave +# that at its default value of 60 (seconds), a value of 1 here will cause +# Nagios to check for external commands every minute.  If you specify a +# number followed by an "s" (i.e. 15s), this will be interpreted to mean +# actual seconds rather than a multiple of the interval_length variable. +# Note: In addition to reading the external command file at regularly  +# scheduled intervals, Nagios will also check for external commands after +# event handlers are executed. +# NOTE: Setting this value to -1 causes Nagios to check the external +# command file as often as possible. + +#command_check_interval=15s +command_check_interval=-1 + + + +# EXTERNAL COMMAND FILE +# This is the file that Nagios checks for external command requests. +# It is also where the command CGI will write commands that are submitted +# by users, so it must be writeable by the user that the web server +# is running as (usually 'nobody').  Permissions should be set at the  +# directory level instead of on the file, as the file is deleted every +# time its contents are processed. +# Debian Users: In case you didn't read README.Debian yet, _NOW_ is the +# time to do it. + +command_file=/var/lib/nagios3/rw/nagios.cmd + + + +# EXTERNAL COMMAND BUFFER SLOTS +# This settings is used to tweak the number of items or "slots" that +# the Nagios daemon should allocate to the buffer that holds incoming  +# external commands before they are processed.  As external commands  +# are processed by the daemon, they are removed from the buffer.   + +external_command_buffer_slots=4096 + + + +# LOCK FILE +# This is the lockfile that Nagios will use to store its PID number +# in when it is running in daemon mode. + +lock_file=/var/run/nagios3/nagios3.pid + + + +# TEMP FILE +# This is a temporary file that is used as scratch space when Nagios +# updates the status log, cleans the comment file, etc.  This file +# is created, used, and deleted throughout the time that Nagios is +# running. + +temp_file=/var/cache/nagios3/nagios.tmp + + + +# TEMP PATH +# This is path where Nagios can create temp files for service and +# host check results, etc. + +temp_path=/tmp + + + +# EVENT BROKER OPTIONS +# Controls what (if any) data gets sent to the event broker. +# Values:  0      = Broker nothing +#         -1      = Broker everything +#         <other> = See documentation + +event_broker_options=-1 + + + +# EVENT BROKER MODULE(S) +# This directive is used to specify an event broker module that should +# by loaded by Nagios at startup.  Use multiple directives if you want +# to load more than one module.  Arguments that should be passed to +# the module at startup are seperated from the module path by a space. +# +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# +# Do NOT overwrite modules while they are being used by Nagios or Nagios +# will crash in a fiery display of SEGFAULT glory.  This is a bug/limitation +# either in dlopen(), the kernel, and/or the filesystem.  And maybe Nagios... +# +# The correct/safe way of updating a module is by using one of these methods: +#    1. Shutdown Nagios, replace the module file, restart Nagios +#    2. Delete the original module file, move the new module file into place, restart Nagios +# +# Example: +# +#   broker_module=<modulepath> [moduleargs] + +#broker_module=/somewhere/module1.o +#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 + + + +# LOG ROTATION METHOD +# This is the log rotation method that Nagios should use to rotate +# the main log file. Values are as follows.. +#	n	= None - don't rotate the log +#	h	= Hourly rotation (top of the hour) +#	d	= Daily rotation (midnight every day) +#	w	= Weekly rotation (midnight on Saturday evening) +#	m	= Monthly rotation (midnight last day of month) + +log_rotation_method=d + + + +# LOG ARCHIVE PATH +# This is the directory where archived (rotated) log files should be  +# placed (assuming you've chosen to do log rotation). + +log_archive_path=/var/log/nagios3/archives + + + +# LOGGING OPTIONS +# If you want messages logged to the syslog facility, as well as the +# Nagios log file set this option to 1.  If not, set it to 0. + +use_syslog=1 + + + +# NOTIFICATION LOGGING OPTION +# If you don't want notifications to be logged, set this value to 0. +# If notifications should be logged, set the value to 1. + +log_notifications=1 + + + +# SERVICE RETRY LOGGING OPTION +# If you don't want service check retries to be logged, set this value +# to 0.  If retries should be logged, set the value to 1. + +log_service_retries=1 + + + +# HOST RETRY LOGGING OPTION +# If you don't want host check retries to be logged, set this value to +# 0.  If retries should be logged, set the value to 1. + +log_host_retries=1 + + + +# EVENT HANDLER LOGGING OPTION +# If you don't want host and service event handlers to be logged, set +# this value to 0.  If event handlers should be logged, set the value +# to 1. + +log_event_handlers=1 + + + +# INITIAL STATES LOGGING OPTION +# If you want Nagios to log all initial host and service states to +# the main log file (the first time the service or host is checked) +# you can enable this option by setting this value to 1.  If you +# are not using an external application that does long term state +# statistics reporting, you do not need to enable this option.  In +# this case, set the value to 0. + +log_initial_states=0 + + + +# EXTERNAL COMMANDS LOGGING OPTION +# If you don't want Nagios to log external commands, set this value +# to 0.  If external commands should be logged, set this value to 1. +# Note: This option does not include logging of passive service +# checks - see the option below for controlling whether or not +# passive checks are logged. + +log_external_commands=1 + + + +# PASSIVE CHECKS LOGGING OPTION +# If you don't want Nagios to log passive host and service checks, set +# this value to 0.  If passive checks should be logged, set +# this value to 1. + +log_passive_checks=1 + + + +# GLOBAL HOST AND SERVICE EVENT HANDLERS +# These options allow you to specify a host and service event handler +# command that is to be run for every host or service state change. +# The global event handler is executed immediately prior to the event +# handler that you have optionally specified in each host or +# service definition. The command argument is the short name of a +# command definition that you define in your host configuration file. +# Read the HTML docs for more information. + +#global_host_event_handler=somecommand +#global_service_event_handler=somecommand + + + +# SERVICE INTER-CHECK DELAY METHOD +# This is the method that Nagios should use when initially +# "spreading out" service checks when it starts monitoring.  The +# default is to use smart delay calculation, which will try to +# space all service checks out evenly to minimize CPU load. +# Using the dumb setting will cause all checks to be scheduled +# at the same time (with no delay between them)!  This is not a +# good thing for production, but is useful when testing the +# parallelization functionality. +#	n	= None - don't use any delay between checks +#	d	= Use a "dumb" delay of 1 second between checks +#	s	= Use "smart" inter-check delay calculation +#       x.xx    = Use an inter-check delay of x.xx seconds + +service_inter_check_delay_method=s + + + +# MAXIMUM SERVICE CHECK SPREAD +# This variable determines the timeframe (in minutes) from the +# program start time that an initial check of all services should +# be completed.  Default is 30 minutes. + +max_service_check_spread=30 + + + +# SERVICE CHECK INTERLEAVE FACTOR +# This variable determines how service checks are interleaved. +# Interleaving the service checks allows for a more even +# distribution of service checks and reduced load on remote +# hosts.  Setting this value to 1 is equivalent to how versions +# of Nagios previous to 0.0.5 did service checks.  Set this +# value to s (smart) for automatic calculation of the interleave +# factor unless you have a specific reason to change it. +#       s       = Use "smart" interleave factor calculation +#       x       = Use an interleave factor of x, where x is a +#                 number greater than or equal to 1. + +service_interleave_factor=s + + + +# HOST INTER-CHECK DELAY METHOD +# This is the method that Nagios should use when initially +# "spreading out" host checks when it starts monitoring.  The +# default is to use smart delay calculation, which will try to +# space all host checks out evenly to minimize CPU load. +# Using the dumb setting will cause all checks to be scheduled +# at the same time (with no delay between them)! +#	n	= None - don't use any delay between checks +#	d	= Use a "dumb" delay of 1 second between checks +#	s	= Use "smart" inter-check delay calculation +#       x.xx    = Use an inter-check delay of x.xx seconds + +host_inter_check_delay_method=s + + + +# MAXIMUM HOST CHECK SPREAD +# This variable determines the timeframe (in minutes) from the +# program start time that an initial check of all hosts should +# be completed.  Default is 30 minutes. + +max_host_check_spread=30 + + + +# MAXIMUM CONCURRENT SERVICE CHECKS +# This option allows you to specify the maximum number of  +# service checks that can be run in parallel at any given time. +# Specifying a value of 1 for this variable essentially prevents +# any service checks from being parallelized.  A value of 0 +# will not restrict the number of concurrent checks that are +# being executed. + +max_concurrent_checks=0 + + + +# HOST AND SERVICE CHECK REAPER FREQUENCY +# This is the frequency (in seconds!) that Nagios will process +# the results of host and service checks. + +check_result_reaper_frequency=10 + + + + +# MAX CHECK RESULT REAPER TIME +# This is the max amount of time (in seconds) that  a single +# check result reaper event will be allowed to run before  +# returning control back to Nagios so it can perform other +# duties. + +max_check_result_reaper_time=30 + + + + +# CHECK RESULT PATH +# This is directory where Nagios stores the results of host and +# service checks that have not yet been processed. +# +# Note: Make sure that only one instance of Nagios has access +# to this directory!   + +check_result_path=/var/lib/nagios3/spool/checkresults + + + + +# MAX CHECK RESULT FILE AGE +# This option determines the maximum age (in seconds) which check +# result files are considered to be valid.  Files older than this  +# threshold will be mercilessly deleted without further processing. + +max_check_result_file_age=3600 + + + + +# CACHED HOST CHECK HORIZON +# This option determines the maximum amount of time (in seconds) +# that the state of a previous host check is considered current. +# Cached host states (from host checks that were performed more +# recently that the timeframe specified by this value) can immensely +# improve performance in regards to the host check logic. +# Too high of a value for this option may result in inaccurate host +# states being used by Nagios, while a lower value may result in a +# performance hit for host checks.  Use a value of 0 to disable host +# check caching. + +cached_host_check_horizon=15 + + + +# CACHED SERVICE CHECK HORIZON +# This option determines the maximum amount of time (in seconds) +# that the state of a previous service check is considered current. +# Cached service states (from service checks that were performed more +# recently that the timeframe specified by this value) can immensely +# improve performance in regards to predictive dependency checks. +# Use a value of 0 to disable service check caching. + +cached_service_check_horizon=15 + + + +# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS +# This option determines whether or not Nagios will attempt to execute +# checks of hosts when it predicts that future dependency logic test +# may be needed.  These predictive checks can help ensure that your +# host dependency logic works well. +# Values: +#  0 = Disable predictive checks +#  1 = Enable predictive checks (default) + +enable_predictive_host_dependency_checks=1 + + + +# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS +# This option determines whether or not Nagios will attempt to execute +# checks of service when it predicts that future dependency logic test +# may be needed.  These predictive checks can help ensure that your +# service dependency logic works well. +# Values: +#  0 = Disable predictive checks +#  1 = Enable predictive checks (default) + +enable_predictive_service_dependency_checks=1 + + + +# SOFT STATE DEPENDENCIES +# This option determines whether or not Nagios will use soft state  +# information when checking host and service dependencies. Normally  +# Nagios will only use the latest hard host or service state when  +# checking dependencies. If you want it to use the latest state (regardless +# of whether its a soft or hard state type), enable this option.  +# Values: +#  0 = Don't use soft state dependencies (default)  +#  1 = Use soft state dependencies  + +soft_state_dependencies=0 + + + +# TIME CHANGE ADJUSTMENT THRESHOLDS +# These options determine when Nagios will react to detected changes +# in system time (either forward or backwards). + +#time_change_threshold=900 + + + +# AUTO-RESCHEDULING OPTION +# This option determines whether or not Nagios will attempt to +# automatically reschedule active host and service checks to +# "smooth" them out over time.  This can help balance the load on +# the monitoring server.   +# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE +# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY + +auto_reschedule_checks=0 + + + +# AUTO-RESCHEDULING INTERVAL +# This option determines how often (in seconds) Nagios will +# attempt to automatically reschedule checks.  This option only +# has an effect if the auto_reschedule_checks option is enabled. +# Default is 30 seconds. +# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE +# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY + +auto_rescheduling_interval=30 + + + +# AUTO-RESCHEDULING WINDOW +# This option determines the "window" of time (in seconds) that +# Nagios will look at when automatically rescheduling checks. +# Only host and service checks that occur in the next X seconds +# (determined by this variable) will be rescheduled. This option +# only has an effect if the auto_reschedule_checks option is +# enabled.  Default is 180 seconds (3 minutes). +# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE +# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY + +auto_rescheduling_window=180 + + + +# SLEEP TIME +# This is the number of seconds to sleep between checking for system +# events and service checks that need to be run. + +sleep_time=0.25 + + + +# TIMEOUT VALUES +# These options control how much time Nagios will allow various +# types of commands to execute before killing them off.  Options +# are available for controlling maximum time allotted for +# service checks, host checks, event handlers, notifications, the +# ocsp command, and performance data commands.  All values are in +# seconds. + +service_check_timeout=60 +host_check_timeout=30 +event_handler_timeout=30 +notification_timeout=30 +ocsp_timeout=5 +perfdata_timeout=5 + + + +# RETAIN STATE INFORMATION +# This setting determines whether or not Nagios will save state +# information for services and hosts before it shuts down.  Upon +# startup Nagios will reload all saved service and host state +# information before starting to monitor.  This is useful for  +# maintaining long-term data on state statistics, etc, but will +# slow Nagios down a bit when it (re)starts.  Since its only +# a one-time penalty, I think its well worth the additional +# startup delay. + +retain_state_information=1 + + + +# STATE RETENTION FILE +# This is the file that Nagios should use to store host and +# service state information before it shuts down.  The state  +# information in this file is also read immediately prior to +# starting to monitor the network when Nagios is restarted. +# This file is used only if the preserve_state_information +# variable is set to 1. + +state_retention_file=/var/lib/nagios3/retention.dat + + + +# RETENTION DATA UPDATE INTERVAL +# This setting determines how often (in minutes) that Nagios +# will automatically save retention data during normal operation. +# If you set this value to 0, Nagios will not save retention +# data at regular interval, but it will still save retention +# data before shutting down or restarting.  If you have disabled +# state retention, this option has no effect. + +retention_update_interval=60 + + + +# USE RETAINED PROGRAM STATE +# This setting determines whether or not Nagios will set  +# program status variables based on the values saved in the +# retention file.  If you want to use retained program status +# information, set this value to 1.  If not, set this value +# to 0. + +use_retained_program_state=1 + + + +# USE RETAINED SCHEDULING INFO +# This setting determines whether or not Nagios will retain +# the scheduling info (next check time) for hosts and services +# based on the values saved in the retention file.  If you +# If you want to use retained scheduling info, set this +# value to 1.  If not, set this value to 0. + +use_retained_scheduling_info=1 + + + +# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) +# The following variables are used to specify specific host and +# service attributes that should *not* be retained by Nagios during +# program restarts. +# +# The values of the masks are bitwise ANDs of values specified +# by the "MODATTR_" definitions found in include/common.h.   +# For example, if you do not want the current enabled/disabled state +# of flap detection and event handlers for hosts to be retained, you +# would use a value of 24 for the host attribute mask... +# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 + +# This mask determines what host attributes are not retained +retained_host_attribute_mask=0 + +# This mask determines what service attributes are not retained +retained_service_attribute_mask=0 + +# These two masks determine what process attributes are not retained. +# There are two masks, because some process attributes have host and service +# options.  For example, you can disable active host checks, but leave active +# service checks enabled. +retained_process_host_attribute_mask=0 +retained_process_service_attribute_mask=0 + +# These two masks determine what contact attributes are not retained. +# There are two masks, because some contact attributes have host and +# service options.  For example, you can disable host notifications for +# a contact, but leave service notifications enabled for them. +retained_contact_host_attribute_mask=0 +retained_contact_service_attribute_mask=0 + + + +# INTERVAL LENGTH +# This is the seconds per unit interval as used in the +# host/contact/service configuration files.  Setting this to 60 means +# that each interval is one minute long (60 seconds).  Other settings +# have not been tested much, so your mileage is likely to vary... + +interval_length=60 + + + +# AGGRESSIVE HOST CHECKING OPTION +# If you don't want to turn on aggressive host checking features, set +# this value to 0 (the default).  Otherwise set this value to 1 to +# enable the aggressive check option.  Read the docs for more info +# on what aggressive host check is or check out the source code in +# base/checks.c + +use_aggressive_host_checking=0 + + + +# SERVICE CHECK EXECUTION OPTION +# This determines whether or not Nagios will actively execute +# service checks when it initially starts.  If this option is  +# disabled, checks are not actively made, but Nagios can still +# receive and process passive check results that come in.  Unless +# you're implementing redundant hosts or have a special need for +# disabling the execution of service checks, leave this enabled! +# Values: 1 = enable checks, 0 = disable checks + +execute_service_checks=1 + + + +# PASSIVE SERVICE CHECK ACCEPTANCE OPTION +# This determines whether or not Nagios will accept passive +# service checks results when it initially (re)starts. +# Values: 1 = accept passive checks, 0 = reject passive checks + +accept_passive_service_checks=1 + + + +# HOST CHECK EXECUTION OPTION +# This determines whether or not Nagios will actively execute +# host checks when it initially starts.  If this option is  +# disabled, checks are not actively made, but Nagios can still +# receive and process passive check results that come in.  Unless +# you're implementing redundant hosts or have a special need for +# disabling the execution of host checks, leave this enabled! +# Values: 1 = enable checks, 0 = disable checks + +execute_host_checks=1 + + + +# PASSIVE HOST CHECK ACCEPTANCE OPTION +# This determines whether or not Nagios will accept passive +# host checks results when it initially (re)starts. +# Values: 1 = accept passive checks, 0 = reject passive checks + +accept_passive_host_checks=1 + + + +# NOTIFICATIONS OPTION +# This determines whether or not Nagios will sent out any host or +# service notifications when it is initially (re)started. +# Values: 1 = enable notifications, 0 = disable notifications + +enable_notifications=1 + + + +# EVENT HANDLER USE OPTION +# This determines whether or not Nagios will run any host or +# service event handlers when it is initially (re)started.  Unless +# you're implementing redundant hosts, leave this option enabled. +# Values: 1 = enable event handlers, 0 = disable event handlers + +enable_event_handlers=1 + + + +# PROCESS PERFORMANCE DATA OPTION +# This determines whether or not Nagios will process performance +# data returned from service and host checks.  If this option is +# enabled, host performance data will be processed using the +# host_perfdata_command (defined below) and service performance +# data will be processed using the service_perfdata_command (also +# defined below).  Read the HTML docs for more information on +# performance data. +# Values: 1 = process performance data, 0 = do not process performance data + +process_performance_data=0 + + + +# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS +# These commands are run after every host and service check is +# performed.  These commands are executed only if the +# enable_performance_data option (above) is set to 1.  The command +# argument is the short name of a command definition that you  +# define in your host configuration file.  Read the HTML docs for +# more information on performance data. + +#host_perfdata_command=process-host-perfdata +#service_perfdata_command=process-service-perfdata + + + +# HOST AND SERVICE PERFORMANCE DATA FILES +# These files are used to store host and service performance data. +# Performance data is only written to these files if the +# enable_performance_data option (above) is set to 1. + +#host_perfdata_file=/tmp/host-perfdata +#service_perfdata_file=/tmp/service-perfdata + + + +# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES +# These options determine what data is written (and how) to the +# performance data files.  The templates may contain macros, special +# characters (\t for tab, \r for carriage return, \n for newline) +# and plain text.  A newline is automatically added after each write +# to the performance data file.  Some examples of what you can do are +# shown below. + +#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ +#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ + + + +# HOST AND SERVICE PERFORMANCE DATA FILE MODES +# This option determines whether or not the host and service +# performance data files are opened in write ("w") or append ("a") +# mode. If you want to use named pipes, you should use the special +# pipe ("p") mode which avoid blocking at startup, otherwise you will +# likely want the defult append ("a") mode. + +#host_perfdata_file_mode=a +#service_perfdata_file_mode=a + + + +# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL +# These options determine how often (in seconds) the host and service +# performance data files are processed using the commands defined +# below.  A value of 0 indicates the files should not be periodically +# processed. + +#host_perfdata_file_processing_interval=0 +#service_perfdata_file_processing_interval=0 + + + +# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS +# These commands are used to periodically process the host and +# service performance data files.  The interval at which the +# processing occurs is determined by the options above. + +#host_perfdata_file_processing_command=process-host-perfdata-file +#service_perfdata_file_processing_command=process-service-perfdata-file + + + +# OBSESS OVER SERVICE CHECKS OPTION +# This determines whether or not Nagios will obsess over service +# checks and run the ocsp_command defined below.  Unless you're +# planning on implementing distributed monitoring, do not enable +# this option.  Read the HTML docs for more information on +# implementing distributed monitoring. +# Values: 1 = obsess over services, 0 = do not obsess (default) + +obsess_over_services=0 + + + +# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND +# This is the command that is run for every service check that is +# processed by Nagios.  This command is executed only if the +# obsess_over_services option (above) is set to 1.  The command  +# argument is the short name of a command definition that you +# define in your host configuration file. Read the HTML docs for +# more information on implementing distributed monitoring. + +#ocsp_command=somecommand + + + +# OBSESS OVER HOST CHECKS OPTION +# This determines whether or not Nagios will obsess over host +# checks and run the ochp_command defined below.  Unless you're +# planning on implementing distributed monitoring, do not enable +# this option.  Read the HTML docs for more information on +# implementing distributed monitoring. +# Values: 1 = obsess over hosts, 0 = do not obsess (default) + +obsess_over_hosts=0 + + + +# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND +# This is the command that is run for every host check that is +# processed by Nagios.  This command is executed only if the +# obsess_over_hosts option (above) is set to 1.  The command  +# argument is the short name of a command definition that you +# define in your host configuration file. Read the HTML docs for +# more information on implementing distributed monitoring. + +#ochp_command=somecommand + + + +# TRANSLATE PASSIVE HOST CHECKS OPTION +# This determines whether or not Nagios will translate +# DOWN/UNREACHABLE passive host check results into their proper +# state for this instance of Nagios.  This option is useful +# if you have distributed or failover monitoring setup.  In +# these cases your other Nagios servers probably have a different +# "view" of the network, with regards to the parent/child relationship +# of hosts.  If a distributed monitoring server thinks a host +# is DOWN, it may actually be UNREACHABLE from the point of +# this Nagios instance.  Enabling this option will tell Nagios +# to translate any DOWN or UNREACHABLE host states it receives +# passively into the correct state from the view of this server. +# Values: 1 = perform translation, 0 = do not translate (default) + +translate_passive_host_checks=0 + + + +# PASSIVE HOST CHECKS ARE SOFT OPTION +# This determines whether or not Nagios will treat passive host +# checks as being HARD or SOFT.  By default, a passive host check +# result will put a host into a HARD state type.  This can be changed +# by enabling this option. +# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT + +passive_host_checks_are_soft=0 + + + +# ORPHANED HOST/SERVICE CHECK OPTIONS +# These options determine whether or not Nagios will periodically  +# check for orphaned host service checks.  Since service checks are +# not rescheduled until the results of their previous execution  +# instance are processed, there exists a possibility that some +# checks may never get rescheduled.  A similar situation exists for +# host checks, although the exact scheduling details differ a bit +# from service checks.  Orphaned checks seem to be a rare +# problem and should not happen under normal circumstances. +# If you have problems with service checks never getting +# rescheduled, make sure you have orphaned service checks enabled. +# Values: 1 = enable checks, 0 = disable checks + +check_for_orphaned_services=1 +check_for_orphaned_hosts=1 + + + +# SERVICE FRESHNESS CHECK OPTION +# This option determines whether or not Nagios will periodically +# check the "freshness" of service results.  Enabling this option +# is useful for ensuring passive checks are received in a timely +# manner. +# Values: 1 = enabled freshness checking, 0 = disable freshness checking + +check_service_freshness=1 + + + +# SERVICE FRESHNESS CHECK INTERVAL +# This setting determines how often (in seconds) Nagios will +# check the "freshness" of service check results.  If you have +# disabled service freshness checking, this option has no effect. + +service_freshness_check_interval=60 + + + +# HOST FRESHNESS CHECK OPTION +# This option determines whether or not Nagios will periodically +# check the "freshness" of host results.  Enabling this option +# is useful for ensuring passive checks are received in a timely +# manner. +# Values: 1 = enabled freshness checking, 0 = disable freshness checking + +check_host_freshness=0 + + + +# HOST FRESHNESS CHECK INTERVAL +# This setting determines how often (in seconds) Nagios will +# check the "freshness" of host check results.  If you have +# disabled host freshness checking, this option has no effect. + +host_freshness_check_interval=60 + + + + +# ADDITIONAL FRESHNESS THRESHOLD LATENCY +# This setting determines the number of seconds that Nagios +# will add to any host and service freshness thresholds that +# it calculates (those not explicitly specified by the user). + +additional_freshness_latency=15 + + + + +# FLAP DETECTION OPTION +# This option determines whether or not Nagios will try +# and detect hosts and services that are "flapping".   +# Flapping occurs when a host or service changes between +# states too frequently.  When Nagios detects that a  +# host or service is flapping, it will temporarily suppress +# notifications for that host/service until it stops +# flapping.  Flap detection is very experimental, so read +# the HTML documentation before enabling this feature! +# Values: 1 = enable flap detection +#         0 = disable flap detection (default) + +enable_flap_detection=1 + + + +# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES +# Read the HTML documentation on flap detection for +# an explanation of what this option does.  This option +# has no effect if flap detection is disabled. + +low_service_flap_threshold=5.0 +high_service_flap_threshold=20.0 +low_host_flap_threshold=5.0 +high_host_flap_threshold=20.0 + + + +# DATE FORMAT OPTION +# This option determines how short dates are displayed. Valid options +# include: +#	us		(MM-DD-YYYY HH:MM:SS) +#	euro    	(DD-MM-YYYY HH:MM:SS) +#	iso8601		(YYYY-MM-DD HH:MM:SS) +#	strict-iso8601	(YYYY-MM-DDTHH:MM:SS) +# + +date_format=iso8601 + + + + +# TIMEZONE OFFSET +# This option is used to override the default timezone that this +# instance of Nagios runs in.  If not specified, Nagios will use +# the system configured timezone. +# +# NOTE: In order to display the correct timezone in the CGIs, you +# will also need to alter the Apache directives for the CGI path  +# to include your timezone.  Example: +# +#   <Directory "/usr/local/nagios/sbin/"> +#      SetEnv TZ "Australia/Brisbane" +#      ... +#   </Directory> + +#use_timezone=US/Mountain +#use_timezone=Australia/Brisbane + + + + +# P1.PL FILE LOCATION +# This value determines where the p1.pl perl script (used by the +# embedded Perl interpreter) is located.  If you didn't compile +# Nagios with embedded Perl support, this option has no effect. + +p1_file=/usr/lib/nagios3/p1.pl + + + +# EMBEDDED PERL INTERPRETER OPTION +# This option determines whether or not the embedded Perl interpreter +# will be enabled during runtime.  This option has no effect if Nagios +# has not been compiled with support for embedded Perl. +# Values: 0 = disable interpreter, 1 = enable interpreter + +enable_embedded_perl=1 + + + +# EMBEDDED PERL USAGE OPTION +# This option determines whether or not Nagios will process Perl plugins +# and scripts with the embedded Perl interpreter if the plugins/scripts +# do not explicitly indicate whether or not it is okay to do so. Read +# the HTML documentation on the embedded Perl interpreter for more  +# information on how this option works. + +use_embedded_perl_implicitly=1 + + + +# ILLEGAL OBJECT NAME CHARACTERS +# This option allows you to specify illegal characters that cannot +# be used in host names, service descriptions, or names of other +# object types. + +illegal_object_name_chars=`~!$%^&*|'"<>?,()= + + + +# ILLEGAL MACRO OUTPUT CHARACTERS +# This option allows you to specify illegal characters that are +# stripped from macros before being used in notifications, event +# handlers, etc.  This DOES NOT affect macros used in service or +# host check commands. +# The following macros are stripped of the characters you specify: +#	$HOSTOUTPUT$ +#	$HOSTPERFDATA$ +#	$HOSTACKAUTHOR$ +#	$HOSTACKCOMMENT$ +#	$SERVICEOUTPUT$ +#	$SERVICEPERFDATA$ +#	$SERVICEACKAUTHOR$ +#	$SERVICEACKCOMMENT$ + +illegal_macro_output_chars=`~$&|'"<> + + + +# REGULAR EXPRESSION MATCHING +# This option controls whether or not regular expression matching +# takes place in the object config files.  Regular expression +# matching is used to match host, hostgroup, service, and service +# group names/descriptions in some fields of various object types. +# Values: 1 = enable regexp matching, 0 = disable regexp matching + +use_regexp_matching=0 + + + +# "TRUE" REGULAR EXPRESSION MATCHING +# This option controls whether or not "true" regular expression  +# matching takes place in the object config files.  This option +# only has an effect if regular expression matching is enabled +# (see above).  If this option is DISABLED, regular expression +# matching only occurs if a string contains wildcard characters +# (* and ?).  If the option is ENABLED, regexp matching occurs +# all the time (which can be annoying). +# Values: 1 = enable true matching, 0 = disable true matching + +use_true_regexp_matching=0 + + + +# ADMINISTRATOR EMAIL/PAGER ADDRESSES +# The email and pager address of a global administrator (likely you). +# Nagios never uses these values itself, but you can access them by +# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification +# commands. + +admin_email=root@localhost +admin_pager=pageroot@localhost + + + +# DAEMON CORE DUMP OPTION +# This option determines whether or not Nagios is allowed to create +# a core dump when it runs as a daemon.  Note that it is generally +# considered bad form to allow this, but it may be useful for +# debugging purposes.  Enabling this option doesn't guarantee that +# a core file will be produced, but that's just life... +# Values: 1 - Allow core dumps +#         0 - Do not allow core dumps (default) + +daemon_dumps_core=0 + + + +# LARGE INSTALLATION TWEAKS OPTION +# This option determines whether or not Nagios will take some shortcuts +# which can save on memory and CPU usage in large Nagios installations. +# Read the documentation for more information on the benefits/tradeoffs +# of enabling this option. +# Values: 1 - Enabled tweaks +#         0 - Disable tweaks (default) + +use_large_installation_tweaks=0 + + + +# ENABLE ENVIRONMENT MACROS +# This option determines whether or not Nagios will make all standard +# macros available as environment variables when host/service checks +# and system commands (event handlers, notifications, etc.) are +# executed.  Enabling this option can cause performance issues in  +# large installations, as it will consume a bit more memory and (more +# importantly) consume more CPU. +# Values: 1 - Enable environment variable macros (default) +#         0 - Disable environment variable macros + +enable_environment_macros=1 + + + +# CHILD PROCESS MEMORY OPTION +# This option determines whether or not Nagios will free memory in +# child processes (processed used to execute system commands and host/ +# service checks).  If you specify a value here, it will override +# program defaults. +# Value: 1 - Free memory in child processes +#        0 - Do not free memory in child processes + +#free_child_process_memory=1 + + + +# CHILD PROCESS FORKING BEHAVIOR +# This option determines how Nagios will fork child processes +# (used to execute system commands and host/service checks).  Normally +# child processes are fork()ed twice, which provides a very high level +# of isolation from problems.  Fork()ing once is probably enough and will +# save a great deal on CPU usage (in large installs), so you might +# want to consider using this.  If you specify a value here, it will +# program defaults. +# Value: 1 - Child processes fork() twice +#        0 - Child processes fork() just once + +#child_processes_fork_twice=1 + + + +# DEBUG LEVEL +# This option determines how much (if any) debugging information will +# be written to the debug file.  OR values together to log multiple +# types of information. +# Values:  +#          -1 = Everything +#          0 = Nothing +#	   1 = Functions +#          2 = Configuration +#          4 = Process information +#	   8 = Scheduled events +#          16 = Host/service checks +#          32 = Notifications +#          64 = Event broker +#          128 = External commands +#          256 = Commands +#          512 = Scheduled downtime +#          1024 = Comments +#          2048 = Macros + +debug_level=0 + + + +# DEBUG VERBOSITY +# This option determines how verbose the debug log out will be. +# Values: 0 = Brief output +#         1 = More detailed +#         2 = Very detailed + +debug_verbosity=1 + + + +# DEBUG FILE +# This option determines where Nagios should write debugging information. + +debug_file=/var/lib/nagios3/nagios.debug + + + +# MAX DEBUG FILE SIZE +# This option determines the maximum size (in bytes) of the debug file.  If +# the file grows larger than this size, it will be renamed with a .old +# extension.  If a file already exists with a .old extension it will +# automatically be deleted.  This helps ensure your disk space usage doesn't +# get out of control when debugging Nagios. + +max_debug_file_size=1000000 + + diff --git a/puppet/modules/nagios/files/configs/Debian/private/resource.cfg.amd64 b/puppet/modules/nagios/files/configs/Debian/private/resource.cfg.amd64 new file mode 100644 index 00000000..3ed732bb --- /dev/null +++ b/puppet/modules/nagios/files/configs/Debian/private/resource.cfg.amd64 @@ -0,0 +1,31 @@ +########################################################################### +# +# RESOURCE.CFG - Resource File for Nagios  +# +# You can define $USERx$ macros in this file, which can in turn be used +# in command definitions in your host config file(s).  $USERx$ macros are +# useful for storing sensitive information such as usernames, passwords,  +# etc.  They are also handy for specifying the path to plugins and  +# event handlers - if you decide to move the plugins or event handlers to +# a different directory in the future, you can just update one or two +# $USERx$ macros, instead of modifying a lot of command definitions. +# +# The CGIs will not attempt to read the contents of resource files, so +# you can set restrictive permissions (600 or 660) on them. +# +# Nagios supports up to 32 $USERx$ macros ($USER1$ through $USER32$) +# +# Resource files may also be used to store configuration directives for +# external data sources like MySQL... +# +########################################################################### + +# Sets $USER1$ to be the path to the plugins +$USER1$=/usr/lib/nagios/plugins + +# Sets $USER2$ to be the path to event handlers +#$USER2$=/usr/lib/nagios/plugins/eventhandlers + +# Store some usernames and passwords (hidden from the CGIs) +#$USER3$=someuser +#$USER4$=somepassword diff --git a/puppet/modules/nagios/files/configs/Debian/private/resource.cfg.i386 b/puppet/modules/nagios/files/configs/Debian/private/resource.cfg.i386 new file mode 100644 index 00000000..3ed732bb --- /dev/null +++ b/puppet/modules/nagios/files/configs/Debian/private/resource.cfg.i386 @@ -0,0 +1,31 @@ +########################################################################### +# +# RESOURCE.CFG - Resource File for Nagios  +# +# You can define $USERx$ macros in this file, which can in turn be used +# in command definitions in your host config file(s).  $USERx$ macros are +# useful for storing sensitive information such as usernames, passwords,  +# etc.  They are also handy for specifying the path to plugins and  +# event handlers - if you decide to move the plugins or event handlers to +# a different directory in the future, you can just update one or two +# $USERx$ macros, instead of modifying a lot of command definitions. +# +# The CGIs will not attempt to read the contents of resource files, so +# you can set restrictive permissions (600 or 660) on them. +# +# Nagios supports up to 32 $USERx$ macros ($USER1$ through $USER32$) +# +# Resource files may also be used to store configuration directives for +# external data sources like MySQL... +# +########################################################################### + +# Sets $USER1$ to be the path to the plugins +$USER1$=/usr/lib/nagios/plugins + +# Sets $USER2$ to be the path to event handlers +#$USER2$=/usr/lib/nagios/plugins/eventhandlers + +# Store some usernames and passwords (hidden from the CGIs) +#$USER3$=someuser +#$USER4$=somepassword diff --git a/puppet/modules/nagios/files/configs/Debian/private/resource.cfg.x86_64 b/puppet/modules/nagios/files/configs/Debian/private/resource.cfg.x86_64 new file mode 100644 index 00000000..3ed732bb --- /dev/null +++ b/puppet/modules/nagios/files/configs/Debian/private/resource.cfg.x86_64 @@ -0,0 +1,31 @@ +########################################################################### +# +# RESOURCE.CFG - Resource File for Nagios  +# +# You can define $USERx$ macros in this file, which can in turn be used +# in command definitions in your host config file(s).  $USERx$ macros are +# useful for storing sensitive information such as usernames, passwords,  +# etc.  They are also handy for specifying the path to plugins and  +# event handlers - if you decide to move the plugins or event handlers to +# a different directory in the future, you can just update one or two +# $USERx$ macros, instead of modifying a lot of command definitions. +# +# The CGIs will not attempt to read the contents of resource files, so +# you can set restrictive permissions (600 or 660) on them. +# +# Nagios supports up to 32 $USERx$ macros ($USER1$ through $USER32$) +# +# Resource files may also be used to store configuration directives for +# external data sources like MySQL... +# +########################################################################### + +# Sets $USER1$ to be the path to the plugins +$USER1$=/usr/lib/nagios/plugins + +# Sets $USER2$ to be the path to event handlers +#$USER2$=/usr/lib/nagios/plugins/eventhandlers + +# Store some usernames and passwords (hidden from the CGIs) +#$USER3$=someuser +#$USER4$=somepassword diff --git a/puppet/modules/nagios/files/configs/apache2.conf b/puppet/modules/nagios/files/configs/apache2.conf new file mode 100644 index 00000000..f0f8b2f3 --- /dev/null +++ b/puppet/modules/nagios/files/configs/apache2.conf @@ -0,0 +1,67 @@ +# apache configuration for nagios 3.x +# note to users of nagios 1.x and 2.x: +#	throughout this file are commented out sections which preserve +#	backwards compatibility with bookmarks/config for older nagios versios. +#	simply look for lines following "nagios 1.x:" and "nagios 2.x" comments. + +ScriptAlias /cgi-bin/nagios3 /usr/lib/cgi-bin/nagios3 +ScriptAlias /nagios3/cgi-bin /usr/lib/cgi-bin/nagios3 +# nagios 1.x: +#ScriptAlias /cgi-bin/nagios /usr/lib/cgi-bin/nagios3 +#ScriptAlias /nagios/cgi-bin /usr/lib/cgi-bin/nagios3 +# nagios 2.x:  +#ScriptAlias /cgi-bin/nagios2 /usr/lib/cgi-bin/nagios3 +#ScriptAlias /nagios2/cgi-bin /usr/lib/cgi-bin/nagios3 + +# Where the stylesheets (config files) reside +Alias /nagios3/stylesheets /etc/nagios3/stylesheets +# nagios 1.x: +#Alias /nagios/stylesheets /etc/nagios3/stylesheets +# nagios 2.x: +#Alias /nagios2/stylesheets /etc/nagios3/stylesheets + +# Where the HTML pages live +Alias /nagios3 /usr/share/nagios3/htdocs +# nagios 2.x:  +#Alias /nagios2 /usr/share/nagios3/htdocs +# nagios 1.x: +#Alias /nagios /usr/share/nagios3/htdocs + +<DirectoryMatch (/usr/share/nagios3/htdocs|/usr/lib/cgi-bin/nagios3|/etc/nagios3/stylesheets)> +	Options FollowSymLinks + +	DirectoryIndex index.php index.html + +	AllowOverride AuthConfig + + +    <IfVersion < 2.3> +        Order Allow,Deny +        Allow From All +    </IfVersion> + +    <IfVersion >= 2.3> +        Require all denied +    </IfVersion> + +	AuthName "Nagios Access" +	AuthType Basic +	AuthUserFile /etc/nagios3/htpasswd.users +	# nagios 1.x: +	#AuthUserFile /etc/nagios/htpasswd.users +	require valid-user +</DirectoryMatch> + +<Directory /usr/share/nagios3/htdocs> +	Options	+ExecCGI	 +</Directory> + +# Enable this ScriptAlias if you want to enable the grouplist patch. +# See http://apan.sourceforge.net/download.html for more info +# It allows you to see a clickable list of all hostgroups in the +# left pane of the Nagios web interface +# XXX This is not tested for nagios 2.x use at your own peril +#ScriptAlias /nagios3/side.html /usr/lib/cgi-bin/nagios3/grouplist.cgi +# nagios 1.x: +#ScriptAlias /nagios/side.html /usr/lib/cgi-bin/nagios3/grouplist.cgi + diff --git a/puppet/modules/nagios/files/configs/cgi.cfg b/puppet/modules/nagios/files/configs/cgi.cfg new file mode 120000 index 00000000..db9667b3 --- /dev/null +++ b/puppet/modules/nagios/files/configs/cgi.cfg @@ -0,0 +1 @@ +Debian/cgi.cfg
\ No newline at end of file diff --git a/puppet/modules/nagios/files/configs/nagios.cfg b/puppet/modules/nagios/files/configs/nagios.cfg new file mode 120000 index 00000000..1409b9e8 --- /dev/null +++ b/puppet/modules/nagios/files/configs/nagios.cfg @@ -0,0 +1 @@ +Debian/nagios.cfg
\ No newline at end of file diff --git a/puppet/modules/nagios/files/configs/nagios_templates.cfg b/puppet/modules/nagios/files/configs/nagios_templates.cfg new file mode 100644 index 00000000..98596713 --- /dev/null +++ b/puppet/modules/nagios/files/configs/nagios_templates.cfg @@ -0,0 +1,49 @@ +define host{ +    name                            generic-host    ; The name of this host template +    notifications_enabled           1       ; Host notifications are enabled +    event_handler_enabled           1       ; Host event handler is enabled +    flap_detection_enabled          1       ; Flap detection is enabled +    failure_prediction_enabled      1       ; Failure prediction is enabled +    process_perf_data               1       ; Process performance data +    retain_status_information       1       ; Retain status information across program restarts +    retain_nonstatus_information    1       ; Retain non-status information across program restarts +    check_command                   check-host-alive +    max_check_attempts              10 +    notification_interval           0 +    notification_period             24x7 +    notification_options            d,u,r +    contact_groups                  admins +    register                        0       ; DONT REGISTER THIS DEFINITION - ITS NOT A REAL HOST, JUST A TEMPLATE! +} + +define service{ +    name                            generic-service ; The 'name' of this service template +    active_checks_enabled           1       ; Active service checks are enabled +    passive_checks_enabled          1       ; Passive service checks are enabled/accepted +    parallelize_check               1       ; Active service checks should be parallelized (disabling this can lead to major performance problems) +    obsess_over_service             1       ; We should obsess over this service (if necessary) +    check_freshness                 0       ; Default is to NOT check service 'freshness' +    notifications_enabled           1       ; Service notifications are enabled +    event_handler_enabled           1       ; Service event handler is enabled +    flap_detection_enabled          1       ; Flap detection is enabled +    failure_prediction_enabled      1       ; Failure prediction is enabled +    process_perf_data               1       ; Process performance data +    retain_status_information       1       ; Retain status information across program restarts +    retain_nonstatus_information    1       ; Retain non-status information across program restarts +    notification_interval           0		; Only send notifications on status change by default. +    is_volatile                     0 +    check_period                    24x7 +    normal_check_interval           5 +    retry_check_interval            1 +    max_check_attempts              4 +    notification_period             24x7 +    notification_options            w,u,c,r +    contact_groups                  admins +    register                        0       ; DONT REGISTER THIS DEFINITION - ITS NOT A REAL SERVICE, JUST A TEMPLATE! +} + +define service{ +    name                            passive-service +    use                             generic-service +    active_checks_enabled           0 +} diff --git a/puppet/modules/nagios/files/htpasswd.users b/puppet/modules/nagios/files/htpasswd.users new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/puppet/modules/nagios/files/htpasswd.users diff --git a/puppet/modules/nagios/files/irc_bot/riseup-nagios-client.pl b/puppet/modules/nagios/files/irc_bot/riseup-nagios-client.pl new file mode 100644 index 00000000..2467058d --- /dev/null +++ b/puppet/modules/nagios/files/irc_bot/riseup-nagios-client.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl -w + +# ############################################################################## +# Infrabot-Client - a simple Infrabot client which sends it's whole command +# line arguments to a local UNIX domain socket. +# ############################################################################## + +use strict; +use IO::Socket; + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# >> CONFIGURATION >> + +# Read a configuration file +#   The arg can be a relative or full path, or +#   it can be a file located somewhere in @INC. +sub ReadCfg +{ +    my $file = $_[0]; + +    our $err; + +    {   # Put config data into a separate namespace +        package CFG; + +        # Process the contents of the config file +        my $rc = do($file); + +        # Check for errors +        if ($@) { +            $::err = "ERROR: Failure compiling '$file' - $@"; +        } elsif (! defined($rc)) { +            $::err = "ERROR: Failure reading '$file' - $!"; +        } elsif (! $rc) { +            $::err = "ERROR: Failure processing '$file'"; +        } +    } + +    return ($err); +} + +# Get our configuration information +if (my $err = ReadCfg('/etc/nagios_nsa.cfg')) { +    print(STDERR $err, "\n"); +    exit(1); +} + +# << CONFIGURATION << +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +if (@ARGV == 0) { +	print "Hey - specify a message, sucker!\n"; +	exit(1); +} + +unless (-S $CFG::Nsa{'socket'}) { +	die "Socket '$CFG::Nsa{'socket'}' doesn't exist or isn't a socket!\n"; +} + +unless (-r $CFG::Nsa{'socket'}) { +	die "Socket '$CFG::Nsa{'socket'}' can't be read!\n"; +} + +my $sock = IO::Socket::UNIX->new ( +	Peer    => $CFG::Nsa{'socket'}, +	Type    => SOCK_DGRAM, +	Timeout => 10 +) || die "Can't open socket '$CFG::Nsa{'socket'}'!\n"; + +print $sock "@ARGV"; +close($sock); diff --git a/puppet/modules/nagios/files/irc_bot/riseup-nagios-server.pl b/puppet/modules/nagios/files/irc_bot/riseup-nagios-server.pl new file mode 100644 index 00000000..5d65e6dd --- /dev/null +++ b/puppet/modules/nagios/files/irc_bot/riseup-nagios-server.pl @@ -0,0 +1,239 @@ +#!/usr/bin/perl -w + +# ############################################################################## +# a simple IRC bot which dispatches messages received via local domain sockets +# ############################################################################## + + +###### +## THIS NEEDS TO BE PORTED TO THE NEW FRAMEWORKS! +## +## STICKY POINTS: the addfh() function doesn't exist in BasicBot or POE::Component::IRC +## +## people suggested we use Anyevent::IRC and POE::Kernel ->select_read and POE::Wheel namespace +## +## in the meantime, inspiration for extensions can be found here: http://svn.foswiki.org/trunk/WikiBot/mozbot.pl + +use strict; +use File::Basename; + +BEGIN { +	unshift @INC, dirname($0); +} + +my $VERSION = '0.2'; +my $running = 1; + +# Read a configuration file +#   The arg can be a relative or full path, or +#   it can be a file located somewhere in @INC. +sub ReadCfg +{ +    my $file = $_[0]; + +    our $err; + +    {   # Put config data into a separate namespace +        package CFG; + +        # Process the contents of the config file +        my $rc = do($file); + +        # Check for errors +        if ($@) { +            $::err = "ERROR: Failure compiling '$file' - $@"; +        } elsif (! defined($rc)) { +            $::err = "ERROR: Failure reading '$file' - $!"; +        } elsif (! $rc) { +            $::err = "ERROR: Failure processing '$file'"; +        } +    } + +    return ($err); +} + +# Get our configuration information +if (my $err = ReadCfg('/etc/nagios_nsa.cfg')) { +    print(STDERR $err, "\n"); +    exit(1); +} + +use POSIX qw(setsid); +use IO::Socket; +use Net::IRC; + +sub new { +	my $self = { +		socket => undef, +		irc => undef, +		conn => undef, +		commandfile => undef, +	}; + +	return bless($self, __PACKAGE__); +} + +sub daemonize { +	my $self = shift; +	my $pid; + +	chdir '/' or die "Can't chdir to /: $!"; + +	open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; +	open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; + +	defined ($pid = fork) or die "Can't fork: $!"; + +	if ($pid && $CFG::Nsa{'pidfile'}) { # write pid of child +		open PID, ">$CFG::Nsa{'pidfile'}" or die "Can't open pid file: $!"; +		print PID $pid; +		close PID; +	} +	exit if $pid; +	setsid or die "Can't start a new session: $!"; + +	#open STDERR, '>&STDOUT' or die "Can't dup stdout: $!"; +} + +sub run { +	my $self = shift; + +	$self->{irc}->do_one_loop(); +} + +sub shutdown { +	my $sig = shift; + +	print STDERR "Received SIG$sig, shutting down...\n"; +	$running = 0; +} + +sub socket_has_data { +    my $self = shift; +     +    $self->{socket}->recv(my $data, 1024); +    if ($CFG::Nsa{'usenotices'}) { +	$self->{conn}->notice($CFG::Nsa{'channel'}, $data); +    } else { +	$self->{conn}->privmsg($CFG::Nsa{'channel'}, $data); +    } +} + +sub irc_on_connect { +	my $self = shift; + +	print STDERR "Joining channel '$CFG::Nsa{'channel'}'...\n"; +	$self->join($CFG::Nsa{'channel'}); +} + +sub irc_on_msg { +    my ($self, $event) = @_; +    my $data = join(' ', $event->args); +    #my $nick = quotemeta($nicks[$nick]); +    my $to = $event->to; +    #my $channel = &toToChannel($self, @$to); +    #my $cmdChar = $commandChar{default}; # FIXME: should look up for CURRENT channel first! +    #if ( exists $commandChar{$channel} ) { $cmdChar = $commandChar{$channel}; } +    my $msg = parse_msg($event); +    if (defined($msg)) { +      #$self->privmsg($event->nick, "alright, sending this message to nagios, hope it figures it out: $msg"); +    } else { +      $self->privmsg($event->nick, "can't parse $data, you want 'ack host service comment'\n"); +    } +} + +sub irc_on_public { +    my ($self, $event) = @_; +    my $data = join(' ', $event->args); +    my $to = $event->to; +    if ($data =~ s/([^:]*):\s+//) { +      if ($1 eq $CFG::Nsa{'nickname'}) { +        my $msg = parse_msg($event); +        if (defined($msg)) { +          #$self->privmsg($event->to, "alright, sending this message to nagios, hope it figures it out: $msg"); +        } else { +          $self->privmsg($event->to, "can't parse $data, you want 'ack host service comment'\n"); +        } +      } else { +        #print STDERR "ignoring message $data, not for me (me being $1)\n"; +      } +    } else { +      #print STDERR "ignoring message $data\n"; +    } +} + +sub parse_msg { +    my $event= shift; +    my $data = join(' ', $event->args); +    my $msg; +    if ($data =~ m/([^:]*:)?\s*ack(?:knowledge)?\s+([a-zA-Z0-9\-\.]+)(?:\s+([-\w\.]+)(?:\s+([\w\s]+))?)?/) { +      #print STDERR "writing to nagios scoket ". $CFG::Nsa{'commandfile'} . "\n"; +      open(my $cmdfile, ">", $CFG::Nsa{'commandfile'}) || die "Can't open Nagios commandfile: $CFG::Nsa{'commandfile'}!\n"; +      my $host = $2; +      my ($service, $comment) = (undef, "no comment (from irc)"); +      if ($4) { +        $service = $3; +	$comment = $4; +      } elsif ($3) { +        $service = $3; +      } +      my $user = $event->nick; +      $msg = '[' . time() . '] '; +      if (defined($service)) { +        $msg .= "ACKNOWLEDGE_SVC_PROBLEM;$host;$service;1;1;1;$user;$comment\n"; +      } else { +        $msg .= "ACKNOWLEDGE_HOST_PROBLEM;$host;1;1;1;$user;$comment\n"; +      } +      print {$cmdfile} $msg; +      close($cmdfile); +    } +    return $msg; +} + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +my $bot = &new; + +if (-e $CFG::Nsa{'socket'}) { +	die "Socket '$CFG::Nsa{'socket'}' exists!\n"; +} + +$bot->{socket} = IO::Socket::UNIX->new ( +	Local  => $CFG::Nsa{'socket'}, +	Type   => SOCK_DGRAM, +	Listen => 5 +) || die "Can't create socket '$CFG::Nsa{'socket'}'!\n"; + +$SIG{INT} = $SIG{TERM} = \&shutdown; + +$bot->daemonize(); +$bot->{irc} = new Net::IRC; + +$bot->{conn} = $bot->{irc}->newconn ( +	Server   => $CFG::Nsa{'server'}, +	Port     => $CFG::Nsa{'port'}, +	Nick     => $CFG::Nsa{'nickname'}, +	Username => $CFG::Nsa{'nickname'}, +	Password => $CFG::Nsa{'password'}, +	Ircname  => $CFG::Nsa{'realname'} . " (NSA $VERSION)", +) || die "Can't connect to server '$CFG::Nsa{'server'}'!\n"; + +$bot->{conn}->add_global_handler(376, \&irc_on_connect); +$bot->{conn}->add_global_handler('nomotd', \&irc_on_connect); +$bot->{conn}->add_global_handler('msg', \&irc_on_msg); +$bot->{conn}->add_global_handler('public', \&irc_on_public); +#$bot->{conn}->add_global_handler('notice', \&irc_on_msg); +$bot->{irc}->addfh($bot->{socket}, \&socket_has_data, 'r', $bot); + +while ($running) { +	$bot->run(); +} + +close($bot->{socket}); +unlink($CFG::Nsa{'socket'}); + +exit(0); + +1; + +__END__ diff --git a/puppet/modules/nagios/files/munin/nagios_hosts b/puppet/modules/nagios/files/munin/nagios_hosts new file mode 100644 index 00000000..3fa00f1d --- /dev/null +++ b/puppet/modules/nagios/files/munin/nagios_hosts @@ -0,0 +1,32 @@ +#!/bin/bash + +if [ -z "$nag_stats_binary" ]; then +    nag_stats_binary=/usr/sbin/nagios3stats +fi + +if [ "$1" = "config" ]; then +	echo 'graph_title Nagios host stats' +	echo 'graph_args --base 1000 -l 0' +	echo 'graph_vlabel hosts' +	echo 'graph_category nagios' +	echo 'graph_info The number of hosts checked by nagios' +	echo 'up.label up' +	echo 'up.draw AREA' +	echo 'up.info number of hosts UP' +	echo 'down.label down' +	echo 'down.draw STACK' +	echo 'down.info number of hosts DOWN' +	echo 'unr.label unr' +	echo 'unr.draw STACK' +	echo 'unr.info number of hosts UNREACHABLE' + +	exit 0 +fi + +echo -n 'up.value ' +$nag_stats_binary --mrtg --data NUMHSTUP +echo -n 'down.value ' +$nag_stats_binary --mrtg --data NUMHSTDOWN +echo -n 'unr.value ' +$nag_stats_binary --mrtg --data NUMHSTUNR + diff --git a/puppet/modules/nagios/files/munin/nagios_perf b/puppet/modules/nagios/files/munin/nagios_perf new file mode 100644 index 00000000..609d62f4 --- /dev/null +++ b/puppet/modules/nagios/files/munin/nagios_perf @@ -0,0 +1,38 @@ +#!/bin/bash + +if [ -z "$nag_stats_binary" ]; then +    nag_stats_binary=/usr/sbin/nagios3stats +fi + +NAME=$(basename $0) + +TYPE=${NAME##nagios_perf_} + +[ "x$TYPE" = 'xhosts' ] && TYPE_ABBR=HST +[ "x$TYPE" = 'xsvc' ] && TYPE_ABBR=SVC +[ -z "$TYPE_ABBR" ] && echo "unknown type $TYPE" >&2 && exit 1 + +if [ "$1" = "config" ]; then +	echo "graph_title Nagios $TYPE performance stats" +	echo "graph_args --base 1000" +	echo "graph_vlabel seconds" +	echo "graph_category nagios" +	echo "graph_info Check performance statistics" + +	echo "act_lat_$TYPE_ABBR.label act lat" +	echo "act_lat_$TYPE_ABBR.type GAUGE" +	echo "act_lat_$TYPE_ABBR.draw AREA" +	echo "act_lat_$TYPE_ABBR.cdef act_lat_$TYPE_ABBR,1000,/" +	echo "act_lat_$TYPE_ABBR.info average latency of active checks over the last 5 minutes" + +	echo "act_ext_$TYPE_ABBR.label act ext" +	echo "act_ext_$TYPE_ABBR.type GAUGE" +	echo "act_ext_$TYPE_ABBR.draw LINE1" +	echo "act_ext_$TYPE_ABBR.cdef act_ext_$TYPE_ABBR,1000,/" +	echo "act_ext_$TYPE_ABBR.info average execution time of active checks over the last 5 minutes" + +	exit 0 +fi + +echo "act_lat_$TYPE_ABBR.value " $($nag_stats_binary --mrtg --data AVGACT${TYPE_ABBR}LAT) +echo "act_ext_$TYPE_ABBR.value " $($nag_stats_binary --mrtg --data AVGACT${TYPE_ABBR}EXT) diff --git a/puppet/modules/nagios/files/munin/nagios_svc b/puppet/modules/nagios/files/munin/nagios_svc new file mode 100644 index 00000000..97c8bfc1 --- /dev/null +++ b/puppet/modules/nagios/files/munin/nagios_svc @@ -0,0 +1,37 @@ +#!/bin/bash + +if [ -z "$nag_stats_binary" ]; then +    nag_stats_binary=/usr/sbin/nagios3stats +fi + +if [ "$1" = "config" ]; then +	echo 'graph_title Nagios service stats' +	echo 'graph_args --base 1000 -l 0' +	echo 'graph_vlabel services' +	echo 'graph_category nagios' +	echo 'graph_info The number of services checked by nagios' +	echo 'ok.label ok' +	echo 'ok.draw AREA' +	echo 'ok.info number of services OK' +	echo 'warn.label warn' +	echo 'warn.draw STACK' +	echo 'warn.info number of services WARNING' +	echo 'crit.label crit' +	echo 'crit.draw STACK' +	echo 'crit.info number of services CRITICAL' +	echo 'unkn.label unkn' +	echo 'unkn.draw STACK' +	echo 'unkn.info number of services UNKNOWN' + +	exit 0 +fi + +echo -n 'ok.value ' +$nag_stats_binary --mrtg --data NUMSVCOK +echo -n 'warn.value ' +$nag_stats_binary --mrtg --data NUMSVCWARN +echo -n 'crit.value ' +$nag_stats_binary --mrtg --data NUMSVCCRIT +echo -n 'unkn.value ' +$nag_stats_binary --mrtg --data NUMSVCUNKN + diff --git a/puppet/modules/nagios/files/nrpe/nrpe_commands.cfg b/puppet/modules/nagios/files/nrpe/nrpe_commands.cfg new file mode 100644 index 00000000..b725a36a --- /dev/null +++ b/puppet/modules/nagios/files/nrpe/nrpe_commands.cfg @@ -0,0 +1,5 @@ +# default plugins +command[check_users]=/usr/lib/nagios/plugins/check_users $ARG1$  +command[check_disk]=/usr/lib/nagios/plugins/check_disk $ARG1$ -x "/dev" -x "/dev/shm" -x "/lib/init/rw"  +command[check_apt]=sudo /usr/lib/nagios/plugins/check_apt -u $ARG1$ +command[check_swap]=/usr/lib/nagios/plugins/check_swap $ARG1$  diff --git a/puppet/modules/nagios/files/nsca/nsca.cfg b/puppet/modules/nagios/files/nsca/nsca.cfg new file mode 100644 index 00000000..0b019ea1 --- /dev/null +++ b/puppet/modules/nagios/files/nsca/nsca.cfg @@ -0,0 +1,197 @@ +# This file is managed by Puppet. +# +#################################################### +# Sample NSCA Daemon Config File  +# Written by: Ethan Galstad (nagios@nagios.org) +#  +# Last Modified: 04-03-2006 +#################################################### + + +# PID FILE +# The name of the file in which the NSCA daemon should write it's process ID +# number.  The file is only written if the NSCA daemon is started by the root +# user as a single- or multi-process daemon. + +pid_file=/var/run/nsca.pid + + + +# PORT NUMBER +# Port number we should wait for connections on. +# This must be a non-priveledged port (i.e. > 1024). + +server_port=5667 + + + +# SERVER ADDRESS +# Address that NSCA has to bind to in case there are +# more as one interface and we do not want NSCA to bind +# (thus listen) on all interfaces. + +#server_address=192.168.1.1 + + + +# NSCA USER +# This determines the effective user that the NSCA daemon should run as.   +# You can either supply a username or a UID. +#  +# NOTE: This option is ignored if NSCA is running under either inetd or xinetd + +nsca_user=nagios + + + +# NSCA GROUP +# This determines the effective group that the NSCA daemon should run as.   +# You can either supply a group name or a GID. +#  +# NOTE: This option is ignored if NSCA is running under either inetd or xinetd + +nsca_group=nogroup + + + +# NSCA CHROOT +# If specified, determines a directory into which the nsca daemon +# will perform a chroot(2) operation before dropping its privileges. +# for the security conscious this can add a layer of protection in +# the event that the nagios daemon is compromised.   +#  +# NOTE: if you specify this option, the command file will be opened +#       relative to this directory. + +#nsca_chroot=/var/run/nagios/rw + + + +# DEBUGGING OPTION +# This option determines whether or not debugging +# messages are logged to the syslog facility.  +# Values: 0 = debugging off, 1 = debugging on + +debug=0 + + + +# COMMAND FILE +# This is the location of the Nagios command file that the daemon +# should write all service check results that it receives. +# Note to debian users: nagios 1.x and nagios 2.x have +# different default locations for this file.  this is the +# default location for nagios 1.x: +#command_file=/var/run/nagios/nagios.cmd +# and this is the default location for nagios2: +#command_file=/var/lib/nagios2/rw/nagios.cmd +# and this is the default location for nagios3: +command_file=/var/lib/nagios3/rw/nagios.cmd + +# ALTERNATE DUMP FILE +# This is used to specify an alternate file the daemon should +# write service check results to in the event the command file +# does not exist.  It is important to note that the command file +# is implemented as a named pipe and only exists when Nagios is +# running.  You may want to modify the startup script for Nagios +# to dump the contents of this file into the command file after +# it starts Nagios.  Or you may simply choose to ignore any +# check results received while Nagios was not running... + +alternate_dump_file=/var/run/nagios/nsca.dump + + +# AGGREGATED WRITES OPTION +# This option determines whether or not the nsca daemon will +# aggregate writes to the external command file for client +# connections that contain multiple check results.  If you +# are queueing service check results on remote hosts and +# sending them to the nsca daemon in bulk, you will probably +# want to enable bulk writes, as this will be a bit more +# efficient. +# Values: 0 = do not aggregate writes, 1 = aggregate writes + +aggregate_writes=0 + + + +# APPEND TO FILE OPTION +# This option determines whether or not the nsca daemon will +# will open the external command file for writing or appending. +# This option should almost *always* be set to 0! +# Values: 0 = open file for writing, 1 = open file for appending + +append_to_file=0 + + + +# MAX PACKET AGE OPTION +# This option is used by the nsca daemon to determine when client +# data is too old to be valid.  Keeping this value as small as +# possible is recommended, as it helps prevent the possibility of +# "replay" attacks.  This value needs to be at least as long as +# the time it takes your clients to send their data to the server. +# Values are in seconds.  The max packet age cannot exceed 15 +# minutes (900 seconds).  If this variable is set to zero (0), no +# packets will be rejected based on their age. + +max_packet_age=30 + + + +# DECRYPTION PASSWORD +# This is the password/passphrase that should be used to descrypt the +# incoming packets.  Note that all clients must encrypt the packets +# they send using the same password! +# IMPORTANT: You don't want all the users on this system to be able +# to read the password you specify here, so make sure to set +# restrictive permissions on this config file! + +#password= + + + +# DECRYPTION METHOD +# This option determines the method by which the nsca daemon will +# decrypt the packets it receives from the clients.  The decryption +# method you choose will be a balance between security and performance, +# as strong encryption methods consume more processor resources. +# You should evaluate your security needs when choosing a decryption +# method. +# +# Note: The decryption method you specify here must match the +#       encryption method the nsca clients use (as specified in +#       the send_nsca.cfg file)!! +# Values: +# +# 	0 = None	(Do NOT use this option) +#       1 = Simple XOR  (No security, just obfuscation, but very fast) +# +#       2 = DES +#       3 = 3DES (Triple DES) +#	4 = CAST-128 +#	5 = CAST-256 +#	6 = xTEA +#	7 = 3WAY +#	8 = BLOWFISH +#	9 = TWOFISH +#	10 = LOKI97 +#	11 = RC2 +#	12 = ARCFOUR +# +#	14 = RIJNDAEL-128 +#	15 = RIJNDAEL-192 +#	16 = RIJNDAEL-256 +# +#	19 = WAKE +#	20 = SERPENT +# +#	22 = ENIGMA (Unix crypt) +#	23 = GOST +#	24 = SAFER64 +#	25 = SAFER128 +#	26 = SAFER+ +# + +decryption_method=1 + diff --git a/puppet/modules/nagios/files/nsca/send_nsca.cfg b/puppet/modules/nagios/files/nsca/send_nsca.cfg new file mode 100644 index 00000000..8127226b --- /dev/null +++ b/puppet/modules/nagios/files/nsca/send_nsca.cfg @@ -0,0 +1,65 @@ +# This file is managed by Puppet. +# +#################################################### +# Sample NSCA Client Config File  +# Written by: Ethan Galstad (nagios@nagios.org) +#  +# Last Modified: 02-21-2002 +#################################################### + + +# ENCRYPTION PASSWORD +# This is the password/passphrase that should be used to encrypt the +# outgoing packets.  Note that the nsca daemon must use the same  +# password when decrypting the packet! +# IMPORTANT: You don't want all the users on this system to be able +# to read the password you specify here, so make sure to set +# restrictive permissions on this config file! + +#password= + + + +# ENCRYPTION METHOD +# This option determines the method by which the send_nsca client will +# encrypt the packets it sends to the nsca daemon.  The encryption +# method you choose will be a balance between security and performance, +# as strong encryption methods consume more processor resources. +# You should evaluate your security needs when choosing an encryption +# method. +# +# Note: The encryption method you specify here must match the +#       decryption method the nsca daemon uses (as specified in +#       the nsca.cfg file)!! +# Values: +# 	0 = None	(Do NOT use this option) +#       1 = Simple XOR  (No security, just obfuscation, but very fast) +# +#       2 = DES +#       3 = 3DES (Triple DES) +#	4 = CAST-128 +#	5 = CAST-256 +#	6 = xTEA +#	7 = 3WAY +#	8 = BLOWFISH +#	9 = TWOFISH +#	10 = LOKI97 +#	11 = RC2 +#	12 = ARCFOUR +# +#	14 = RIJNDAEL-128 +#	15 = RIJNDAEL-192 +#	16 = RIJNDAEL-256 +# +#	19 = WAKE +#	20 = SERPENT +# +#	22 = ENIGMA (Unix crypt) +#	23 = GOST +#	24 = SAFER64 +#	25 = SAFER128 +#	26 = SAFER+ +# + +encryption_method=1 + diff --git a/puppet/modules/nagios/files/plugin_data/sks-keyservers.netCA.pem b/puppet/modules/nagios/files/plugin_data/sks-keyservers.netCA.pem new file mode 100644 index 00000000..24a2ad2e --- /dev/null +++ b/puppet/modules/nagios/files/plugin_data/sks-keyservers.netCA.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFizCCA3OgAwIBAgIJAK9zyLTPn4CPMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNV +BAYTAk5PMQ0wCwYDVQQIDARPc2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5u +ZXQgQ0ExHjAcBgNVBAMMFXNrcy1rZXlzZXJ2ZXJzLm5ldCBDQTAeFw0xMjEwMDkw +MDMzMzdaFw0yMjEwMDcwMDMzMzdaMFwxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARP +c2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5uZXQgQ0ExHjAcBgNVBAMMFXNr +cy1rZXlzZXJ2ZXJzLm5ldCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBANdsWy4PXWNUCkS3L//nrd0GqN3dVwoBGZ6w94Tw2jPDPifegwxQozFXkG6I +6A4TK1CJLXPvfz0UP0aBYyPmTNadDinaB9T4jIwd4rnxl+59GiEmqkN3IfPsv5Jj +MkKUmJnvOT0DEVlEaO1UZIwx5WpfprB3mR81/qm4XkAgmYrmgnLXd/pJDAMk7y1F +45b5zWofiD5l677lplcIPRbFhpJ6kDTODXh/XEdtF71EAeaOdEGOvyGDmCO0GWqS +FDkMMPTlieLA/0rgFTcz4xwUYj/cD5e0ZBuSkYsYFAU3hd1cGfBue0cPZaQH2HYx +Qk4zXD8S3F4690fRhr+tki5gyG6JDR67aKp3BIGLqm7f45WkX1hYp+YXywmEziM4 +aSbGYhx8hoFGfq9UcfPEvp2aoc8u5sdqjDslhyUzM1v3m3ZGbhwEOnVjljY6JJLx +MxagxnZZSAY424ZZ3t71E/Mn27dm2w+xFRuoy8JEjv1d+BT3eChM5KaNwrj0IO/y +u8kFIgWYA1vZ/15qMT+tyJTfyrNVV/7Df7TNeWyNqjJ5rBmt0M6NpHG7CrUSkBy9 +p8JhimgjP5r0FlEkgg+lyD+V79H98gQfVgP3pbJICz0SpBQf2F/2tyS4rLm+49rP +fcOajiXEuyhpcmzgusAj/1FjrtlynH1r9mnNaX4e+rLWzvU5AgMBAAGjUDBOMB0G +A1UdDgQWBBTkwyoJFGfYTVISTpM8E+igjdq28zAfBgNVHSMEGDAWgBTkwyoJFGfY +TVISTpM8E+igjdq28zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAR +OXnYwu3g1ZjHyley3fZI5aLPsaE17cOImVTehC8DcIphm2HOMR/hYTTL+V0G4P+u +gH+6xeRLKSHMHZTtSBIa6GDL03434y9CBuwGvAFCMU2GV8w92/Z7apkAhdLToZA/ +X/iWP2jeaVJhxgEcH8uPrnSlqoPBcKC9PrgUzQYfSZJkLmB+3jEa3HKruy1abJP5 +gAdQvwvcPpvYRnIzUc9fZODsVmlHVFBCl2dlu/iHh2h4GmL4Da2rRkUMlbVTdioB +UYIvMycdOkpH5wJftzw7cpjsudGas0PARDXCFfGyKhwBRFY7Xp7lbjtU5Rz0Gc04 +lPrhDf0pFE98Aw4jJRpFeWMjpXUEaG1cq7D641RpgcMfPFvOHY47rvDTS7XJOaUT +BwRjmDt896s6vMDcaG/uXJbQjuzmmx3W2Idyh3s5SI0GTHb0IwMKYb4eBUIpQOnB +cE77VnCYqKvN1NVYAqhWjXbY7XasZvszCRcOG+W3FqNaHOK/n/0ueb0uijdLan+U +f4p1bjbAox8eAOQS/8a3bzkJzdyBNUKGx1BIK2IBL9bn/HravSDOiNRSnZ/R3l9G +ZauX0tu7IIDlRCILXSyeazu0aj/vdT3YFQXPcvt5Fkf5wiNTo53f72/jYEJd6qph +WrpoKqrwGwTpRUCMhYIUt65hsTxCiJJ5nKe39h46sg== +-----END CERTIFICATE----- diff --git a/puppet/modules/nagios/files/plugins/check_dns2 b/puppet/modules/nagios/files/plugins/check_dns2 new file mode 100644 index 00000000..21956315 --- /dev/null +++ b/puppet/modules/nagios/files/plugins/check_dns2 @@ -0,0 +1,102 @@ +#!/bin/bash +# Written by Damien Gy +# damien.gy+nagiosexchange(AT)gmail.com +# 2007-09-28 + +PROGNAME=`basename $0` +REVISION=1.00 +TMP=/tmp/tmpdig +DIG=/usr/bin/dig + +print_revision() { +	echo $PROGNAME $REVISION +} + +print_usage() { +	echo "Usage:" +	echo "	$PROGNAME -c|--check <host> <type> <server>" +	echo "	$PROGNAME -h|--help" +	echo "	$PROGNAME -v|--version" +} + +print_help() { +	print_revision +	echo "" +	print_usage +	echo "Where:" +	echo "	host	the name of the resource record to be looked up" +	echo "	type	indicates the query required (any, a, mx, etc.)" +	echo "	server	the name or IP address of the name server to query" +	echo "" +	echo "	-h|--help	prints this help screen" +	echo "" +	echo "	-v|--version	prints version and license information" +	echo "" +	echo " Created by Damien Gy, questions or problems e-mail damien.gy+nagiosexchange(AT)gmail.com" +	echo "" +} + +check_dns() { + +	if [ $# -ne 3 ] +	then +	        echo "Number of arguments incorrect" +	        exit 3 +	fi +	if [ ! -e $DIG ] +	then +		echo "$DIG not found" +		exit 3 +	fi +	$DIG $1 $2 @$3 > $TMP + +	if ( grep "status" $TMP > /dev/null ) +	then +	        # DNS server answered +	        if ( grep "NOERROR" $TMP > /dev/null ) +	        then +	                echo "DNS OK "`grep "time:" $TMP` +	                rm -f $TMP +	                exit 0 +	        else +	                echo "WARNING "`grep "time:" $TMP` +	                rm -f $TMP +	                exit 1 +	        fi + +	else +	        # no answer +	        echo "CRITICAL - Connection timed out" +	        rm -f $TMP +	        exit 2 +	fi +} + +case "$1" in +--help) +                print_help +        exit 0 +        ;; +-h) +                print_help +        exit 0 +        ;; +--version) +                print_revision +        exit 0 +        ;; +-v) +                print_revision +        exit 0 +        ;; +--check) +                check_dns $2 $3 $4 +        ;; +-c) +                check_dns $2 $3 $4 +        ;; +*) +                print_usage +        exit 3 + +esac diff --git a/puppet/modules/nagios/files/plugins/check_dnsbl b/puppet/modules/nagios/files/plugins/check_dnsbl new file mode 100644 index 00000000..93cea375 --- /dev/null +++ b/puppet/modules/nagios/files/plugins/check_dnsbl @@ -0,0 +1,107 @@ +#!/bin/sh +# +# dnsbl-check-nagios.sh +# +# (c) 2009 Damon Tajeddini & heise Netze +# +STATE_OK=0 +STATE_WARNING=1 +STATE_CRITICAL=2 +STATE_UNKNOWN=3 +STATE_DEPENDENT=4 + +FOUND_ADRESS=0 + +DNSBLlist=`grep -v ^# <<! +cbl.abuseat.org +dnsbl.ahbl.org +ircbl.ahbl.org +virbl.dnsbl.bit.nl +blackholes.five-ten-sg.com +dnsbl.inps.de +ix.dnsbl.manitu.net +no-more-funn.moensted.dk +combined.njabl.org +dnsbl.njabl.org +dnsbl.sorbs.net +bl.spamcannibal.org +bl.spamcop.net +sbl.spamhaus.org +xbl.spamhaus.org +pbl.spamhaus.org +dnsbl-1.uceprotect.net +# dnsbl-2.uceprotect.net +# dnsbl-3.uceprotect.net +psbl.surriel.com +l2.apews.org +dnsrbl.swinog.ch +db.wpbl.info +!` + +# reverse IP address +convertIP() +{ + set `IFS=".";echo $1` + echo $4.$3.$2.$1 +} + +usage() +{ + echo "Usage: $0 [-H] <host>] [-p]" + echo "    -H  check Host " + echo "    -p  print list of DNSBLs" + exit 3 +} + +# Checks the IP with list of DNSBL servers +check() +{ +  count=0; +  for i in $DNSBLlist +  do +    count=$(($count + 1)) +    if nslookup $ip_arpa.$i | grep -q "127.0.0." ; +    then +      FOUND_ADRESS=$(($FOUND_ADRESS + 1)) +      echo "DNSBL-Alarm: $ip is listed on $i" +    fi +  done +  if [ $FOUND_ADRESS -ge 1 ] +  then +    exit 1 +  fi +  echo "OK - $ip not on $count DNSBLs" +  exit 0 +} + +case $1 in +  -H) +    if [ -z "$2" ] +    then +      echo "ip address missing" +      exit +    fi +    ip=$2 +    ip_arpa=`convertIP $ip` +    check;; + +  -p) +    for i in $DNSBLlist +    do +      echo $i +    done +    exit $STATE_WARNING +    exit;; + +  --help) +    usage +    exit;; + +  *) +    if [ -z "$1" ] +    then +      usage +    fi +    echo "unknown command: $1" +    exit;; +esac diff --git a/puppet/modules/nagios/files/plugins/check_gpg b/puppet/modules/nagios/files/plugins/check_gpg new file mode 100644 index 00000000..eb9fa51f --- /dev/null +++ b/puppet/modules/nagios/files/plugins/check_gpg @@ -0,0 +1,115 @@ +#!/bin/bash +# +# Nagios plugin that checks whether a key ID has expired, or will expire within +# a certain time. +# +# note: the plugin will issue a critical state if the required key has been +# revoked. +# +# usage: check_gpg [-w <num_days>] [--gnupg-homedir <path>] <key_id> +# +# <key_id> is any PGP key ID that GnuPG accepts with "gpg --list-key <key_id>" +# +# The option -w parameter lets you specify the number of days within which key +# expiry will trigger a warning. e.g. if <key_id> expires within <num_days> +# days, make nagios issue a warning. +# +# num_days must be an integer value +# +# optionally, if the keyring directory you want GPG to use is not located in +# the user's ~/.gnupg, you can specify the path to the keyring directory with +# the --gnupg-homedir parameter. +# +# Thanks a bunch to Daniel Kahn Gillmor for providing example commands that +# made up most of the core of this plugin. +# +# Copyleft Gabriel Filion +# +# This plugin is released under the GPL v3+ license. To get a copy of the +# license text visit: https://www.gnu.org/licenses/gpl-3.0.txt +# +SECS_IN_DAY=86400 + +function debug () { +  if [ -n "$DEBUG" ]; then +      echo "$1" >&2 +  fi +} + +debug "got args: $*" + +now=$(date +%s) +debug "current timestamp: $now" + +warning_threshold= +homedir= +homedir_path=~/.gnupg +for arg in $*; do +    case $arg in +        "-w") +            if [ -z "$2" ]; then +                echo "UNKNOWN: argument -w got no value. integer needed" +                exit 3 +            fi +            if [ "`echo $2 | egrep ^[[:digit:]]+$`" = "" ]; then +                echo "UNKNOWN: invalid value '$2' passed to -w. integer needed" +                exit 3 +            fi +            warning_threshold=$(( $now + ($2*$SECS_IN_DAY) )) +            debug "setting warning_threshold to '$warning_threshold'" + +            shift 2 +        ;; +        "--gnupg-homedir") +            if [ -z "$2" ]; then +                echo "UNKNOWN: argument --gnupg-homedir got no value. path needed" +                exit 3 +            fi +            if [ ! -d "$2" ]; then +                echo "UNKNOWN: homedir '$2' does not exist or is not a directory" +                exit 3 +            fi +            homedir_path=$2 +            homedir="--homedir ${homedir_path}" +            debug "setting homedir to '$homedir_path'" + +            shift 2 +        ;; +    esac +done + +if [ -z "$1" ]; then +    echo "UNKNOWN: must provide a key ID" +    exit 3 +fi +key="$1" + +# GPG is too stupid to error out when asked to refresh a key that's not in the +# local keyring so we need to perform another call to verify this first. +output=$( { gpg $homedir --list-key "$key" >/dev/null && gpg $homedir --refresh --keyserver hkps://hkps.pool.sks-keyservers.net --keyserver-options ca-cert-file=$homedir_path/sks-keyservers.netCA.pem "$key" >/dev/null; } 2>&1 ) +if [ $? -ne 0 ]; then +    echo "UNKNOWN: $output" +    exit 3 +fi + +if [ "$(gpg $homedir --check-sig "$key" | grep "^rev!")" != "" ]; then +    echo "CRITICAL: key '$key' has been revoked!" +    exit 1 +fi + +for expiry in $(gpg $homedir --with-colons --fixed-list-mode --list-key "$key" 2>/dev/null | awk -F: '/^pub:/{ print $7 }'); +do +    debug "expiry value: $expiry" + +    if [ "$now" -gt "$expiry" ] ; then +        printf "CRITICAL: %s has expired on %s\n" "$key" "$(date -d "$expiry seconds")"; +        exit 1; +    fi; +    if [ -n "$warning_threshold" ] && [ "$warning_threshold" -gt "$expiry" ]; then +        remaining=$(( ($expiry-$now) / $SECS_IN_DAY )) +        printf "WARNING: %s expires in %s days\n" "$key" "$remaining"; +        exit 2; +    fi +done + +echo "OK: key '$key' has not expired." diff --git a/puppet/modules/nagios/files/plugins/check_horde_login b/puppet/modules/nagios/files/plugins/check_horde_login new file mode 100644 index 00000000..8c821e48 --- /dev/null +++ b/puppet/modules/nagios/files/plugins/check_horde_login @@ -0,0 +1,94 @@ +#!/bin/env python +# vi:si:et:sw=4:sts=4:ts=4 +# -*- coding: UTF-8 -*- +# -*- Mode: Python -*- +# +# Copyright (C) 2015 mh <mh@immerda.ch> + +# This file may be distributed and/or modified under the terms of +# the GNU General Public License version 2 as published by +# the Free Software Foundation. +# This file is distributed without any warranty; without even the implied +# warranty of merchantability or fitness for a particular purpose. +# + +import sys, os, requests, getopt +from time import time + +def usage(): +    print sys.argv[0] + " -u username "+ \ +                          "-p password " + \ +                          "-s server path" + \ +                          "[-w warning_in_s] " + \ +                          "[-c critical_in_s]" +    sys.exit(1) + +def main(): +    try: +        opts, args = getopt.getopt(sys.argv[1:], "u:p:s:h:w:c") +    except getopt.GetoptError: +        usage() +        return 3 + +    user = url = password = None +    warning = 5 +    critical = 10 + +    for o, a in opts: +        if o == "-u": +            user = a +        elif o == "-p": +            password = a +        elif o == "-w": +            warning = a +        elif o == "-c": +            critical = a +        elif o == "-s": +            url = a + "/login.php" +        elif o == '-h': +            usage() + +    if user == None or password == None or url == None: +        usage() + +    params = { 'horde_user':         user, +               'horde_pass':         password, +               'horde_select_view':  'auto', +               'anchor_string':      '', +               'app':                '', +               'login_post':         1, +               'new_lang':           'en_US', +               'url':                '', +             } + + +    timestamp = time() +    try: +      r = requests.post(url, data=params, allow_redirects=False) +    except Exception, e: +      print "CRITICAL Horde Login Failed: %s" % e +      sys.exit(2) + +    timestamp = time() - timestamp +    if r.status_code == 302: +        if timestamp < warning: +          status = "OK" +          exitcode = 0 +        if timestamp >= warning: +          status = "WARNING" +          exitcode = 1 +        if timestamp >= critical: +          status = "CRITICAL" +          exitcode = 2 +    else: +        status   = "ERROR" +        exitcode = 2 +    # on a successfully login we are redirected to the mailbox +    print '%s Horde Login | response_time=%.3fs;%.3f;%.3f' % (status, timestamp, warning, critical) +    sys.exit(exitcode) + + +if __name__ == "__main__": +    sys.exit(main()) + + diff --git a/puppet/modules/nagios/files/plugins/check_imap_login b/puppet/modules/nagios/files/plugins/check_imap_login new file mode 100644 index 00000000..d059822b --- /dev/null +++ b/puppet/modules/nagios/files/plugins/check_imap_login @@ -0,0 +1,80 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +# -*- Mode: Python -*- +# +# Copyright (C) 2006 Bertera Pietro <pietro@bertera.it> +# Response time monitoring with perfdata modification by Ivan Savcic <isavcic@gmail.com> and Milos Buncic, 2012. +# From: https://github.com/isavcic/check_imap_login + +# This file may be distributed and/or modified under the terms of +# the GNU General Public License version 2 as published by +# the Free Software Foundation. +# This file is distributed without any warranty; without even the implied +# warranty of merchantability or fitness for a particular purpose. + +import sys, os, imaplib, getopt +from time import time + +def usage(): +	print sys.argv[0] + " -u <user> -p <password> -H <host> [-s] -w <warning threshold (sec)> -c <critical threshold (sec)>\n -s is for using IMAPS" + +def main(): +	try: +		opts, args = getopt.getopt(sys.argv[1:], "u:p:sH:w:c:") +	except getopt.GetoptError: +		usage() +		return 3 +     +	user = host = password = use_ssl = warning = critical = None + +	for o, a in opts: +		if o == "-u": +			user = a +		elif o == "-p": +			password = a +		elif o == "-s": +			use_ssl = True +		elif o == "-H": +			host = a +		elif o == "-w": +			warning = float(a) +		elif o == "-c": +			critical = float(a) + +	if user == None or password == None or host == None or warning == None or critical == None: +		usage() +		return 1 +     +	if use_ssl: +		M = imaplib.IMAP4_SSL(host=host) +	else: +		M = imaplib.IMAP4(host) +     +	timestamp = time() +	 +	try:	 +		M.login(user, password) +	except Exception, e: +		print "CRITICAL IMAP Login Failed: %s" % e +		return 2 + +	M.logout() + +	timestamp = time() - timestamp + +	if timestamp < warning: +		status = "OK" +		exitcode = 0 +	if timestamp >= warning: +		status = "WARNING" +		exitcode = 1 +	if timestamp >= critical: +		status = "CRITICAL" +		exitcode = 2 + +	print '%s IMAP Login | response_time=%.3fs;%.3f;%.3f' % (status, timestamp, warning, critical) + +	return exitcode + +if __name__ == "__main__": +	sys.exit(main()) diff --git a/puppet/modules/nagios/files/plugins/check_jabber_login b/puppet/modules/nagios/files/plugins/check_jabber_login new file mode 100644 index 00000000..dac0e1fe --- /dev/null +++ b/puppet/modules/nagios/files/plugins/check_jabber_login @@ -0,0 +1,30 @@ +#!/usr/bin/env ruby +require 'rubygems' +require 'xmpp4r' + + +def usage +  puts "#{$0} jabberid password" +  exit 3 +end + +usage unless ARGV.size == 2 + +begin +      my_client = Jabber::Client.new(ARGV[0]) +      my_client.connect +      my_client.auth(ARGV[1]) +rescue Jabber::ClientAuthenticationFailure => detail +  puts "CRITICAL: Login Error" +  exit 2 +rescue Errno::ECONNREFUSED => detail +  puts "CRITICAL: Connection refused" +  exit 2 +rescue SocketError => detail +  puts "CRITICAL: Socket Error" +  exit 2 +#rescue  +#  puts "CRITICAL: Unknown Error" +#  exit 2 +end +puts "OK: Login for #{ARGV[0]} successfull" diff --git a/puppet/modules/nagios/files/plugins/check_mysql_health b/puppet/modules/nagios/files/plugins/check_mysql_health new file mode 100755 index 00000000..9292ae09 --- /dev/null +++ b/puppet/modules/nagios/files/plugins/check_mysql_health @@ -0,0 +1,3780 @@ +#! /usr/bin/perl -w +# nagios: -epn + +my %ERRORS=( OK => 0, WARNING => 1, CRITICAL => 2, UNKNOWN => 3 ); +my %ERRORCODES=( 0 => 'OK', 1 => 'WARNING', 2 => 'CRITICAL', 3 => 'UNKNOWN' ); +package DBD::MySQL::Server::Instance::Innodb; + +use strict; + +our @ISA = qw(DBD::MySQL::Server::Instance); + + +sub new { +  my $class = shift; +  my %params = @_; +  my $self = { +    handle => $params{handle}, +    internals => undef, +    warningrange => $params{warningrange}, +    criticalrange => $params{criticalrange}, +  }; +  bless $self, $class; +  $self->init(%params); +  return $self; +} + +sub init { +  my $self = shift; +  my %params = @_; +  $self->init_nagios(); +  if ($params{mode} =~ /server::instance::innodb/) { +    $self->{internals} = +        DBD::MySQL::Server::Instance::Innodb::Internals->new(%params); +  } +} + +sub nagios { +  my $self = shift; +  my %params = @_; +  if ($params{mode} =~ /server::instance::innodb/) { +    $self->{internals}->nagios(%params); +    $self->merge_nagios($self->{internals}); +  } +} + + +package DBD::MySQL::Server::Instance::Innodb::Internals; + +use strict; + +our @ISA = qw(DBD::MySQL::Server::Instance::Innodb); + +our $internals; # singleton, nur ein einziges mal instantiierbar + +sub new { +  my $class = shift; +  my %params = @_; +  unless ($internals) { +    $internals = { +      handle => $params{handle}, +      bufferpool_hitrate => undef, +      wait_free => undef, +      log_waits => undef, +      have_innodb => undef, +      warningrange => $params{warningrange}, +      criticalrange => $params{criticalrange}, +    }; +    bless($internals, $class); +    $internals->init(%params); +  } +  return($internals); +} + +sub init { +  my $self = shift; +  my %params = @_; +  my $dummy; +  $self->debug("enter init"); +  $self->init_nagios(); +  ($dummy, $self->{have_innodb})  +      = $self->{handle}->fetchrow_array(q{ +      SHOW VARIABLES LIKE 'have_innodb' +  }); +  if ($self->{have_innodb} eq "NO") { +    $self->add_nagios_critical("the innodb engine has a problem (have_innodb=no)"); +  } elsif ($self->{have_innodb} eq "DISABLED") { +    # add_nagios_ok later +  } elsif ($params{mode} =~ /server::instance::innodb::bufferpool::hitrate/) { +    ($dummy, $self->{bufferpool_reads})  +        = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Innodb_buffer_pool_reads' +    }); +    ($dummy, $self->{bufferpool_read_requests})  +        = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Innodb_buffer_pool_read_requests' +    }); +    if (! defined $self->{bufferpool_reads}) { +      $self->add_nagios_critical("no innodb buffer pool info available"); +    } else { +      $self->valdiff(\%params, qw(bufferpool_reads +          bufferpool_read_requests)); +      $self->{bufferpool_hitrate_now} = +          $self->{delta_bufferpool_read_requests} > 0 ? +          100 - (100 * $self->{delta_bufferpool_reads} /  +              $self->{delta_bufferpool_read_requests}) : 100; +      $self->{bufferpool_hitrate} = +          $self->{bufferpool_read_requests} > 0 ? +          100 - (100 * $self->{bufferpool_reads} / +              $self->{bufferpool_read_requests}) : 100; +    } +  } elsif ($params{mode} =~ /server::instance::innodb::bufferpool::waitfree/) { +    ($dummy, $self->{bufferpool_wait_free}) +        = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Innodb_buffer_pool_wait_free' +    }); +    if (! defined $self->{bufferpool_wait_free}) { +      $self->add_nagios_critical("no innodb buffer pool info available"); +    } else { +      $self->valdiff(\%params, qw(bufferpool_wait_free)); +      $self->{bufferpool_wait_free_rate} = +          $self->{delta_bufferpool_wait_free} / $self->{delta_timestamp}; +    } +  } elsif ($params{mode} =~ /server::instance::innodb::logwaits/) { +    ($dummy, $self->{log_waits}) +        = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Innodb_log_waits' +    }); +    if (! defined $self->{log_waits}) { +      $self->add_nagios_critical("no innodb log info available"); +    } else { +      $self->valdiff(\%params, qw(log_waits)); +      $self->{log_waits_rate} = +          $self->{delta_log_waits} / $self->{delta_timestamp}; +    } +  } elsif ($params{mode} =~ /server::instance::innodb::needoptimize/) { +#fragmentation=$(($datafree * 100 / $datalength)) + +#http://www.electrictoolbox.com/optimize-tables-mysql-php/ +    my  @result = $self->{handle}->fetchall_array(q{ +SHOW TABLE STATUS WHERE Data_free / Data_length > 0.1 AND Data_free > 102400 +}); +printf "%s\n", Data::Dumper::Dumper(\@result); + +  } +} + +sub nagios { +  my $self = shift; +  my %params = @_; +  my $now = $params{lookback} ? '_now' : ''; +  if ($self->{have_innodb} eq "DISABLED") { +    $self->add_nagios_ok("the innodb engine has been disabled"); +  } elsif (! $self->{nagios_level}) { +    if ($params{mode} =~ /server::instance::innodb::bufferpool::hitrate/) { +      my $refkey = 'bufferpool_hitrate'.($params{lookback} ? '_now' : ''); +      $self->add_nagios( +          $self->check_thresholds($self->{$refkey}, "99:", "95:"), +              sprintf "innodb buffer pool hitrate at %.2f%%", $self->{$refkey}); +      $self->add_perfdata(sprintf "bufferpool_hitrate=%.2f%%;%s;%s;0;100", +          $self->{bufferpool_hitrate}, +          $self->{warningrange}, $self->{criticalrange}); +      $self->add_perfdata(sprintf "bufferpool_hitrate_now=%.2f%%", +          $self->{bufferpool_hitrate_now}); +    } elsif ($params{mode} =~ /server::instance::innodb::bufferpool::waitfree/) { +      $self->add_nagios( +          $self->check_thresholds($self->{bufferpool_wait_free_rate}, "1", "10"), +          sprintf "%ld innodb buffer pool waits in %ld seconds (%.4f/sec)", +          $self->{delta_bufferpool_wait_free}, $self->{delta_timestamp}, +          $self->{bufferpool_wait_free_rate}); +      $self->add_perfdata(sprintf "bufferpool_free_waits_rate=%.4f;%s;%s;0;100", +          $self->{bufferpool_wait_free_rate}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::innodb::logwaits/) { +      $self->add_nagios( +          $self->check_thresholds($self->{log_waits_rate}, "1", "10"), +          sprintf "%ld innodb log waits in %ld seconds (%.4f/sec)", +          $self->{delta_log_waits}, $self->{delta_timestamp}, +          $self->{log_waits_rate}); +      $self->add_perfdata(sprintf "innodb_log_waits_rate=%.4f;%s;%s;0;100", +          $self->{log_waits_rate}, +          $self->{warningrange}, $self->{criticalrange}); +    } +  } +} + + + + +package DBD::MySQL::Server::Instance::MyISAM; + +use strict; + +our @ISA = qw(DBD::MySQL::Server::Instance); + + +sub new { +  my $class = shift; +  my %params = @_; +  my $self = { +    handle => $params{handle}, +    internals => undef, +    warningrange => $params{warningrange}, +    criticalrange => $params{criticalrange}, +  }; +  bless $self, $class; +  $self->init(%params); +  return $self; +} + +sub init { +  my $self = shift; +  my %params = @_; +  $self->init_nagios(); +  if ($params{mode} =~ /server::instance::myisam/) { +    $self->{internals} = +        DBD::MySQL::Server::Instance::MyISAM::Internals->new(%params); +  } +} + +sub nagios { +  my $self = shift; +  my %params = @_; +  if ($params{mode} =~ /server::instance::myisam/) { +    $self->{internals}->nagios(%params); +    $self->merge_nagios($self->{internals}); +  } +} + + +package DBD::MySQL::Server::Instance::MyISAM::Internals; + +use strict; + +our @ISA = qw(DBD::MySQL::Server::Instance::MyISAM); + +our $internals; # singleton, nur ein einziges mal instantiierbar + +sub new { +  my $class = shift; +  my %params = @_; +  unless ($internals) { +    $internals = { +      handle => $params{handle}, +      keycache_hitrate => undef, +      warningrange => $params{warningrange}, +      criticalrange => $params{criticalrange}, +    }; +    bless($internals, $class); +    $internals->init(%params); +  } +  return($internals); +} + +sub init { +  my $self = shift; +  my %params = @_; +  my $dummy; +  $self->debug("enter init"); +  $self->init_nagios(); +  if ($params{mode} =~ /server::instance::myisam::keycache::hitrate/) { +    ($dummy, $self->{key_reads}) +        = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Key_reads' +    }); +    ($dummy, $self->{key_read_requests}) +        = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Key_read_requests' +    }); +    if (! defined $self->{key_read_requests}) { +      $self->add_nagios_critical("no myisam keycache info available"); +    } else { +      $self->valdiff(\%params, qw(key_reads key_read_requests)); +      $self->{keycache_hitrate} = +          $self->{key_read_requests} > 0 ? +          100 - (100 * $self->{key_reads} / +              $self->{key_read_requests}) : 100; +      $self->{keycache_hitrate_now} = +          $self->{delta_key_read_requests} > 0 ? +          100 - (100 * $self->{delta_key_reads} / +              $self->{delta_key_read_requests}) : 100; +    } +  } elsif ($params{mode} =~ /server::instance::myisam::sonstnochwas/) { +  } +} + +sub nagios { +  my $self = shift; +  my %params = @_; +  if (! $self->{nagios_level}) { +    if ($params{mode} =~ /server::instance::myisam::keycache::hitrate/) { +      my $refkey = 'keycache_hitrate'.($params{lookback} ? '_now' : ''); +      $self->add_nagios( +          $self->check_thresholds($self->{$refkey}, "99:", "95:"), +              sprintf "myisam keycache hitrate at %.2f%%", $self->{$refkey}); +      $self->add_perfdata(sprintf "keycache_hitrate=%.2f%%;%s;%s", +          $self->{keycache_hitrate}, +          $self->{warningrange}, $self->{criticalrange}); +      $self->add_perfdata(sprintf "keycache_hitrate_now=%.2f%%;%s;%s", +          $self->{keycache_hitrate_now}, +          $self->{warningrange}, $self->{criticalrange}); +    } +  } +} + + +package DBD::MySQL::Server::Instance::Replication; + +use strict; + +our @ISA = qw(DBD::MySQL::Server::Instance); + + +sub new { +  my $class = shift; +  my %params = @_; +  my $self = { +    handle => $params{handle}, +    internals => undef, +    warningrange => $params{warningrange}, +    criticalrange => $params{criticalrange}, +  }; +  bless $self, $class; +  $self->init(%params); +  return $self; +} + +sub init { +  my $self = shift; +  my %params = @_; +  $self->init_nagios(); +  if ($params{mode} =~ /server::instance::replication/) { +    $self->{internals} = +        DBD::MySQL::Server::Instance::Replication::Internals->new(%params); +  } +} + +sub nagios { +  my $self = shift; +  my %params = @_; +  if ($params{mode} =~ /server::instance::replication/) { +    $self->{internals}->nagios(%params); +    $self->merge_nagios($self->{internals}); +  } +} + + +package DBD::MySQL::Server::Instance::Replication::Internals; + +use strict; + +our @ISA = qw(DBD::MySQL::Server::Instance::Replication); + +our $internals; # singleton, nur ein einziges mal instantiierbar + +sub new { +  my $class = shift; +  my %params = @_; +  unless ($internals) { +    $internals = { +      handle => $params{handle}, +      seconds_behind_master => undef, +      slave_io_running => undef, +      slave_sql_running => undef, +      warningrange => $params{warningrange}, +      criticalrange => $params{criticalrange}, +    }; +    bless($internals, $class); +    $internals->init(%params); +  } +  return($internals); +} + +sub init { +  my $self = shift; +  my %params = @_; +  $self->debug("enter init"); +  $self->init_nagios(); +  if ($params{mode} =~ /server::instance::replication::slavelag/) { +    # "show slave status", "Seconds_Behind_Master" +    my $slavehash = $self->{handle}->selectrow_hashref(q{ +            SHOW SLAVE STATUS +        }); +    if ((! defined $slavehash->{Seconds_Behind_Master}) &&  +        (lc $slavehash->{Slave_IO_Running} eq 'no')) { +      $self->add_nagios_critical( +          "unable to get slave lag, because io thread is not running"); +    } elsif (! defined $slavehash->{Seconds_Behind_Master}) { +      $self->add_nagios_critical(sprintf "unable to get replication info%s", +          $self->{handle}->{errstr} ? $self->{handle}->{errstr} : ""); +    } else { +      $self->{seconds_behind_master} = $slavehash->{Seconds_Behind_Master}; +    } +  } elsif ($params{mode} =~ /server::instance::replication::slaveiorunning/) { +    # "show slave status", "Slave_IO_Running" +    my $slavehash = $self->{handle}->selectrow_hashref(q{ +            SHOW SLAVE STATUS +        }); +    if (! defined $slavehash->{Slave_IO_Running}) { +      $self->add_nagios_critical(sprintf "unable to get replication info%s", +          $self->{handle}->{errstr} ? $self->{handle}->{errstr} : ""); +    } else { +      $self->{slave_io_running} = $slavehash->{Slave_IO_Running}; +    } +  } elsif ($params{mode} =~ /server::instance::replication::slavesqlrunning/) { +    # "show slave status", "Slave_SQL_Running" +    my $slavehash = $self->{handle}->selectrow_hashref(q{ +            SHOW SLAVE STATUS +        }); +    if (! defined $slavehash->{Slave_SQL_Running}) { +      $self->add_nagios_critical(sprintf "unable to get replication info%s", +          $self->{handle}->{errstr} ? $self->{handle}->{errstr} : ""); +    } else { +      $self->{slave_sql_running} = $slavehash->{Slave_SQL_Running}; +    } +  } +} + +sub nagios { +  my $self = shift; +  my %params = @_; +  if (! $self->{nagios_level}) { +    if ($params{mode} =~ /server::instance::replication::slavelag/) { +      $self->add_nagios( +          $self->check_thresholds($self->{seconds_behind_master}, "10", "20"), +          sprintf "Slave is %d seconds behind master", +          $self->{seconds_behind_master}); +      $self->add_perfdata(sprintf "slave_lag=%d;%s;%s", +          $self->{seconds_behind_master}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::replication::slaveiorunning/) { +      if (lc $self->{slave_io_running} eq "yes") { +        $self->add_nagios_ok("Slave io is running"); +      } else { +        $self->add_nagios_critical("Slave io is not running"); +      } +    } elsif ($params{mode} =~ /server::instance::replication::slavesqlrunning/) { +      if (lc $self->{slave_sql_running} eq "yes") { +        $self->add_nagios_ok("Slave sql is running"); +      } else { +        $self->add_nagios_critical("Slave sql is not running"); +      } +    } +  } +} + + + +package DBD::MySQL::Server::Instance; + +use strict; + +our @ISA = qw(DBD::MySQL::Server); + + +sub new { +  my $class = shift; +  my %params = @_; +  my $self = { +    handle => $params{handle}, +    uptime => $params{uptime}, +    warningrange => $params{warningrange}, +    criticalrange => $params{criticalrange}, +    threads_connected => undef, +    threads_created => undef, +    connections => undef, +    threadcache_hitrate => undef, +    querycache_hitrate => undef, +    lowmem_prunes_per_sec => undef, +    slow_queries_per_sec => undef, +    longrunners => undef, +    tablecache_hitrate => undef, +    index_usage => undef, +    engine_innodb => undef, +    engine_myisam => undef, +    replication => undef, +  }; +  bless $self, $class; +  $self->init(%params); +  return $self; +} + +sub init { +  my $self = shift; +  my %params = @_; +  my $dummy; +  $self->init_nagios(); +  if ($params{mode} =~ /server::instance::connectedthreads/) { +    ($dummy, $self->{threads_connected}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Threads_connected' +    }); +  } elsif ($params{mode} =~ /server::instance::createdthreads/) { +    ($dummy, $self->{threads_created}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Threads_created' +    }); +    $self->valdiff(\%params, qw(threads_created)); +    $self->{threads_created_per_sec} = $self->{delta_threads_created} / +        $self->{delta_timestamp}; +  } elsif ($params{mode} =~ /server::instance::runningthreads/) { +    ($dummy, $self->{threads_running}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Threads_running' +    }); +  } elsif ($params{mode} =~ /server::instance::cachedthreads/) { +    ($dummy, $self->{threads_cached}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Threads_cached' +    }); +  } elsif ($params{mode} =~ /server::instance::abortedconnects/) { +    ($dummy, $self->{connects_aborted}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Aborted_connects' +    }); +    $self->valdiff(\%params, qw(connects_aborted)); +    $self->{connects_aborted_per_sec} = $self->{delta_connects_aborted} / +        $self->{delta_timestamp}; +  } elsif ($params{mode} =~ /server::instance::abortedclients/) { +    ($dummy, $self->{clients_aborted}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Aborted_clients' +    }); +    $self->valdiff(\%params, qw(clients_aborted)); +    $self->{clients_aborted_per_sec} = $self->{delta_clients_aborted} / +        $self->{delta_timestamp}; +  } elsif ($params{mode} =~ /server::instance::threadcachehitrate/) { +    ($dummy, $self->{threads_created}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Threads_created' +    }); +    ($dummy, $self->{connections}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Connections' +    }); +    $self->valdiff(\%params, qw(threads_created connections)); +    if ($self->{delta_connections} > 0) { +      $self->{threadcache_hitrate_now} =  +          100 - ($self->{delta_threads_created} * 100.0 / +          $self->{delta_connections}); +    } else { +      $self->{threadcache_hitrate_now} = 100; +    } +    $self->{threadcache_hitrate} = 100 -  +        ($self->{threads_created} * 100.0 / $self->{connections}); +    $self->{connections_per_sec} = $self->{delta_connections} / +        $self->{delta_timestamp}; +  } elsif ($params{mode} =~ /server::instance::querycachehitrate/) { +    ($dummy, $self->{com_select}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Com_select' +    }); +    ($dummy, $self->{qcache_hits}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Qcache_hits' +    }); +    #    SHOW VARIABLES WHERE Variable_name = 'have_query_cache' for 5.x, but LIKE is compatible +    ($dummy, $self->{have_query_cache}) = $self->{handle}->fetchrow_array(q{ +        SHOW VARIABLES LIKE 'have_query_cache' +    }); +    #    SHOW VARIABLES WHERE Variable_name = 'query_cache_size' +    ($dummy, $self->{query_cache_size}) = $self->{handle}->fetchrow_array(q{ +        SHOW VARIABLES LIKE 'query_cache_size' +    }); +    $self->valdiff(\%params, qw(com_select qcache_hits)); +    $self->{querycache_hitrate_now} =  +        ($self->{delta_com_select} + $self->{delta_qcache_hits}) > 0 ? +        100 * $self->{delta_qcache_hits} / +            ($self->{delta_com_select} + $self->{delta_qcache_hits}) : +        0; +    $self->{querycache_hitrate} = +        100 * $self->{qcache_hits} / ($self->{com_select} + $self->{qcache_hits}); +    $self->{selects_per_sec} = +        $self->{delta_com_select} / $self->{delta_timestamp}; +  } elsif ($params{mode} =~ /server::instance::querycachelowmemprunes/) { +    ($dummy, $self->{lowmem_prunes}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Qcache_lowmem_prunes' +    }); +    $self->valdiff(\%params, qw(lowmem_prunes)); +    $self->{lowmem_prunes_per_sec} = $self->{delta_lowmem_prunes} /  +        $self->{delta_timestamp}; +  } elsif ($params{mode} =~ /server::instance::slowqueries/) { +    ($dummy, $self->{slow_queries}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Slow_queries' +    }); +    $self->valdiff(\%params, qw(slow_queries)); +    $self->{slow_queries_per_sec} = $self->{delta_slow_queries} /  +        $self->{delta_timestamp}; +  } elsif ($params{mode} =~ /server::instance::longprocs/) { +    if (DBD::MySQL::Server::return_first_server()->version_is_minimum("5.1")) { +      ($self->{longrunners}) = $self->{handle}->fetchrow_array(q{ +          SELECT +              COUNT(*) +          FROM +              information_schema.processlist +          WHERE user <> 'replication'  +          AND id <> CONNECTION_ID()  +          AND time > 60  +          AND command <> 'Sleep' +      }); +    } else { +      $self->{longrunners} = 0 if ! defined $self->{longrunners}; +      foreach ($self->{handle}->fetchall_array(q{ +          SHOW PROCESSLIST +      })) { +        my($id, $user, $host, $db, $command, $tme, $state, $info) = @{$_}; +        if (($user ne 'replication') && +            ($tme > 60) && +            ($command ne 'Sleep')) { +          $self->{longrunners}++; +        } +      } +    } +  } elsif ($params{mode} =~ /server::instance::tablecachehitrate/) { +    ($dummy, $self->{open_tables}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Open_tables' +    }); +    ($dummy, $self->{opened_tables}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Opened_tables' +    }); +    if (DBD::MySQL::Server::return_first_server()->version_is_minimum("5.1.3")) { +      #      SHOW VARIABLES WHERE Variable_name = 'table_open_cache' +      ($dummy, $self->{table_cache}) = $self->{handle}->fetchrow_array(q{ +          SHOW VARIABLES LIKE 'table_open_cache' +      }); +    } else { +      #    SHOW VARIABLES WHERE Variable_name = 'table_cache' +      ($dummy, $self->{table_cache}) = $self->{handle}->fetchrow_array(q{ +          SHOW VARIABLES LIKE 'table_cache' +      }); +    } +    $self->{table_cache} ||= 0; +    #$self->valdiff(\%params, qw(open_tables opened_tables table_cache)); +    # _now ist hier sinnlos, da opened_tables waechst, aber open_tables wieder  +    # schrumpfen kann weil tabellen geschlossen werden. +    if ($self->{opened_tables} != 0 && $self->{table_cache} != 0) { +      $self->{tablecache_hitrate} =  +          100 * $self->{open_tables} / $self->{opened_tables}; +      $self->{tablecache_fillrate} =  +          100 * $self->{open_tables} / $self->{table_cache}; +    } elsif ($self->{opened_tables} == 0 && $self->{table_cache} != 0) { +      $self->{tablecache_hitrate} = 100; +      $self->{tablecache_fillrate} =  +          100 * $self->{open_tables} / $self->{table_cache}; +    } else { +      $self->{tablecache_hitrate} = 0; +      $self->{tablecache_fillrate} = 0; +      $self->add_nagios_critical("no table cache"); +    } +  } elsif ($params{mode} =~ /server::instance::tablelockcontention/) { +    ($dummy, $self->{table_locks_waited}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Table_locks_waited' +    }); +    ($dummy, $self->{table_locks_immediate}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Table_locks_immediate' +    }); +    $self->valdiff(\%params, qw(table_locks_waited table_locks_immediate)); +    $self->{table_lock_contention} =  +        ($self->{table_locks_waited} + $self->{table_locks_immediate}) > 0 ? +        100 * $self->{table_locks_waited} /  +        ($self->{table_locks_waited} + $self->{table_locks_immediate}) : +        100; +    $self->{table_lock_contention_now} =  +        ($self->{delta_table_locks_waited} + $self->{delta_table_locks_immediate}) > 0 ? +        100 * $self->{delta_table_locks_waited} /  +        ($self->{delta_table_locks_waited} + $self->{delta_table_locks_immediate}) : +        100; +  } elsif ($params{mode} =~ /server::instance::tableindexusage/) { +    # http://johnjacobm.wordpress.com/2007/06/ +    # formula for calculating the percentage of full table scans +    ($dummy, $self->{handler_read_first}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Handler_read_first' +    }); +    ($dummy, $self->{handler_read_key}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Handler_read_key' +    }); +    ($dummy, $self->{handler_read_next}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Handler_read_next' +    }); +    ($dummy, $self->{handler_read_prev}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Handler_read_prev' +    }); +    ($dummy, $self->{handler_read_rnd}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Handler_read_rnd' +    }); +    ($dummy, $self->{handler_read_rnd_next}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Handler_read_rnd_next' +    }); +    $self->valdiff(\%params, qw(handler_read_first handler_read_key +        handler_read_next handler_read_prev handler_read_rnd +        handler_read_rnd_next)); +    my $delta_reads = $self->{delta_handler_read_first} + +        $self->{delta_handler_read_key} + +        $self->{delta_handler_read_next} + +        $self->{delta_handler_read_prev} + +        $self->{delta_handler_read_rnd} + +        $self->{delta_handler_read_rnd_next}; +    my $reads = $self->{handler_read_first} + +        $self->{handler_read_key} + +        $self->{handler_read_next} + +        $self->{handler_read_prev} + +        $self->{handler_read_rnd} + +        $self->{handler_read_rnd_next}; +    $self->{index_usage_now} = ($delta_reads == 0) ? 0 : +        100 - (100.0 * ($self->{delta_handler_read_rnd} + +        $self->{delta_handler_read_rnd_next}) / +        $delta_reads); +    $self->{index_usage} = ($reads == 0) ? 0 : +        100 - (100.0 * ($self->{handler_read_rnd} + +        $self->{handler_read_rnd_next}) / +        $reads); +  } elsif ($params{mode} =~ /server::instance::tabletmpondisk/) { +    ($dummy, $self->{created_tmp_tables}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Created_tmp_tables' +    }); +    ($dummy, $self->{created_tmp_disk_tables}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Created_tmp_disk_tables' +    }); +    $self->valdiff(\%params, qw(created_tmp_tables created_tmp_disk_tables)); +    $self->{pct_tmp_on_disk} = $self->{created_tmp_tables} > 0 ? +        100 * $self->{created_tmp_disk_tables} / $self->{created_tmp_tables} : +        100; +    $self->{pct_tmp_on_disk_now} = $self->{delta_created_tmp_tables} > 0 ? +        100 * $self->{delta_created_tmp_disk_tables} / $self->{delta_created_tmp_tables} : +        100; +  } elsif ($params{mode} =~ /server::instance::openfiles/) { +    ($dummy, $self->{open_files_limit}) = $self->{handle}->fetchrow_array(q{ +        SHOW VARIABLES LIKE 'open_files_limit' +    }); +    ($dummy, $self->{open_files}) = $self->{handle}->fetchrow_array(q{ +        SHOW /*!50000 global */ STATUS LIKE 'Open_files' +    }); +    $self->{pct_open_files} = 100 * $self->{open_files} / $self->{open_files_limit}; +  } elsif ($params{mode} =~ /server::instance::needoptimize/) { +    $self->{fragmented} = []; +    #http://www.electrictoolbox.com/optimize-tables-mysql-php/ +    my  @result = $self->{handle}->fetchall_array(q{ +        SHOW TABLE STATUS +    }); +    foreach (@result) { +      my ($name, $engine, $data_length, $data_free) = +          ($_->[0], $_->[1], $_->[6 ], $_->[9]); +      next if ($params{name} && $params{name} ne $name); +      my $fragmentation = $data_length ? $data_free * 100 / $data_length : 0; +      push(@{$self->{fragmented}}, +          [$name, $fragmentation, $data_length, $data_free]); +    } +  } elsif ($params{mode} =~ /server::instance::myisam/) { +    $self->{engine_myisam} = DBD::MySQL::Server::Instance::MyISAM->new( +        %params +    ); +  } elsif ($params{mode} =~ /server::instance::innodb/) { +    $self->{engine_innodb} = DBD::MySQL::Server::Instance::Innodb->new( +        %params +    ); +  } elsif ($params{mode} =~ /server::instance::replication/) { +    $self->{replication} = DBD::MySQL::Server::Instance::Replication->new( +        %params +    ); +  } +} + +sub nagios { +  my $self = shift; +  my %params = @_; +  if (! $self->{nagios_level}) { +    if ($params{mode} =~ /server::instance::connectedthreads/) { +      $self->add_nagios( +          $self->check_thresholds($self->{threads_connected}, 10, 20), +          sprintf "%d client connection threads", $self->{threads_connected}); +      $self->add_perfdata(sprintf "threads_connected=%d;%d;%d", +          $self->{threads_connected}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::createdthreads/) { +      $self->add_nagios( +          $self->check_thresholds($self->{threads_created_per_sec}, 10, 20), +          sprintf "%.2f threads created/sec", $self->{threads_created_per_sec}); +      $self->add_perfdata(sprintf "threads_created_per_sec=%.2f;%.2f;%.2f", +          $self->{threads_created_per_sec}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::runningthreads/) { +      $self->add_nagios( +          $self->check_thresholds($self->{threads_running}, 10, 20), +          sprintf "%d running threads", $self->{threads_running}); +      $self->add_perfdata(sprintf "threads_running=%d;%d;%d", +          $self->{threads_running}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::cachedthreads/) { +      $self->add_nagios( +          $self->check_thresholds($self->{threads_cached}, 10, 20), +          sprintf "%d cached threads", $self->{threads_cached}); +      $self->add_perfdata(sprintf "threads_cached=%d;%d;%d", +          $self->{threads_cached}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::abortedconnects/) { +      $self->add_nagios( +          $self->check_thresholds($self->{connects_aborted_per_sec}, 1, 5), +          sprintf "%.2f aborted connections/sec", $self->{connects_aborted_per_sec}); +      $self->add_perfdata(sprintf "connects_aborted_per_sec=%.2f;%.2f;%.2f", +          $self->{connects_aborted_per_sec}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::abortedclients/) { +      $self->add_nagios( +          $self->check_thresholds($self->{clients_aborted_per_sec}, 1, 5), +          sprintf "%.2f aborted (client died) connections/sec", $self->{clients_aborted_per_sec}); +      $self->add_perfdata(sprintf "clients_aborted_per_sec=%.2f;%.2f;%.2f", +          $self->{clients_aborted_per_sec}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::threadcachehitrate/) { +      my $refkey = 'threadcache_hitrate'.($params{lookback} ? '_now' : ''); +      $self->add_nagios( +          $self->check_thresholds($self->{$refkey}, "90:", "80:"), +          sprintf "thread cache hitrate %.2f%%", $self->{$refkey}); +      $self->add_perfdata(sprintf "thread_cache_hitrate=%.2f%%;%s;%s", +          $self->{threadcache_hitrate}, +          $self->{warningrange}, $self->{criticalrange}); +      $self->add_perfdata(sprintf "thread_cache_hitrate_now=%.2f%%", +          $self->{threadcache_hitrate_now}); +      $self->add_perfdata(sprintf "connections_per_sec=%.2f", +          $self->{connections_per_sec}); +    } elsif ($params{mode} =~ /server::instance::querycachehitrate/) { +      my $refkey = 'querycache_hitrate'.($params{lookback} ? '_now' : ''); +      if ((lc $self->{have_query_cache} eq 'yes') && ($self->{query_cache_size})) { +        $self->add_nagios( +            $self->check_thresholds($self->{$refkey}, "90:", "80:"), +            sprintf "query cache hitrate %.2f%%", $self->{$refkey}); +      } else { +        $self->check_thresholds($self->{$refkey}, "90:", "80:"); +        $self->add_nagios_ok( +            sprintf "query cache hitrate %.2f%% (because it's turned off)", +            $self->{querycache_hitrate}); +      } +      $self->add_perfdata(sprintf "qcache_hitrate=%.2f%%;%s;%s", +          $self->{querycache_hitrate}, +          $self->{warningrange}, $self->{criticalrange}); +      $self->add_perfdata(sprintf "qcache_hitrate_now=%.2f%%", +          $self->{querycache_hitrate_now}); +      $self->add_perfdata(sprintf "selects_per_sec=%.2f", +          $self->{selects_per_sec}); +    } elsif ($params{mode} =~ /server::instance::querycachelowmemprunes/) { +      $self->add_nagios( +          $self->check_thresholds($self->{lowmem_prunes_per_sec}, "1", "10"), +          sprintf "%d query cache lowmem prunes in %d seconds (%.2f/sec)", +          $self->{delta_lowmem_prunes}, $self->{delta_timestamp}, +          $self->{lowmem_prunes_per_sec}); +      $self->add_perfdata(sprintf "qcache_lowmem_prunes_rate=%.2f;%s;%s", +          $self->{lowmem_prunes_per_sec}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::slowqueries/) { +      $self->add_nagios( +          $self->check_thresholds($self->{slow_queries_per_sec}, "0.1", "1"), +          sprintf "%d slow queries in %d seconds (%.2f/sec)", +          $self->{delta_slow_queries}, $self->{delta_timestamp}, +          $self->{slow_queries_per_sec}); +      $self->add_perfdata(sprintf "slow_queries_rate=%.2f%%;%s;%s", +          $self->{slow_queries_per_sec}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::longprocs/) { +      $self->add_nagios( +          $self->check_thresholds($self->{longrunners}, 10, 20), +          sprintf "%d long running processes", $self->{longrunners}); +      $self->add_perfdata(sprintf "long_running_procs=%d;%d;%d", +          $self->{longrunners}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /server::instance::tablecachehitrate/) { +      if ($self->{tablecache_fillrate} < 95) { +        $self->add_nagios_ok( +            sprintf "table cache hitrate %.2f%%, %.2f%% filled", +                $self->{tablecache_hitrate}, +                $self->{tablecache_fillrate}); +        $self->check_thresholds($self->{tablecache_hitrate}, "99:", "95:"); +      } else { +        $self->add_nagios( +            $self->check_thresholds($self->{tablecache_hitrate}, "99:", "95:"), +            sprintf "table cache hitrate %.2f%%", $self->{tablecache_hitrate}); +      } +      $self->add_perfdata(sprintf "tablecache_hitrate=%.2f%%;%s;%s", +          $self->{tablecache_hitrate}, +          $self->{warningrange}, $self->{criticalrange}); +      $self->add_perfdata(sprintf "tablecache_fillrate=%.2f%%", +          $self->{tablecache_fillrate}); +    } elsif ($params{mode} =~ /server::instance::tablelockcontention/) { +      my $refkey = 'table_lock_contention'.($params{lookback} ? '_now' : ''); +      if ($self->{uptime} > 10800) { # MySQL Bug #30599 +        $self->add_nagios( +            $self->check_thresholds($self->{$refkey}, "1", "2"), +                sprintf "table lock contention %.2f%%", $self->{$refkey}); +      } else { +        $self->check_thresholds($self->{$refkey}, "1", "2"); +        $self->add_nagios_ok( +            sprintf "table lock contention %.2f%% (uptime < 10800)", +            $self->{$refkey}); +      } +      $self->add_perfdata(sprintf "tablelock_contention=%.2f%%;%s;%s", +          $self->{table_lock_contention}, +          $self->{warningrange}, $self->{criticalrange}); +      $self->add_perfdata(sprintf "tablelock_contention_now=%.2f%%", +          $self->{table_lock_contention_now}); +    } elsif ($params{mode} =~ /server::instance::tableindexusage/) { +      my $refkey = 'index_usage'.($params{lookback} ? '_now' : ''); +      $self->add_nagios( +          $self->check_thresholds($self->{$refkey}, "90:", "80:"), +              sprintf "index usage  %.2f%%", $self->{$refkey}); +      $self->add_perfdata(sprintf "index_usage=%.2f%%;%s;%s", +          $self->{index_usage}, +          $self->{warningrange}, $self->{criticalrange}); +      $self->add_perfdata(sprintf "index_usage_now=%.2f%%", +          $self->{index_usage_now}); +    } elsif ($params{mode} =~ /server::instance::tabletmpondisk/) { +      my $refkey = 'pct_tmp_on_disk'.($params{lookback} ? '_now' : ''); +      $self->add_nagios( +          $self->check_thresholds($self->{$refkey}, "25", "50"), +              sprintf "%.2f%% of %d tables were created on disk", +              $self->{$refkey}, $self->{delta_created_tmp_tables}); +      $self->add_perfdata(sprintf "pct_tmp_table_on_disk=%.2f%%;%s;%s", +          $self->{pct_tmp_on_disk}, +          $self->{warningrange}, $self->{criticalrange}); +      $self->add_perfdata(sprintf "pct_tmp_table_on_disk_now=%.2f%%", +          $self->{pct_tmp_on_disk_now}); +    } elsif ($params{mode} =~ /server::instance::openfiles/) { +      $self->add_nagios( +          $self->check_thresholds($self->{pct_open_files}, 80, 95), +          sprintf "%.2f%% of the open files limit reached (%d of max. %d)", +              $self->{pct_open_files}, +              $self->{open_files}, $self->{open_files_limit}); +      $self->add_perfdata(sprintf "pct_open_files=%.3f%%;%.3f;%.3f", +          $self->{pct_open_files}, +          $self->{warningrange}, +          $self->{criticalrange}); +      $self->add_perfdata(sprintf "open_files=%d;%d;%d", +          $self->{open_files}, +          $self->{open_files_limit} * $self->{warningrange} / 100, +          $self->{open_files_limit} * $self->{criticalrange} / 100); +    } elsif ($params{mode} =~ /server::instance::needoptimize/) { +      foreach (@{$self->{fragmented}}) { +        $self->add_nagios( +            $self->check_thresholds($_->[1], 10, 25), +            sprintf "table %s is %.2f%% fragmented", $_->[0], $_->[1]); +        if ($params{name}) { +          $self->add_perfdata(sprintf "'%s_frag'=%.2f%%;%d;%d", +              $_->[0], $_->[1], $self->{warningrange}, $self->{criticalrange}); +        } +      } +    } elsif ($params{mode} =~ /server::instance::myisam/) { +      $self->{engine_myisam}->nagios(%params); +      $self->merge_nagios($self->{engine_myisam}); +    } elsif ($params{mode} =~ /server::instance::innodb/) { +      $self->{engine_innodb}->nagios(%params); +      $self->merge_nagios($self->{engine_innodb}); +    } elsif ($params{mode} =~ /server::instance::replication/) { +      $self->{replication}->nagios(%params); +      $self->merge_nagios($self->{replication}); +    } +  } +} + + + +package DBD::MySQL::Server; + +use strict; +use Time::HiRes; +use IO::File; +use File::Copy 'cp'; +use Data::Dumper; + + +{ +  our $verbose = 0; +  our $scream = 0; # scream if something is not implemented +  our $access = "dbi"; # how do we access the database.  +  our $my_modules_dyn_dir = ""; # where we look for self-written extensions + +  my @servers = (); +  my $initerrors = undef; + +  sub add_server { +    push(@servers, shift); +  } + +  sub return_servers { +    return @servers; +  } +   +  sub return_first_server() { +    return $servers[0]; +  } + +} + +sub new { +  my $class = shift; +  my %params = @_; +  my $self = { +    access => $params{method} || 'dbi', +    hostname => $params{hostname}, +    database => $params{database} || 'information_schema', +    port => $params{port}, +    socket => $params{socket}, +    username => $params{username}, +    password => $params{password}, +    timeout => $params{timeout}, +    warningrange => $params{warningrange}, +    criticalrange => $params{criticalrange}, +    verbose => $params{verbose}, +    report => $params{report}, +    labelformat => $params{labelformat}, +    version => 'unknown', +    instance => undef, +    handle => undef, +  }; +  bless $self, $class; +  $self->init_nagios(); +  if ($self->dbconnect(%params)) { +    ($self->{dummy}, $self->{version}) = $self->{handle}->fetchrow_array( +        #q{ SHOW VARIABLES WHERE Variable_name = 'version' } +        q{ SHOW VARIABLES LIKE 'version' } +    ); +    $self->{version} = (split "-", $self->{version})[0]; +    ($self->{dummy}, $self->{uptime}) = $self->{handle}->fetchrow_array( +        q{ SHOW STATUS LIKE 'Uptime' } +    ); +    DBD::MySQL::Server::add_server($self); +    $self->init(%params); +  } +  return $self; +} + +sub init { +  my $self = shift; +  my %params = @_; +  $params{handle} = $self->{handle}; +  $params{uptime} = $self->{uptime}; +  $self->set_global_db_thresholds(\%params); +  if ($params{mode} =~ /^server::instance/) { +    $self->{instance} = DBD::MySQL::Server::Instance->new(%params); +  } elsif ($params{mode} =~ /^server::sql/) { +    $self->set_local_db_thresholds(%params); +    if ($params{regexp}) { +      # sql output is treated as text +      if ($params{name2} eq $params{name}) { +        $self->add_nagios_unknown(sprintf "where's the regexp????"); +      } else { +        $self->{genericsql} = +            $self->{handle}->fetchrow_array($params{selectname}); +        if (! defined $self->{genericsql}) { +          $self->add_nagios_unknown(sprintf "got no valid response for %s", +              $params{selectname}); +        } +      } +    } else { +      # sql output must be a number (or array of numbers) +      @{$self->{genericsql}} = +          $self->{handle}->fetchrow_array($params{selectname}); +      if (! (defined $self->{genericsql} && +          (scalar(grep { /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/ } @{$self->{genericsql}})) ==  +          scalar(@{$self->{genericsql}}))) { +        $self->add_nagios_unknown(sprintf "got no valid response for %s", +            $params{selectname}); +      } else { +        # name2 in array +        # units in array +      } +    } +  } elsif ($params{mode} =~ /^server::uptime/) { +    # already set with the connection. but use minutes here +  } elsif ($params{mode} =~ /^server::connectiontime/) { +    $self->{connection_time} = $self->{tac} - $self->{tic}; +  } elsif ($params{mode} =~ /^my::([^:.]+)/) { +    my $class = $1; +    my $loaderror = undef; +    substr($class, 0, 1) = uc substr($class, 0, 1); +    foreach my $libpath (split(":", $DBD::MySQL::Server::my_modules_dyn_dir)) { +      foreach my $extmod (glob $libpath."/CheckMySQLHealth*.pm") { +        eval { +          $self->trace(sprintf "loading module %s", $extmod); +          require $extmod; +        }; +        if ($@) { +          $loaderror = $extmod; +          $self->trace(sprintf "failed loading module %s: %s", $extmod, $@); +        } +      } +    } +    my $obj = { +        handle => $params{handle}, +        warningrange => $params{warningrange}, +        criticalrange => $params{criticalrange}, +    }; +    bless $obj, "My$class"; +    $self->{my} = $obj; +    if ($self->{my}->isa("DBD::MySQL::Server")) { +      my $dos_init = $self->can("init"); +      my $dos_nagios = $self->can("nagios"); +      my $my_init = $self->{my}->can("init"); +      my $my_nagios = $self->{my}->can("nagios"); +      if ($my_init == $dos_init) { +          $self->add_nagios_unknown( +              sprintf "Class %s needs an init() method", ref($self->{my})); +      } elsif ($my_nagios == $dos_nagios) { +          $self->add_nagios_unknown( +              sprintf "Class %s needs a nagios() method", ref($self->{my})); +      } else { +        $self->{my}->init_nagios(%params); +        $self->{my}->init(%params); +      } +    } else { +      $self->add_nagios_unknown( +          sprintf "Class %s is not a subclass of DBD::MySQL::Server%s",  +              ref($self->{my}), +              $loaderror ? sprintf " (syntax error in %s?)", $loaderror : "" ); +    } +  } else { +    printf "broken mode %s\n", $params{mode}; +  } +} + +sub dump { +  my $self = shift; +  my $message = shift || ""; +  printf "%s %s\n", $message, Data::Dumper::Dumper($self); +} + +sub nagios { +  my $self = shift; +  my %params = @_; +  if (! $self->{nagios_level}) { +    if ($params{mode} =~ /^server::instance/) { +      $self->{instance}->nagios(%params); +      $self->merge_nagios($self->{instance}); +    } elsif ($params{mode} =~ /^server::database/) { +      $self->{database}->nagios(%params); +      $self->merge_nagios($self->{database}); +    } elsif ($params{mode} =~ /^server::uptime/) { +      $self->add_nagios( +          $self->check_thresholds($self->{uptime} / 60, "10:", "5:"), +          sprintf "database is up since %d minutes", $self->{uptime} / 60); +      $self->add_perfdata(sprintf "uptime=%ds", +          $self->{uptime}); +    } elsif ($params{mode} =~ /^server::connectiontime/) { +      $self->add_nagios( +          $self->check_thresholds($self->{connection_time}, 1, 5), +          sprintf "%.2f seconds to connect as %s", +              $self->{connection_time}, ($self->{username} || getpwuid($<))); +      $self->add_perfdata(sprintf "connection_time=%.4fs;%d;%d", +          $self->{connection_time}, +          $self->{warningrange}, $self->{criticalrange}); +    } elsif ($params{mode} =~ /^server::sql/) { +      if ($params{regexp}) { +        if (substr($params{name2}, 0, 1) eq '!') { +          $params{name2} =~ s/^!//; +          if ($self->{genericsql} !~ /$params{name2}/) { +            $self->add_nagios_ok( +                sprintf "output %s does not match pattern %s", +                    $self->{genericsql}, $params{name2}); +          } else { +            $self->add_nagios_critical( +                sprintf "output %s matches pattern %s", +                    $self->{genericsql}, $params{name2}); +          } +        } else { +          if ($self->{genericsql} =~ /$params{name2}/) { +            $self->add_nagios_ok( +                sprintf "output %s matches pattern %s", +                    $self->{genericsql}, $params{name2}); +          } else { +            $self->add_nagios_critical( +                sprintf "output %s does not match pattern %s", +                    $self->{genericsql}, $params{name2}); +          } +        } +      } else { +        $self->add_nagios( +            # the first item in the list will trigger the threshold values +            $self->check_thresholds($self->{genericsql}[0], 1, 5), +                sprintf "%s: %s%s", +                $params{name2} ? lc $params{name2} : lc $params{selectname}, +                # float as float, integers as integers +                join(" ", map { +                    (sprintf("%d", $_) eq $_) ? $_ : sprintf("%f", $_) +                } @{$self->{genericsql}}), +                $params{units} ? $params{units} : ""); +        my $i = 0; +        # workaround... getting the column names from the database would be nicer +        my @names2_arr = split(/\s+/, $params{name2}); +        foreach my $t (@{$self->{genericsql}}) { +          $self->add_perfdata(sprintf "\'%s\'=%s%s;%s;%s", +              $names2_arr[$i] ? lc $names2_arr[$i] : lc $params{selectname}, +              # float as float, integers as integers +              (sprintf("%d", $t) eq $t) ? $t : sprintf("%f", $t), +              $params{units} ? $params{units} : "", +            ($i == 0) ? $self->{warningrange} : "", +              ($i == 0) ? $self->{criticalrange} : "" +          ); +          $i++; +        } +      } +    } elsif ($params{mode} =~ /^my::([^:.]+)/) { +      $self->{my}->nagios(%params); +      $self->merge_nagios($self->{my}); +    } +  } +} + + +sub init_nagios { +  my $self = shift; +  no strict 'refs'; +  if (! ref($self)) { +    my $nagiosvar = $self."::nagios"; +    my $nagioslevelvar = $self."::nagios_level"; +    $$nagiosvar = { +      messages => { +        0 => [], +        1 => [], +        2 => [], +        3 => [], +      }, +      perfdata => [], +    }; +    $$nagioslevelvar = $ERRORS{OK}, +  } else { +    $self->{nagios} = { +      messages => { +        0 => [], +        1 => [], +        2 => [], +        3 => [], +      }, +      perfdata => [], +    }; +    $self->{nagios_level} = $ERRORS{OK}, +  } +} + +sub check_thresholds { +  my $self = shift; +  my $value = shift; +  my $defaultwarningrange = shift; +  my $defaultcriticalrange = shift; +  my $level = $ERRORS{OK}; +  $self->{warningrange} = defined $self->{warningrange} ? +      $self->{warningrange} : $defaultwarningrange; +  $self->{criticalrange} = defined $self->{criticalrange} ? +      $self->{criticalrange} : $defaultcriticalrange; +  if ($self->{warningrange} !~ /:/ && $self->{criticalrange} !~ /:/) { +    # warning = 10, critical = 20, warn if > 10, crit if > 20 +    $level = $ERRORS{WARNING} if $value > $self->{warningrange}; +    $level = $ERRORS{CRITICAL} if $value > $self->{criticalrange}; +  } elsif ($self->{warningrange} =~ /([\d\.]+):/ &&  +      $self->{criticalrange} =~ /([\d\.]+):/) { +    # warning = 98:, critical = 95:, warn if < 98, crit if < 95 +    $self->{warningrange} =~ /([\d\.]+):/; +    $level = $ERRORS{WARNING} if $value < $1; +    $self->{criticalrange} =~ /([\d\.]+):/; +    $level = $ERRORS{CRITICAL} if $value < $1; +  } +  return $level; +  # +  # syntax error must be reported with returncode -1 +  # +} + +sub add_nagios { +  my $self = shift; +  my $level = shift; +  my $message = shift; +  push(@{$self->{nagios}->{messages}->{$level}}, $message); +  # recalc current level +  foreach my $llevel qw(CRITICAL WARNING UNKNOWN OK) { +    if (scalar(@{$self->{nagios}->{messages}->{$ERRORS{$llevel}}})) { +      $self->{nagios_level} = $ERRORS{$llevel}; +    } +  } +} + +sub add_nagios_ok { +  my $self = shift; +  my $message = shift; +  $self->add_nagios($ERRORS{OK}, $message); +} + +sub add_nagios_warning { +  my $self = shift; +  my $message = shift; +  $self->add_nagios($ERRORS{WARNING}, $message); +} + +sub add_nagios_critical { +  my $self = shift; +  my $message = shift; +  $self->add_nagios($ERRORS{CRITICAL}, $message); +} + +sub add_nagios_unknown { +  my $self = shift; +  my $message = shift; +  $self->add_nagios($ERRORS{UNKNOWN}, $message); +} + +sub add_perfdata { +  my $self = shift; +  my $data = shift; +  push(@{$self->{nagios}->{perfdata}}, $data); +} + +sub merge_nagios { +  my $self = shift; +  my $child = shift; +  foreach my $level (0..3) { +    foreach (@{$child->{nagios}->{messages}->{$level}}) { +      $self->add_nagios($level, $_); +    } +    #push(@{$self->{nagios}->{messages}->{$level}}, +    #    @{$child->{nagios}->{messages}->{$level}}); +  } +  push(@{$self->{nagios}->{perfdata}}, @{$child->{nagios}->{perfdata}}); +} + +sub calculate_result { +  my $self = shift; +  my $labels = shift || {}; +  my $multiline = 0; +  map { +    $self->{nagios_level} = $ERRORS{$_} if +        (scalar(@{$self->{nagios}->{messages}->{$ERRORS{$_}}})); +  } ("OK", "UNKNOWN", "WARNING", "CRITICAL"); +  if ($ENV{NRPE_MULTILINESUPPORT} && +      length join(" ", @{$self->{nagios}->{perfdata}}) > 200) { +    $multiline = 1; +  } +  my $all_messages = join(($multiline ? "\n" : ", "), map { +      join(($multiline ? "\n" : ", "), @{$self->{nagios}->{messages}->{$ERRORS{$_}}}) +  } grep { +      scalar(@{$self->{nagios}->{messages}->{$ERRORS{$_}}}) +  } ("CRITICAL", "WARNING", "UNKNOWN", "OK")); +  my $bad_messages = join(($multiline ? "\n" : ", "), map { +      join(($multiline ? "\n" : ", "), @{$self->{nagios}->{messages}->{$ERRORS{$_}}}) +  } grep { +      scalar(@{$self->{nagios}->{messages}->{$ERRORS{$_}}}) +  } ("CRITICAL", "WARNING", "UNKNOWN")); +  my $all_messages_short = $bad_messages ? $bad_messages : 'no problems'; +  my $all_messages_html = "<table style=\"border-collapse: collapse;\">". +      join("", map { +          my $level = $_; +          join("", map { +              sprintf "<tr valign=\"top\"><td class=\"service%s\">%s</td></tr>", +              $level, $_; +          } @{$self->{nagios}->{messages}->{$ERRORS{$_}}}); +      } grep { +          scalar(@{$self->{nagios}->{messages}->{$ERRORS{$_}}}) +      } ("CRITICAL", "WARNING", "UNKNOWN", "OK")). +  "</table>"; +  if (exists $self->{identstring}) { +    $self->{nagios_message} .= $self->{identstring}; +  } +  if ($self->{report} eq "long") { +    $self->{nagios_message} .= $all_messages; +  } elsif ($self->{report} eq "short") { +    $self->{nagios_message} .= $all_messages_short; +  } elsif ($self->{report} eq "html") { +    $self->{nagios_message} .= $all_messages_short."\n".$all_messages_html; +  } +  if ($self->{labelformat} eq "pnp4nagios") { +    $self->{perfdata} = join(" ", @{$self->{nagios}->{perfdata}}); +  } else { +    $self->{perfdata} = join(" ", map { +        my $perfdata = $_; +        if ($perfdata =~ /^(.*?)=(.*)/) { +          my $label = $1; +          my $data = $2; +          if (exists $labels->{$label} && +              exists $labels->{$label}->{$self->{labelformat}}) { +            $labels->{$label}->{$self->{labelformat}}."=".$data; +          } else { +            $perfdata; +          } +        } else { +          $perfdata; +        } +    } @{$self->{nagios}->{perfdata}}); +  } +} + +sub set_global_db_thresholds { +  my $self = shift; +  my $params = shift; +  my $warning = undef; +  my $critical = undef; +  return unless defined $params->{dbthresholds}; +  $params->{name0} = $params->{dbthresholds}; +  # :pluginmode   :name     :warning    :critical +  # mode          empty      +  #  +  eval { +    if ($self->{handle}->fetchrow_array(q{ +        SELECT table_name +        FROM information_schema.tables +        WHERE table_schema = ? +        AND table_name = 'CHECK_MYSQL_HEALTH_THRESHOLDS'; +      }, $self->{database})) { # either --database... or information_schema +      my @dbthresholds = $self->{handle}->fetchall_array(q{ +          SELECT * FROM check_mysql_health_thresholds +      }); +      $params->{dbthresholds} = \@dbthresholds; +      foreach (@dbthresholds) {  +        if (($_->[0] eq $params->{cmdlinemode}) && +            (! defined $_->[1] || ! $_->[1])) { +          ($warning, $critical) = ($_->[2], $_->[3]); +        } +      } +    } +  }; +  if (! $@) { +    if ($warning) { +      $params->{warningrange} = $warning; +      $self->trace("read warningthreshold %s from database", $warning); +    } +    if ($critical) { +      $params->{criticalrange} = $critical; +      $self->trace("read criticalthreshold %s from database", $critical); +    } +  } +} + +sub set_local_db_thresholds { +  my $self = shift; +  my %params = @_; +  my $warning = undef; +  my $critical = undef; +  # :pluginmode   :name     :warning    :critical +  # mode          name0 +  # mode          name2 +  # mode          name +  # +  # first: argument of --dbthresholds, it it exists +  # second: --name2 +  # third: --name +  if (ref($params{dbthresholds}) eq 'ARRAY') { +    my $marker; +    foreach (@{$params{dbthresholds}}) { +      if ($_->[0] eq $params{cmdlinemode}) { +        if (defined $_->[1] && $params{name0} && $_->[1] eq $params{name0}) { +          ($warning, $critical) = ($_->[2], $_->[3]); +          $marker = $params{name0}; +          last; +        } elsif (defined $_->[1] && $params{name2} && $_->[1] eq $params{name2}) { +          ($warning, $critical) = ($_->[2], $_->[3]); +          $marker = $params{name2}; +          last; +        } elsif (defined $_->[1] && $params{name} && $_->[1] eq $params{name}) { +          ($warning, $critical) = ($_->[2], $_->[3]); +          $marker = $params{name}; +          last; +        } +      } +    } +    if ($warning) { +      $self->{warningrange} = $warning; +      $self->trace("read warningthreshold %s for %s from database", +         $marker, $warning); +    } +    if ($critical) { +      $self->{criticalrange} = $critical; +      $self->trace("read criticalthreshold %s for %s from database", +          $marker, $critical); +    } +  } +} + +sub debug { +  my $self = shift; +  my $msg = shift; +  if ($DBD::MySQL::Server::verbose) { +    printf "%s %s\n", $msg, ref($self); +  } +} + +sub dbconnect { +  my $self = shift; +  my %params = @_; +  my $retval = undef; +  $self->{tic} = Time::HiRes::time(); +  $self->{handle} = DBD::MySQL::Server::Connection->new(%params); +  if ($self->{handle}->{errstr}) { +    if ($params{mode} =~ /^server::tnsping/ && +        $self->{handle}->{errstr} =~ /ORA-01017/) { +      $self->add_nagios($ERRORS{OK}, +          sprintf "connection established to %s.", $self->{connect}); +      $retval = undef; +    } elsif ($self->{handle}->{errstr} eq "alarm\n") { +      $self->add_nagios($ERRORS{CRITICAL}, +          sprintf "connection could not be established within %d seconds", +              $self->{timeout}); +    } else { +      $self->add_nagios($ERRORS{CRITICAL}, +          sprintf "cannot connect to %s. %s", +          $self->{database}, $self->{handle}->{errstr}); +      $retval = undef; +    } +  } else { +    $retval = $self->{handle}; +  } +  $self->{tac} = Time::HiRes::time(); +  return $retval; +} + +sub trace { +  my $self = shift; +  my $format = shift; +  $self->{trace} = -f "/tmp/check_mysql_health.trace" ? 1 : 0; +  if ($self->{verbose}) { +    printf("%s: ", scalar localtime); +    printf($format, @_); +  } +  if ($self->{trace}) { +    my $logfh = new IO::File; +    $logfh->autoflush(1); +    if ($logfh->open("/tmp/check_mysql_health.trace", "a")) { +      $logfh->printf("%s: ", scalar localtime); +      $logfh->printf($format, @_); +      $logfh->printf("\n"); +      $logfh->close(); +    } +  } +} + +sub DESTROY { +  my $self = shift; +  my $handle1 = "null"; +  my $handle2 = "null"; +  if (defined $self->{handle}) { +    $handle1 = ref($self->{handle}); +    if (defined $self->{handle}->{handle}) { +      $handle2 = ref($self->{handle}->{handle}); +    } +  } +  $self->trace(sprintf "DESTROY %s with handle %s %s", ref($self), $handle1, $handle2); +  if (ref($self) eq "DBD::MySQL::Server") { +  } +  $self->trace(sprintf "DESTROY %s exit with handle %s %s", ref($self), $handle1, $handle2); +  if (ref($self) eq "DBD::MySQL::Server") { +    #printf "humpftata\n"; +  } +} + +sub save_state { +  my $self = shift; +  my %params = @_; +  my $extension = ""; +  my $mode = $params{mode}; +  if ($params{connect} && $params{connect} =~ /(\w+)\/(\w+)@(\w+)/) { +    $params{connect} = $3; +  } elsif ($params{connect}) { +    # just to be sure +    $params{connect} =~ s/\//_/g; +  } +  if ($^O =~ /MSWin/) { +    $mode =~ s/::/_/g; +    $params{statefilesdir} = $self->system_vartmpdir(); +  } +  if (! -d $params{statefilesdir}) { +    eval { +      use File::Path; +      mkpath $params{statefilesdir}; +    }; +  } +  if ($@ || ! -w $params{statefilesdir}) { +    $self->add_nagios($ERRORS{CRITICAL}, +        sprintf "statefilesdir %s does not exist or is not writable\n", +        $params{statefilesdir}); +    return; +  } +  my $statefile = sprintf "%s_%s", $params{hostname}, $mode; +  $extension .= $params{differenciator} ? "_".$params{differenciator} : ""; +  $extension .= $params{socket} ? "_".$params{socket} : ""; +  $extension .= $params{port} ? "_".$params{port} : ""; +  $extension .= $params{database} ? "_".$params{database} : ""; +  $extension .= $params{tablespace} ? "_".$params{tablespace} : ""; +  $extension .= $params{datafile} ? "_".$params{datafile} : ""; +  $extension .= $params{name} ? "_".$params{name} : ""; +  $extension =~ s/\//_/g; +  $extension =~ s/\(/_/g; +  $extension =~ s/\)/_/g; +  $extension =~ s/\*/_/g; +  $extension =~ s/\s/_/g; +  $statefile .= $extension; +  $statefile = lc $statefile; +  $statefile = sprintf "%s/%s", $params{statefilesdir}, $statefile; +  if (open(STATE, ">$statefile")) { +    if ((ref($params{save}) eq "HASH") && exists $params{save}->{timestamp}) { +      $params{save}->{localtime} = scalar localtime $params{save}->{timestamp}; +    } +    printf STATE Data::Dumper::Dumper($params{save}); +    close STATE; +  } else {  +    $self->add_nagios($ERRORS{CRITICAL}, +        sprintf "statefile %s is not writable", $statefile); +  } +  $self->debug(sprintf "saved %s to %s", +      Data::Dumper::Dumper($params{save}), $statefile); +} + +sub load_state { +  my $self = shift; +  my %params = @_; +  my $extension = ""; +  my $mode = $params{mode}; +  if ($params{connect} && $params{connect} =~ /(\w+)\/(\w+)@(\w+)/) { +    $params{connect} = $3; +  } elsif ($params{connect}) { +    # just to be sure +    $params{connect} =~ s/\//_/g; +  } +  if ($^O =~ /MSWin/) { +    $mode =~ s/::/_/g; +    $params{statefilesdir} = $self->system_vartmpdir(); +  } +  my $statefile = sprintf "%s_%s", $params{hostname}, $mode; +  $extension .= $params{differenciator} ? "_".$params{differenciator} : ""; +  $extension .= $params{socket} ? "_".$params{socket} : ""; +  $extension .= $params{port} ? "_".$params{port} : ""; +  $extension .= $params{database} ? "_".$params{database} : ""; +  $extension .= $params{tablespace} ? "_".$params{tablespace} : ""; +  $extension .= $params{datafile} ? "_".$params{datafile} : ""; +  $extension .= $params{name} ? "_".$params{name} : ""; +  $extension =~ s/\//_/g; +  $extension =~ s/\(/_/g; +  $extension =~ s/\)/_/g; +  $extension =~ s/\*/_/g; +  $extension =~ s/\s/_/g; +  $statefile .= $extension; +  $statefile = lc $statefile; +  $statefile = sprintf "%s/%s", $params{statefilesdir}, $statefile; +  if ( -f $statefile) { +    our $VAR1; +    eval { +      require $statefile; +    }; +    if($@) { +      $self->add_nagios($ERRORS{CRITICAL}, +          sprintf "statefile %s is corrupt", $statefile); +    } +    $self->debug(sprintf "load %s", Data::Dumper::Dumper($VAR1)); +    return $VAR1; +  } else { +    return undef; +  } +} + +sub valdiff { +  my $self = shift; +  my $pparams = shift; +  my %params = %{$pparams}; +  my @keys = @_; +  my $now = time; +  my $last_values = $self->load_state(%params) || eval { +    my $empty_events = {}; +    foreach (@keys) { +      $empty_events->{$_} = 0; +    } +    $empty_events->{timestamp} = 0; +    if ($params{lookback}) { +      $empty_events->{lookback_history} = {}; +    } +    $empty_events; +  }; +  foreach (@keys) { +    if ($params{lookback}) { +      # find a last_value in the history which fits lookback best +      # and overwrite $last_values->{$_} with historic data +      if (exists $last_values->{lookback_history}->{$_}) { +        foreach my $date (sort {$a <=> $b} keys %{$last_values->{lookback_history}->{$_}}) { +          if ($date >= ($now - $params{lookback})) { +            $last_values->{$_} = $last_values->{lookback_history}->{$_}->{$date}; +            $last_values->{timestamp} = $date; +            last; +          } else { +            delete $last_values->{lookback_history}->{$_}->{$date}; +          } +        } +      } +    } +    $last_values->{$_} = 0 if ! exists $last_values->{$_}; +    if ($self->{$_} >= $last_values->{$_}) { +      $self->{'delta_'.$_} = $self->{$_} - $last_values->{$_}; +    } else { +      # vermutlich db restart und zaehler alle auf null +      $self->{'delta_'.$_} = $self->{$_}; +    } +    $self->debug(sprintf "delta_%s %f", $_, $self->{'delta_'.$_}); +  } +  $self->{'delta_timestamp'} = $now - $last_values->{timestamp}; +  $params{save} = eval { +    my $empty_events = {}; +    foreach (@keys) { +      $empty_events->{$_} = $self->{$_}; +    } +    $empty_events->{timestamp} = $now; +    if ($params{lookback}) { +      $empty_events->{lookback_history} = $last_values->{lookback_history}; +      foreach (@keys) { +        $empty_events->{lookback_history}->{$_}->{$now} = $self->{$_}; +      } +    } +    $empty_events; +  }; +  $self->save_state(%params); +} + +sub requires_version { +  my $self = shift; +  my $version = shift; +  my @instances = DBD::MySQL::Server::return_servers(); +  my $instversion = $instances[0]->{version}; +  if (! $self->version_is_minimum($version)) { +    $self->add_nagios($ERRORS{UNKNOWN},  +        sprintf "not implemented/possible for MySQL release %s", $instversion); +  } +} + +sub version_is_minimum { +  # the current version is newer or equal +  my $self = shift; +  my $version = shift; +  my $newer = 1; +  my @instances = DBD::MySQL::Server::return_servers(); +  my @v1 = map { $_ eq "x" ? 0 : $_ } split(/\./, $version); +  my @v2 = split(/\./, $instances[0]->{version}); +  if (scalar(@v1) > scalar(@v2)) { +    push(@v2, (0) x (scalar(@v1) - scalar(@v2))); +  } elsif (scalar(@v2) > scalar(@v1)) { +    push(@v1, (0) x (scalar(@v2) - scalar(@v1))); +  } +  foreach my $pos (0..$#v1) { +    if ($v2[$pos] > $v1[$pos]) { +      $newer = 1; +      last; +    } elsif ($v2[$pos] < $v1[$pos]) { +      $newer = 0; +      last; +    } +  } +  #printf STDERR "check if %s os minimum %s\n", join(".", @v2), join(".", @v1); +  return $newer; +} + +sub instance_thread { +  my $self = shift; +  my @instances = DBD::MySQL::Server::return_servers(); +  return $instances[0]->{thread}; +} + +sub windows_server { +  my $self = shift; +  my @instances = DBD::MySQL::Server::return_servers(); +  if ($instances[0]->{os} =~ /Win/i) { +    return 1; +  } else { +    return 0; +  } +} + +sub system_vartmpdir { +  my $self = shift; +  if ($^O =~ /MSWin/) { +    return $self->system_tmpdir(); +  } else { +    return "/var/tmp/check_mysql_health"; +  } +} + +sub system_oldvartmpdir { +  my $self = shift; +  return "/tmp"; +} + +sub system_tmpdir { +  my $self = shift; +  if ($^O =~ /MSWin/) { +    return $ENV{TEMP} if defined $ENV{TEMP}; +    return $ENV{TMP} if defined $ENV{TMP}; +    return File::Spec->catfile($ENV{windir}, 'Temp') +        if defined $ENV{windir}; +    return 'C:\Temp'; +  } else { +    return "/tmp"; +  } +} + + +package DBD::MySQL::Server::Connection; + +use strict; + +our @ISA = qw(DBD::MySQL::Server); + + +sub new { +  my $class = shift; +  my %params = @_; +  my $self = { +    mode => $params{mode}, +    timeout => $params{timeout}, +    access => $params{method} || "dbi", +    hostname => $params{hostname}, +    database => $params{database} || "information_schema", +    port => $params{port}, +    socket => $params{socket}, +    username => $params{username}, +    password => $params{password}, +    handle => undef, +  }; +  bless $self, $class; +  if ($params{method} eq "dbi") { +    bless $self, "DBD::MySQL::Server::Connection::Dbi"; +  } elsif ($params{method} eq "mysql") { +    bless $self, "DBD::MySQL::Server::Connection::Mysql"; +  } elsif ($params{method} eq "sqlrelay") { +    bless $self, "DBD::MySQL::Server::Connection::Sqlrelay"; +  } +  $self->init(%params); +  return $self; +} + + +package DBD::MySQL::Server::Connection::Dbi; + +use strict; +use Net::Ping; + +our @ISA = qw(DBD::MySQL::Server::Connection); + + +sub init { +  my $self = shift; +  my %params = @_; +  my $retval = undef; +  if ($self->{mode} =~ /^server::tnsping/) { +    if (! $self->{connect}) { +      $self->{errstr} = "Please specify a database"; +    } else { +      $self->{sid} = $self->{connect}; +      $self->{username} ||= time;  # prefer an existing user +      $self->{password} = time; +    } +  } else { +    if (($self->{hostname} ne 'localhost') && (! $self->{username} || ! $self->{password})) { +      $self->{errstr} = "Please specify hostname, username and password"; +      return undef; +    } +    $self->{dsn} = "DBI:mysql:"; +    $self->{dsn} .= sprintf "database=%s", $self->{database}; +    $self->{dsn} .= sprintf ";host=%s", $self->{hostname}; +    $self->{dsn} .= sprintf ";port=%s", $self->{port} +        unless $self->{socket} || $self->{hostname} eq 'localhost'; +    $self->{dsn} .= sprintf ";mysql_socket=%s", $self->{socket}  +        if $self->{socket}; +  } +  if (! exists $self->{errstr}) { +    eval { +      require DBI; +      use POSIX ':signal_h'; +      local $SIG{'ALRM'} = sub { +        die "alarm\n"; +      }; +      my $mask = POSIX::SigSet->new( SIGALRM ); +      my $action = POSIX::SigAction->new( +          sub { die "alarm\n" ; }, $mask); +      my $oldaction = POSIX::SigAction->new(); +      sigaction(SIGALRM ,$action ,$oldaction ); +      alarm($self->{timeout} - 1); # 1 second before the global unknown timeout +      if ($self->{handle} = DBI->connect( +          $self->{dsn}, +          $self->{username}, +          $self->{password}, +          { RaiseError => 0, AutoCommit => 0, PrintError => 0 })) { +#        $self->{handle}->do(q{ +#            ALTER SESSION SET NLS_NUMERIC_CHARACTERS=".," }); +        $retval = $self; +      } else { +        $self->{errstr} = DBI::errstr(); +      } +    }; +    if ($@) { +      $self->{errstr} = $@; +      $retval = undef; +    } +  } +  $self->{tac} = Time::HiRes::time(); +  return $retval; +} + +sub selectrow_hashref { +  my $self = shift; +  my $sql = shift; +  my @arguments = @_; +  my $sth = undef; +  my $hashref = undef; +  eval { +    $self->trace(sprintf "SQL:\n%s\nARGS:\n%s\n", +        $sql, Data::Dumper::Dumper(\@arguments)); +    # helm auf! jetzt wirds dreckig. +    if ($sql =~ /^\s*SHOW/) { +      $hashref = $self->{handle}->selectrow_hashref($sql); +    } else { +      $sth = $self->{handle}->prepare($sql); +      if (scalar(@arguments)) { +        $sth->execute(@arguments); +      } else { +        $sth->execute(); +      } +      $hashref = $sth->selectrow_hashref(); +    } +    $self->trace(sprintf "RESULT:\n%s\n", +        Data::Dumper::Dumper($hashref)); +  }; +  if ($@) { +    $self->debug(sprintf "bumm %s", $@); +  } +  if (-f "/tmp/check_mysql_health_simulation/".$self->{mode}) { +    my $simulation = do { local (@ARGV, $/) = +        "/tmp/check_mysql_health_simulation/".$self->{mode}; <> }; +    # keine lust auf den scheiss +  } +  return $hashref; +} + +sub fetchrow_array { +  my $self = shift; +  my $sql = shift; +  my @arguments = @_; +  my $sth = undef; +  my @row = (); +  eval { +    $self->trace(sprintf "SQL:\n%s\nARGS:\n%s\n", +        $sql, Data::Dumper::Dumper(\@arguments)); +    $sth = $self->{handle}->prepare($sql); +    if (scalar(@arguments)) { +      $sth->execute(@arguments); +    } else { +      $sth->execute(); +    } +    @row = $sth->fetchrow_array(); +    $self->trace(sprintf "RESULT:\n%s\n", +        Data::Dumper::Dumper(\@row)); +  };  +  if ($@) { +    $self->debug(sprintf "bumm %s", $@); +  } +  if (-f "/tmp/check_mysql_health_simulation/".$self->{mode}) { +    my $simulation = do { local (@ARGV, $/) =  +        "/tmp/check_mysql_health_simulation/".$self->{mode}; <> }; +    @row = split(/\s+/, (split(/\n/, $simulation))[0]); +  } +  return $row[0] unless wantarray; +  return @row; +} + +sub fetchall_array { +  my $self = shift; +  my $sql = shift; +  my @arguments = @_; +  my $sth = undef; +  my $rows = undef; +  eval { +    $self->trace(sprintf "SQL:\n%s\nARGS:\n%s\n", +        $sql, Data::Dumper::Dumper(\@arguments)); +    $sth = $self->{handle}->prepare($sql); +    if (scalar(@arguments)) { +      $sth->execute(@arguments); +    } else { +      $sth->execute(); +    } +    $rows = $sth->fetchall_arrayref(); +    $self->trace(sprintf "RESULT:\n%s\n", +        Data::Dumper::Dumper($rows)); +  };  +  if ($@) { +    printf STDERR "bumm %s\n", $@; +  } +  if (-f "/tmp/check_mysql_health_simulation/".$self->{mode}) { +    my $simulation = do { local (@ARGV, $/) =  +        "/tmp/check_mysql_health_simulation/".$self->{mode}; <> }; +    @{$rows} = map { [ split(/\s+/, $_) ] } split(/\n/, $simulation); +  } +  return @{$rows}; +} + +sub func { +  my $self = shift; +  $self->{handle}->func(@_); +} + + +sub execute { +  my $self = shift; +  my $sql = shift; +  eval { +    my $sth = $self->{handle}->prepare($sql); +    $sth->execute(); +  }; +  if ($@) { +    printf STDERR "bumm %s\n", $@; +  } +} + +sub errstr { +  my $self = shift; +  return $self->{errstr}; +} + +sub DESTROY { +  my $self = shift; +  $self->trace(sprintf "disconnecting DBD %s", +      $self->{handle} ? "with handle" : "without handle"); +  $self->{handle}->disconnect() if $self->{handle}; +} + +package DBD::MySQL::Server::Connection::Mysql; + +use strict; +use File::Temp qw/tempfile/; + +our @ISA = qw(DBD::MySQL::Server::Connection); + + +sub init { +  my $self = shift; +  my %params = @_; +  my $retval = undef; +  $self->{loginstring} = "traditional"; +  ($self->{sql_commandfile_handle}, $self->{sql_commandfile}) = +      tempfile($self->{mode}."XXXXX", SUFFIX => ".sql",  +      DIR => $self->system_tmpdir() ); +  close $self->{sql_commandfile_handle}; +  ($self->{sql_resultfile_handle}, $self->{sql_resultfile}) = +      tempfile($self->{mode}."XXXXX", SUFFIX => ".out",  +      DIR => $self->system_tmpdir() ); +  close $self->{sql_resultfile_handle}; +  if ($self->{mode} =~ /^server::tnsping/) { +    if (! $self->{connect}) { +      $self->{errstr} = "Please specify a database"; +    } else { +      $self->{sid} = $self->{connect}; +      $self->{username} ||= time;  # prefer an existing user +      $self->{password} = time; +    } +  } else { +    if (! $self->{username} || ! $self->{password}) { +      $self->{errstr} = "Please specify database, username and password"; +      return undef; +    } elsif (! (($self->{hostname} && $self->{port}) || $self->{socket})) { +      $self->{errstr} = "Please specify hostname and port or socket"; +      return undef; +    } +  } +  if (! exists $self->{errstr}) { +    eval { +      my $mysql = '/'.'usr'.'/'.'bin'.'/'.'mysql'; +      if (! -x $mysql) { +        die "nomysql\n"; +      } +      if ($self->{loginstring} eq "traditional") { +        $self->{sqlplus} = sprintf "%s ", $mysql; +        $self->{sqlplus} .= sprintf "--batch --raw --skip-column-names "; +        $self->{sqlplus} .= sprintf "--database=%s ", $self->{database}; +        $self->{sqlplus} .= sprintf "--host=%s ", $self->{hostname}; +        $self->{sqlplus} .= sprintf "--port=%s ", $self->{port} +            unless $self->{socket} || $self->{hostname} eq "localhost"; +        $self->{sqlplus} .= sprintf "--socket=%s ", $self->{socket} +            if $self->{socket}; +        $self->{sqlplus} .= sprintf "--user=%s --password=%s < %s > %s", +            $self->{username}, $self->{password}, +            $self->{sql_commandfile}, $self->{sql_resultfile}; +      } +   +      use POSIX ':signal_h'; +      local $SIG{'ALRM'} = sub { +        die "alarm\n"; +      }; +      my $mask = POSIX::SigSet->new( SIGALRM ); +      my $action = POSIX::SigAction->new( +          sub { die "alarm\n" ; }, $mask); +      my $oldaction = POSIX::SigAction->new(); +      sigaction(SIGALRM ,$action ,$oldaction ); +      alarm($self->{timeout} - 1); # 1 second before the global unknown timeout +   +      my $answer = $self->fetchrow_array( +          q{ SELECT 42 FROM dual}); +      die unless defined $answer and $answer == 42; +      $retval = $self; +    }; +    if ($@) { +      $self->{errstr} = $@; +      $self->{errstr} =~ s/at $0 .*//g; +      chomp $self->{errstr}; +      $retval = undef; +    } +  } +  $self->{tac} = Time::HiRes::time(); +  return $retval; +} + +sub selectrow_hashref { +  my $self = shift; +  my $sql = shift; +  my @arguments = @_; +  my $sth = undef; +  my $hashref = undef; +  foreach (@arguments) { +    # replace the ? by the parameters +    if (/^\d+$/) { +      $sql =~ s/\?/$_/; +    } else { +      $sql =~ s/\?/'$_'/; +    } +  } +  if ($sql =~ /^\s*SHOW/) { +    $sql .= '\G'; # http://dev.mysql.com/doc/refman/5.1/de/show-slave-status.html +  } +  $self->trace(sprintf "SQL (? resolved):\n%s\nARGS:\n%s\n", +      $sql, Data::Dumper::Dumper(\@arguments)); +  $self->create_commandfile($sql); +  my $exit_output = `$self->{sqlplus}`; +  if ($?) { +    printf STDERR "fetchrow_array exit bumm \n"; +    my $output = do { local (@ARGV, $/) = $self->{sql_resultfile}; <> }; +    my @oerrs = map { +      /((ERROR \d+).*)/ ? $1 : (); +    } split(/\n/, $output); +    $self->{errstr} = join(" ", @oerrs); +  } else { +    my $output = do { local (@ARGV, $/) = $self->{sql_resultfile}; <> }; +    if ($sql =~ /^\s*SHOW/) { +      map { +        if (/^\s*([\w_]+):\s*(.*)/) { +          $hashref->{$1} = $2; +        } +      } split(/\n/, $output); +    } else { +      # i dont mess around here and you shouldn't either +    } +    $self->trace(sprintf "RESULT:\n%s\n", +        Data::Dumper::Dumper($hashref)); +  } +  unlink $self->{sql_commandfile}; +  unlink $self->{sql_resultfile}; +  return $hashref; +} + +sub fetchrow_array { +  my $self = shift; +  my $sql = shift; +  my @arguments = @_; +  my $sth = undef; +  my @row = (); +  foreach (@arguments) { +    # replace the ? by the parameters +    if (/^\d+$/) { +      $sql =~ s/\?/$_/; +    } else { +      $sql =~ s/\?/'$_'/; +    } +  } +  $self->trace(sprintf "SQL (? resolved):\n%s\nARGS:\n%s\n", +      $sql, Data::Dumper::Dumper(\@arguments)); +  $self->create_commandfile($sql); +  my $exit_output = `$self->{sqlplus}`; +  if ($?) { +    printf STDERR "fetchrow_array exit bumm \n"; +    my $output = do { local (@ARGV, $/) = $self->{sql_resultfile}; <> }; +    my @oerrs = map { +      /((ERROR \d+).*)/ ? $1 : (); +    } split(/\n/, $output); +    $self->{errstr} = join(" ", @oerrs); +  } else { +    my $output = do { local (@ARGV, $/) = $self->{sql_resultfile}; <> }; +    @row = map { convert($_) }  +        map { s/^\s+([\.\d]+)$/$1/g; $_ }         # strip leading space from numbers +        map { s/\s+$//g; $_ }                     # strip trailing space +        split(/\t/, (split(/\n/, $output))[0]); +    $self->trace(sprintf "RESULT:\n%s\n", +        Data::Dumper::Dumper(\@row)); +  } +  if ($@) { +    $self->debug(sprintf "bumm %s", $@); +  } +  unlink $self->{sql_commandfile}; +  unlink $self->{sql_resultfile}; +  return $row[0] unless wantarray; +  return @row; +} + +sub fetchall_array { +  my $self = shift; +  my $sql = shift; +  my @arguments = @_; +  my $sth = undef; +  my $rows = undef; +  foreach (@arguments) { +    # replace the ? by the parameters +    if (/^\d+$/) { +      $sql =~ s/\?/$_/; +    } else { +      $sql =~ s/\?/'$_'/; +    } +  } +  $self->trace(sprintf "SQL (? resolved):\n%s\nARGS:\n%s\n", +      $sql, Data::Dumper::Dumper(\@arguments)); +  $self->create_commandfile($sql); +  my $exit_output = `$self->{sqlplus}`; +  if ($?) { +    printf STDERR "fetchrow_array exit bumm %s\n", $exit_output; +    my $output = do { local (@ARGV, $/) = $self->{sql_resultfile}; <> }; +    my @oerrs = map { +      /((ERROR \d+).*)/ ? $1 : (); +    } split(/\n/, $output); +    $self->{errstr} = join(" ", @oerrs); +  } else { +    my $output = do { local (@ARGV, $/) = $self->{sql_resultfile}; <> }; +    my @rows = map { [  +        map { convert($_) }  +        map { s/^\s+([\.\d]+)$/$1/g; $_ } +        map { s/\s+$//g; $_ } +        split /\t/ +    ] } grep { ! /^\d+ rows selected/ }  +        grep { ! /^Elapsed: / } +        grep { ! /^\s*$/ } split(/\n/, $output); +    $rows = \@rows; +    $self->trace(sprintf "RESULT:\n%s\n", +        Data::Dumper::Dumper($rows)); +  } +  if ($@) { +    $self->debug(sprintf "bumm %s", $@); +  } +  unlink $self->{sql_commandfile}; +  unlink $self->{sql_resultfile}; +  return @{$rows}; +} + +sub func { +  my $self = shift; +  my $function = shift; +  $self->{handle}->func(@_); +} + +sub convert { +  my $n = shift; +  # mostly used to convert numbers in scientific notation +  if ($n =~ /^\s*\d+\s*$/) { +    return $n; +  } elsif ($n =~ /^\s*([-+]?)(\d*[\.,]*\d*)[eE]{1}([-+]?)(\d+)\s*$/) { +    my ($vor, $num, $sign, $exp) = ($1, $2, $3, $4); +    $n =~ s/E/e/g; +    $n =~ s/,/\./g; +    $num =~ s/,/\./g; +    my $sig = $sign eq '-' ? "." . ($exp - 1 + length $num) : ''; +    my $dec = sprintf "%${sig}f", $n; +    $dec =~ s/\.[0]+$//g; +    return $dec; +  } elsif ($n =~ /^\s*([-+]?)(\d+)[\.,]*(\d*)\s*$/) { +    return $1.$2.".".$3; +  } elsif ($n =~ /^\s*(.*?)\s*$/) { +    return $1; +  } else { +    return $n; +  } +} + + +sub execute { +  my $self = shift; +  my $sql = shift; +  eval { +    my $sth = $self->{handle}->prepare($sql); +    $sth->execute(); +  }; +  if ($@) { +    printf STDERR "bumm %s\n", $@; +  } +} + +sub errstr { +  my $self = shift; +  return $self->{errstr}; +} + +sub DESTROY { +  my $self = shift; +  $self->trace("try to clean up command and result files"); +  unlink $self->{sql_commandfile} if -f $self->{sql_commandfile}; +  unlink $self->{sql_resultfile} if -f $self->{sql_resultfile}; +} + +sub create_commandfile { +  my $self = shift; +  my $sql = shift; +  open CMDCMD, "> $self->{sql_commandfile}";  +  printf CMDCMD "%s\n", $sql; +  close CMDCMD; +} + + +package DBD::MySQL::Server::Connection::Sqlrelay; + +use strict; +use Net::Ping; + +our @ISA = qw(DBD::MySQL::Server::Connection); + + +sub init { +  my $self = shift; +  my %params = @_; +  my $retval = undef; +  if ($self->{mode} =~ /^server::tnsping/) { +    if (! $self->{connect}) { +      $self->{errstr} = "Please specify a database"; +    } else { +      if ($self->{connect} =~ /([\.\w]+):(\d+)/) { +        $self->{host} = $1; +        $self->{port} = $2; +        $self->{socket} = ""; +      } elsif ($self->{connect} =~ /([\.\w]+):([\w\/]+)/) { +        $self->{host} = $1; +        $self->{socket} = $2; +        $self->{port} = ""; +      } +    } +  } else { +    if (! $self->{hostname} || ! $self->{username} || ! $self->{password}) { +      if ($self->{hostname} && $self->{hostname} =~ /(\w+)\/(\w+)@([\.\w]+):(\d+)/) { +        $self->{username} = $1; +        $self->{password} = $2; +        $self->{hostname} = $3; +        $self->{port} = $4; +        $self->{socket} = ""; +      } elsif ($self->{hostname} && $self->{hostname} =~ /(\w+)\/(\w+)@([\.\w]+):([\w\/]+)/) { +        $self->{username} = $1; +        $self->{password} = $2; +        $self->{hostname} = $3; +        $self->{socket} = $4; +        $self->{port} = ""; +      } else { +        $self->{errstr} = "Please specify database, username and password"; +        return undef; +      } +    } else { +      if ($self->{hostname} =~ /([\.\w]+):(\d+)/) { +        $self->{hostname} = $1; +        $self->{port} = $2; +        $self->{socket} = ""; +      } elsif ($self->{hostname} =~ /([\.\w]+):([\w\/]+)/) { +        $self->{hostname} = $1; +        $self->{socket} = $2; +        $self->{port} = ""; +      } else { +        $self->{errstr} = "Please specify hostname, username, password and port/socket"; +        return undef; +      } +    } +  } +  if (! exists $self->{errstr}) { +    eval { +      require DBI; +      use POSIX ':signal_h'; +      local $SIG{'ALRM'} = sub { +        die "alarm\n"; +      }; +      my $mask = POSIX::SigSet->new( SIGALRM ); +      my $action = POSIX::SigAction->new( +      sub { die "alarm\n" ; }, $mask); +      my $oldaction = POSIX::SigAction->new(); +      sigaction(SIGALRM ,$action ,$oldaction ); +      alarm($self->{timeout} - 1); # 1 second before the global unknown timeout +      if ($self->{handle} = DBI->connect( +          sprintf("DBI:SQLRelay:host=%s;port=%d;socket=%s",  +          $self->{hostname}, $self->{port}, $self->{socket}), +          $self->{username}, +          $self->{password}, +          { RaiseError => 1, AutoCommit => 0, PrintError => 1 })) { +        $retval = $self; +        if ($self->{mode} =~ /^server::tnsping/ && $self->{handle}->ping()) { +          # database connected. fake a "unknown user" +          $self->{errstr} = "ORA-01017"; +        } +      } else { +        $self->{errstr} = DBI::errstr(); +      } +    }; +    if ($@) { +      $self->{errstr} = $@; +      $self->{errstr} =~ s/at [\w\/\.]+ line \d+.*//g; +      $retval = undef; +    } +  } +  $self->{tac} = Time::HiRes::time(); +  return $retval; +} + +sub fetchrow_array { +  my $self = shift; +  my $sql = shift; +  my @arguments = @_; +  my $sth = undef; +  my @row = (); +  $self->trace(sprintf "fetchrow_array: %s", $sql); +  eval { +    $sth = $self->{handle}->prepare($sql); +    if (scalar(@arguments)) { +      $sth->execute(@arguments); +    } else { +      $sth->execute(); +    } +    @row = $sth->fetchrow_array(); +  }; +  if ($@) { +    $self->debug(sprintf "bumm %s", $@); +  } +  if (-f "/tmp/check_mysql_health_simulation/".$self->{mode}) { +    my $simulation = do { local (@ARGV, $/) = +        "/tmp/check_mysql_health_simulation/".$self->{mode}; <> }; +    @row = split(/\s+/, (split(/\n/, $simulation))[0]); +  } +  return $row[0] unless wantarray; +  return @row; +} + +sub fetchall_array { +  my $self = shift; +  my $sql = shift; +  my @arguments = @_; +  my $sth = undef; +  my $rows = undef; +  $self->trace(sprintf "fetchall_array: %s", $sql); +  eval { +    $sth = $self->{handle}->prepare($sql); +    if (scalar(@arguments)) { +      $sth->execute(@arguments); +    } else { +      $sth->execute(); +    } +    $rows = $sth->fetchall_arrayref(); +  }; +  if ($@) { +    printf STDERR "bumm %s\n", $@; +  } +  if (-f "/tmp/check_mysql_health_simulation/".$self->{mode}) { +    my $simulation = do { local (@ARGV, $/) = +        "/tmp/check_mysql_health_simulation/".$self->{mode}; <> }; +    @{$rows} = map { [ split(/\s+/, $_) ] } split(/\n/, $simulation); +  } +  return @{$rows}; +} + +sub func { +  my $self = shift; +  $self->{handle}->func(@_); +} + +sub execute { +  my $self = shift; +  my $sql = shift; +  eval { +    my $sth = $self->{handle}->prepare($sql); +    $sth->execute(); +  }; +  if ($@) { +    printf STDERR "bumm %s\n", $@; +  } +} + +sub DESTROY { +  my $self = shift; +  #$self->trace(sprintf "disconnecting DBD %s", +  #    $self->{handle} ? "with handle" : "without handle"); +  #$self->{handle}->disconnect() if $self->{handle}; +} + + + + +package DBD::MySQL::Cluster; + +use strict; +use Time::HiRes; +use IO::File; +use Data::Dumper; + + +{ +  our $verbose = 0; +  our $scream = 0; # scream if something is not implemented +  our $access = "dbi"; # how do we access the database.  +  our $my_modules_dyn_dir = ""; # where we look for self-written extensions + +  my @clusters = (); +  my $initerrors = undef; + +  sub add_cluster { +    push(@clusters, shift); +  } + +  sub return_clusters { +    return @clusters; +  } +   +  sub return_first_cluster() { +    return $clusters[0]; +  } + +} + +sub new { +  my $class = shift; +  my %params = @_; +  my $self = { +    hostname => $params{hostname}, +    port => $params{port}, +    username => $params{username}, +    password => $params{password}, +    timeout => $params{timeout}, +    warningrange => $params{warningrange}, +    criticalrange => $params{criticalrange}, +    version => 'unknown', +    nodes => [], +    ndbd_nodes => 0, +    ndb_mgmd_nodes => 0, +    mysqld_nodes => 0, +  }; +  bless $self, $class; +  $self->init_nagios(); +  if ($self->connect(%params)) { +    DBD::MySQL::Cluster::add_cluster($self); +    $self->init(%params); +  } +  return $self; +} + +sub init { +  my $self = shift; +  my %params = @_; +  if ($self->{show}) { +    my $type = undef; +    foreach (split /\n/, $self->{show}) { +      if (/\[(\w+)\((\w+)\)\]\s+(\d+) node/) { +        $type = uc $2; +      } elsif (/id=(\d+)(.*)/) { +        push(@{$self->{nodes}}, DBD::MySQL::Cluster::Node->new( +            type => $type, +            id => $1, +            status => $2, +        )); +      } +    } +  } else { +  } +  if ($params{mode} =~ /^cluster::ndbdrunning/) { +    foreach my $node (@{$self->{nodes}}) { +      $node->{type} eq "NDB" && $node->{status} eq "running" && $self->{ndbd_nodes}++; +      $node->{type} eq "MGM" && $node->{status} eq "running" && $self->{ndb_mgmd_nodes}++; +      $node->{type} eq "API" && $node->{status} eq "running" && $self->{mysqld_nodes}++; +    } +  } else { +    printf "broken mode %s\n", $params{mode}; +  } +} + +sub dump { +  my $self = shift; +  my $message = shift || ""; +  printf "%s %s\n", $message, Data::Dumper::Dumper($self); +} + +sub nagios { +  my $self = shift; +  my %params = @_; +  my $dead_ndb = 0; +  my $dead_api = 0; +  if (! $self->{nagios_level}) { +    if ($params{mode} =~ /^cluster::ndbdrunning/) { +      foreach my $node (grep { $_->{type} eq "NDB"} @{$self->{nodes}}) { +        next if $params{selectname} && $params{selectname} ne $_->{id}; +        if (! $node->{connected}) { +          $self->add_nagios_critical( +              sprintf "ndb node %d is not connected", $node->{id}); +          $dead_ndb++; +        } +      } +      foreach my $node (grep { $_->{type} eq "API"} @{$self->{nodes}}) { +        next if $params{selectname} && $params{selectname} ne $_->{id}; +        if (! $node->{connected}) { +          $self->add_nagios_critical( +              sprintf "api node %d is not connected", $node->{id}); +          $dead_api++; +        } +      } +      if (! $dead_ndb) { +        $self->add_nagios_ok("all ndb nodes are connected"); +      } +      if (! $dead_api) { +        $self->add_nagios_ok("all api nodes are connected"); +      } +    } +  } +  $self->add_perfdata(sprintf "ndbd_nodes=%d ndb_mgmd_nodes=%d mysqld_nodes=%d", +      $self->{ndbd_nodes}, $self->{ndb_mgmd_nodes}, $self->{mysqld_nodes}); +} + + +sub init_nagios { +  my $self = shift; +  no strict 'refs'; +  if (! ref($self)) { +    my $nagiosvar = $self."::nagios"; +    my $nagioslevelvar = $self."::nagios_level"; +    $$nagiosvar = { +      messages => { +        0 => [], +        1 => [], +        2 => [], +        3 => [], +      }, +      perfdata => [], +    }; +    $$nagioslevelvar = $ERRORS{OK}, +  } else { +    $self->{nagios} = { +      messages => { +        0 => [], +        1 => [], +        2 => [], +        3 => [], +      }, +      perfdata => [], +    }; +    $self->{nagios_level} = $ERRORS{OK}, +  } +} + +sub check_thresholds { +  my $self = shift; +  my $value = shift; +  my $defaultwarningrange = shift; +  my $defaultcriticalrange = shift; +  my $level = $ERRORS{OK}; +  $self->{warningrange} = $self->{warningrange} ? +      $self->{warningrange} : $defaultwarningrange; +  $self->{criticalrange} = $self->{criticalrange} ? +      $self->{criticalrange} : $defaultcriticalrange; +  if ($self->{warningrange} !~ /:/ && $self->{criticalrange} !~ /:/) { +    # warning = 10, critical = 20, warn if > 10, crit if > 20 +    $level = $ERRORS{WARNING} if $value > $self->{warningrange}; +    $level = $ERRORS{CRITICAL} if $value > $self->{criticalrange}; +  } elsif ($self->{warningrange} =~ /([\d\.]+):/ &&  +      $self->{criticalrange} =~ /([\d\.]+):/) { +    # warning = 98:, critical = 95:, warn if < 98, crit if < 95 +    $self->{warningrange} =~ /([\d\.]+):/; +    $level = $ERRORS{WARNING} if $value < $1; +    $self->{criticalrange} =~ /([\d\.]+):/; +    $level = $ERRORS{CRITICAL} if $value < $1; +  } +  return $level; +  # +  # syntax error must be reported with returncode -1 +  # +} + +sub add_nagios { +  my $self = shift; +  my $level = shift; +  my $message = shift; +  push(@{$self->{nagios}->{messages}->{$level}}, $message); +  # recalc current level +  foreach my $llevel qw(CRITICAL WARNING UNKNOWN OK) { +    if (scalar(@{$self->{nagios}->{messages}->{$ERRORS{$llevel}}})) { +      $self->{nagios_level} = $ERRORS{$llevel}; +    } +  } +} + +sub add_nagios_ok { +  my $self = shift; +  my $message = shift; +  $self->add_nagios($ERRORS{OK}, $message); +} + +sub add_nagios_warning { +  my $self = shift; +  my $message = shift; +  $self->add_nagios($ERRORS{WARNING}, $message); +} + +sub add_nagios_critical { +  my $self = shift; +  my $message = shift; +  $self->add_nagios($ERRORS{CRITICAL}, $message); +} + +sub add_nagios_unknown { +  my $self = shift; +  my $message = shift; +  $self->add_nagios($ERRORS{UNKNOWN}, $message); +} + +sub add_perfdata { +  my $self = shift; +  my $data = shift; +  push(@{$self->{nagios}->{perfdata}}, $data); +} + +sub merge_nagios { +  my $self = shift; +  my $child = shift; +  foreach my $level (0..3) { +    foreach (@{$child->{nagios}->{messages}->{$level}}) { +      $self->add_nagios($level, $_); +    } +    #push(@{$self->{nagios}->{messages}->{$level}}, +    #    @{$child->{nagios}->{messages}->{$level}}); +  } +  push(@{$self->{nagios}->{perfdata}}, @{$child->{nagios}->{perfdata}}); +} + + +sub calculate_result { +  my $self = shift; +  if ($ENV{NRPE_MULTILINESUPPORT} &&  +      length join(" ", @{$self->{nagios}->{perfdata}}) > 200) { +    foreach my $level ("CRITICAL", "WARNING", "UNKNOWN", "OK") { +      # first the bad news +      if (scalar(@{$self->{nagios}->{messages}->{$ERRORS{$level}}})) { +        $self->{nagios_message} .= +            "\n".join("\n", @{$self->{nagios}->{messages}->{$ERRORS{$level}}}); +      } +    } +    $self->{nagios_message} =~ s/^\n//g; +    $self->{perfdata} = join("\n", @{$self->{nagios}->{perfdata}}); +  } else { +    foreach my $level ("CRITICAL", "WARNING", "UNKNOWN", "OK") { +      # first the bad news +      if (scalar(@{$self->{nagios}->{messages}->{$ERRORS{$level}}})) { +        $self->{nagios_message} .=  +            join(", ", @{$self->{nagios}->{messages}->{$ERRORS{$level}}}).", "; +      } +    } +    $self->{nagios_message} =~ s/, $//g; +    $self->{perfdata} = join(" ", @{$self->{nagios}->{perfdata}}); +  } +  foreach my $level ("OK", "UNKNOWN", "WARNING", "CRITICAL") { +    if (scalar(@{$self->{nagios}->{messages}->{$ERRORS{$level}}})) { +      $self->{nagios_level} = $ERRORS{$level}; +    } +  } +} + +sub debug { +  my $self = shift; +  my $msg = shift; +  if ($DBD::MySQL::Cluster::verbose) { +    printf "%s %s\n", $msg, ref($self); +  } +} + +sub connect { +  my $self = shift; +  my %params = @_; +  my $retval = undef; +  $self->{tic} = Time::HiRes::time(); +  eval { +    use POSIX ':signal_h'; +    local $SIG{'ALRM'} = sub { +      die "alarm\n"; +    }; +    my $mask = POSIX::SigSet->new( SIGALRM ); +    my $action = POSIX::SigAction->new( +        sub { die "connection timeout\n" ; }, $mask); +    my $oldaction = POSIX::SigAction->new(); +    sigaction(SIGALRM ,$action ,$oldaction ); +    alarm($self->{timeout} - 1); # 1 second before the global unknown timeout +    my $ndb_mgm = "ndb_mgm"; +    $params{hostname} = "127.0.0.1" if ! $params{hostname}; +    $ndb_mgm .= sprintf " --ndb-connectstring=%s", $params{hostname} +        if $params{hostname}; +    $ndb_mgm .= sprintf ":%d", $params{port} +        if $params{port}; +    $self->{show} = `$ndb_mgm -e show 2>&1`; +    if ($? == -1) { +      $self->add_nagios_critical("ndb_mgm failed to execute $!"); +    } elsif ($? & 127) { +      $self->add_nagios_critical("ndb_mgm failed to execute $!"); +    } elsif ($? >> 8 != 0) { +      $self->add_nagios_critical("ndb_mgm unable to connect"); +    } else { +      if ($self->{show} !~ /Cluster Configuration/) { +        $self->add_nagios_critical("got no cluster configuration"); +      } else { +        $retval = 1; +      } +    } +  }; +  if ($@) { +    $self->{errstr} = $@; +    $self->{errstr} =~ s/at $0 .*//g; +    chomp $self->{errstr}; +    $self->add_nagios_critical($self->{errstr}); +    $retval = undef; +  } +  $self->{tac} = Time::HiRes::time(); +  return $retval; +} + +sub trace { +  my $self = shift; +  my $format = shift; +  $self->{trace} = -f "/tmp/check_mysql_health.trace" ? 1 : 0; +  if ($self->{verbose}) { +    printf("%s: ", scalar localtime); +    printf($format, @_); +  } +  if ($self->{trace}) { +    my $logfh = new IO::File; +    $logfh->autoflush(1); +    if ($logfh->open("/tmp/check_mysql_health.trace", "a")) { +      $logfh->printf("%s: ", scalar localtime); +      $logfh->printf($format, @_); +      $logfh->printf("\n"); +      $logfh->close(); +    } +  } +} + +sub DESTROY { +  my $self = shift; +  my $handle1 = "null"; +  my $handle2 = "null"; +  if (defined $self->{handle}) { +    $handle1 = ref($self->{handle}); +    if (defined $self->{handle}->{handle}) { +      $handle2 = ref($self->{handle}->{handle}); +    } +  } +  $self->trace(sprintf "DESTROY %s with handle %s %s", ref($self), $handle1, $handle2); +  if (ref($self) eq "DBD::MySQL::Cluster") { +  } +  $self->trace(sprintf "DESTROY %s exit with handle %s %s", ref($self), $handle1, $handle2); +  if (ref($self) eq "DBD::MySQL::Cluster") { +    #printf "humpftata\n"; +  } +} + +sub save_state { +  my $self = shift; +  my %params = @_; +  my $extension = ""; +  mkdir $params{statefilesdir} unless -d $params{statefilesdir}; +  my $statefile = sprintf "%s/%s_%s",  +      $params{statefilesdir}, $params{hostname}, $params{mode}; +  $extension .= $params{differenciator} ? "_".$params{differenciator} : ""; +  $extension .= $params{socket} ? "_".$params{socket} : ""; +  $extension .= $params{port} ? "_".$params{port} : ""; +  $extension .= $params{database} ? "_".$params{database} : ""; +  $extension .= $params{tablespace} ? "_".$params{tablespace} : ""; +  $extension .= $params{datafile} ? "_".$params{datafile} : ""; +  $extension .= $params{name} ? "_".$params{name} : ""; +  $extension =~ s/\//_/g; +  $extension =~ s/\(/_/g; +  $extension =~ s/\)/_/g; +  $extension =~ s/\*/_/g; +  $extension =~ s/\s/_/g; +  $statefile .= $extension; +  $statefile = lc $statefile; +  open(STATE, ">$statefile"); +  if ((ref($params{save}) eq "HASH") && exists $params{save}->{timestamp}) { +    $params{save}->{localtime} = scalar localtime $params{save}->{timestamp}; +  } +  printf STATE Data::Dumper::Dumper($params{save}); +  close STATE; +  $self->debug(sprintf "saved %s to %s", +      Data::Dumper::Dumper($params{save}), $statefile); +} + +sub load_state { +  my $self = shift; +  my %params = @_; +  my $extension = ""; +  my $statefile = sprintf "%s/%s_%s",  +      $params{statefilesdir}, $params{hostname}, $params{mode}; +  $extension .= $params{differenciator} ? "_".$params{differenciator} : ""; +  $extension .= $params{socket} ? "_".$params{socket} : ""; +  $extension .= $params{port} ? "_".$params{port} : ""; +  $extension .= $params{database} ? "_".$params{database} : ""; +  $extension .= $params{tablespace} ? "_".$params{tablespace} : ""; +  $extension .= $params{datafile} ? "_".$params{datafile} : ""; +  $extension .= $params{name} ? "_".$params{name} : ""; +  $extension =~ s/\//_/g; +  $extension =~ s/\(/_/g; +  $extension =~ s/\)/_/g; +  $extension =~ s/\*/_/g; +  $extension =~ s/\s/_/g; +  $statefile .= $extension; +  $statefile = lc $statefile; +  if ( -f $statefile) { +    our $VAR1; +    eval { +      require $statefile; +    }; +    if($@) { +printf "rumms\n"; +    } +    $self->debug(sprintf "load %s", Data::Dumper::Dumper($VAR1)); +    return $VAR1; +  } else { +    return undef; +  } +} + +sub valdiff { +  my $self = shift; +  my $pparams = shift; +  my %params = %{$pparams}; +  my @keys = @_; +  my $last_values = $self->load_state(%params) || eval { +    my $empty_events = {}; +    foreach (@keys) { +      $empty_events->{$_} = 0; +    } +    $empty_events->{timestamp} = 0; +    $empty_events; +  }; +  foreach (@keys) { +    $self->{'delta_'.$_} = $self->{$_} - $last_values->{$_}; +    $self->debug(sprintf "delta_%s %f", $_, $self->{'delta_'.$_}); +  } +  $self->{'delta_timestamp'} = time - $last_values->{timestamp}; +  $params{save} = eval { +    my $empty_events = {}; +    foreach (@keys) { +      $empty_events->{$_} = $self->{$_}; +    } +    $empty_events->{timestamp} = time; +    $empty_events; +  }; +  $self->save_state(%params); +} + +sub requires_version { +  my $self = shift; +  my $version = shift; +  my @instances = DBD::MySQL::Cluster::return_clusters(); +  my $instversion = $instances[0]->{version}; +  if (! $self->version_is_minimum($version)) { +    $self->add_nagios($ERRORS{UNKNOWN},  +        sprintf "not implemented/possible for MySQL release %s", $instversion); +  } +} + +sub version_is_minimum { +  # the current version is newer or equal +  my $self = shift; +  my $version = shift; +  my $newer = 1; +  my @instances = DBD::MySQL::Cluster::return_clusters(); +  my @v1 = map { $_ eq "x" ? 0 : $_ } split(/\./, $version); +  my @v2 = split(/\./, $instances[0]->{version}); +  if (scalar(@v1) > scalar(@v2)) { +    push(@v2, (0) x (scalar(@v1) - scalar(@v2))); +  } elsif (scalar(@v2) > scalar(@v1)) { +    push(@v1, (0) x (scalar(@v2) - scalar(@v1))); +  } +  foreach my $pos (0..$#v1) { +    if ($v2[$pos] > $v1[$pos]) { +      $newer = 1; +      last; +    } elsif ($v2[$pos] < $v1[$pos]) { +      $newer = 0; +      last; +    } +  } +  #printf STDERR "check if %s os minimum %s\n", join(".", @v2), join(".", @v1); +  return $newer; +} + +sub instance_rac { +  my $self = shift; +  my @instances = DBD::MySQL::Cluster::return_clusters(); +  return (lc $instances[0]->{parallel} eq "yes") ? 1 : 0; +} + +sub instance_thread { +  my $self = shift; +  my @instances = DBD::MySQL::Cluster::return_clusters(); +  return $instances[0]->{thread}; +} + +sub windows_cluster { +  my $self = shift; +  my @instances = DBD::MySQL::Cluster::return_clusters(); +  if ($instances[0]->{os} =~ /Win/i) { +    return 1; +  } else { +    return 0; +  } +} + +sub system_vartmpdir { +  my $self = shift; +  if ($^O =~ /MSWin/) { +    return $self->system_tmpdir(); +  } else { +    return "/var/tmp/check_mysql_health"; +  } +} + +sub system_oldvartmpdir { +  my $self = shift; +  return "/tmp"; +} + +sub system_tmpdir { +  my $self = shift; +  if ($^O =~ /MSWin/) { +    return $ENV{TEMP} if defined $ENV{TEMP}; +    return $ENV{TMP} if defined $ENV{TMP}; +    return File::Spec->catfile($ENV{windir}, 'Temp') +        if defined $ENV{windir}; +    return 'C:\Temp'; +  } else { +    return "/tmp"; +  } +} + + +package DBD::MySQL::Cluster::Node; + +use strict; + +our @ISA = qw(DBD::MySQL::Cluster); + + +sub new { +  my $class = shift; +  my %params = @_; +  my $self = { +    mode => $params{mode}, +    timeout => $params{timeout}, +    type => $params{type}, +    id => $params{id}, +    status => $params{status}, +  }; +  bless $self, $class; +  $self->init(%params); +  if ($params{type} eq "NDB") { +    bless $self, "DBD::MySQL::Cluster::Node::NDB"; +    $self->init(%params); +  } +  return $self; +} + +sub init { +  my $self = shift; +  my %params = @_; +  if ($self->{status} =~ /@(\d+\.\d+\.\d+\.\d+)\s/) { +    $self->{addr} = $1; +    $self->{connected} = 1; +  } elsif ($self->{status} =~ /accepting connect from (\d+\.\d+\.\d+\.\d+)/) { +    $self->{addr} = $1; +    $self->{connected} = 0; +  } +  if ($self->{status} =~ /starting,/) { +    $self->{status} = "starting"; +  } elsif ($self->{status} =~ /shutting,/) { +    $self->{status} = "shutting"; +  } else { +    $self->{status} = $self->{connected} ? "running" : "dead"; +  } +} + + +package DBD::MySQL::Cluster::Node::NDB; + +use strict; + +our @ISA = qw(DBD::MySQL::Cluster::Node); + + +sub init { +  my $self = shift; +  my %params = @_; +  if ($self->{status} =~ /Nodegroup:\s*(\d+)/) { +    $self->{nodegroup} = $1; +  } +  $self->{master} = ($self->{status} =~ /Master\)/) ? 1 : 0; +} + + +package Extraopts; + +use strict; +use File::Basename; +use Data::Dumper; + +sub new { +  my $class = shift; +  my %params = @_; +  my $self = { +    file => $params{file}, +    commandline => $params{commandline}, +    config => {}, +    section => 'default_no_section', +  }; +  bless $self, $class; +  $self->prepare_file_and_section(); +  $self->init(); +  return $self; +} + +sub prepare_file_and_section { +  my $self = shift; +  if (! defined $self->{file}) { +    # ./check_stuff --extra-opts +    $self->{section} = basename($0); +    $self->{file} = $self->get_default_file(); +  } elsif ($self->{file} =~ /^[^@]+$/) { +    # ./check_stuff --extra-opts=special_opts +    $self->{section} = $self->{file}; +    $self->{file} = $self->get_default_file(); +  } elsif ($self->{file} =~ /^@(.*)/) { +    # ./check_stuff --extra-opts=@/etc/myconfig.ini +    $self->{section} = basename($0); +    $self->{file} = $1; +  } elsif ($self->{file} =~ /^(.*?)@(.*)/) { +    # ./check_stuff --extra-opts=special_opts@/etc/myconfig.ini +    $self->{section} = $1; +    $self->{file} = $2; +  } +} + +sub get_default_file { +  my $self = shift; +  foreach my $default (qw(/etc/nagios/plugins.ini +      /usr/local/nagios/etc/plugins.ini +      /usr/local/etc/nagios/plugins.ini +      /etc/opt/nagios/plugins.ini +      /etc/nagios-plugins.ini +      /usr/local/etc/nagios-plugins.ini +      /etc/opt/nagios-plugins.ini)) { +    if (-f $default) { +      return $default; +    } +  } +  return undef; +} + +sub init { +  my $self = shift; +  if (! defined $self->{file}) { +    $self->{errors} = sprintf 'no extra-opts file specified and no default file found'; +  } elsif (! -f $self->{file}) { +    $self->{errors} = sprintf 'could not open %s', $self->{file}; +  } else { +    my $data = do { local (@ARGV, $/) = $self->{file}; <> }; +    my $in_section = 'default_no_section'; +    foreach my $line (split(/\n/, $data)) { +      if ($line =~ /\[(.*)\]/) { +        $in_section = $1; +      } elsif ($line =~ /(.*?)\s*=\s*(.*)/) { +        $self->{config}->{$in_section}->{$1} = $2; +      } +    } +  } +} + +sub is_valid { +  my $self = shift; +  return ! exists $self->{errors}; +} + +sub overwrite { +  my $self = shift; +  my %commandline = (); +  if (scalar(keys %{$self->{config}->{default_no_section}}) > 0) { +    foreach (keys %{$self->{config}->{default_no_section}}) { +      $commandline{$_} = $self->{config}->{default_no_section}->{$_}; +    } +  } +  if (exists $self->{config}->{$self->{section}}) { +    foreach (keys %{$self->{config}->{$self->{section}}}) { +      $commandline{$_} = $self->{config}->{$self->{section}}->{$_}; +    } +  } +  foreach (keys %commandline) { +    if (! exists $self->{commandline}->{$_}) { +      $self->{commandline}->{$_} = $commandline{$_}; +    } +  } +} + + + +package main; + +use strict; +use Getopt::Long qw(:config no_ignore_case); +use File::Basename; +use lib dirname($0); + + + +use vars qw ($PROGNAME $REVISION $CONTACT $TIMEOUT $STATEFILESDIR $needs_restart %commandline); + +$PROGNAME = "check_mysql_health"; +$REVISION = '$Revision: 2.1.7 $'; +$CONTACT = 'gerhard.lausser@consol.de'; +$TIMEOUT = 60; +$STATEFILESDIR = '/var/tmp/check_mysql_health'; +$needs_restart = 0; + +my @modes = ( +  ['server::connectiontime', +      'connection-time', undef, +      'Time to connect to the server' ], +  ['server::uptime', +      'uptime', undef, +      'Time the server is running' ], +  ['server::instance::connectedthreads', +      'threads-connected', undef, +      'Number of currently open connections' ], +  ['server::instance::threadcachehitrate', +      'threadcache-hitrate', undef, +      'Hit rate of the thread-cache' ], +  ['server::instance::createdthreads', +      'threads-created', undef, +      'Number of threads created per sec' ], +  ['server::instance::runningthreads', +      'threads-running', undef, +      'Number of currently running threads' ], +  ['server::instance::cachedthreads', +      'threads-cached', undef, +      'Number of currently cached threads' ], +  ['server::instance::abortedconnects', +      'connects-aborted', undef, +      'Number of aborted connections per sec' ], +  ['server::instance::abortedclients', +      'clients-aborted', undef, +      'Number of aborted connections (because the client died) per sec' ], +  ['server::instance::replication::slavelag', +      'slave-lag', ['replication-slave-lag'], +      'Seconds behind master' ], +  ['server::instance::replication::slaveiorunning', +      'slave-io-running', ['replication-slave-io-running'], +      'Slave io running: Yes' ], +  ['server::instance::replication::slavesqlrunning', +      'slave-sql-running', ['replication-slave-sql-running'], +      'Slave sql running: Yes' ], +  ['server::instance::querycachehitrate', +      'qcache-hitrate', ['querycache-hitrate'], +      'Query cache hitrate' ], +  ['server::instance::querycachelowmemprunes', +      'qcache-lowmem-prunes', ['querycache-lowmem-prunes'], +      'Query cache entries pruned because of low memory' ], +  ['server::instance::myisam::keycache::hitrate', +      'keycache-hitrate', ['myisam-keycache-hitrate'], +      'MyISAM key cache hitrate' ], +  ['server::instance::innodb::bufferpool::hitrate', +      'bufferpool-hitrate', ['innodb-bufferpool-hitrate'], +      'InnoDB buffer pool hitrate' ], +  ['server::instance::innodb::bufferpool::waitfree', +      'bufferpool-wait-free', ['innodb-bufferpool-wait-free'], +      'InnoDB buffer pool waits for clean page available' ], +  ['server::instance::innodb::logwaits', +      'log-waits', ['innodb-log-waits'], +      'InnoDB log waits because of a too small log buffer' ], +  ['server::instance::tablecachehitrate', +      'tablecache-hitrate', undef, +      'Table cache hitrate' ], +  ['server::instance::tablelockcontention', +      'table-lock-contention', undef, +      'Table lock contention' ], +  ['server::instance::tableindexusage', +      'index-usage', undef, +      'Usage of indices' ], +  ['server::instance::tabletmpondisk', +      'tmp-disk-tables', undef, +      'Percent of temp tables created on disk' ], +  ['server::instance::needoptimize', +      'table-fragmentation', undef, +      'Show tables which should be optimized' ], +  ['server::instance::openfiles', +      'open-files', undef, +      'Percent of opened files' ], +  ['server::instance::slowqueries', +      'slow-queries', undef, +      'Slow queries' ], +  ['server::instance::longprocs', +      'long-running-procs', undef, +      'long running processes' ], +  ['cluster::ndbdrunning', +      'cluster-ndbd-running', undef, +      'ndnd nodes are up and running' ], +  ['server::sql', +      'sql', undef, +      'any sql command returning a single number' ], +); + +# rrd data store names are limited to 19 characters +my %labels = ( +  bufferpool_hitrate => { +    groundwork => 'bp_hitrate', +  }, +  bufferpool_hitrate_now => { +    groundwork => 'bp_hitrate_now', +  }, +  bufferpool_free_waits_rate => { +    groundwork => 'bp_freewaits', +  }, +  innodb_log_waits_rate => { +    groundwork => 'inno_log_waits', +  }, +  keycache_hitrate => { +    groundwork => 'kc_hitrate', +  }, +  keycache_hitrate_now => { +    groundwork => 'kc_hitrate_now', +  }, +  threads_created_per_sec => { +    groundwork => 'thrds_creat_per_s', +  }, +  connects_aborted_per_sec => { +    groundwork => 'conn_abrt_per_s', +  }, +  clients_aborted_per_sec => { +    groundwork => 'clnt_abrt_per_s', +  }, +  thread_cache_hitrate => { +    groundwork => 'tc_hitrate', +  }, +  thread_cache_hitrate_now => { +    groundwork => 'tc_hitrate_now', +  }, +  qcache_lowmem_prunes_rate => { +    groundwork => 'qc_lowm_prnsrate', +  }, +  slow_queries_rate => { +    groundwork => 'slow_q_rate', +  }, +  tablecache_hitrate => { +    groundwork => 'tac_hitrate', +  }, +  tablecache_fillrate => { +    groundwork => 'tac_fillrate', +  }, +  tablelock_contention => { +    groundwork => 'tl_contention', +  }, +  tablelock_contention_now => { +    groundwork => 'tl_contention_now', +  }, +  pct_tmp_table_on_disk => { +    groundwork => 'tmptab_on_disk', +  }, +  pct_tmp_table_on_disk_now => { +    groundwork => 'tmptab_on_disk_now', +  }, +); + +sub print_usage () { +  print <<EOUS; +  Usage: +    $PROGNAME [-v] [-t <timeout>] [[--hostname <hostname>]  +        [--port <port> | --socket <socket>] +        --username <username> --password <password>] --mode <mode> +        [--method mysql] +    $PROGNAME [-h | --help] +    $PROGNAME [-V | --version] + +  Options: +    --hostname +       the database server's hostname +    --port +       the database's port. (default: 3306) +    --socket +       the database's unix socket. +    --username +       the mysql db user +    --password +       the mysql db user's password +    --database +       the database's name. (default: information_schema) +    --warning +       the warning range +    --critical +       the critical range +    --mode +       the mode of the plugin. select one of the following keywords: +EOUS +  my $longest = length ((reverse sort {length $a <=> length $b} map { $_->[1] } @modes)[0]); +  my $format = "       %-". +  (length ((reverse sort {length $a <=> length $b} map { $_->[1] } @modes)[0])). +  "s\t(%s)\n"; +  foreach (@modes) { +    printf $format, $_->[1], $_->[3]; +  } +  printf "\n"; +  print <<EOUS; +    --name +       the name of something that needs to be further specified, +       currently only used for sql statements +    --name2 +       if name is a sql statement, this statement would appear in +       the output and the performance data. This can be ugly, so  +       name2 can be used to appear instead. +    --regexp +       if this parameter is used, name will be interpreted as a  +       regular expression. +    --units +       one of %, KB, MB, GB. This is used for a better output of mode=sql +       and for specifying thresholds for mode=tablespace-free +    --labelformat +       one of pnp4nagios (which is the default) or groundwork. +       It is used to shorten performance data labels to 19 characters. + +  In mode sql you can url-encode the statement so you will not have to mess +  around with special characters in your Nagios service definitions. +  Instead of  +  --name="select count(*) from v\$session where status = 'ACTIVE'" +  you can say  +  --name=select%20count%28%2A%29%20from%20v%24session%20where%20status%20%3D%20%27ACTIVE%27 +  For your convenience you can call check_mysql_health with the --mode encode +  option and it will encode the standard input. + +  You can find the full documentation at  +  http://www.consol.de/opensource/nagios/check-mysql-health + +EOUS +   +} + +sub print_help () { +  print "Copyright (c) 2009 Gerhard Lausser\n\n"; +  print "\n"; +  print "  Check various parameters of MySQL databases \n"; +  print "\n"; +  print_usage(); +  support(); +} + + +sub print_revision ($$) { +  my $commandName = shift; +  my $pluginRevision = shift; +  $pluginRevision =~ s/^\$Revision: //; +  $pluginRevision =~ s/ \$\s*$//; +  print "$commandName ($pluginRevision)\n"; +  print "This nagios plugin comes with ABSOLUTELY NO WARRANTY. You may redistribute\ncopies of this plugin under the terms of the GNU General Public License.\n"; +} + +sub support () { +  my $support='Send email to gerhard.lausser@consol.de if you have questions\nregarding use of this software. \nPlease include version information with all correspondence (when possible,\nuse output from the --version option of the plugin itself).\n'; +  $support =~ s/@/\@/g; +  $support =~ s/\\n/\n/g; +  print $support; +} + +sub contact_author ($$) { +  my $item = shift; +  my $strangepattern = shift; +  if ($commandline{verbose}) { +    printf STDERR +        "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n". +        "You found a line which is not recognized by %s\n". +        "This means, certain components of your system cannot be checked.\n". +        "Please contact the author %s and\nsend him the following output:\n\n". +        "%s /%s/\n\nThank you!\n". +        "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n", +            $PROGNAME, $CONTACT, $item, $strangepattern; +  } +} + +%commandline = (); +my @params = ( +    "timeout|t=i", +    "version|V", +    "help|h", +    "verbose|v", +    "debug|d", +    "hostname|H=s", +    "database=s", +    "port|P=s", +    "socket|S=s", +    "username|u=s", +    "password|p=s", +    "mode|m=s", +    "name=s", +    "name2=s", +    "regexp", +    "perfdata", +    "warning=s", +    "critical=s", +    "dbthresholds:s", +    "absolute|a", +    "environment|e=s%", +    "method=s", +    "runas|r=s", +    "scream", +    "shell", +    "eyecandy", +    "encode", +    "units=s", +    "lookback=i", +    "3", +    "statefilesdir=s", +    "with-mymodules-dyn-dir=s", +    "report=s", +    "labelformat=s", +    "extra-opts:s"); + +if (! GetOptions(\%commandline, @params)) { +  print_help(); +  exit $ERRORS{UNKNOWN}; +} + +if (exists $commandline{'extra-opts'}) { +  # read the extra file and overwrite other parameters +  my $extras = Extraopts->new(file => $commandline{'extra-opts'}, commandline => + \%commandline); +  if (! $extras->is_valid()) { +    printf "extra-opts are not valid: %s\n", $extras->{errors}; +    exit $ERRORS{UNKNOWN}; +  } else { +    $extras->overwrite(); +  } +} + +if (exists $commandline{version}) { +  print_revision($PROGNAME, $REVISION); +  exit $ERRORS{OK}; +} + +if (exists $commandline{help}) { +  print_help(); +  exit $ERRORS{OK}; +} elsif (! exists $commandline{mode}) { +  printf "Please select a mode\n"; +  print_help(); +  exit $ERRORS{OK}; +} + +if ($commandline{mode} eq "encode") { +  my $input = <>; +  chomp $input; +  $input =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg; +  printf "%s\n", $input; +  exit $ERRORS{OK}; +} + +if (exists $commandline{3}) { +  $ENV{NRPE_MULTILINESUPPORT} = 1; +} + +if (exists $commandline{timeout}) { +  $TIMEOUT = $commandline{timeout}; +} + +if (exists $commandline{verbose}) { +  $DBD::MySQL::Server::verbose = exists $commandline{verbose}; +} + +if (exists $commandline{scream}) { +#  $DBD::MySQL::Server::hysterical = exists $commandline{scream}; +} + +if (exists $commandline{method}) { +  # snmp or mysql cmdline +} else { +  $commandline{method} = "dbi"; +} + +if (exists $commandline{report}) { +  # short, long, html +} else { +  $commandline{report} = "long"; +} + +if (exists $commandline{labelformat}) { +  # groundwork +} else { +  $commandline{labelformat} = "pnp4nagios"; +} + +if (exists $commandline{'with-mymodules-dyn-dir'}) { +  $DBD::MySQL::Server::my_modules_dyn_dir = $commandline{'with-mymodules-dyn-dir'}; +} else { +  $DBD::MySQL::Server::my_modules_dyn_dir = '/usr/local/nagios/libexec'; +} + +if (exists $commandline{environment}) { +  # if the desired environment variable values are different from +  # the environment of this running script, then a restart is necessary. +  # because setting $ENV does _not_ change the environment of the running script. +  foreach (keys %{$commandline{environment}}) { +    if ((! $ENV{$_}) || ($ENV{$_} ne $commandline{environment}->{$_})) { +      $needs_restart = 1; +      $ENV{$_} = $commandline{environment}->{$_}; +      printf STDERR "new %s=%s forces restart\n", $_, $ENV{$_}  +          if $DBD::MySQL::Server::verbose; +    } +  } +  # e.g. called with --runas dbnagio. shlib_path environment variable is stripped +  # during the sudo. +  # so the perl interpreter starts without a shlib_path. but --runas cares for +  # a --environment shlib_path=... +  # so setting the environment variable in the code above and restarting the  +  # perl interpreter will help it find shared libs +} + +if (exists $commandline{runas}) { +  # remove the runas parameter +  # exec sudo $0 ... the remaining parameters +  $needs_restart = 1; +  # if the calling script has a path for shared libs and there is no --environment +  # parameter then the called script surely needs the variable too. +  foreach my $important_env qw(LD_LIBRARY_PATH SHLIB_PATH  +      ORACLE_HOME TNS_ADMIN ORA_NLS ORA_NLS33 ORA_NLS10) { +    if ($ENV{$important_env} && ! scalar(grep { /^$important_env=/ }  +        keys %{$commandline{environment}})) { +      $commandline{environment}->{$important_env} = $ENV{$important_env}; +      printf STDERR "add important --environment %s=%s\n",  +          $important_env, $ENV{$important_env} if $DBD::MySQL::Server::verbose; +    } +  } +} + +if ($needs_restart) { +  my @newargv = (); +  my $runas = undef; +  if (exists $commandline{runas}) { +    $runas = $commandline{runas}; +    delete $commandline{runas}; +  } +  foreach my $option (keys %commandline) { +    if (grep { /^$option/ && /=/ } @params) { +      if (ref ($commandline{$option}) eq "HASH") { +        foreach (keys %{$commandline{$option}}) { +          push(@newargv, sprintf "--%s", $option); +          push(@newargv, sprintf "%s=%s", $_, $commandline{$option}->{$_}); +        } +      } else { +        push(@newargv, sprintf "--%s", $option); +        push(@newargv, sprintf "%s", $commandline{$option}); +      } +    } else { +      push(@newargv, sprintf "--%s", $option); +    } +  } +  if ($runas) { +    exec "sudo", "-S", "-u", $runas, $0, @newargv; +  } else { +    exec $0, @newargv;   +    # this makes sure that even a SHLIB or LD_LIBRARY_PATH are set correctly +    # when the perl interpreter starts. Setting them during runtime does not +    # help loading e.g. libclntsh.so +  } +  exit; +} + +if (exists $commandline{shell}) { +  # forget what you see here. +  system("/bin/sh"); +} + +if (! exists $commandline{statefilesdir}) { +  if (exists $ENV{OMD_ROOT}) { +    $commandline{statefilesdir} = $ENV{OMD_ROOT}."/var/tmp/check_mysql_health"; +  } else { +    $commandline{statefilesdir} = $STATEFILESDIR; +  } +} + +if (exists $commandline{name}) { +  # objects can be encoded like an url +  # with s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg; +  if (($commandline{mode} ne "sql") ||  +      (($commandline{mode} eq "sql") && +       ($commandline{name} =~ /select%20/i))) { # protect ... like '%cac%' ... from decoding +    $commandline{name} =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg; +  } +  if ($commandline{name} =~ /^0$/) { +    # without this, $params{selectname} would be treated like undef +    $commandline{name} = "00"; +  }  +} + +$SIG{'ALRM'} = sub { +  printf "UNKNOWN - %s timed out after %d seconds\n", $PROGNAME, $TIMEOUT; +  exit $ERRORS{UNKNOWN}; +}; +alarm($TIMEOUT); + +my $nagios_level = $ERRORS{UNKNOWN}; +my $nagios_message = ""; +my $perfdata = ""; +if ($commandline{mode} =~ /^my-([^\-.]+)/) { +  my $param = $commandline{mode}; +  $param =~ s/\-/::/g; +  push(@modes, [$param, $commandline{mode}, undef, 'my extension']); +} elsif ((! grep { $commandline{mode} eq $_ } map { $_->[1] } @modes) && +    (! grep { $commandline{mode} eq $_ } map { defined $_->[2] ? @{$_->[2]} : () } @modes)) { +  printf "UNKNOWN - mode %s\n", $commandline{mode}; +  print_usage(); +  exit 3; +} + +my %params = ( +    timeout => $TIMEOUT, +    mode => ( +        map { $_->[0] } +        grep { +           ($commandline{mode} eq $_->[1]) || +           ( defined $_->[2] && grep { $commandline{mode} eq $_ } @{$_->[2]}) +        } @modes +    )[0], +    cmdlinemode => $commandline{mode}, +    method => $commandline{method} || +        $ENV{NAGIOS__SERVICEMYSQL_METH} || +        $ENV{NAGIOS__HOSTMYSQL_METH} || 'dbi', +    hostname => $commandline{hostname} ||  +        $ENV{NAGIOS__SERVICEMYSQL_HOST} || +        $ENV{NAGIOS__HOSTMYSQL_HOST} || 'localhost', +    database => $commandline{database} ||  +        $ENV{NAGIOS__SERVICEMYSQL_DATABASE} || +        $ENV{NAGIOS__HOSTMYSQL_DATABASE} || 'information_schema', +    port => $commandline{port}  || (($commandline{mode} =~ /^cluster/) ? +        ($ENV{NAGIOS__SERVICENDBMGM_PORT} || $ENV{NAGIOS__HOSTNDBMGM_PORT} || 1186) : +        ($ENV{NAGIOS__SERVICEMYSQL_PORT} || $ENV{NAGIOS__HOSTMYSQL_PORT} || 3306)), +    socket => $commandline{socket}  ||  +        $ENV{NAGIOS__SERVICEMYSQL_SOCKET} || +        $ENV{NAGIOS__HOSTMYSQL_SOCKET}, +    username => $commandline{username} ||  +        $ENV{NAGIOS__SERVICEMYSQL_USER} || +        $ENV{NAGIOS__HOSTMYSQL_USER}, +    password => $commandline{password} ||  +        $ENV{NAGIOS__SERVICEMYSQL_PASS} || +        $ENV{NAGIOS__HOSTMYSQL_PASS}, +    warningrange => $commandline{warning}, +    criticalrange => $commandline{critical}, +    dbthresholds => $commandline{dbthresholds}, +    absolute => $commandline{absolute}, +    lookback => $commandline{lookback}, +    selectname => $commandline{name} || $commandline{tablespace} || $commandline{datafile}, +    regexp => $commandline{regexp}, +    name => $commandline{name}, +    name2 => $commandline{name2} || $commandline{name}, +    units => $commandline{units}, +    lookback => $commandline{lookback} || 0, +    eyecandy => $commandline{eyecandy}, +    statefilesdir => $commandline{statefilesdir}, +    verbose => $commandline{verbose}, +    report => $commandline{report}, +    labelformat => $commandline{labelformat}, +); + +my $server = undef; +my $cluster = undef; + +if ($params{mode} =~ /^(server|my)/) { +  $server = DBD::MySQL::Server->new(%params); +  $server->nagios(%params); +  $server->calculate_result(\%labels); +  $nagios_message = $server->{nagios_message}; +  $nagios_level = $server->{nagios_level}; +  $perfdata = $server->{perfdata}; +} elsif ($params{mode} =~ /^cluster/) { +  $cluster = DBD::MySQL::Cluster->new(%params); +  $cluster->nagios(%params); +  $cluster->calculate_result(\%labels); +  $nagios_message = $cluster->{nagios_message}; +  $nagios_level = $cluster->{nagios_level}; +  $perfdata = $cluster->{perfdata}; +} + +printf "%s - %s", $ERRORCODES{$nagios_level}, $nagios_message; +printf " | %s", $perfdata if $perfdata; +printf "\n"; +exit $nagios_level; + + +__END__ + + diff --git a/puppet/modules/nagios/files/plugins/check_openvpn_server.pl b/puppet/modules/nagios/files/plugins/check_openvpn_server.pl new file mode 100755 index 00000000..b74ace89 --- /dev/null +++ b/puppet/modules/nagios/files/plugins/check_openvpn_server.pl @@ -0,0 +1,109 @@ +#!/usr/bin/perl +# +# Filaname: check_openvpn +# Created:  2012-06-15 +# Website:  http://blog.kernelpicnic.net +# +# Description: +# This script is for verifying the status of an OpenVPN daemon. It has been +# written to integrate directly with Nagios / Opsview. +# +# Usage: +#    check_openvpn [OPTIONS]... +# +#      -H, --hostname      Host to check +#      -p, --port          Port number to check +#      -h, --help          Display help. +# +############################################################################# + +# Custom library path for Nagis modules. +use lib qw ( /usr/local/nagios/perl/lib ); + +# Enforce sanity. +use strict; +use warnings; + +# Required modules. +use Getopt::Long qw(:config no_ignore_case); +use Nagios::Plugin; +use IO::Socket; + +# Define defaults. +my $help    = 0; +my $timeout = 5; + +# Ensure required variables are set. +my($hostname, $port); + +my $options = GetOptions( +                         "hostname|H=s" => \$hostname, +                         "timeout|t=s"  => \$timeout, +                         "port|p=s"     => \$port, +                         "help|h"       => \$help, +); + +# Check if help has been requested. +if($help || !$hostname || !$port) { + +    printf("\n"); +    printf("Usage: check_openvpn [OPTIONS]...\n\n"); +    printf("  -H, --hostname      Host to check\n"); +    printf("  -p, --port          Port number to check\n"); +    printf("  -h, --help          This help page\n"); +    printf("  -t, --timeout       Socket timeout\n"); +    printf("\n"); + +    exit(-1); + +} + +# Setup a new Nagios::Plugin object. +my $nagios = Nagios::Plugin->new(); + +# Define the check string to send to the OpenVPN server - as binary due +# to non-printable characters. +my $check_string = "001110000011001010010010011011101000000100010001110" +                  ."100110110101010110011000000000000000000000000000000" +                  ."0000000000"; + +# Attempt to setup a socket to the specified host. +my $host_sock = IO::Socket::INET->new( +                                      Proto    => 'udp', +                                      PeerAddr => $hostname, +                                      PeerPort => $port, +); + +# Ensure we have a socket. +if(!$host_sock) { +    $nagios->nagios_exit(UNKNOWN, "Unable to bind socket"); +} + +# Fire off the check request. +$host_sock->send(pack("B*", $check_string)); + +# Wait for $timeout for response for a response, otherwise, fail. +my $response; + +eval { + +    # Define how to handle ALARM. +    local $SIG{ALRM} = sub { +        $nagios->nagios_exit(CRITICAL, "No response received"); +    }; + +    # Set the alarm for the given timeout value. +    alarm($timeout); + +    # Check for response. +    $host_sock->recv($response, 1) +      or $nagios->nagios_exit(CRITICAL, "No response received"); + +    # Alright, response received, cancel alarm. +    alarm(0); +    1; + +}; + +# Reply received, return okay. +$nagios->nagios_exit(OK, "Response received from host"); diff --git a/puppet/modules/nagios/files/plugins/check_pop3_login b/puppet/modules/nagios/files/plugins/check_pop3_login new file mode 100644 index 00000000..4eb29b88 --- /dev/null +++ b/puppet/modules/nagios/files/plugins/check_pop3_login @@ -0,0 +1,83 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +# -*- Mode: Python -*- +# +# Copyright (C) 2006 Bertera Pietro <pietro@bertera.it> +# Copyright (C) 2015 mh <mh@immerda.ch> +# Response time monitoring with perfdata modification by Ivan Savcic <isavcic@gmail.com> and Milos Buncic, 2012. +# Derived from: https://github.com/isavcic/check_imap_login + +# This file may be distributed and/or modified under the terms of +# the GNU General Public License version 2 as published by +# the Free Software Foundation. +# This file is distributed without any warranty; without even the implied +# warranty of merchantability or fitness for a particular purpose. + +import sys, os, poplib, getopt +from time import time + +def usage(): +  print sys.argv[0] + " -u <user> -p <password> -H <host> [-s] -w <warning threshold (sec)> -c <critical threshold (sec)>\n -s is for using POP3s" + +def main(): +  try: +    opts, args = getopt.getopt(sys.argv[1:], "u:p:sH:w:c:") +  except getopt.GetoptError: +    usage() +    return 3 + +  user = host = password = use_ssl = warning = critical = None + +  for o, a in opts: +    if o == "-u": +      user = a +    elif o == "-p": +      password = a +    elif o == "-s": +      use_ssl = True +    elif o == "-H": +      host = a +    elif o == "-w": +      warning = float(a) +    elif o == "-c": +      critical = float(a) + +  if user == None or password == None or host == None or warning == None or critical == None: +    usage() +    return 1 + +  if use_ssl: +    M = poplib.POP3_SSL(host=host) +  else: +    M = poplib.POP3(host) + +  timestamp = time() + +  try: +    M.getwelcome() +    M.user(user) +    M.pass_(password) +  except Exception, e: +    print "CRITICAL POP3 Login Failed: %s" % e +    return 2 + +  M.quit() + +  timestamp = time() - timestamp + +  if timestamp < warning: +    status = "OK" +    exitcode = 0 +  if timestamp >= warning: +    status = "WARNING" +    exitcode = 1 +  if timestamp >= critical: +    status = "CRITICAL" +    exitcode = 2 + +  print '%s POP3 Login | response_time=%.3fs;%.3f;%.3f' % (status, timestamp, warning, critical) + +  return exitcode + +if __name__ == "__main__": +  sys.exit(main()) diff --git a/puppet/modules/nagios/files/pnp4nagios/action.gif b/puppet/modules/nagios/files/pnp4nagios/action.gifBinary files differ new file mode 100644 index 00000000..96571a40 --- /dev/null +++ b/puppet/modules/nagios/files/pnp4nagios/action.gif diff --git a/puppet/modules/nagios/files/pnp4nagios/apache.conf b/puppet/modules/nagios/files/pnp4nagios/apache.conf new file mode 100644 index 00000000..816bf05c --- /dev/null +++ b/puppet/modules/nagios/files/pnp4nagios/apache.conf @@ -0,0 +1,31 @@ +# SAMPLE CONFIG SNIPPETS FOR APACHE WEB SERVER + +Alias /pnp4nagios "/usr/share/pnp4nagios/html" + +<Directory "/usr/share/pnp4nagios/html"> +        AllowOverride None +        Order allow,deny +        Allow from all +        # +        # Use the same value as defined in nagios.conf +        # +        AuthName "Nagios Access" +        AuthType Basic +        AuthUserFile /etc/nagios3/htpasswd.users +        Require valid-user +        <IfModule mod_rewrite.c> +                # Turn on URL rewriting +                RewriteEngine On +                Options FollowSymLinks +                # Installation directory +                RewriteBase /pnp4nagios/ +                # Protect application and system files from being viewed +                RewriteRule ^(application|modules|system) - [F,L] +                # Allow any files or directories that exist to be displayed directly +                RewriteCond %{REQUEST_FILENAME} !-f +                RewriteCond %{REQUEST_FILENAME} !-d +                # Rewrite all other URLs to index.php/URL +                RewriteRule .* index.php/$0 [PT,L] +        </IfModule> +        DirectoryIndex index.php +</Directory> diff --git a/puppet/modules/nagios/files/pnp4nagios/npcd b/puppet/modules/nagios/files/pnp4nagios/npcd new file mode 100644 index 00000000..64b3d4d9 --- /dev/null +++ b/puppet/modules/nagios/files/pnp4nagios/npcd @@ -0,0 +1,8 @@ +# Default settings for the NPCD init script. + +# Should NPCD be started? ("yes" to enable) +RUN="yes" + +# Additional options that are passed to the daemon. +DAEMON_OPTS="-d -f /etc/pnp4nagios/npcd.cfg" + diff --git a/puppet/modules/nagios/files/pnp4nagios/pnp4nagios-popup-templates.cfg b/puppet/modules/nagios/files/pnp4nagios/pnp4nagios-popup-templates.cfg new file mode 100644 index 00000000..de17d841 --- /dev/null +++ b/puppet/modules/nagios/files/pnp4nagios/pnp4nagios-popup-templates.cfg @@ -0,0 +1,31 @@ +# http://docs.pnp4nagios.org/de/pnp-0.6/webfe + +define host { +   name       host-pnp +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=_HOST_ +   register   0 +} + +define service { +   name       srv-pnp +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/index.php/popup?host=$HOSTNAME$&srv=$SERVICEDESC$ +   register   0 +} + +# templates for explicit use, i.e. +# use => 'generic-host-pnp' + +define host { +    name        generic-host-pnp +    use         generic-host,host-pnp +#   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_ +   register   0 +} + +define service { +    name        generic-service-pnp +    use         generic-service,srv-pnp +#   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_ +   register   0 +} + diff --git a/puppet/modules/nagios/files/pnp4nagios/pnp4nagios-templates.cfg b/puppet/modules/nagios/files/pnp4nagios/pnp4nagios-templates.cfg new file mode 100644 index 00000000..64c51865 --- /dev/null +++ b/puppet/modules/nagios/files/pnp4nagios/pnp4nagios-templates.cfg @@ -0,0 +1,33 @@ +# http://docs.pnp4nagios.org/de/pnp-0.6/webfe + +# templates for additional use, i.e. +# use => 'generic-host,host-pnp' +define host { +   name       host-pnp +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_ +   register   0 +} + +define service { +   name       srv-pnp +   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=$SERVICEDESC$ +   register   0 +} + +# templates for explicit use, i.e. +# use => 'generic-host-pnp' + +define host { +    name	generic-host-pnp +    use		generic-host,host-pnp +#   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_ +   register   0 +} + +define service { +    name        generic-service-pnp +    use         generic-service,srv-pnp +#   action_url /pnp4nagios/index.php/graph?host=$HOSTNAME$&srv=_HOST_ +   register   0 +} + diff --git a/puppet/modules/nagios/files/pnp4nagios/status-header.ssi b/puppet/modules/nagios/files/pnp4nagios/status-header.ssi new file mode 100644 index 00000000..472be3a2 --- /dev/null +++ b/puppet/modules/nagios/files/pnp4nagios/status-header.ssi @@ -0,0 +1,8 @@ +<script src="/pnp4nagios/media/js/jquery-min.js" type="text/javascript"></script> +<script src="/pnp4nagios/media/js/jquery.cluetip.js" type="text/javascript"></script> +<script type="text/javascript"> +$(document).ready(function() { +  $('a.tips').cluetip({ajaxCache: false, dropShadow: false,showTitle: false }); +}); +</script> + | 
