#!/usr/bin/env python

# Copyright (C) 2009-2012 :
#    Gabes Jean, naparuba@gmail.com
#    Gerhard Lausser, Gerhard.Lausser@consol.de
#    Gregory Starck, g.starck@gmail.com
#    Hartmut Goebel, h.goebel@goebel-consult.de
#
# This file is part of Shinken.
#
# Shinken is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Shinken 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Shinken.  If not, see <http://www.gnu.org/licenses/>.


import optparse
import sys
import os

try:
    import shinken
except ImportError:
    # If importing shinken fails, try to load from current directory
    # or parent directory to support running without installation.
    # Submodules will then be loaded from there, too.
    import imp
    imp.load_module('shinken', *imp.find_module('shinken', [os.path.realpath("."), os.path.realpath(".."), os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), "..")]))

from shinken.discovery.discoverymanager import DiscoveryManager


VERSION = '1.0.1'
if os.name != 'nt': 
    DEFAULT_CFG = '/etc/shinken/discovery.cfg'
else:
    DEFAULT_CFG = 'c:\\shinken\\etc\\discovery.cfg'


parser = optparse.OptionParser(
    "%prog [options] -c discovery_config -o config_output -m list of macros",
    version="%prog " + VERSION)
parser.add_option('-c', '--cfg-input',
                  dest="cfg_input", help=('Discovery configuration file (discovery.cfg)'))
parser.add_option('-o', '--dir-output', dest="output_dir",
                  help="Directory output for results")
parser.add_option('-w', '--overwrite', dest="overwrite", action='store_true',
                  help="Allow overwriting an existing file (disabled by default)")
parser.add_option('-r', '--runners', dest="runners",
                  help="List of runners you allow to run, (like nmap,vsphere)")
parser.add_option('-m', '--macros', dest="macros",
                  help="List of macros (like NMAPTARGETS=192.168.0.0/24). Should be the last argument")
parser.add_option('--db', dest="dbmod",
                  help="Optional : Name of the database module to use")
parser.add_option('--backend', dest="backend",
                  help="Optional : Name of a module that will totally manage the object writing/update thing. If you don't know what it means, maybe you should not use this option :)")
parser.add_option('--modules_path', dest="modules_path",
                  help="Optional : Path for the module loading. If you don't know what it means, maybe you should not use this option :)")
parser.add_option('--merge', dest="merge", action='store_true',
                  help="Optional : In multiple discovery level, it is the final host name which wins. Make possible merge of multiple IP but same final device")



opts, args = parser.parse_args()

raw_macros = []
macros=[]

if not opts.cfg_input:
    if not os.path.exists(DEFAULT_CFG):
        parser.error("Requires a discovery configuration file, discovery.cfg (option -c/--cfg-input)")
    else : # take the default file
        opts.cfg_input = DEFAULT_CFG

if not opts.output_dir and not opts.dbmod and not opts.backend:
    parser.error("Requires one output directory (option -o/--dir-output) or database output (option --db)")

if not opts.overwrite:
    overwrite = False
else:
    overwrite = opts.overwrite

if not opts.merge:
    merge = False
else:
    merge = opts.merge

if not opts.runners:
    runners = ['*']
else:
    runners = opts.runners.split(',')

if opts.macros:
    raw_macros.append(opts.macros)

if args:
    raw_macros.extend(args)

backend = opts.backend or None

print "Macros", raw_macros

for m in raw_macros:
    elts = m.split('=')
    if len(elts) < 2:
        print "The macro '%s' is malformed. I bail out" % m
        sys.exit(2)
    macros.append( (elts[0], '='.join(elts[1:])))

print "Got macros", macros

#    # We search if our potential parent is present in the
#    # other detected hosts. If so, set it as my parent
#    def look_for_parent(self, all_hosts):
#        parent = self.h.parent
#        print "Look for my parent", self.h.get_name(), "->", parent
#        # Ok, we didn't find any parent
#        # we bail out
#        if parent == '':
#            return
#        for h in all_hosts:
#            print "Is it you?", h.get_name()
#            if h.get_name() == parent:
#                print "Houray, we find our parent", self.h.get_name(), "->", h.get_name()
#                self.parents.append(h.get_name())
        

cfg_input = opts.cfg_input
output_dir = opts.output_dir
overwrite = opts.overwrite
dbmod = opts.dbmod
modules_path = opts.modules_path or ''


# Get the Manager for all of the discovery thing
d = DiscoveryManager(cfg_input, macros, overwrite, runners, output_dir=output_dir, dbmod=dbmod, backend=backend, modules_path=modules_path, merge=merge)

# #Ok, let start the plugins that will give us the data
d.launch_runners()
d.wait_for_runners_ends()

# We get the results, now we can reap the data
d.get_runners_outputs()

# and parse them
d.read_disco_buf()

# Now look for rules
d.match_rules()

d.loop_discovery()

# Ok, we know what to create, now do it!
d.write_config()
