#!/usr/bin/python2.6

# Nagios Plugin to check Pinba data
#
# Author : Camille NERON <camille.neron@gmail.com>
# Company : Carpe Hora <www.carpe-hora.com>
#
# GNU/GPL v2
#

#
# Module and variable defnition
#
from optparse import OptionParser
import sys
import MySQLdb

# Nagios return codes
OK = 0
WARNING = 1
CRITICAL = 2
UNKNOWN = 3

#
# Help and options
#

parser = OptionParser(usage="""%prog -H db_hostname -u user -p password -D db_name -r table_name -q column_name -v filter_link_with_table_name
Description :

Pinba is a realtime monitoring/statistics server for PHP using MySQL as a read-only interface. http://pinba.org
Pinba stock data in Mysql database. They are few tables, mainly this : 

* info
* report_by_hostname
* report_by_hostname_and_script
* report_by_hostname_and_server
* report_by_hostname_server_and_script
* report_by_script_name
* report_by_server_and_script
* report_by_server_name
* request

Actually, juste the report_by_hostname, by script_name and by server_name are supported. But the support, will be enlarge according the needs.

To use this plugin you must specify :

* database host
* pinba database name
* login and password to connect to the pinba database
* the table that you want check (report_by ...)
* the column that you want get. For example, to report_by_hostname, req_count column (check your table content)
* the value of the report type. For example, to report_by_hostname, you must specify the app server name
* and in almost all plugin nagios, the warning and critical value

An example of using : 

./check_pinba.py -H localhost -u pinba -p password -D pinba -r report_by_hostname -q req_count -v apache00

The plugin, will be connect to the database, and get the data with a SQL request.

Requirements :

* mysqldb : to Debian aptitude install python-mysqldb""", 
                    
                    version="%prog 0.1")

parser.add_option("-H", "--hostname", dest="hostname", default="localhost",
                  help="mysql hostname \nDefault : localhost", metavar="localhost")

parser.add_option("-u", "--username", dest="username", 
                  help="mysql username with grant to access to pinba database", metavar="pinba")

parser.add_option("-p", "--password", dest="password", 
                  help="mysql password", metavar="password")

parser.add_option("-D", "--database", dest="database", 
                  help="pinba database name", metavar="pinba")

parser.add_option("-P", "--port", dest="port", default=3306,
                  help="mysql port\nDefault: 3306", metavar="pinba")

parser.add_option("-r", "--report", dest="report", 
                 help="report type, corresponding to the table name", metavar="report_by_hostname")

parser.add_option("-q", "--query", dest="query", default="req_count",
                 help="corresponding to the column name of the table. Default: req_count", metavar="req_count")

parser.add_option("-v", "--value", dest="value", 
                 help="value on the report type. For example, the app server \"app00\"", metavar="app00")

parser.add_option("-w", "--warning", dest="warning", 
                  help="warning value, depending of -r, -q and -v options", metavar=5)

parser.add_option("-c", "--critical", dest="critical", 
                  help="critical value, depending of -r, -q and -v options", metavar=10)

(options, args) = parser.parse_args()

#
# Methods
#

def mysql_connect(hostname, username, password, database, port):
  """connect to the mysql database"""
  conn = MySQLdb.connect (host = hostname,
                           user = username,
                           passwd = password,
                           db = database,
                           port = port)
  return conn

def mysql_disconnect(conn):
  """disconnect to mysql(cursor, conn)"""
  conn.close()

def value_column(report):
  """return the value column name, to the where condition of the sql request"""
  if report == "report_by_hostname":
    retour = "hostname"
  elif report == "report_by_script_name":
    retour = "script_name"
  elif report == "report_by_server_name":
    retour = "server_name"

  return retour

def get_data(report, query, value, conn):
  """get data in fonction of the argument (report, query, value) and the connection (conn)"""
  cursor = conn.cursor()
  where_column = value_column(report)
  try:
    cursor.execute ("SELECT %s FROM %s WHERE %s='%s'" %(query, report, where_column, value))
    row = cursor.fetchone ()
    return row[0]
  except:
    print "error"


def end(status, message, perfdata):
    """Exits the script with the first argument as the return code and the
       second as the message to generate output."""

    if status == OK:
        print "OK: %s | %s" % (message, perfdata)
        sys.exit(0)
    elif status == WARNING:
        print "WARNING: %s | %s" % (message, perfdata)
        sys.exit(1)
    elif status == CRITICAL:
        print "CRITICAL: %s | %s" % (message, perfdata)
        sys.exit(2)
    else:
        print "UNKNOWN: %s | %s" % (message, perfdata)
        sys.exit(3)

def validate_thresholds(warning, critical):
    """Validates warning and critical thresholds in several ways."""

    if critical != -1 and warning == -2:
        end(UNKNOWN, "Please also set a warning value when using warning/" +
	             "critical thresholds!", "")
    if critical == -1 and warning != -2:
        end(UNKNOWN, "Please also set a critical value when using warning/" +
	             "critical thresholds!", "")
    if critical <= warning:
        end(UNKNOWN, "When using thresholds the critical value has to be " +
	              "higher than the warning value. Please adjust your " +
		      "thresholds.", "")

def return_nagios_status(data, warning, critical, message):
  """ find the nagios status before use the end methods """
  validate_thresholds(warning, critical)
  perfdata = "time=%s" %data

  if data < warning:
    end(OK, message, perfdata)
  if data >= warning and data < critical:
    end(WARNING, message, perfdata)
  if data >= critical:
    end(CRITICAL, message, perfdata)


#
# Main
#

if __name__ == "__main__":
  conn=mysql_connect(options.hostname, 
                  options.username, 
                  options.password, 
                  options.database, 
                  options.port)

  data = get_data(options.report, options.query, options.value, conn)

  mysql_disconnect(conn)
  message = "%s:%s %s:%s" %(options.report,  options.value, options.query, data)
  return_nagios_status(float(data), float(options.warning), float(options.critical), message)