#    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 datetime
import json

from junit_xml import TestSuite, TestCase

from tcp_tests import logger
from tcp_tests import settings


LOG = logger.logger


class RallyManager(object):
    """docstring for RallyManager"""

    image_name = 'rallyforge/rally'
    image_version = '0.5.0'

    def __init__(self, underlay, admin_host):
        super(RallyManager, self).__init__()
        self._admin_host = admin_host
        self._underlay = underlay

    def prepare(self):
        content = """
sed -i 's|#swift_operator_role = Member|swift_operator_role=SwiftOperator|g' /etc/rally/rally.conf  # noqa
source /home/rally/openrc
rally-manage db recreate
rally deployment create --fromenv --name=tempest
rally verify install
rally verify genconfig
rally verify showconfig"""
        cmd = "cat > {path} << EOF\n{content}\nEOF".format(
            path='/root/rally/install_tempest.sh', content=content)
        cmd1 = "chmod +x /root/rally/install_tempest.sh"
        cmd2 = "scp ctl01:/root/keystonerc /root/rally/openrc"

        with self._underlay.remote(host=self._admin_host) as remote:
            LOG.info("Create rally workdir")
            remote.check_call('mkdir -p /root/rally')
            LOG.info("Create install_tempest.sh")
            remote.check_call(cmd)
            LOG.info("Chmod +x install_tempest.sh")
            remote.check_call(cmd1)
            LOG.info("Copy openstackrc")
            remote.check_call(cmd2)

    def pull_image(self, version=None):
        version = version or self.image_version
        image = self.image_name
        cmd = ("apt-get -y install docker.io &&"
               " docker pull {image}:{version}".format(image=image,
                                                       version=version))
        with self._underlay.remote(host=self._admin_host) as remote:
            LOG.info("Pull {image}:{version}".format(image=image,
                                                     version=version))
            remote.check_call(cmd)

        with self._underlay.remote(host=self._admin_host) as remote:
            LOG.info("Getting image id")
            cmd = "docker images | grep 0.5.0| awk '{print $3}'"
            res = remote.check_call(cmd)
            self.image_id = res['stdout'][0].strip()
            LOG.info("Image ID is {}".format(self.image_id))

    def run(self):
        with self._underlay.remote(host=self._admin_host) as remote:
            cmd = ("docker run --net host -v /root/rally:/home/rally "
                   "-tid -u root {image_id}".format(image_id=self.image_id))
            LOG.info("Run Rally container")
            remote.check_call(cmd)

            cmd = ("docker ps | grep {image_id} | "
                   "awk '{{print $1}}'| head -1").format(
                       image_id=self.image_id)
            LOG.info("Getting container id")
            res = remote.check_call(cmd)
            self.docker_id = res['stdout'][0].strip()
            LOG.info("Container ID is {}".format(self.docker_id))

    def run_tempest(self, test=''):
        docker_exec = ('source /root/rally/openrc; '
                       'docker exec -i {docker_id} bash -c "{cmd}"')
        commands = [
            docker_exec.format(cmd="./install_tempest.sh",
                               docker_id=self.docker_id),
            docker_exec.format(
                cmd="source /home/rally/openrc && "
                    "rally verify start {test}".format(test=test),
                docker_id=self.docker_id),
            docker_exec.format(
                cmd="rally verify results --json --output-file result.json",
                docker_id=self.docker_id),
            docker_exec.format(
                cmd="rally verify results --html --output-file result.html",
                docker_id=self.docker_id),
        ]
        with self._underlay.remote(host=self._admin_host) as remote:
            LOG.info("Run tempest inside Rally container")
            for cmd in commands:
                remote.check_call(cmd, verbose=True)

    def get_results(self, store=True, store_file='tempest.xml'):
        LOG.info('Storing tests results...')
        res_file_name = 'result.json'
        file_prefix = 'results_' + datetime.datetime.now().strftime(
            '%Y%m%d_%H%M%S') + '_'
        file_dst = '{0}/logs/{1}{2}'.format(
            settings.LOGS_DIR, file_prefix, res_file_name)
        with self._underlay.remote(host=self._admin_host) as remote:
            remote.download(
                '/root/rally/{1}'.format(res_file_name),
                file_dst)
            res = json.load(remote.open('/root/rally/result.json'))
        if not store:
            return res

        formatted_tc = []
        failed_cases = [res['test_cases'][case]
                        for case in res['test_cases']
                        if res['test_cases'][case]['status']
                        in 'fail']
        for case in failed_cases:
            if case:
                tc = TestCase(case['name'])
                tc.add_failure_info(case['traceback'])
                formatted_tc.append(tc)

        skipped_cases = [res['test_cases'][case]
                         for case in res['test_cases']
                         if res['test_cases'][case]['status'] in 'skip']
        for case in skipped_cases:
            if case:
                tc = TestCase(case['name'])
                tc.add_skipped_info(case['reason'])
                formatted_tc.append(tc)

        error_cases = [res['test_cases'][case] for case in res['test_cases']
                       if res['test_cases'][case]['status'] in 'error']

        for case in error_cases:
            if case:
                tc = TestCase(case['name'])
                tc.add_error_info(case['traceback'])
                formatted_tc.append(tc)

        success = [res['test_cases'][case] for case in res['test_cases']
                   if res['test_cases'][case]['status'] in 'success']
        for case in success:
            if case:
                tc = TestCase(case['name'])
                formatted_tc.append(tc)

        ts = TestSuite("tempest", formatted_tc)
        with open(store_file, 'w') as f:
            ts.to_file(f, [ts], prettyprint=False)

        return res
