#!@PYTHON@

# Copyright (C) 2010  Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import sys; sys.path.append ('@@PYTHONPATH@@')

from isc.config.cfgmgr import ConfigManager, ConfigManagerDataReadError
from isc.cc import SessionError
import isc.util.process
import signal
import os
from optparse import OptionParser
import glob
import os.path

isc.util.process.rename()

# If B10_FROM_SOURCE is set in the environment, we use data files
# from a directory relative to the value of that variable, or, if defined,
# relative to the value of B10_FROM_SOURCE_LOCALSTATEDIR.  Otherwise
# we use the ones installed on the system.
# B10_FROM_SOURCE_LOCALSTATEDIR is specifically intended to be used for
# tests where we want to use variuos types of configuration within the test
# environment.  (We may want to make it even more generic so that the path is
# passed from the boss process)
if "B10_FROM_SOURCE" in os.environ:
    if "B10_FROM_SOURCE_LOCALSTATEDIR" in os.environ:
        DATA_PATH = os.environ["B10_FROM_SOURCE_LOCALSTATEDIR"]
    else:
        DATA_PATH = os.environ["B10_FROM_SOURCE"]
    PLUGIN_PATHS = [DATA_PATH + '/src/bin/cfgmgr/plugins']
else:
    PREFIX = "@prefix@"
    DATA_PATH = "@localstatedir@/@PACKAGE@".replace("${prefix}", PREFIX)
    PLUGIN_PATHS = ["@prefix@/share/@PACKAGE@/config_plugins"]
DEFAULT_CONFIG_FILE = "b10-config.db"

cm = None

def parse_options(args=sys.argv[1:], Parser=OptionParser):
    parser = Parser()
    parser.add_option("-p", "--data-path", dest="data_path",
                      help="Directory to search for configuration files " +
                      "(default=" + DATA_PATH + ")", default=DATA_PATH)
    parser.add_option("-c", "--config-filename", dest="config_file",
                      help="Configuration database filename " +
                      "(default=" + DEFAULT_CONFIG_FILE + ")",
                      default=DEFAULT_CONFIG_FILE)
    (options, args) = parser.parse_args(args)
    if args:
        parser.error("No non-option arguments allowed")
    return options

def signal_handler(signal, frame):
    global cm
    if cm:
        cm.running = False

def load_plugins(path, cm):
    """Load all python files in the given path and treat them as plugins."""
    # Find the python files
    plugins = glob.glob(path + os.sep + '*.py')
    # Search this directory first, but leave the others there for the imports
    # of the modules
    sys.path.insert(0, path)
    try:
        for plugin in plugins:
            # Generate the name of the plugin
            filename = os.path.basename(plugin)
            name = filename[:-3]
            # Load it
            module = __import__(name)
            # Ask it to provide the spec and checking function
            (spec, check_func) = module.load()
            # And insert it into the manager
            cm.set_virtual_module(spec, check_func)
    finally:
        # Restore the search path
        sys.path = sys.path[1:]

def main():
    options = parse_options()
    global cm
    try:
        cm = ConfigManager(options.data_path, options.config_file)
        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)
        cm.read_config()
        for ppath in PLUGIN_PATHS:
            load_plugins(ppath, cm)
        cm.notify_boss()
        cm.run()
    except SessionError as se:
        print("[b10-cfgmgr] Error creating config manager, "
              "is the command channel daemon running?")
        return 1
    except KeyboardInterrupt as kie:
        print("[b10-cfgmgr] Interrupted, exiting")
    except ConfigManagerDataReadError as cmdre:
        print("[b10-cfgmgr] " + str(cmdre))
        return 2
    return 0

if __name__ == "__main__":
    sys.exit(main())
