#!/usr/bin/python
# Copyright 2017 Cumulus Networks Inc, all rights reserved
#
# ASIC monitor tool
#
#
#
#
#
#
#

import sys
import signal
import argparse
import getopt
import os
import exceptions
import re
import subprocess
import json
import math
import time
import logging
import logging.handlers
import traceback
import cumulus.datapath_utils

# error exit value to prevent restart
no_restart_return_value = 30

# initialize the global logger
global logger
logger  = logging.getLogger('asic-monitor')
fmt     = logging.Formatter(fmt='%(name)s %(levelname)s: %(message)s')
handler = logging.handlers.SysLogHandler('/dev/log')
handler.setFormatter(fmt)
logger.setLevel(logging.INFO)
logger.addHandler(handler)

if cumulus.datapath_utils.is_platform_vx():
    logger.info('ASIC monitor is not supported on VX')
    sys.exit(0)

from cumulus.asic_exception import ChipNotSupportedError
from cumulus.asic_exception import ConfigFileError
from cumulus.asic_monitor import AsicMonitor

SIGNALS_TO_NAMES_DICT = dict((getattr(signal, n), n) \
                                 for n in dir(signal) if n.startswith('SIG') and '_' not in n )

# ----------------------------------------------------------
#
def handle_signal(signal_number, frame):
    signal_handler.exit_flag = True
    signal_label = SIGNALS_TO_NAMES_DICT.get(signal_number,
                                             'Unnamed signal: %d' % signal_number)
    logger.info('received signal %s' % signal_label)

# ==========================================================
#
class SignalHandler(object):
    def __init__(self, signal_list):
        super(SignalHandler,self).__init__()
        self.exit_flag = False
        for signal_number in signal_list:
            signal.signal(signal_number, handle_signal)


global signal_handler
# contingency planning
signal_handler = SignalHandler([signal.SIGTERM, signal.SIGINT, signal.SIGHUP])

# -------------------------------------------------
#
# check to see if an instance is already running
#
def already_running(pidfile):
    myname=os.path.basename(sys.argv[0])
    try:
        if not os.path.isfile(pidfile):
            return False
        oldpid = re.findall('\D*(\d+).*', (file(pidfile, 'r').readline()))[0]
        if not os.path.exists('/proc/%s' % oldpid):
            return False
        if myname not in file('/proc/%s/cmdline' % oldpid, 'r').readline():
            return False
        sys.stderr.write("%s already running as process %s\n" % (myname, oldpid))
        return True
    except Exception as e:
        logger.error("unable to validate pidfile %s: %s" % (pidfile, str(e)))

# ----------------------------------------------------------
#
def exit_monitor(monitor, exit_value):
    if monitor:
        monitor.clean_up()
    sys.exit(exit_value)

# ----------------------------------------------------------
#
def main(argv) :

    pidfile = "/var/run/asic-monitor.pid"
    if already_running(pidfile):
        sys.exit(0)
    else:
        file(pidfile, 'w').write(str(os.getpid()))
    exit_flag = False

    # create the asic monitor
    monitor = AsicMonitor(signal_handler)
    if monitor == None:
        logger.error('monitor object was not created')
        return
    try:
        monitor.run()
    except ChipNotSupportedError as e:
        logger.info('%s is not supported by the ASIC monitor' % e.chip_name)
        exit_monitor(monitor, no_restart_return_value)
    except ConfigFileError as e:
        logger.info('Configuration error %s: halting' % e.message)
        exit_monitor(monitor, no_restart_return_value)
    except Exception as e:
        logger.error('ASIC monitor exception: ' + str(e))
        traceback.print_stack()
        print '--------------'
        traceback.print_exc()
        exit_monitor(monitor, 1)
    exit_monitor(monitor, 0)

# ----------------------------------------------------------
#
#                        e n t r y
#
# ----------------------------------------------------------

if __name__ == "__main__":
    main(sys.argv[1:])



