#! /usr/bin/env python
# Memory Overcommitment Manager
# Copyright (C) 2010 Adam Litke, IBM Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

import sys
import signal
import time
import os
import atexit
import re
from optparse import OptionParser
import ConfigParser
import logging
import logging.handlers
import mom

mom_instance = None

def daemonize(pid_file):
    try:
        pid = os.fork()
        if pid > 0:
            sys.exit(0)
    except OSError, e:
        sys.stderr.write("momd: fork failed: %d (%s)\n" % (e.errno, e.strerror))
        sys.exit(1)

    os.chdir("/")
    os.setsid()

    try:
        pid = os.fork()
        if pid > 0:
            sys.exit(0)
    except OSError, e:
        sys.stderr.write("momd: fork failed: %d (%s)\n" % (e.errno, e.strerror))
        sys.exit(1)

    pid = str(os.getpid())
    try:
        file(pid_file,'w+').write("%s\n" % pid)
    except EnvironmentError, e:
        sys.stderr.write("momd: failed to write pid file: %d (%s)\n" %
                         (e.errno, e.strerror))
        sys.exit(1)
    atexit.register(delpid, pid_file)

    sys.stdout.flush()
    sys.stderr.flush()
    si = file('/dev/null', 'r')
    so = file('/dev/null', 'a+')
    se = file('/dev/null', 'a+', 0)
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())

def delpid(pid_file):
    try:
        os.remove(pid_file)
    except OSError, e:
        logger = logging.getLogger('momd')
        logger.error("Unable to remove pid file (%s): %s", pid_file, e.strerror)

def signal_quit(signum, frame):
    global mom_instance
    logger = logging.getLogger('momd')
    logger.info("Caught signal -- shutting down")
    mom_instance.shutdown()

def get_option_overrides(options):
    config = ConfigParser.SafeConfigParser()
    config.add_section('main')
    config.add_section('logging')
    if options.plot_dir is not None:
        config.set('main', 'plot-dir', options.plot_dir)
    if options.log is not None:
        config.set('logging', 'log', options.log)
    if options.verbosity is not None:
        config.set('logging', 'verbosity', options.verbosity)
    if options.rules_file is not None:
        config.set('main', 'policy', options.rules_file)
    if options.policy_dir is not None:
        config.set('main', 'policy-dir', options.policy_dir)
    return config

def main():
    global mom_instance

    cmdline = OptionParser()
    cmdline.add_option('-c', '--config-file', dest='config_file',
                       help='Load configuration from FILE', metavar='FILE',
                       default='/etc/mom.conf')
    cmdline.add_option('-r', '--rules-file', dest='rules_file',
                       help='Load rules from FILE', metavar='FILE')
    cmdline.add_option('-P', '--policy-dir', dest='policy_dir',
                       help='Load policies from DIR', metavar='DIR')
    cmdline.add_option('-p', '--plot-dir', dest='plot_dir',
                       help='Save data plot files in DIR', metavar='DIR')
    cmdline.add_option('-l', '--log', dest='log', metavar='TARGET',
                       help='Set the log to TARGET (stdout, or <file>')
    cmdline.add_option('-v', '--verbose', dest='verbosity', metavar='LEVEL',
                       help='Set logging verbosity to LEVEL (0-4)')
    cmdline.add_option('-d', '--daemon', action='store_true', dest='daemonize')
    cmdline.add_option('', '--pid-file', dest='pid_file', metavar='FILE',
                       help='When running as a daemon, write pid to FILE',
                       default='/var/run/momd.pid')

    (options, args) = cmdline.parse_args()
    config_overrides = get_option_overrides(options)

    if options.daemonize:
        daemonize(options.pid_file)

    signal.signal(signal.SIGINT, signal_quit)
    signal.signal(signal.SIGTERM, signal_quit)

    mom_instance = mom.MOM(options.config_file, config_overrides)
    mom_instance.run()
    sys.exit(0)

if __name__ == "__main__":
    mom.enable_i8()
    main()
