#!/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
import sys
import getopt
import signal
import getpass
import pwd
import grp
import threading
import logging
import syslog
from logging import config as lconfig

from vdsm import constants
import zombieReaper
import dsaversion
if sys.version_info[0] == 2:
    # as long as we work with Python 2, we need to monkey-patch threading
    # module before it is ever used.
    import pthreading
    pthreading.monkey_patch()

loggerConfFile = constants.P_VDSM_CONF + 'logger.conf'


def usage():
    print "Usage:  vdsm [OPTIONS]"
    print "     -h  - Display this help message"


def serve_clients(log):
    cif = None

    def sigtermHandler(signum, frame):
        if cif:
            cif.prepareForShutdown()

    def sigusr1Handler(signum, frame):
        if cif and cif.irs:
            cif.irs.spmStop(
                    cif.irs.getConnectedStoragePoolsList()['poollist'][0])

    signal.signal(signal.SIGTERM, sigtermHandler)
    signal.signal(signal.SIGUSR1, sigusr1Handler)
    zombieReaper.registerSignalHandler()

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


def run():
    lconfig.fileConfig(loggerConfFile)
    logging.addLevelName(5, 'TRACE')
    logging.TRACE = 5  # impolite but helpful

    # Used to debug vdsm. on production machines
    # vdsmDebugPlugin.py should not exists
    try:
        import vdsmDebugPlugin
    except ImportError:
        # This is OK, it just means the file isn't
        # there and we are not running in debug mode.
        # Any other error is an error in the debug
        # plugin and we would like to print that out.
        pass

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

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

        sysname, nodename, release, version, machine = os.uname()
        log.info('I am the actual vdsm %s %s (%s)',
             dsaversion.raw_version_revision, nodename, release)
        serve_clients(log)
    except:
        log.error("Exception raised", exc_info=True)

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


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

    if len(args) >= 1:
        usage()
        sys.exit(1)


def __assertLogPermission():
    if not os.access(constants.P_VDSM_LOG, os.W_OK):
        syslog.syslog("vdsm log directory is not accessible")
        sys.exit(1)

    logfile = constants.P_VDSM_LOG + "/vdsm.log"
    if not os.path.exists(logfile):
        # if file not exist, and vdsm has an access to log directory- continue
        return

    if not os.access(logfile, os.W_OK):
        syslog.syslog("error in accessing vdsm log file")
        sys.exit(1)


def __assertVdsmUser():
    username = getpass.getuser()
    if username != constants.VDSM_USER:
        syslog.syslog("VDSM failed to start: running user is not %s, trying "
                      "to run from user %s" % (constants.VDSM_USER, username))
        sys.exit(1)
    group = grp.getgrnam(constants.VDSM_GROUP)
    if (constants.VDSM_USER not in group.gr_mem) and \
       (pwd.getpwnam(constants.VDSM_USER).pw_gid != group.gr_gid):
        syslog.syslog("VDSM failed to start: vdsm user is not in KVM group")
        sys.exit(1)


if __name__ == '__main__':
    __assertVdsmUser()
    __assertLogPermission()
    os.setpgrp()
    parse_args()
    run()
