"""
Installs and configures puppet
"""
import sys
import logging
import os
import platform
import time

from packstack.installer import utils
from packstack.installer import basedefs, output_messages
from packstack.installer.exceptions import ScriptRuntimeError

from packstack.modules.ospluginutils import (gethostlist,
                                             manifestfiles,
                                             scan_puppet_logfile,
                                             validate_puppet_logfile)

# Controller object will be initialized from main flow
controller = None

# Plugin name
PLUGIN_NAME = "OSPUPPET"
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')

logging.debug("plugin %s loaded", __name__)

PUPPETDIR = os.path.abspath(os.path.join(basedefs.DIR_PROJECT_DIR, 'puppet'))
MODULEDIR = os.path.join(PUPPETDIR, "modules")


def initConfig(controllerObject):
    global controller
    controller = controllerObject
    logging.debug("Adding OpenStack Puppet configuration")
    paramsList = [
                 ]

    groupDict = {"GROUP_NAME"            : "PUPPET",
                 "DESCRIPTION"           : "Puppet Config parameters",
                 "PRE_CONDITION"         : lambda x: 'yes',
                 "PRE_CONDITION_MATCH"   : "yes",
                 "POST_CONDITION"        : False,
                 "POST_CONDITION_MATCH"  : True}

    controller.addGroup(groupDict, paramsList)


def getinstallhostlist(conf):
    list = []
    exclude_list = map(str.strip, conf['EXCLUDE_SERVERS'].split(','))
    for host in gethostlist(conf):
        if host not in exclude_list:
            list.append(host)
    return list


def initSequences(controller):
    puppetpresteps = [
             {'title': 'Clean Up', 'functions':[runCleanup]},
    ]
    controller.insertSequence("Clean Up", [], [], puppetpresteps, index=0)

    puppetsteps = [
             {'title': 'Installing Dependencies', 'functions':[installdeps]},
             {'title': 'Copying Puppet modules and manifests', 'functions':[copyPuppetModules]},
             {'title': 'Applying Puppet manifests', 'functions':[applyPuppetManifest]},
    ]
    controller.addSequence("Puppet", [], [], puppetsteps)


def runCleanup(config):
    localserver = utils.ScriptRunner()
    localserver.append("rm -rf %s/*pp" % basedefs.PUPPET_MANIFEST_DIR)
    localserver.execute()


def installdeps(config):
    for hostname in getinstallhostlist(controller.CONF):
        server = utils.ScriptRunner(hostname)
        for package in ("puppet", "openssh-clients", "tar", "nc"):
            server.append("rpm -q %s || yum install -y %s" % (package, package))
        server.execute()


def copyPuppetModules(config):
    os_modules = ' '.join(('apache', 'cinder', 'concat',
                           'create_resources', 'firewall',
                           'glance', 'horizon', 'inifile',
                           'keystone', 'memcached', 'mysql',
                           'nova', 'openstack', 'packstack',
                           'qpid', 'neutron', 'rsync', 'ssh', 'stdlib',
                           'swift', 'sysctl', 'tempest', 'vcsrepo',
                           'vlan', 'vswitch', 'xinetd'))

    # write puppet manifest to disk
    manifestfiles.writeManifests()

    server = utils.ScriptRunner()
    tar_opts = ""
    if platform.linux_distribution()[0] == "Fedora":
        tar_opts += "--exclude create_resources "
    for hostname in getinstallhostlist(controller.CONF):
        host_dir = controller.temp_map[hostname]
        puppet_dir = os.path.join(host_dir, basedefs.PUPPET_MANIFEST_RELATIVE)
        server.append("cd %s/puppet" % basedefs.DIR_PROJECT_DIR)
        # copy Packstack facts
        server.append("tar %s --dereference -cpzf - facts | "
                      "ssh -o StrictHostKeyChecking=no "
                          "-o UserKnownHostsFile=/dev/null "
                          "root@%s tar -C %s -xpzf -" % (tar_opts, hostname, host_dir))
        # copy Packstack manifests
        server.append("cd %s" % basedefs.PUPPET_MANIFEST_DIR)
        server.append("tar %s --dereference -cpzf - ../manifests | "
                      "ssh -o StrictHostKeyChecking=no "
                          "-o UserKnownHostsFile=/dev/null "
                          "root@%s tar -C %s -xpzf -" % (tar_opts, hostname, host_dir))

        # copy resources
        for path, localname in controller.resources.get(hostname, []):
            server.append("scp -o StrictHostKeyChecking=no "
                "-o UserKnownHostsFile=/dev/null %s root@%s:%s/resources/%s" %
                (path, hostname, host_dir, localname))

        # copy Puppet modules required by Packstack
        server.append("cd %s/puppet/modules" % basedefs.DIR_PROJECT_DIR)
        server.append("tar %s --dereference -cpzf - %s | "
                      "ssh -o StrictHostKeyChecking=no "
                          "-o UserKnownHostsFile=/dev/null "
                          "root@%s tar -C %s -xpzf -" %
                                (tar_opts, os_modules, hostname,
                                 os.path.join(host_dir, 'modules')))