blob: 039afa18b53b7168ddcd5f1d490255a95ad01ef0 [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2012 OpenStack Foundation
Jay Pipes051075a2012-04-28 17:39:37 -04002# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
Attila Fazekasf86fa312013-07-30 19:56:39 +020016import atexit
Masayuki Igawa80c1b9f2013-10-07 17:19:11 +090017import functools
Ian Wienand98c35f32013-07-23 20:34:23 +100018import os
Attila Fazekas53943322014-02-10 16:07:34 +010019import sys
Jay Pipes051075a2012-04-28 17:39:37 -040020
Jordan Pittier35a63752016-08-30 13:09:12 +020021import debtcollector.moves
Matthew Treinish78561ad2013-07-26 11:41:56 -040022import fixtures
Doug Hellmann583ce2c2015-03-11 14:55:46 +000023from oslo_log import log as logging
Chris Hoge296558c2015-02-19 00:29:49 -060024import six
ivan-zhu1feeb382013-01-24 10:14:39 +080025import testtools
Jay Pipes051075a2012-04-28 17:39:37 -040026
Matthew Treinish3e046852013-07-23 16:00:24 -040027from tempest import clients
Andrea Frittoli (andreaf)290b3e12015-10-08 10:25:02 +010028from tempest.common import credentials_factory as credentials
Rohan Kanade9ce97df2013-12-10 18:59:35 +053029from tempest.common import fixed_network
nithya-ganesan222efd72015-01-22 12:20:27 +000030import tempest.common.validation_resources as vresources
Attila Fazekasdc216422013-01-29 15:12:14 +010031from tempest import config
Matthew Treinish16c43792013-09-09 19:55:23 +000032from tempest import exceptions
Matthew Treinish3787e4c2016-10-07 21:25:33 -040033from tempest.lib.common import cred_client
Jordan Pittier35a63752016-08-30 13:09:12 +020034from tempest.lib.common.utils import test_utils
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050035from tempest.lib import decorators
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +010036from tempest.lib import exceptions as lib_exc
Jay Pipes051075a2012-04-28 17:39:37 -040037
38LOG = logging.getLogger(__name__)
39
Sean Dague86bd8422013-12-20 09:56:44 -050040CONF = config.CONF
41
Matthew Treinishc1802bc2015-12-03 18:48:11 -050042idempotent_id = decorators.idempotent_id
43
Jay Pipes051075a2012-04-28 17:39:37 -040044
Yaroslav Lobankovda999f72015-06-30 20:32:55 +030045def attr(**kwargs):
liuchenhong00caec52015-07-19 22:40:28 +080046 """A decorator which applies the testtools attr decorator
Chris Yeoh55530bb2013-02-08 16:04:27 +103047
Matthew Treinisha74f5d42014-02-07 20:25:44 -050048 This decorator applies the testtools.testcase.attr if it is in the list of
49 attributes to testtools we want to apply.
Attila Fazekasb2902af2013-02-16 16:22:44 +010050 """
Chris Yeoh55530bb2013-02-08 16:04:27 +103051
52 def decorator(f):
Giulio Fidente4946a052013-05-14 12:23:51 +020053 if 'type' in kwargs and isinstance(kwargs['type'], str):
54 f = testtools.testcase.attr(kwargs['type'])(f)
55 elif 'type' in kwargs and isinstance(kwargs['type'], list):
56 for attr in kwargs['type']:
57 f = testtools.testcase.attr(attr)(f)
Matthew Treinisha74f5d42014-02-07 20:25:44 -050058 return f
Chris Yeoh55530bb2013-02-08 16:04:27 +103059
60 return decorator
61
62
Matthew Treinish3d8c7322014-08-03 23:53:28 -040063def get_service_list():
Matthew Treinish8afbffd2014-01-21 23:56:13 +000064 service_list = {
65 'compute': CONF.service_available.nova,
66 'image': CONF.service_available.glance,
67 'volume': CONF.service_available.cinder,
Matthew Treinish8afbffd2014-01-21 23:56:13 +000068 'network': True,
69 'identity': True,
70 'object_storage': CONF.service_available.swift,
Matthew Treinish8afbffd2014-01-21 23:56:13 +000071 }
Matthew Treinish3d8c7322014-08-03 23:53:28 -040072 return service_list
Matthew Treinish16c43792013-09-09 19:55:23 +000073
Matthew Treinish3d8c7322014-08-03 23:53:28 -040074
Yaroslav Lobankovda999f72015-06-30 20:32:55 +030075def services(*args):
Matthew Treinish3d8c7322014-08-03 23:53:28 -040076 """A decorator used to set an attr for each service used in a test case
77
78 This decorator applies a testtools attr for each service that gets
79 exercised by a test case.
80 """
Matthew Treinish16c43792013-09-09 19:55:23 +000081 def decorator(f):
Masayuki Igawa22b30082016-06-27 16:18:59 +090082 services = ['compute', 'image', 'baremetal', 'volume',
83 'network', 'identity', 'object_storage']
Matthew Treinish16c43792013-09-09 19:55:23 +000084 for service in args:
Matthew Treinish3d8c7322014-08-03 23:53:28 -040085 if service not in services:
86 raise exceptions.InvalidServiceTag('%s is not a valid '
87 'service' % service)
Matthew Treinish16c43792013-09-09 19:55:23 +000088 attr(type=list(args))(f)
Matthew Treinish8afbffd2014-01-21 23:56:13 +000089
90 @functools.wraps(f)
91 def wrapper(self, *func_args, **func_kwargs):
Matthew Treinish3d8c7322014-08-03 23:53:28 -040092 service_list = get_service_list()
93
Matthew Treinish8afbffd2014-01-21 23:56:13 +000094 for service in args:
95 if not service_list[service]:
96 msg = 'Skipped because the %s service is not available' % (
97 service)
98 raise testtools.TestCase.skipException(msg)
99 return f(self, *func_args, **func_kwargs)
100 return wrapper
Matthew Treinish16c43792013-09-09 19:55:23 +0000101 return decorator
102
103
Yaroslav Lobankovda999f72015-06-30 20:32:55 +0300104def requires_ext(**kwargs):
Matthew Treinishe3d26142013-11-26 19:14:58 +0000105 """A decorator to skip tests if an extension is not enabled
106
107 @param extension
108 @param service
109 """
110 def decorator(func):
111 @functools.wraps(func)
112 def wrapper(*func_args, **func_kwargs):
113 if not is_extension_enabled(kwargs['extension'],
114 kwargs['service']):
115 msg = "Skipped because %s extension: %s is not enabled" % (
116 kwargs['service'], kwargs['extension'])
117 raise testtools.TestCase.skipException(msg)
118 return func(*func_args, **func_kwargs)
119 return wrapper
120 return decorator
121
122
123def is_extension_enabled(extension_name, service):
124 """A function that will check the list of enabled extensions from config
125
126 """
Matthew Treinishe3d26142013-11-26 19:14:58 +0000127 config_dict = {
Matthew Treinishbc0e03e2014-01-30 16:51:06 +0000128 'compute': CONF.compute_feature_enabled.api_extensions,
Matthew Treinishbc0e03e2014-01-30 16:51:06 +0000129 'volume': CONF.volume_feature_enabled.api_extensions,
130 'network': CONF.network_feature_enabled.api_extensions,
131 'object': CONF.object_storage_feature_enabled.discoverable_apis,
Jane Zadorozhna121576d2015-06-23 12:57:13 +0300132 'identity': CONF.identity_feature_enabled.api_extensions
Matthew Treinishe3d26142013-11-26 19:14:58 +0000133 }
Simeon Monov5d7effe2014-07-16 07:32:38 +0300134 if len(config_dict[service]) == 0:
135 return False
Matthew Treinishe3d26142013-11-26 19:14:58 +0000136 if config_dict[service][0] == 'all':
137 return True
138 if extension_name in config_dict[service]:
139 return True
140 return False
141
Ian Wienand98c35f32013-07-23 20:34:23 +1000142
Ken'ichi Ohmichia1111c52016-12-01 19:42:03 -0800143def related_bug(bug, status_code=None):
144 """A decorator useful to know solutions from launchpad bug reports
145
146 @param bug: The launchpad bug number causing the test
147 @param status_code: The status code related to the bug report
148 """
149 def decorator(f):
150 @functools.wraps(f)
151 def wrapper(self, *func_args, **func_kwargs):
152 try:
153 return f(self, *func_args, **func_kwargs)
154 except Exception as exc:
155 exc_status_code = getattr(exc, 'status_code', None)
156 if status_code is None or status_code == exc_status_code:
157 LOG.error('Hints: This test was made for the bug %s. '
158 'The failure could be related to '
Jordan Pittier525ec712016-12-07 17:51:26 +0100159 'https://launchpad.net/bugs/%s', bug, bug)
Ken'ichi Ohmichia1111c52016-12-01 19:42:03 -0800160 raise exc
161 return wrapper
162 return decorator
163
164
Yair Fried95914122016-03-03 09:14:40 +0200165def is_scheduler_filter_enabled(filter_name):
ghanshyam5817e142016-12-01 11:38:46 +0900166 """Check the list of enabled compute scheduler filters from config.
167
168 This function checks whether the given compute scheduler filter is
169 available and configured in the config file. If the
170 scheduler_available_filters option is set to 'all' (Default value. which
171 means default filters are configured in nova) in tempest.conf then, this
172 function returns True with assumption that requested filter 'filter_name'
173 is one of available filter in nova ("nova.scheduler.filters.all_filters").
174 """
Yair Friedca5cfb52016-01-04 15:41:55 +0200175
176 filters = CONF.compute_feature_enabled.scheduler_available_filters
177 if len(filters) == 0:
178 return False
179 if 'all' in filters:
180 return True
181 if filter_name in filters:
182 return True
183 return False
184
185
Attila Fazekasf86fa312013-07-30 19:56:39 +0200186at_exit_set = set()
187
188
189def validate_tearDownClass():
190 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -0400191 LOG.error(
192 "tearDownClass does not call the super's "
193 "tearDownClass in these classes: \n"
194 + str(at_exit_set))
195
Attila Fazekasf86fa312013-07-30 19:56:39 +0200196
197atexit.register(validate_tearDownClass)
198
Attila Fazekas53943322014-02-10 16:07:34 +0100199
Matthew Treinish2474f412014-11-17 18:11:56 -0500200class BaseTestCase(testtools.testcase.WithAttributes,
201 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100202 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000203
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100204 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
205 by subclasses (enforced via hacking rule T105).
206
207 Set-up is split in a series of steps (setup stages), which can be
208 overwritten by test classes. Set-up stages are:
209 - skip_checks
210 - setup_credentials
211 - setup_clients
212 - resource_setup
213
214 Tear-down is also split in a series of steps (teardown stages), which are
215 stacked for execution only if the corresponding setup stage had been
216 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700217 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100218 - resource_cleanup
219 """
Attila Fazekasc43fec82013-04-09 23:17:52 +0200220
Attila Fazekasf86fa312013-07-30 19:56:39 +0200221 setUpClassCalled = False
222
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000223 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100224 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
225 # a list of roles - the first element of the list being a label, and the
226 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000227 credentials = []
nithya-ganesan222efd72015-01-22 12:20:27 +0000228 # Resources required to validate a server using ssh
229 validation_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500230 network_resources = {}
231
Sean Dague2ef32ac2014-06-09 11:32:23 -0400232 # NOTE(sdague): log_format is defined inline here instead of using the oslo
233 # default because going through the config path recouples config to the
234 # stress tests too early, and depending on testr order will fail unit tests
235 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
236 '[%(name)s] %(message)s')
237
Ryota MIBU60687e52015-12-09 18:37:39 +0900238 # Client manager class to use in this test case.
239 client_manager = clients.Manager
240
Sean Dague02620fd2016-03-02 15:52:51 -0500241 # A way to adjust slow test classes
242 TIMEOUT_SCALING_FACTOR = 1
243
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200244 @classmethod
245 def setUpClass(cls):
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100246 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200247 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
248 super(BaseTestCase, cls).setUpClass()
Attila Fazekasf86fa312013-07-30 19:56:39 +0200249 cls.setUpClassCalled = True
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100250 # Stack of (name, callable) to be invoked in reverse order at teardown
251 cls.teardowns = []
252 # All the configuration checks that may generate a skip
253 cls.skip_checks()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100254 try:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100255 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700256 cls.teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100257 cls.setup_credentials()
258 # Shortcuts to clients
259 cls.setup_clients()
260 # Additional class-wide test resources
261 cls.teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100262 cls.resource_setup()
263 except Exception:
264 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100265 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
266 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100267 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100268 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400269 six.reraise(etype, value, trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100270 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100271 del trace # to avoid circular refs
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200272
Attila Fazekasf86fa312013-07-30 19:56:39 +0200273 @classmethod
274 def tearDownClass(cls):
Attila Fazekas5d275302013-08-29 12:35:12 +0200275 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100276 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200277 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
278 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100279 # Save any existing exception, we always want to re-raise the original
280 # exception only
281 etype, value, trace = sys.exc_info()
282 # If there was no exception during setup we shall re-raise the first
283 # exception in teardown
284 re_raise = (etype is None)
285 while cls.teardowns:
286 name, teardown = cls.teardowns.pop()
287 # Catch any exception in tearDown so we can re-raise the original
288 # exception at the end
289 try:
290 teardown()
291 except Exception as te:
292 sys_exec_info = sys.exc_info()
293 tetype = sys_exec_info[0]
294 # TODO(andreaf): Till we have the ability to cleanup only
295 # resources that were successfully setup in resource_cleanup,
296 # log AttributeError as info instead of exception.
297 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100298 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100299 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100300 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100301 if not etype:
302 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800303 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100304 # the first one
305 if re_raise and etype is not None:
306 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400307 six.reraise(etype, value, trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100308 finally:
309 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100310
311 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100312 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000313 """Class level skip checks.
314
315 Subclasses verify in here all conditions that might prevent the
316 execution of the entire test class.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100317 Checks implemented here may not make use API calls, and should rely on
318 configuration alone.
319 In general skip checks that require an API call are discouraged.
320 If one is really needed it may be implemented either in the
321 resource_setup or at test level.
322 """
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100323 identity_version = cls.get_identity_version()
324 if 'admin' in cls.credentials and not credentials.is_admin_available(
325 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000326 msg = "Missing Identity Admin API credentials in configuration."
327 raise cls.skipException(msg)
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100328 if 'alt' in cls.credentials and not credentials.is_alt_available(
329 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000330 msg = "Missing a 2nd set of API credentials in configuration."
331 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100332 if hasattr(cls, 'identity_version'):
333 if cls.identity_version == 'v2':
334 if not CONF.identity_feature_enabled.api_v2:
335 raise cls.skipException("Identity api v2 is not enabled")
336 elif cls.identity_version == 'v3':
337 if not CONF.identity_feature_enabled.api_v3:
338 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100339
340 @classmethod
341 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300342 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000343
edannon6cc6fbc2016-05-03 11:56:12 +0300344 For every element of credentials param function creates tenant/user,
345 Then it creates client manager for that credential.
346
347 Network related tests must override this function with
348 set_network_resources() method, otherwise it will create
349 network resources(network resources are created in a later step).
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000350 """
351 for credentials_type in cls.credentials:
352 # This may raise an exception in case credentials are not available
353 # In that case we want to let the exception through and the test
354 # fail accordingly
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100355 if isinstance(credentials_type, six.string_types):
356 manager = cls.get_client_manager(
357 credential_type=credentials_type)
358 setattr(cls, 'os_%s' % credentials_type, manager)
359 # Setup some common aliases
360 # TODO(andreaf) The aliases below are a temporary hack
361 # to avoid changing too much code in one patch. They should
362 # be removed eventually
363 if credentials_type == 'primary':
364 cls.os = cls.manager = cls.os_primary
365 if credentials_type == 'admin':
366 cls.os_adm = cls.admin_manager = cls.os_admin
367 if credentials_type == 'alt':
368 cls.alt_manager = cls.os_alt
369 elif isinstance(credentials_type, list):
370 manager = cls.get_client_manager(roles=credentials_type[1:],
371 force_new=True)
372 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100373
374 @classmethod
375 def setup_clients(cls):
376 """Create links to the clients into the test object."""
377 # TODO(andreaf) There is a fair amount of code that could me moved from
378 # base / test classes in here. Ideally tests should be able to only
379 # specify which client is `client` and nothing else.
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100380 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200381
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000382 @classmethod
383 def resource_setup(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000384 """Class level resource setup for test cases."""
nithya-ganesan222efd72015-01-22 12:20:27 +0000385 if hasattr(cls, "os"):
386 cls.validation_resources = vresources.create_validation_resources(
387 cls.os, cls.validation_resources)
388 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000389 LOG.warning("Client manager not found, validation resources not"
390 " created")
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000391
392 @classmethod
393 def resource_cleanup(cls):
394 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000395
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000396 Resource cleanup must be able to handle the case of partially setup
397 resources, in case a failure during `resource_setup` should happen.
398 """
nithya-ganesan222efd72015-01-22 12:20:27 +0000399 if cls.validation_resources:
400 if hasattr(cls, "os"):
401 vresources.clear_validation_resources(cls.os,
402 cls.validation_resources)
403 cls.validation_resources = {}
404 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000405 LOG.warning("Client manager not found, validation resources "
406 "not deleted")
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000407
Attila Fazekasf86fa312013-07-30 19:56:39 +0200408 def setUp(self):
409 super(BaseTestCase, self).setUp()
410 if not self.setUpClassCalled:
411 raise RuntimeError("setUpClass does not calls the super's"
412 "setUpClass in the "
413 + self.__class__.__name__)
414 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400415 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
416 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500417 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400418 except ValueError:
419 test_timeout = 0
420 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200421 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400422
423 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
424 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200425 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
426 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400427 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
428 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200429 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
430 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200431 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
432 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200433 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400434 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200435 level=None))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400436
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100437 @property
438 def credentials_provider(self):
439 return self._get_credentials_provider()
440
Jamie Lennox15350172015-08-17 10:54:25 +1000441 @property
442 def identity_utils(self):
443 """A client that abstracts v2 and v3 identity operations.
444
445 This can be used for creating and tearing down projects in tests. It
446 should not be used for testing identity features.
447 """
448 if CONF.identity.auth_version == 'v2':
449 client = self.os_admin.identity_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000450 users_client = self.os_admin.users_client
Daniel Melladob04da902015-11-20 17:43:12 +0100451 project_client = self.os_admin.tenants_client
Daniel Mellado6b16b922015-12-07 12:43:08 +0000452 roles_client = self.os_admin.roles_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000453 domains_client = None
Jamie Lennox15350172015-08-17 10:54:25 +1000454 else:
455 client = self.os_admin.identity_v3_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000456 users_client = self.os_admin.users_v3_client
Arx Cruz24bcb882016-02-10 15:20:16 +0100457 project_client = self.os_admin.projects_client
458 roles_client = self.os_admin.roles_v3_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000459 domains_client = self.os_admin.domains_client
Jamie Lennox15350172015-08-17 10:54:25 +1000460
461 try:
462 domain = client.auth_provider.credentials.project_domain_name
463 except AttributeError:
464 domain = 'Default'
465
Daniel Melladob04da902015-11-20 17:43:12 +0100466 return cred_client.get_creds_client(client, project_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +0000467 users_client,
Daniel Mellado7aea5342016-02-09 09:10:12 +0000468 roles_client,
Daniel Mellado91a26b62016-02-11 11:13:04 +0000469 domains_client,
Daniel Melladob04da902015-11-20 17:43:12 +0100470 project_domain_name=domain)
Jamie Lennox15350172015-08-17 10:54:25 +1000471
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100472 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100473 def get_identity_version(cls):
474 """Returns the identity version used by the test class"""
475 identity_version = getattr(cls, 'identity_version', None)
476 return identity_version or CONF.identity.auth_version
477
478 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100479 def _get_credentials_provider(cls):
480 """Returns a credentials provider
481
482 If no credential provider exists yet creates one.
483 It uses self.identity_version if defined, or the configuration value
484 """
485 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
486 not cls._creds_provider.name == cls.__name__):
487 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
488 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100489
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700490 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100491 name=cls.__name__, network_resources=cls.network_resources,
492 force_tenant_isolation=force_tenant_isolation,
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100493 identity_version=cls.get_identity_version())
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100494 return cls._creds_provider
495
Matthew Treinish3e046852013-07-23 16:00:24 -0400496 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100497 def get_client_manager(cls, credential_type=None, roles=None,
498 force_new=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100499 """Returns an OpenStack client manager
500
501 Returns an OpenStack client manager based on either credential_type
502 or a list of roles. If neither is specified, it defaults to
503 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100504 :param credential_type: string - primary, alt or admin
505 :param roles: list of roles
506
lei zhangdd552b22015-11-25 20:41:48 +0800507 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100508 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700509 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100510 if all([roles, credential_type]):
511 msg = "Cannot get credentials by type and roles at the same time"
512 raise ValueError(msg)
513 if not any([roles, credential_type]):
514 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100515 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100516 if roles:
517 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100518 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100519 skip_msg = (
520 "%s skipped because the configured credential provider"
521 " is not able to provide credentials with the %s role "
522 "assigned." % (cls.__name__, role))
523 raise cls.skipException(skip_msg)
524 params = dict(roles=roles)
525 if force_new is not None:
526 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100527 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000528 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100529 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100530 if hasattr(cred_provider, credentials_method):
531 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100532 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100533 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100534 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100535 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000536 # NOTE(andreaf) Ensure credentials have user and project id fields.
537 # It may not be the case when using pre-provisioned credentials.
538 manager.auth_provider.set_auth()
539 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700540
541 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700542 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000543 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200544 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700545 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700546
547 @classmethod
nithya-ganesan222efd72015-01-22 12:20:27 +0000548 def set_validation_resources(cls, keypair=None, floating_ip=None,
549 security_group=None,
550 security_group_rules=None):
551 """Specify which ssh server validation resources should be created.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000552
nithya-ganesan222efd72015-01-22 12:20:27 +0000553 Each of the argument must be set to either None, True or False, with
554 None - use default from config (security groups and security group
555 rules get created when set to None)
556 False - Do not create the validation resource
557 True - create the validation resource
558
559 @param keypair
560 @param security_group
561 @param security_group_rules
562 @param floating_ip
563 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400564 if not CONF.validation.run_validation:
565 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100566
nithya-ganesan222efd72015-01-22 12:20:27 +0000567 if keypair is None:
Jordan Pittier79cd1822016-12-08 17:20:35 +0100568 keypair = (CONF.validation.auth_method.lower() == "keypair")
569
nithya-ganesan222efd72015-01-22 12:20:27 +0000570 if floating_ip is None:
Jordan Pittier79cd1822016-12-08 17:20:35 +0100571 floating_ip = (CONF.validation.connect_method.lower() ==
572 "floating")
573
nithya-ganesan222efd72015-01-22 12:20:27 +0000574 if security_group is None:
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500575 security_group = CONF.validation.security_group
Jordan Pittier79cd1822016-12-08 17:20:35 +0100576
nithya-ganesan222efd72015-01-22 12:20:27 +0000577 if security_group_rules is None:
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500578 security_group_rules = CONF.validation.security_group_rules
579
nithya-ganesan222efd72015-01-22 12:20:27 +0000580 if not cls.validation_resources:
581 cls.validation_resources = {
582 'keypair': keypair,
583 'security_group': security_group,
584 'security_group_rules': security_group_rules,
585 'floating_ip': floating_ip}
586
587 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000588 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500589 dhcp=False):
590 """Specify which network resources should be created
591
592 @param network
593 @param router
594 @param subnet
595 @param dhcp
596 """
Salvatore Orlando5a337242014-01-15 22:49:22 +0000597 # network resources should be set only once from callers
598 # in order to ensure that even if it's called multiple times in
599 # a chain of overloaded methods, the attribute is set only
600 # in the leaf class
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000601 if not cls.network_resources:
602 cls.network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000603 'network': network,
604 'router': router,
605 'subnet': subnet,
606 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500607
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530608 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000609 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530610 """Get the network to be used in testing
611
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000612 :param credentials_type: The type of credentials for which to get the
613 tenant network
614
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530615 :return: network dict including 'id' and 'name'
616 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000617 # Get a manager for the given credentials_type, but at least
618 # always fall back on getting the manager for primary credentials
619 if isinstance(credentials_type, six.string_types):
620 manager = cls.get_client_manager(credential_type=credentials_type)
621 elif isinstance(credentials_type, list):
622 manager = cls.get_client_manager(roles=credentials_type[1:])
623 else:
624 manager = cls.get_client_manager()
625
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700626 # Make sure cred_provider exists and get a network client
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000627 networks_client = manager.compute_networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100628 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100629 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800630 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100631 # for their servers, so using an admin network client to validate
632 # the network name
633 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100634 credentials.is_admin_available(
635 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100636 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100637 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400638 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900639 return fixed_network.get_tenant_network(
640 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530641
Mark Maglana5885eb32014-02-28 10:57:34 -0800642 def assertEmpty(self, list, msg=None):
Béla Vancsics64862f72016-11-08 09:12:31 +0100643 self.assertEqual(0, len(list), msg)
Mark Maglana5885eb32014-02-28 10:57:34 -0800644
645 def assertNotEmpty(self, list, msg=None):
Béla Vancsics64862f72016-11-08 09:12:31 +0100646 self.assertGreater(len(list), 0, msg)
Mark Maglana5885eb32014-02-28 10:57:34 -0800647
Attila Fazekasdc216422013-01-29 15:12:14 +0100648
Jordan Pittier35a63752016-08-30 13:09:12 +0200649call_until_true = debtcollector.moves.moved_function(
650 test_utils.call_until_true, 'call_until_true', __name__,
651 version='Newton', removal_version='Ocata')