#!/usr/bin/python
#
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
#
# Licensed to you under the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.  See the files README and
# LICENSE_GPL_v2 which accompany this distribution.
#

import os, sys, getopt, signal
import time
import threading
import logging
import traceback
from logging import config as lconfig
from logging import handlers as lhandlers
from config import config
import utils
import constants

confFile = '/etc/vdsm/vdsm.conf'
loggerConfFile = '/etc/vdsm/logger.conf'
daemonize = True

def usage():
    print "Usage:  vdsm [OPTIONS] [Configuration_file]"
    print "     -h  - Display this help message"
    print "     -l  - Search for files in the working directory instead of the install path"
    print "Configuration file: The server configuration file. Default is ./vdsm.conf"

def startWatchdog(log):
    pidfile = constants.P_VDSM_RUN + 'respawn.pid'
    file(pidfile, 'w').write(str(os.getpid()) + "\n")
    os.chmod(pidfile, 0664)

    while True:
        lastForkTime = time.time()
        pid = os.fork()
        if pid:
            log.info('I am Watchdog - vdsm pid is ' + str(pid))
            os.waitpid(pid, 0)
            # log may be very old by now; rollover to make sure we use an
            # existing file.
            for h in log.handlers:
                if isinstance(h, lhandlers.RotatingFileHandler):
                    h.doRollover()
            if time.time() - lastForkTime < 2:
                log.error('VDSMD crashed immediately - ( < 2 sec) exiting without recovering')
                sys.exit(3)
            log.error('VDSMD crashed - Recovering')
        else:
            os.setpgrp()
            log.info('I am the actual vdsmd')
            break

def serve_clients(log):
    cif = None
    def sigtermHandler(signum, frame):
        if cif:
            cif.prepareForShutdown()

    signal.signal(signal.SIGTERM, sigtermHandler)

    import clientIF # must import after config is read
    cif = clientIF.clientIF(log)
    cif.serve()

def run():
    if not os.path.exists(confFile):
        sys.stderr.write('%s does not exist. using defaults\n' % confFile)
    config.read([confFile])

    if daemonize:
        utils.createDaemon()

    lconfig.fileConfig(loggerConfFile)

    log = logging.getLogger('vds')
    try:
        if not daemonize:
            logging.root.handlers.append(logging.StreamHandler())
            log.handlers.append(logging.StreamHandler())

        if daemonize:
            startWatchdog(log)

        pidfile = constants.P_VDSM_RUN + 'vdsmd.pid'
        file(pidfile, 'w').write(str(os.getpid()) + "\n")
        os.chmod(pidfile, 0664)

        serve_clients(log)
    except:
        log.error(traceback.format_exc())

    log.info("VDSM main thread ended. Waiting for %d other threads..." % (threading.activeCount() - 1))
    for t in threading.enumerate():
        if 'stop' in dir(t): t.stop()
        log.info(str(t))

def parse_args():
    global daemonize, confFile

    opts, args = getopt.getopt(sys.argv[1:], "hl", ["help", "runlocal"])
    for o,v in opts:
        o = o.lower()
        if o == "-h" or o == "--help":
            usage()
            sys.exit(0)
        if o == "-l" or o == "--runlocal":
            daemonize = False

    if len(args) >= 2:
        usage()
        sys.exit(1)
    elif len(args) == 1:
        confFile = args[0]

if __name__ == '__main__':
    parse_args()
    run()
