#!/usr/local/bin/python -u
# -*- coding: iso-8859-1 -*-

# Script maintenu sur le serveur subversion.
# svn co svn://svn/radius/scripts/check_radius_db_synchro.py

# Script Nagios de vérification de synchronisation des bases locales
# des serveurs RADIUS avec les bases maîtres.
# Lancer le script avec le nom du serveur à vérifier.
# On compte le nombre d'enregistrements dans les tables répliquées, si
# le nombre d'enregistrements diffère de error_tolerance %, une alarme est générée.

from __future__ import division # Python 3 donnera un float pour une division entre deux entiers
import string, os, sys, time, string, re, traceback, MySQLdb as mysql

interactive = os.isatty(sys.stdout.fileno())
debug = 0
mysql_read_default_file = "/usr/local/libexec/nagios.clara/data/radius/my.cnf"
error_tolerance = 0.5 # en pourcent, la différence en nombre d'enregistrements qu'on accepte
desynchronised_databases = []
exit_code = 0 # code de retour Nagios, 0 = OK, 1 = warning, 2 = critical, 3 = unknown

def exit_unknown(message):
  print message
  if interactive:
  	if interactive: traceback.print_exc()
  os._exit(3);

if len(sys.argv) != 2:
        exit_unknown("Utilisation : %s serveur" % sys.argv[0])

server = sys.argv[1].lower()

# La clé est le nom de la base en local.
backup_databases = {	

	'freesurfpw':	{
				'comment': 'utilisateurs Freesurf',
				'mysql_read_default_group': 'freesurf.fr_2',
				'tables': [ 'clarapw' ],
			},

	'clarapw':	{
				'comment': 'utilisateurs Claranet',
				'mysql_read_default_group': 'claranet.fr_2',
				'tables': [ 'clarapw' ],
			},

	'easy':	{
				'comment': 'utilisateurs Easy',
				'mysql_read_default_group': 'unknown',
				'tables': [ 'mbox', 'domain' ],
				'full_dump_only': True
			},

	'netmedicompw':	{
				'comment': 'utilisateurs Netmedicom',
				'mysql_read_default_group': 'netmedicom.com_2',
				'tables': [ 'clarapw' ],
			},

#	'skyrockpw':	{
#				'comment': 'utilisateurs Skyrock',
#				'mysql_read_default_group': 'skyrock.com_2',
#				'tables': [ 'clarapw' ],
#			},

	'compaqnetpw':	{
				'comment': 'utilisateurs Compaqnet',
				'mysql_read_default_group': 'compaqnet.fr_2',
				'tables': [ 'clarapw' ],
			},

			
}

for backup_database in backup_databases.keys():

	# Trop vieille version de mysql sur adduser.compaqnet.fr pour mysqldump
        if backup_database == "compaqnetpw": continue
	master_mysql_default_group = backup_databases[backup_database]['mysql_read_default_group']
	comment = backup_databases[backup_database]['comment']

	try:
		if debug: print "Connecting to %s..." % master_mysql_default_group
		sql_master = mysql.connect(read_default_file = mysql_read_default_file,
					read_default_group = master_mysql_default_group)
		sqlc_master = sql_master.cursor()
	except:
		exit_unknown("Erreur connexion %s" % master_mysql_default_group)

	try:
		if debug: print "Connecting to %s, base %s..." % (server, backup_database)
		sql_slave = mysql.connect(host = server, user = 'radius', passwd = 'skaj2002', db = backup_database)
		sqlc_slave = sql_slave.cursor()
	except:
		exit_unknown("Erreur connexion %s" % server)

	for table in backup_databases[backup_database]['tables']:
		# on compte les enregistrements de la table distante
		statement = "SELECT COUNT(*) FROM %s" % table
		if debug: print statement
		try:
			sqlc_master.execute(statement)
			row = sqlc_master.fetchone()
			master_count = row[0]
			if interactive:
				print("%i enregistrements sur le master %s, base %s, table %s." %
			  	(master_count, master_mysql_default_group, backup_database, table) )
		except:
			exit_unknown("Erreur exécution %s sur %s" % (statement, master_mysql_default_group) )
			
		try:
			sqlc_slave.execute(statement)
			row = sqlc_slave.fetchone()
			slave_count = row[0]
			if interactive:
				print("%i enregistrements sur le slave %s, base %s, table %s." %
			  	(slave_count, server, backup_database, table) )
		except:
			exit_unknown("Erreur exécution %s sur %s" % (statement, server) )

			
		high_count = max(master_count, slave_count)
		low_count = min(master_count, slave_count)
		
		if low_count & high_count == 0:
			print "Erreur sur calcul Ratio: low_count zero value"
			sys.exit(0)

		ratio = high_count / low_count
		
		if debug: print "Ratio: %s" % ratio
		max_ratio = 1 + (error_tolerance / 100)
		if debug: print "Max ratio: %s" % max_ratio
		if ratio > max_ratio and master_count > slave_count:
			exit_code = 2
			desynchronised_databases.append(backup_database)
		if interactive: print

	

if exit_code == 2:
	databases = string.join(desynchronised_databases, ', ')
	sys.stdout.write("!!!! Bases locales RADIUS désynchronisées : %s.\n" % databases)
	sys.stdout.flush()
	os._exit(2)
else:
	sys.stdout.write('OK\n')
	sys.stdout.flush()
	os._exit(0)


# vim: set ft=python ts=3 sw=3:
