Merge "Add handling for inherited stress attributes"
diff --git a/tempest/stress/run_stress.py b/tempest/stress/run_stress.py
index aab2afd..886d94b 100755
--- a/tempest/stress/run_stress.py
+++ b/tempest/stress/run_stress.py
@@ -17,16 +17,16 @@
 #    limitations under the License.
 
 import argparse
+import inspect
 import json
 import sys
 from testtools.testsuite import iterate_tests
 from unittest import loader
 
 
-def discover_stress_tests(path="./", filter_attr=None):
+def discover_stress_tests(path="./", filter_attr=None, call_inherited=False):
     """Discovers all tempest tests and create action out of them
     """
-
     tests = []
     testloader = loader.TestLoader()
     list = testloader.discover(path)
@@ -52,6 +52,11 @@
                                  "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
 
@@ -63,7 +68,8 @@
     if not ns.all:
         tests = json.load(open(ns.tests, 'r'))
     else:
-        tests = discover_stress_tests(filter_attr=ns.type)
+        tests = discover_stress_tests(filter_attr=ns.type,
+                                      call_inherited=ns.call_inherited)
 
     if ns.serial:
         for test in tests:
@@ -79,22 +85,25 @@
     return result
 
 
-parser = argparse.ArgumentParser(description='Run stress tests. ')
+parser = argparse.ArgumentParser(description='Run stress tests')
 parser.add_argument('-d', '--duration', default=300, type=int,
-                    help="Duration of test in secs.")
+                    help="Duration of test in secs")
 parser.add_argument('-s', '--serial', action='store_true',
-                    help="Trigger running tests serially.")
+                    help="Trigger running tests serially")
 parser.add_argument('-S', '--stop', action='store_true',
-                    default=False, help="Stop on first error.")
+                    default=False, help="Stop on first error")
 parser.add_argument('-n', '--number', type=int,
-                    help="How often an action is executed for each process.")
+                    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.")
+                   help="Name of the file with test description")
 
 if __name__ == "__main__":
     sys.exit(main(parser.parse_args()))
diff --git a/tempest/test.py b/tempest/test.py
index ca626da..decae94 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -67,12 +67,17 @@
            ``application``: once in the stress job lifetime
            ``process``: once in the worker process lifetime
            ``action``: on each action
+    @param allow_inheritance: allows inheritance of this attribute
     """
     def decorator(f):
         if 'class_setup_per' in kwargs:
             setattr(f, "st_class_setup_per", kwargs['class_setup_per'])
         else:
             setattr(f, "st_class_setup_per", 'process')
+        if 'allow_inheritance' in kwargs:
+            setattr(f, "st_allow_inheritance", kwargs['allow_inheritance'])
+        else:
+            setattr(f, "st_allow_inheritance", False)
         attr(type='stress')(f)
         return f
     return decorator