#    Copyright 2019 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 os
import netaddr
import yaml

from devops.helpers import helpers
from devops.helpers.helpers import ssh_client
from retry import retry

from cached_property import cached_property

from heatclient import client as heatclient
from heatclient import exc as heat_exceptions
from heatclient.common import template_utils
from keystoneauth1.identity import v3 as keystone_v3
from keystoneauth1 import session as keystone_session

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning

from oslo_config import cfg
from paramiko.ssh_exception import (
    AuthenticationException,
    BadAuthenticationType)

from tcp_tests import settings
from tcp_tests import settings_oslo
from tcp_tests.helpers import exceptions
from tcp_tests import logger

LOG = logger.logger

EXPECTED_STACK_STATUS = "CREATE_COMPLETE"
BAD_STACK_STATUSES = ["CREATE_FAILED", "DELETE_FAILED"]

# Disable multiple notifications like:
# "InsecureRequestWarning: Unverified HTTPS request is being made."
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


class EnvironmentManagerHeat(object):
    """Class-helper for creating VMs via devops environments"""

    __config = None

    # Do not use self.__heatclient directly! Use properties
    # for necessary resources with catching HTTPUnauthorized exception
    __heatclient = None

    def __init__(self, config=None):
        """Create/connect to the Heat stack with test environment

        :param config: oslo.config object
        :param config.hardware.heat_version: Heat version
        :param config.hardware.os_auth_url: OS auth URL to access heat
        :param config.hardware.os_username: OS username
        :param config.hardware.os_password: OS password
        :param config.hardware.os_project_name: OS tenant name
        """
        self.__config = config

        if not self.__config.hardware.heat_stack_name:
            self.__config.hardware.heat_stack_name = settings.ENV_NAME

        self.__init_heatclient()

        try:
            stack_status = self._current_stack.stack_status
            if stack_status != EXPECTED_STACK_STATUS:
                raise exceptions.EnvironmentWrongStatus(
                    self.__config.hardware.heat_stack_name,
                    EXPECTED_STACK_STATUS,
                    stack_status
                )
            LOG.info("Heat stack '{0}' already exists".format(
                self.__config.hardware.heat_stack_name))
        except heat_exceptions.HTTPNotFound:
            self._create_environment()
            LOG.info("Heat stack '{0}' created".format(
                self.__config.hardware.heat_stack_name))

        self.set_address_pools_config()
        self.set_dhcp_ranges_config()

    @cached_property
    def _keystone_session(self):
        keystone_auth = keystone_v3.Password(
            auth_url=settings.OS_AUTH_URL,
            username=settings.OS_USERNAME,
            password=settings.OS_PASSWORD,
            project_name=settings.OS_PROJECT_NAME,
            user_domain_name=settings.OS_USER_DOMAIN_NAME,
            project_domain_name='Default')
        return keystone_session.Session(auth=keystone_auth, verify=False)

    def __init_heatclient(self):
        token = self._keystone_session.get_token()
        endpoint_url = self._keystone_session.get_endpoint(
            service_type='orchestration', endpoint_type='publicURL')
        self.__heatclient = heatclient.Client(
            version=settings.OS_HEAT_VERSION, endpoint=endpoint_url,
            token=token, insecure=True)

    @property
    def _current_stack(self):
        return self.__stacks.get(
            self.__config.hardware.heat_stack_name)

    @property
    def __stacks(self):
        try:
            return self.__heatclient.stacks
        except heat_exceptions.HTTPUnauthorized:
            LOG.warning("Authorization token outdated, refreshing")
            self.__init_heatclient()
            return self.__heatclient.stacks

    @property
    def __resources(self):
        try:
            return self.__heatclient.resources
        except heat_exceptions.HTTPUnauthorized:
            LOG.warning("Authorization token outdated, refreshing")
            self.__init_heatclient()
            return self.__heatclient.resources

    def __get_stack_parent(self, stack_id, stacks):
        """Find the parent ID of the specified stack_id in the 'stacks' list"""
        for stack in stacks:
            if stack_id == stack.id:
                if stack.parent:
                    return self.__get_stack_parent(stack.parent, stacks)
                else:
                    return stack.id
        raise Exception("stack with ID {} not found!".format(stack_id))

    @property
    def __nested_resources(self):
        resources = []
        stacks = [s for s in self.__stacks.list(show_nested=True)]
        current_stack_id = self._current_stack.id
        for stack in stacks:
            parent_stack_id = self.__get_stack_parent(stack.id, stacks)
            if parent_stack_id == current_stack_id:
                # Add resources to list
                LOG.info("Get resources from stack {0}"
                         .format(stack.stack_name))
                resources.extend([
                    res for res in self.__resources.list(stack.id)
                ])
        LOG.info("Found {0} resources".format(len(resources)))
        return resources

    def _get_resources_by_type(self, resource_type):
        res = []
        for item in self.__nested_resources:
            if item.resource_type == resource_type:
                resource = self.__resources.get(
                    item.stack_name,
                    item.resource_name)
                res.append(resource)
        return res

    @cached_property
    def _nodes(self):
        """Get list of nodenames from heat

        Returns list of dicts.
        Example:
        - name: cfg01
          roles:
          - salt_master
          addresses:  # Optional. May be an empty dict
            admin-pool01: p.p.p.202
        - name: ctl01
          roles:
          - salt_minion
          - openstack_controller
          - openstack_messaging
          - openstack_database
          addresses: {} # Optional. May be an empty dict

        'name': taken from heat template resource's ['name'] parameter
        'roles': a list taken from resource's ['metadata']['roles'] parameter
        """
        address_pools = self._address_pools
        nodes = []
        for heat_node in self._get_resources_by_type("OS::Nova::Server"):
            # addresses will have the following dict structure:
            #   {'admin-pool01': <floating_ip1>,
            #    'private-pool01': <floating_ip2>,
            #    'external-pool01': <floating_ip3>
            #   }
            # , where key is one of roles from OS::Neutron::Subnet,
            # and value is a floating IP associated to the fixed IP
            # in this subnet (if exists).
            # If no floating IPs associated to the server,
            # then addresses will be an empty list.
            addresses = {}
            for network in heat_node.attributes['addresses']:
                fixed = None
                floating = None
                for address in heat_node.attributes['addresses'][network]:
                    addr_type = address['OS-EXT-IPS:type']
                    if addr_type == 'fixed':
                        fixed = address['addr']
                    elif addr_type == 'floating':
                        floating = address['addr']
                    else:
                        LOG.error("Unexpected OS-EXT-IPS:type={0} "
                                  "in node '{1}' for network '{2}'"
                                  .format(addr_type,
                                          heat_node.attributes['name'],
                                          network))
                if fixed is None and floating is None:
                    LOG.error("Unable to determine the correct IP address "
                              "in node '{0}' for network '{1}'"
                              .format(heat_node.attributes['name'], network))
                    continue
                # Check which address pool has the fixed address, and set
                # the floating address as the access to this address pool.
                for address_pool in address_pools:
                    pool_net = netaddr.IPNetwork(address_pool['cidr'])
                    if fixed in pool_net:
                        for role in address_pool['roles']:
                            # addresses[role] = floating
                            # Use fixed addresses for SSH access
                            addresses[role] = fixed
            if 'metadata' not in heat_node.attributes or \
                    'roles' not in heat_node.attributes['metadata']:
                raise Exception("Node {} doesn't have metadata:roles:[...,...]"
                                .format(heat_node.attributes['name']))

            nodes.append({
                'name': heat_node.attributes['name'],
                'roles': yaml.load(heat_node.attributes['metadata']['roles']),
                'addresses': addresses,
            })
        return nodes

    @cached_property
    def _address_pools(self):
        """Get address pools from subnets OS::Neutron::Subnet

        Returns list of dicts.
        Example:
        - roles:
          - admin-pool01
          cidr: x.x.x.x/y
          start: x.x.x.2
          end: x.x.x.254
          gateway: x.x.x.1 # or None
        """
        pools = []
        for heat_subnet in self._get_resources_by_type("OS::Neutron::Subnet"):
            pools.append({
                'roles': heat_subnet.attributes['tags'],
                'cidr': heat_subnet.attributes['cidr'],
                'gateway': heat_subnet.attributes['gateway_ip'],
                'start': heat_subnet.attributes[
                    'allocation_pools'][0]['start'],
                'end': heat_subnet.attributes['allocation_pools'][0]['end'],
            })
        return pools

    def _get_nodes_by_roles(self, roles=None):
        nodes = []
        if roles is None:
            return self._nodes

        for node in self._nodes:
            if set(node['roles']).intersection(set(roles)):
                nodes.append(node)
        return nodes

    def get_ssh_data(self, roles=None):
        """Generate ssh config for Underlay

        :param roles: list of strings
        """
        if roles is None:
            raise Exception("No roles specified for the environment!")

        config_ssh = []
        for d_node in self._get_nodes_by_roles(roles=roles):
            for pool_name in d_node['addresses']:
                ssh_data = {
                    'node_name': d_node['name'],
                    'minion_id': d_node['name'],
                    'roles': d_node['roles'],
                    'address_pool': pool_name,
                    'host': d_node['addresses'][pool_name],
                    'login': settings.SSH_NODE_CREDENTIALS['login'],
                    'password': settings.SSH_NODE_CREDENTIALS['password'],
                    'keys': [k['private']
                             for k in self.__config.underlay.ssh_keys]
                }
            config_ssh.append(ssh_data)
        return config_ssh

    def _get_resources_with_wrong_status(self):
        res = []
        for item in self.__nested_resources:
            if item.resource_status in BAD_STACK_STATUSES:
                res.append({
                    'resource_name': item.resource_name,
                    'resource_status': item.resource_status,
                    'resource_status_reason': item.resource_status_reason,
                    'resource_type': item.resource_type
                })
        wrong_resources = '\n'.join([
            "*** Heat stack resource '{0}' ({1}) has wrong status '{2}': {3}"
            .format(item['resource_name'],
                    item['resource_type'],
                    item['resource_status'],
                    item['resource_status_reason'])
            for item in res
        ])
        return wrong_resources

    def wait_of_stack_status(self, status, delay=30, tries=60,
                             wait_for_delete=False):

        @retry(exceptions.EnvironmentWrongStatus, delay=delay, tries=tries)
        def wait():
            try:
                st = self._current_stack.stack_status
            except heat_exceptions.HTTPNotFound as ex:
                if wait_for_delete is True:
                    return
                raise ex
            if st == status:
                return
            elif st in BAD_STACK_STATUSES:
                wrong_resources = self._get_resources_with_wrong_status()
                raise exceptions.EnvironmentBadStatus(
                    self.__config.hardware.heat_stack_name,
                    status,
                    st,
                    wrong_resources
                )
            else:
                LOG.info("Stack {0} status: {1}".format(
                    self.__config.hardware.heat_stack_name, st))
                raise exceptions.EnvironmentWrongStatus(
                    self.__config.hardware.heat_stack_name,
                    status,
                    st
                )
        LOG.info("Waiting for stack '{0}' status <{1}>".format(
            self.__config.hardware.heat_stack_name, status))
        wait()

    def revert_snapshot(self, name):
        """Revert snapshot by name

        - Revert the heat snapshot in the environment
        - Try to reload 'config' object from a file 'config_<name>.ini'
          If the file not found, then pass with defaults.
        - Set <name> as the current state of the environment after reload

        :param name: string
        """
        LOG.info("Reading INI config (without reverting env to snapshot) "
                 "named '{0}'".format(name))

        try:
            test_config_path = self._get_snapshot_config_name(name)
            settings_oslo.reload_snapshot_config(self.__config,
                                                 test_config_path)
        except cfg.ConfigFilesNotFoundError as conf_err:
            LOG.error("Config file(s) {0} not found!".format(
                conf_err.config_files))

        self.__config.hardware.current_snapshot = name

    def create_snapshot(self, name, *args, **kwargs):
        """Create named snapshot of current env.

        - Create a snapshot for the environment
        - Save 'config' object to a file 'config_<name>.ini'

        :name: string
        """
        if not settings.MAKE_SNAPSHOT_STAGES:
            msg = ("[ SKIP snapshot '{0}' because MAKE_SNAPSHOT_STAGES=false ]"
                   .format(name))
            LOG.info("\n\n{0}\n{1}".format(msg, '*' * len(msg)))
            return

        LOG.info("Store INI config (without env snapshot) named '{0}'"
                 .format(name))
        self.__config.hardware.current_snapshot = name
        settings_oslo.save_config(self.__config,
                                  name,
                                  self.__config.hardware.heat_stack_name)

    def _get_snapshot_config_name(self, snapshot_name):
        """Get config name for the environment"""
        env_name = self.__config.hardware.heat_stack_name
        if env_name is None:
            env_name = 'config'
        test_config_path = os.path.join(
            settings.LOGS_DIR, '{0}_{1}.ini'.format(env_name, snapshot_name))
        return test_config_path

    def has_snapshot(self, name):
        # Heat doesn't support live snapshots, so just
        # check if an INI file was created for this environment,
        # assuming that the environment has the configuration
        # described in this INI.
        return self.has_snapshot_config(name)

    def has_snapshot_config(self, name):
        test_config_path = self._get_snapshot_config_name(name)
        return os.path.isfile(test_config_path)

    def start(self, underlay_node_roles, timeout=480):
        """Start environment"""
        LOG.warning("HEAT Manager doesn't support start environment feature. "
                    "Waiting for finish the bootstrap process on the nodes "
                    "with accessible SSH")

        check_cloudinit_started = '[ -f /is_cloud_init_started ]'
        check_cloudinit_finished = ('[ -f /is_cloud_init_finished ] || '
                                    '[ -f /var/log/mcp/.bootstrap_done ]')
        check_cloudinit_failed = 'cat /is_cloud_init_failed'
        passed = {}
        for node in self._get_nodes_by_roles(roles=underlay_node_roles):

            try:
                node_ip = self.node_ip(node)
            except exceptions.EnvironmentNodeAccessError:
                LOG.warning("Node {0} doesn't have accessible IP address"
                            ", skipping".format(node['name']))
                continue

            LOG.info("Waiting for SSH on node '{0}' / {1} ...".format(
                node['name'], node_ip))

            def _ssh_check(host,
                           port,
                           username=settings.SSH_NODE_CREDENTIALS['login'],
                           password=settings.SSH_NODE_CREDENTIALS['password'],
                           timeout=0):
                try:
                    ssh = ssh_client.SSHClient(
                        host=host, port=port,
                        auth=ssh_client.SSHAuth(
                            username=username,
                            password=password))

                    # If '/is_cloud_init_started' exists, then wait for
                    # the flag /is_cloud_init_finished
                    if ssh.execute(check_cloudinit_started)['exit_code'] == 0:
                        result = ssh.execute(check_cloudinit_failed)
                        if result['exit_code'] == 0:
                            raise exceptions.EnvironmentNodeIsNotStarted(
                                "{0}:{1}".format(host, port),
                                result.stdout_str)

                        status = ssh.execute(
                            check_cloudinit_finished)['exit_code'] == 0
                    # Else, just wait for SSH
                    else:
                        status = ssh.execute('echo ok')['exit_code'] == 0
                    return status

                except (AuthenticationException, BadAuthenticationType):
                    return True
                except Exception:
                    return False

            def _ssh_wait(host,
                          port,
                          username=settings.SSH_NODE_CREDENTIALS['login'],
                          password=settings.SSH_NODE_CREDENTIALS['password'],
                          timeout=0):

                if host in passed and passed[host] >= 2:
                    # host already passed the check
                    return True

                for node in self._get_nodes_by_roles(
                        roles=underlay_node_roles):
                    ip = node_ip
                    if ip not in passed:
                        passed[ip] = 0
                    if _ssh_check(ip, port):
                        passed[ip] += 1
                    else:
                        passed[ip] = 0

            helpers.wait(
                lambda: _ssh_wait(node_ip, 22),
                timeout=timeout,
                timeout_msg="Node '{}' didn't open SSH in {} sec".format(
                    node['name'], timeout
                )
            )
        LOG.info('Heat stack "{0}" ready'
                 .format(self.__config.hardware.heat_stack_name))

    def _verify_resources_status(self, status):
        """Check that all resources have verified `status`

        In case when all resources have expected status return empty list,
            otherwise return a list with resources with incorrect status.
        """
        ret = [r for r in self.__nested_resources if
               r.resource_status != status]
        return ret

    def _create_environment(self):
        tpl_files, template = template_utils.get_template_contents(
            self.__config.hardware.heat_conf_path)
        env_files_list = []
        env_files, env = (
            template_utils.process_multiple_environments_and_files(
                env_paths=[self.__config.hardware.heat_env_path],
                env_list_tracker=env_files_list))

        fields = {
            'stack_name': self.__config.hardware.heat_stack_name,
            'template': template,
            'files': dict(list(tpl_files.items()) + list(env_files.items())),
            'environment': env,
            'parameters': {
                'mcp_version': settings.MCP_VERSION,
                'env_name': settings.ENV_NAME,
            }
        }

        if env_files_list:
            fields['environment_files'] = env_files_list

        @retry(heat_exceptions.HTTPBadGateway, delay=15, tries=20)
        def safe_heat_stack_create():
            self.__stacks.create(**fields)

        @retry(exceptions.EnvironmentBadStatus, delay=60, tries=3)
        def safe_create():
            self.delete_environment()
            safe_heat_stack_create()
            self.wait_of_stack_status(EXPECTED_STACK_STATUS, tries=140)
            LOG.info("Stack '%s' created",
                     self.__config.hardware.heat_stack_name)
            incorrect_resources = self._verify_resources_status(
                EXPECTED_STACK_STATUS)
            if incorrect_resources:
                LOG.info("Recreate the stack because some resources have "
                         "incorrect status")
                for r in incorrect_resources:
                    LOG.error(
                        'The resource %s has status %s. But it should be %s',
                        r.resource_name,
                        r.resource_status,
                        EXPECTED_STACK_STATUS)
                st = self._current_stack.stack_status
                raise exceptions.EnvironmentBadStatus(
                    self.__config.hardware.heat_stack_name,
                    EXPECTED_STACK_STATUS,
                    st,
                    incorrect_resources)
        safe_create()

    def stop(self):
        """Stop environment"""
        LOG.warning("HEAT Manager doesn't support stop environment feature")
        pass

    def delete_environment(self):
        if list(self.__stacks.list(
                    stack_name=self.__config.hardware.heat_stack_name)):
            LOG.info("Delete stack '%s'",
                     self.__config.hardware.heat_stack_name)

            @retry(heat_exceptions.HTTPBadGateway, delay=15, tries=20)
            def safe_heat_stack_delete():
                self.__stacks.delete(self._current_stack.id)

            safe_heat_stack_delete()
            self.wait_of_stack_status('DELETE_COMPLETE',
                                      delay=30, tries=20,
                                      wait_for_delete=True)
        else:
            LOG.warning("Can't delete stack '%s' due is absent",
                        self.__config.hardware.heat_stack_name)

