#    Copyright 2016 Mirantis, Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.
import json
import os

from devops.helpers import decorators

from tcp_tests.managers.execute_commands import ExecuteCommandsMixin
from tcp_tests.managers.clients.prometheus import prometheus_client
from tcp_tests import logger
from tcp_tests import settings

LOG = logger.logger


class SLManager(ExecuteCommandsMixin):
    """docstring for OpenstackManager"""

    __config = None
    __underlay = None

    def __init__(self, config, underlay, salt):
        self.__config = config
        self.__underlay = underlay
        self._salt = salt
        self._p_client = None
        super(SLManager, self).__init__(
            config=config, underlay=underlay)

    def install(self, commands, label='Install SL services'):
        self.execute_commands(commands, label=label)
        self.__config.stack_light.stacklight_installed = True

    def get_sl_vip(self):
        tgt = 'I@prometheus:server:enabled:True'
        pillar = 'keepalived:cluster:instance:prometheus_server_vip:address'
        pill = 'keepalived:cluster:instance:stacklight_monitor_vip:address'
        sl_vip_address_pillars = self._salt.get_pillar(tgt=tgt,
                                                       pillar=pillar)
        sl_vip_ip = set([ip
                         for item in sl_vip_address_pillars
                         for node, ip in item.items() if ip])
        if not sl_vip_ip:
            tgt = 'I@prometheus:server:enabled:True and mon*'
            pillar = 'keepalived:cluster:instance:VIP:address'
            sl_vip_address_pillars = self._salt.get_pillar(tgt=tgt,
                                                           pillar=pillar)
            sl_vip_ip = set([ip
                             for item in sl_vip_address_pillars
                             for node, ip in item.items() if ip])
        if len(sl_vip_ip) != 1:
            sl_vip_address_pillars = self._salt.get_pillar(tgt=tgt,
                                                           pillar=pill)
            sl_vip_ip = set([ip
                             for item in sl_vip_address_pillars
                             for node, ip in item.items() if ip])
            LOG.info("Current response is {}".format(sl_vip_address_pillars))
        assert len(sl_vip_ip) == 1, (
            "SL VIP not found or found more than one SL VIP in pillars:{0}, "
            "expected one!").format(sl_vip_ip)
        sl_vip_ip_host = sl_vip_ip.pop()
        return sl_vip_ip_host

    @property
    def api(self):
        if self._p_client is None:
            self.__config.stack_light.sl_vip_host = self.get_sl_vip()
            self._p_client = prometheus_client.PrometheusClient(
                host=self.__config.stack_light.sl_vip_host,
                port=self.__config.stack_light.sl_prometheus_port,
                proto=self.__config.stack_light.sl_prometheus_proto)
        return self._p_client

    def get_monitoring_nodes(self):
        return [node_name for node_name
                in self.__underlay.node_names() if 'mon' in node_name]

    def get_service_info_from_node(self, node_name):
        service_stat_dict = {}
        with self.__underlay.remote(node_name=node_name) as node_remote:
            result = node_remote.execute(
                "docker service ls --format '{{.Name}}:{{.Replicas}}'")
            LOG.debug("Service ls result {0} from node {1}".format(
                result['stdout'], node_name))
            for line in result['stdout']:
                tmp = line.split(':')
                service_stat_dict.update({tmp[0]: tmp[1]})
        return service_stat_dict

    def setup_sl_functional_tests(self, node_to_run,
                                  repo_path='/root/stacklight-pytest',
                                  sl_test_repo=settings.SL_TEST_REPO,
                                  sl_test_commit=settings.SL_TEST_COMMIT):
        target_node_name = [node_name for node_name
                            in self.__underlay.node_names()
                            if node_to_run in node_name]
        cmd_install = (
            "set -ex;"
            "apt-get install -y  build-essential python-dev "
            "    virtualenv;"
            "[ -d venv-stacklight-pytest ] || "
            "    virtualenv --system-site-packages venv-stacklight-pytest;"
            ". venv-stacklight-pytest/bin/activate;"
            "if [ ! -d {repo_path} ]; then"
            "    git clone {sl_test_repo} {repo_path};"
            "fi;"
            "pushd {repo_path};"
            "git checkout {sl_test_commit};"
            "popd;"
            "pip install {repo_path};"
            .format(repo_path=repo_path,
                    sl_test_repo=sl_test_repo,
                    sl_test_commit=sl_test_commit)
        )

        cmd_configure = (
            "set -ex;"
            ". venv-stacklight-pytest/bin/activate;"
            "stl-tests gen-config-mk;"
            "cp venv-stacklight-pytest/lib/python2.7/site-packages/"
            "stacklight_tests/fixtures/config.yaml "
            "{repo_path}/stacklight_tests/fixtures/config.yaml;"
            .format(repo_path=repo_path)
        )

        with self.__underlay.remote(node_name=target_node_name[0]) \
                as node_remote:
            LOG.info("Install stacklight-pytest on the node {0}".format(
                target_node_name[0]))
            node_remote.check_call(cmd_install, verbose=True)

            LOG.info("Configure stacklight-pytest on the node {0}".format(
                target_node_name[0]))
            node_remote.check_call(cmd_configure, verbose=True)

    def run_sl_functional_tests(self, node_to_run, tests_path,
                                test_to_run, skip_tests,
                                reruns=5, reruns_delay=60,
                                junit_report_name='report.xml'):
        target_node_name = [node_name for node_name
                            in self.__underlay.node_names()
                            if node_to_run in node_name]
        cmd = ("set -ex;"
               ". venv-stacklight-pytest/bin/activate;"
               "cd {tests_path}; "
               "export VOLUME_STATUS='available';"
               "pytest {reruns} {reruns_delay} --junit-xml={junit_report_name}"
               " -k {skip_tests} {test_to_run}".format(**{
                   "tests_path": tests_path,
                   "skip_tests": ("'not " + skip_tests + "'"
                                  if skip_tests else ''),
                   "test_to_run": test_to_run,
                   "reruns": ("--reruns {}".format(reruns)
                              if reruns > 1 else ""),
                   "reruns_delay": ("--reruns-delay {}".format(reruns_delay)
                                    if reruns_delay > 0 else ""),
                   "junit_report_name": junit_report_name,
                   }))

        with self.__underlay.remote(node_name=target_node_name[0]) \
                as node_remote:
            LOG.debug("Run {0} on the node {1}".format(
                cmd, target_node_name[0]))
            result = node_remote.execute(cmd, verbose=True)
            LOG.debug("Test execution result is {}".format(result))
        return result

    def run_sl_tests_json(self, node_to_run, tests_path,
                          test_to_run, skip_tests, reruns=5, reruns_delay=60):
        target_node_name = [node_name for node_name
                            in self.__underlay.node_names()
                            if node_to_run in node_name]
        cmd = ("set -ex;"
               ". venv-stacklight-pytest/bin/activate;"
               "cd {tests_path}; "
               "export VOLUME_STATUS='available';"
               "pip install pytest-json;"
               "pytest --json=report.json {reruns} {reruns_delay} "
               "-k {skip_tests} {test_to_run}".format(**{
                   "tests_path": tests_path,
                   "skip_tests": ("'not " + skip_tests + "'"
                                  if skip_tests else ''),
                   "test_to_run": test_to_run,
                   "reruns": ("--reruns {}".format(reruns)
                              if reruns > 1 else ""),
                   "reruns_delay": ("--reruns-delay {}".format(reruns_delay)
                                    if reruns_delay > 0 else ""),
                   }))

        with self.__underlay.remote(node_name=target_node_name[0]) \
                as node_remote:
            LOG.debug("Run {0} on the node {1}".format(
                cmd, target_node_name[0]))
            node_remote.execute(cmd, verbose=True)
            res = node_remote.check_call('cd {0}; cat report.json'.format(
                tests_path), verbose=True)
            LOG.debug("Test execution result is {}".format(res['stdout']))
            result = json.loads(res['stdout'][0])
        return result['report']['tests']

    def download_sl_test_report(self, stored_node, file_path):
        target_node_name = [node_name for node_name
                            in self.__underlay.node_names()
                            if stored_node in node_name]
        with self.__underlay.remote(node_name=target_node_name[0]) as r:
            r.download(
                destination=file_path,
                target=os.getcwd())

    def check_docker_services(self, nodes, expected_services):
        """Check presense of the specified docker services on all the nodes
        :param nodes: list of strings, names of nodes to check
        :param expected_services: list of strings, names of services to find
        """
        for node in nodes:
            services_status = self.get_service_info_from_node(node)
            assert set(services_status) >= set(expected_services), \
                'Some services are missed on node {0}. ' \
                'Current service list: {1}\nExpected service list: {2}' \
                .format(node, services_status, expected_services)
            for service in expected_services:
                assert service in services_status,\
                    'Missing service {0} in {1}'.format(service,
                                                        services_status)
                assert '0' not in services_status.get(service),\
                    'Service {0} failed to start'.format(service)

    @decorators.retry(AssertionError, count=10, delay=5)
    def check_prometheus_targets(self, nodes):
        """Check the status for Prometheus targets
        :param nodes: list of strings, names of nodes with keepalived VIP
        """
        prometheus_client = self.api
        current_targets = prometheus_client.get_targets()

        LOG.debug('Current targets after install {0}'
                  .format(current_targets))
        # Assert that targets are up
        for entry in current_targets:
            assert 'up' in entry['health'], \
                'Next target is down {}'.format(entry)

    def kill_sl_service_on_node(self, node_sub_name, service_name):
        target_node_name = [node_name for node_name
                            in self.__underlay.node_names()
                            if node_sub_name in node_name]
        cmd = 'kill -9 $(pidof {0})'.format(service_name)
        with self.__underlay.remote(node_name=target_node_name[0]) \
                as node_remote:
            LOG.debug("Run {0} on the node {1}".format(
                cmd, target_node_name[0]))
            res = node_remote.execute(cmd)
            LOG.debug("Test execution result is {}".format(res))
            assert res['exit_code'] == 0, (
                'Unexpected exit code for command {0}, '
                'current result {1}'.format(cmd, res))

    def stop_sl_service_on_node(self, node_sub_name, service_name):
        target_node_name = [node_name for node_name
                            in self.__underlay.node_names()
                            if node_sub_name in node_name]
        cmd = 'systemctl stop {}'.format(service_name)
        with self.__underlay.remote(node_name=target_node_name[0]) \
                as node_remote:
            LOG.debug("Run {0} on the node {1}".format(
                cmd, target_node_name[0]))
            res = node_remote.execute(cmd)
            LOG.debug("Test execution result is {}".format(res))
            assert res['exit_code'] == 0, (
                'Unexpected exit code for command {0}, '
                'current result {1}'.format(cmd, res))

    def post_data_into_influx(self, node_sub_name):
        target_node_name = [node_name for node_name
                            in self.__underlay.node_names()
                            if node_sub_name in node_name]
        vip = self.get_sl_vip()
        cmd = ("curl -POST 'http://{0}:8086/write?db=lma' -u "
               "lma:lmapass --data-binary 'mymeas value=777'".format(vip))
        with self.__underlay.remote(node_name=target_node_name[0]) \
                as node_remote:
            LOG.debug("Run {0} on the node {1}".format(
                cmd, target_node_name[0]))
            res = node_remote.execute(cmd)
            assert res['exit_code'] == 0, (
                'Unexpected exit code for command {0}, '
                'current result {1}'.format(cmd, res))

    def check_data_in_influxdb(self, node_sub_name):
        target_node_name = [node_name for node_name
                            in self.__underlay.node_names()
                            if node_sub_name in node_name]
        vip = self.get_sl_vip()
        cmd = ("influx -host {0} -port 8086 -database lma  "
               "-username lma -password lmapass -execute "
               "'select * from mymeas' -precision rfc3339;".format(vip))
        with self.__underlay.remote(node_name=target_node_name[0]) \
                as node_remote:
            LOG.debug("Run {0} on the node {1}".format(
                cmd, target_node_name[0]))
            res = node_remote.execute(cmd)
            assert res['exit_code'] == 0, (
                'Unexpected exit code for command {0}, '
                'current result {1}'.format(cmd, res))
            if res['stdout']:
                return res['stdout'][0].rstrip()
            else:
                return ''

    def start_service(self, node_sub_name, service_name):
        target_node_name = [node_name for node_name
                            in self.__underlay.node_names()
                            if node_sub_name in node_name]
        cmd = 'systemctl start {0}'.format(service_name)
        with self.__underlay.remote(node_name=target_node_name[0]) \
                as node_remote:
            LOG.debug("Run {0} on the node {1}".format(
                cmd, target_node_name[0]))
            res = node_remote.execute(cmd)
            assert res['exit_code'] == 0, (
                'Unexpected exit code for command {0}, '
                'current result {1}'.format(cmd, res))
