#!/usr/bin/python

# Copyright (C) 2013:
#    Gabes Jean, j.gabes@shinken-solutions.com
#
# This file is part of Shinken Enterprise, all rights reserved.

import sys
import os
import optparse
import subprocess
import socket

try:
    from shinkensolutions.localinstall import VERSION
except ImportError:
    print 'Cannot import shinken lib, please install it before launching this tool'
    sys.exit(2)

from shinkensolutions.localinstall import get_local_daemons, set_local_daemon_instance, VERSION, WARNING_COLOR, ERROR_COLOR, OK_COLOR, check_root, POSSIBLE_DAEMONS, get_local_instances_for_type, get_local_daemon_configuration_file_path, \
    get_instance_name, stop_daemon

from shinkensolutions.system_tools import run_command

DEFAULT_UMASK = 0022
# Set umask to avoid problems when creating files
os.umask(DEFAULT_UMASK)

if __name__ == '__main__':
    parser = optparse.OptionParser("%prog [poller synchronizer scheduler reactionner receiver broker]", version="%prog: " + VERSION, description='This tool is used to enable/disable daemons on the local server')
    parser.add_option('--enable', dest='mode_enable', action='store_true', help="Enable a local daemon.")
    parser.add_option('--disable', dest='mode_disable', action='store_true', help="Disable a local daemon.")
    parser.add_option('--force', dest='mode_force', action='store_true', help="Do not look at the previous state before doing the change.")
    parser.add_option('--id', dest='daemon_id', help="[optional] enable/disable a specific daemon instance. If missing, all are enabled/disabled.")
    
    opts, args = parser.parse_args()
    
    # If not root, exit
    check_root()
    
    if len(args) == 0:
        print "Missing daemon to enable/disable"
        sys.exit(2)
    
    if not opts.mode_enable and not opts.mode_disable:
        print "Please select at least either --enable or --disable option"
        sys.exit(2)
    
    if opts.mode_force is None:
        opts.mode_force = False
    
    daemon_id = opts.daemon_id
    
    daemons = [d.strip() for d in args if d.strip()]
    
    must_sanatize = False
    
    for d in daemons:
        if d not in POSSIBLE_DAEMONS:
            print "The daemon %s is unknown, exiting" % d
            sys.exit(2)
    
    already_enabled = get_local_daemons()
    is_central = 'arbiter' in already_enabled
    
    for d in daemons:
        local_instances = get_local_instances_for_type(d)
        if daemon_id:
            local_instances = [(k, enabled) for (k, enabled) in local_instances if str(k) == str(daemon_id)]
            if not local_instances:
                print ' [id:%s] :\033[%dm ID NOT FOUND, skipping\033[0m' % (daemon_id, WARNING_COLOR)
                continue
        
        for (k, enabled) in local_instances:
            instance_name = get_instance_name(d, k)
            
            # Look at previous state, but only if we are not in a force mode
            if not opts.mode_force:
                # Maybe already enabled
                if opts.mode_enable:
                    if enabled:
                        print ' [id:%s] %s:\033[%dm ALREADY ENABLED, skipping\033[0m' % (k, instance_name.ljust(20), WARNING_COLOR)
                        continue
                
                # Maybe already disable
                if opts.mode_disable:
                    if not enabled:
                        print ' [id:%s] %s:\033[%dm ALREADY DISABLED, skipping\033[0m' % (k, instance_name.ljust(20), WARNING_COLOR)
                        continue
            
            cfg_p = get_local_daemon_configuration_file_path(d, k)
            
            if opts.mode_enable:
                _from = '0'
                _to = '1'
                mode_set = True  # in context
                if d == 'synchronizer':
                    must_sanatize = True
            else:  # disable
                _from = '1'
                _to = '0'
                mode_set = False  # in context
            
            # If we are an arbiter, try to detect which cfg file is impacted, and disable/enable it
            if is_central:
                # try to search also in local if we have such a daemon on our address
                cmd = """hostname -I"""
                p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
                out = p.stdout.read()
                err = p.stderr.read()
                if err:
                    print ' \033[%dm ERROR (%s): %s\033[0m' % (ERROR_COLOR, instance_name, err)
                    continue
                local_addresses = out.split(' ')
                local_addresses.append('localhost')
                local_addresses.append('127.0.0.1')
                
                # now look at local daemons
                
                cmd = """grep -H address /etc/shinken/%ss/*cfg""" % d
                p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
                out = p.stdout.read()
                err = p.stderr.read()
                if err:
                    out = ''
                for line in out.splitlines():
                    elts = [s.strip() for s in line.split(' ') if s.strip()]
                    pth = elts[0].split(':')[0]
                    try:
                        if elts[1].startswith('#'):
                            continue
                        
                        addr = elts[2]
                    except IndexError:
                        continue
                    
                    # try to resolve addr
                    try:
                        addr = socket.gethostbyname(addr)
                    except Exception, exp:
                        pass
                    
                    # maybe we did found our local daemon
                    if addr in local_addresses:
                        change_daemon_enable = True
                        if daemon_id:
                            # If a daemon_id is set we search for the good cfg file to change
                            cmd = """grep %s_name %s""" % (d, pth)
                            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
                            out = p.stdout.read()
                            err = p.stderr.read()
                            if err:
                                out = ''
                            for line in out.splitlines():
                                elts = [s.strip() for s in line.split(' ') if s.strip()]
                                try:
                                    if elts[0].startswith('#'):
                                        continue
                                    if elts[1] != get_instance_name(d, daemon_id):
                                        change_daemon_enable = False
                                        continue
                                except IndexError:
                                    continue
                        
                        if change_daemon_enable:
                            # IMPORTANT: as we can have 'enabled 0' in comments, only allow space between enabled 0/1 so
                            # it will match the parameter and not enabled in the parameter and the value in the comment!
                            cmd = """sed -i "s/enabled\s*%s/enabled  %s/" %s""" % (_from, _to, pth)
                            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
                            out = p.stdout.read()
                            err = p.stderr.read()
            
            # If disable, try to stop the daemon
            if opts.mode_disable:
                stop_daemon(d, k)
            
            # Now edit the local configuration part
            cmd = """sed -i "s/daemon_enabled=%s/daemon_enabled=%s/" %s""" % (_from, _to, cfg_p)
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
            out = p.stdout.read()
            err = p.stderr.read()
            if err:
                print ' \033[%dm ERROR (%s): %s\033[0m' % (ERROR_COLOR, instance_name, err)
                continue
            
            set_local_daemon_instance(d, k, mode_set)
            
            if opts.mode_enable:
                print ' [id:%s] %s:\033[%dm ENABLED\033[0m' % (k, instance_name.ljust(20), OK_COLOR)
            if opts.mode_disable:
                print ' [id:%s] %s:\033[%dm DISABLED\033[0m' % (k, instance_name.ljust(20), WARNING_COLOR)
    
    if must_sanatize:
        print '\nYou have enabled a synchronizer instance. We need to start mongod and launch sanatize to make sure the data is consistent.'
        
        launch_mongod = '''service mongod start'''
        print run_command(launch_mongod)
        
        print 'Launching data and configuration checks and fixes (may take few minutes)'
        cmd = """/var/lib/shinken/libexec/tools/sanatize-data.py -a"""
        print run_command(cmd)
