#!/usr/bin/python
# -*- coding: utf8 -*-

import sys
import os
import json
import time
import multiprocessing
import tempfile
import traceback
import logging
import datetime

sys.path.insert(0, '/opt/check-db-availability')
sys.path.insert(0, 'opt/check-db-availability')
import check_db_utils


current_date = datetime.datetime.now().strftime("%Y%m%d")
LOG_PATH = u'/var/log/yandex/check-db-availability'
MAIN_LOG_FILE = u'/var/log/yandex/check-db-availability/main.log'
SERVICE_NAME = 'db_availability'
ALLDB_CONFIG = '/etc/yandex-direct/alldb-config.json'


def master_alive_with_maybe_fresh_slave(user, pass_file, db_config, instance_config, instance_name, fresh_slave_check=False):
    master_host, master_port, slaves, max_freshness, max_trx_age = check_db_utils.get_data_from_instance_conf(instance_config, db_config)

    #delete old
    crit_messages = []
    crit_messages.append(check_db_utils.is_host_alive(master_host, master_port, user, pass_file)[1])
    if fresh_slave_check and  not crit_messages[-1]:
        crit_messages.append(
            check_db_utils.has_fresh_slave(
                instance_config.get('project', ''),
                instance_config.get('type', ''),
                master_host, master_port, slaves, user, pass_file, max_freshness
            )[1])

    #print crit_messages
    check_db_utils.report_to_juggler(SERVICE_NAME, instance_name, crit_messages)
    #end delete

    check_db_utils.report_to_juggler(SERVICE_NAME + "_host_alive", instance_name, 
            [check_db_utils.is_host_alive(
                master_host, master_port, user, pass_file
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_read_only", instance_name,
            [check_db_utils.is_not_read_only_state(
                master_host, master_port, user, pass_file
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_fresh_slave", instance_name,
            [check_db_utils.has_fresh_slave(
                instance_config.get('project', ''),
                instance_config.get('type', ''),
                master_host, master_port, slaves, user, pass_file, max_freshness
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_trx_max_age", instance_name,
            [check_db_utils.not_have_max_transactions(
                master_host, master_port, user, pass_file, max_trx_age
            )[1]])


def master_alive(user, pass_file, db_config, instance_config, instance_name):
    master_alive_with_maybe_fresh_slave(
        user, pass_file, db_config, instance_config, instance_name, fresh_slave_check=False
    )


def master_alive_with_fresh_slave(user, pass_file, db_config, instance_config, instance_name):
    master_alive_with_maybe_fresh_slave(
        user, pass_file, db_config, instance_config, instance_name, fresh_slave_check=True
    )


def check_ppcdict(user, pass_file, db_config, instance_config, instance_name):
    master_host, master_port, slaves, max_freshness, max_trx_age = check_db_utils.get_data_from_instance_conf(instance_config, db_config)

    #delete code
    crit_messages = []
    crit_messages.append(check_db_utils.is_host_alive(master_host, master_port, user, pass_file)[1])
    if not crit_messages[-1]:
        crit_messages.append(check_db_utils.is_single_xtradb_ok(master_host, master_port, user, pass_file)[1])
    if not crit_messages[-1]:
        crit_messages.append(
            check_db_utils.has_fresh_slave(
                instance_config.get('project', ''),
                instance_config.get('type', ''),
                master_host, master_port, slaves, user, pass_file, max_freshness
            )[1])
    check_db_utils.report_to_juggler(SERVICE_NAME, instance_name, crit_messages)    
    #end delete

    check_db_utils.report_to_juggler(SERVICE_NAME + "_host_alive", instance_name, 
            [check_db_utils.is_host_alive(
                master_host, master_port, user, pass_file
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_single_xtradb", instance_name, 
            [check_db_utils.is_host_alive(
                master_host, master_port, user, pass_file
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_read_only", instance_name,
            [check_db_utils.is_not_read_only_state(
                master_host, master_port, user, pass_file
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_fresh_slave", instance_name, 
            [check_db_utils.has_fresh_slave(
                instance_config.get('project', ''), 
                instance_config.get('type', ''), 
                master_host, master_port, slaves, user, pass_file, max_freshness
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_trx_max_age", instance_name,
            [check_db_utils.not_have_max_transactions(
                master_host, master_port, user, pass_file, max_trx_age
            )[1]])

def check_ppcdict_semi(user, pass_file, db_config, instance_config, instance_name):
    master_host, master_port, slaves, max_freshness, max_trx_age = check_db_utils.get_data_from_instance_conf(instance_config, db_config)

    check_db_utils.report_to_juggler(SERVICE_NAME + "_host_alive", instance_name,
            [check_db_utils.is_host_alive(
                master_host, master_port, user, pass_file
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_read_only", instance_name,
            [check_db_utils.is_not_read_only_state(
                master_host, master_port, user, pass_file
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_fresh_slave", instance_name,
            [check_db_utils.has_fresh_slave(
                instance_config.get('project', ''),
                instance_config.get('type', ''),
                master_host, master_port, slaves, user, pass_file, max_freshness
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_semisync_master", instance_name,
            [check_db_utils.is_semisync_master(
                master_host, master_port, user, pass_file
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_semisync_slaves", instance_name,
            [check_db_utils.is_semisync_slaves(
                master_host, slaves, master_port, user, pass_file
            )[1]])
    check_db_utils.report_to_juggler(SERVICE_NAME + "_trx_max_age", instance_name,
            [check_db_utils.not_have_max_transactions(
                master_host, master_port, user, pass_file, max_trx_age
            )[1]])


def set_logger(filename):
    for handler in logging.root.handlers[:]:
        logging.root.removeHandler(handler)

    logging.basicConfig(
        format=u'%(levelname)-8s [%(asctime)s] %(message)s',
        level=logging.INFO,
        filename="%s.%s" % (filename, current_date)
    )


def run_check(instance_name, db_config, instance_config):
    set_logger(u"%s/%s.log" % (LOG_PATH, instance_name))
    logging.info("start checking")

    user = instance_config.get('mysql_user', '')
    password = (check_db_utils.read_file(all_db_config[instance]['mysql_pass_file']).strip()
                if 'mysql_pass_file' in all_db_config[instance]
                else "")

    pass_file = tempfile.NamedTemporaryFile(delete=True)
    os.chmod(pass_file.name, 0600)
    check_db_utils.write_pass_to_file(pass_file, password)

    if instance_name.startswith("ppcdata"):
        check = "ppcdata"
    else:
        check = instance_name

    checks_table[check](user, pass_file, db_config, instance_config, instance_name)
    logging.info("checking is done")


checks_table = {
    'ppcdata': master_alive_with_fresh_slave,
    'ppcmonitor': master_alive_with_fresh_slave,
    'ppcdict-pxc': check_ppcdict,
    'ppcdict': check_ppcdict_semi,
    'sandbox': master_alive,
    'gorynych': master_alive_with_fresh_slave,
    'int-constructor': master_alive_with_fresh_slave,
}


if __name__ == '__main__':
    set_logger(MAIN_LOG_FILE)
    with open(ALLDB_CONFIG, "r") as alldb_fh:
        all_db_config = json.load(alldb_fh)['instances']
    processes = []
    configs_dict = {}

    for instance in all_db_config:
        try:
            db_config = check_db_utils.get_db_config(all_db_config[instance], instance)

            #временный кусок
            if instance == 'ppcdict-semi':
                db_config = check_db_utils.get_db_config(all_db_config[instance], 'ppcdict')
            #

            logging.info(u"running check for %s" % instance)
            proc = multiprocessing.Process(
                target=run_check, args=(instance, db_config, all_db_config[instance])
            )
            proc.start()
            processes.append(proc) 

        except Exception as e:
            logging.error("Exception occurred", exc_info=True)

    for proc in processes:
        proc.join()

