Merge "Create discovery option for stress tests"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 703d92a..d39ef70 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -390,3 +390,11 @@
heat = false
# Whether or not horizon is expected to be available
horizon = True
+
+[stress]
+# Maximum number of instances to create during test
+max_instances = 32
+# Time (in seconds) between log file error checks
+log_check_interval = 60
+# The default number of threads created while stress test
+default_thread_number_per_action=4
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 2a1e2c4..9fa86b6 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -18,6 +18,7 @@
from tempest.api.volume.base import BaseVolumeTest
from tempest.common.utils.data_utils import rand_name
from tempest.test import attr
+from tempest.test import stresstest
class VolumesActionsTest(BaseVolumeTest):
@@ -52,6 +53,7 @@
super(VolumesActionsTest, cls).tearDownClass()
+ @stresstest(class_setup_per='process')
@attr(type='smoke')
def test_attach_detach_volume_to_instance(self):
# Volume is attached and detached successfully from an instance
@@ -65,6 +67,7 @@
self.assertEqual(202, resp.status)
self.client.wait_for_volume_status(self.volume['id'], 'available')
+ @stresstest(class_setup_per='process')
@attr(type='gate')
def test_get_volume_attachment(self):
# Verify that a volume's attachment information is retrieved
diff --git a/tempest/config.py b/tempest/config.py
index e0ac843..3b09b5e 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -519,7 +519,10 @@
help='regexp for list of log files.'),
cfg.StrOpt('log_check_interval',
default=60,
- help='time between log file error checks.')
+ help='time (in seconds) between log file error checks.'),
+ cfg.StrOpt('default_thread_number_per_action',
+ default=4,
+ help='The number of threads created while stress test.')
]
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index efc57a9..5171da2 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -102,6 +102,8 @@
"""
logfiles = admin_manager.config.stress.target_logfiles
log_check_interval = int(admin_manager.config.stress.log_check_interval)
+ default_thread_num = int(admin_manager.config.stress.
+ default_thread_number_per_action)
if logfiles:
controller = admin_manager.config.stress.target_controller
computes = _get_compute_nodes(controller)
@@ -112,7 +114,7 @@
manager = admin_manager
else:
manager = clients.Manager()
- for p_number in xrange(test.get('threads', 1)):
+ for p_number in xrange(test.get('threads', default_thread_num)):
if test.get('use_isolated_tenants', False):
username = rand_name("stress_user")
tenant_name = rand_name("stress_tenant")
diff --git a/tempest/stress/run_stress.py b/tempest/stress/run_stress.py
index 32e3ae0..aab2afd 100755
--- a/tempest/stress/run_stress.py
+++ b/tempest/stress/run_stress.py
@@ -19,13 +19,52 @@
import argparse
import json
import sys
+from testtools.testsuite import iterate_tests
+from unittest import loader
+
+
+def discover_stress_tests(path="./", filter_attr=None):
+ """Discovers all tempest tests and create action out of them
+ """
+
+ tests = []
+ testloader = loader.TestLoader()
+ list = testloader.discover(path)
+ for func in (iterate_tests(list)):
+ 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 not filter_attr 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
+ }
+ }
+ tests.append(action)
+ return tests
def main(ns):
# NOTE(mkoderer): moved import to make "-h" possible without OpenStack
from tempest.stress import driver
result = 0
- tests = json.load(open(ns.tests, 'r'))
+ if not ns.all:
+ tests = json.load(open(ns.tests, 'r'))
+ else:
+ tests = discover_stress_tests(filter_attr=ns.type)
+
if ns.serial:
for test in tests:
step_result = driver.stress_openstack([test],
@@ -49,7 +88,13 @@
default=False, help="Stop on first error.")
parser.add_argument('-n', '--number', type=int,
help="How often an action is executed for each process.")
-parser.add_argument('tests', help="Name of the file with test description.")
+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)")
+group.add_argument('-t', "--tests", nargs='?',
+ help="Name of the file with test description.")
if __name__ == "__main__":
sys.exit(main(parser.parse_args()))
diff --git a/tempest/stress/stressaction.py b/tempest/stress/stressaction.py
index 3719841..6284cef 100644
--- a/tempest/stress/stressaction.py
+++ b/tempest/stress/stressaction.py
@@ -60,6 +60,8 @@
while self.max_runs is None or (shared_statistic['runs'] <
self.max_runs):
+ self.logger.debug("Trigger new run (run %d)" %
+ shared_statistic['runs'])
try:
self.run()
except Exception:
diff --git a/tempest/test.py b/tempest/test.py
index 68cedf0..8b3cfa6 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -57,6 +57,27 @@
return decorator
+def stresstest(*args, **kwargs):
+ """Add stress test decorator
+
+ For all functions with this decorator a attr stress will be
+ set automatically.
+
+ @param class_setup_per: allowed values are application, process, action
+ ``application``: once in the stress job lifetime
+ ``process``: once in the worker process lifetime
+ ``action``: on each action
+ """
+ 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')
+ attr(type='stress')(f)
+ return f
+ return decorator
+
+
# there is a mis-match between nose and testtools for older pythons.
# testtools will set skipException to be either
# unittest.case.SkipTest, unittest2.case.SkipTest or an internal skip
diff --git a/tox.ini b/tox.ini
index a101a9e..c60e19e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -78,7 +78,7 @@
sitepackages = True
setenv = VIRTUAL_ENV={envdir}
commands =
- python -m tempest/stress/run_stress tempest/stress/etc/stress-tox-job.json -d 3600
+ python -m tempest/stress/run_stress -a -d 3600
[testenv:venv]
commands = {posargs}