#!/usr/bin/env python

# Copyright 2013 Quanta Research Cambridge, 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 argparse
import inspect
import sys
try:
    from unittest import loader
except ImportError:
    # unittest in python 2.6 does not contain loader, so uses unittest2
    from unittest2 import loader
import traceback
import warnings

from cliff import command
from oslo_log import log as logging
from oslo_serialization import jsonutils as json
from testtools import testsuite

from tempest.stress import driver

LOG = logging.getLogger(__name__)


def discover_stress_tests(path="./", filter_attr=None, call_inherited=False):
    """Discovers all tempest tests and create action out of them"""
    LOG.info("Start test discovery")
    tests = []
    testloader = loader.TestLoader()
    list = testloader.discover(path)
    for func in (testsuite.iterate_tests(list)):
        attrs = []
        try:
            method_name = getattr(func, '_testMethodName')
            full_name = "%s.%s.%s" % (func.__module__,
                                      func.__class__.__name__,
                                      method_name)
            test_func = getattr(func, method_name)
            # NOTE(mkoderer): this contains a list of all type attributes
            attrs = getattr(test_func, "__testtools_attrs")
        except Exception:
            next
        if 'stress' in attrs:
            if filter_attr is not None and filter_attr not in attrs:
                continue
            class_setup_per = getattr(test_func, "st_class_setup_per")

            action = {'action':
                      "tempest.stress.actions.unit_test.UnitTest",
                      'kwargs': {"test_method": full_name,
                                 "class_setup_per": class_setup_per
                                 }
                      }
            if (not call_inherited and
                getattr(test_func, "st_allow_inheritance") is not True):
                class_structure = inspect.getmro(test_func.im_class)
                if test_func.__name__ not in class_structure[0].__dict__:
                    continue
            tests.append(action)
    return tests


class TempestRunStress(command.Command):

    @staticmethod
    def display_deprecation_warning():
        warnings.simplefilter('once', category=DeprecationWarning)
        warnings.warn(
            'Stress tests are deprecated and will be removed from Tempest '
            'in the Newton release.',
            DeprecationWarning)
        warnings.resetwarnings()

    def get_parser(self, prog_name):
        self.display_deprecation_warning()
        pa = super(TempestRunStress, self).get_parser(prog_name)
        pa = add_arguments(pa)
        return pa

    def take_action(self, pa):
        try:
            action(pa)
        except Exception:
            LOG.exception("Failure in the stress test framework")
            traceback.print_exc()
            raise

    def get_description(self):
        return 'Run tempest stress tests'


def add_arguments(parser):
    parser.add_argument('-d', '--duration', default=300, type=int,
                        help="Duration of test in secs")
    parser.add_argument('-s', '--serial', action='store_true',
                        help="Trigger running tests serially")
    parser.add_argument('-S', '--stop', action='store_true',
                        default=False, help="Stop on first error")
    parser.add_argument('-n', '--number', type=int,
                        help="How often an action is executed for each "
                        "process")
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-a', '--all', action='store_true',
                       help="Execute all stress tests")
    parser.add_argument('-T', '--type',
                        help="Filters tests of a certain type (e.g. gate)")
    parser.add_argument('-i', '--call-inherited', action='store_true',
                        default=False,
                        help="Call also inherited function with stress "
                        "attribute")
    group.add_argument('-t', "--tests", nargs='?',
                       help="Name of the file with test description")
    return parser


def action(ns):
    result = 0
    if not ns.all:
        tests = json.load(open(ns.tests, 'r'))
    else:
        tests = discover_stress_tests(filter_attr=ns.type,
                                      call_inherited=ns.call_inherited)

    if ns.serial:
        # Duration is total time
        duration = ns.duration / len(tests)
        for test in tests:
            step_result = driver.stress_openstack([test],
                                                  duration,
                                                  ns.number,
                                                  ns.stop)
            # NOTE(mkoderer): we just save the last result code
            if (step_result != 0):
                result = step_result
                if ns.stop:
                    return result
    else:
        result = driver.stress_openstack(tests,
                                         ns.duration,
                                         ns.number,
                                         ns.stop)
    return result


def main():
    TempestRunStress.display_deprecation_warning()
    parser = argparse.ArgumentParser(description='Run stress tests')
    pa = add_arguments(parser)
    ns = pa.parse_args()
    return action(ns)


if __name__ == "__main__":
    try:
        sys.exit(main())
    except Exception:
        LOG.exception("Failure in the stress test framework")
        traceback.print_exc()
        sys.exit(1)