# TODO(ddmitriev): add all Environment methods
    @staticmethod
    def node_ip(node, address_pool_name='admin-pool01'):
        """Determine node's IP

        :param node: a dict element from the self._nodes
        :return: string
        """
        if address_pool_name in node['addresses']:
            addr = node['addresses'][address_pool_name]
            LOG.debug('{0} IP= {1}'.format(node['name'], addr))
            return addr
        else:
            raise exceptions.EnvironmentNodeAccessError(
                node['name'],
                "No addresses available for the subnet {0}"
                .format(address_pool_name))

    def set_address_pools_config(self):
        """Store address pools CIDRs in config object"""
        for ap in self._address_pools:
            for role in ap['roles']:
                self.__config.underlay.address_pools[role] = ap['cidr']

    def set_dhcp_ranges_config(self):
        """Store DHCP ranges in config object"""
        for ap in self._address_pools:
            for role in ap['roles']:
                self.__config.underlay.dhcp_ranges[role] = {
                    "cidr": ap['cidr'],
                    "start": ap['start'],
                    "end": ap['end'],
                    "gateway": ap['gateway'],
                }

    def wait_for_node_state(self, node_name, state, timeout):
        raise NotImplementedError()

    def warm_shutdown_nodes(self, underlay, nodes_prefix, timeout=600):
        raise NotImplementedError()

    def warm_restart_nodes(self, underlay, nodes_prefix, timeout=600):
        raise NotImplementedError()

    @property
    def slave_nodes(self):
        raise NotImplementedError()
