blob: 451b876433bfc1cde908f8ffd24bde96e688a65d [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,
Adam Gandelman4a48a602014-03-20 18:23:18 -070067 'baremetal': CONF.service_available.ironic,
Matthew Treinish8afbffd2014-01-21 23:56:13 +000068 'volume': CONF.service_available.cinder,
Matthew Treinish8afbffd2014-01-21 23:56:13 +000069 'network': True,
70 'identity': True,
71 'object_storage': CONF.service_available.swift,
Matthew Treinish8afbffd2014-01-21 23:56:13 +000072 }
Matthew Treinish3d8c7322014-08-03 23:53:28 -040073 return service_list
Matthew Treinish16c43792013-09-09 19:55:23 +000074
Matthew Treinish3d8c7322014-08-03 23:53:28 -040075
Yaroslav Lobankovda999f72015-06-30 20:32:55 +030076def services(*args):
Matthew Treinish3d8c7322014-08-03 23:53:28 -040077 """A decorator used to set an attr for each service used in a test case
78
79 This decorator applies a testtools attr for each service that gets
80 exercised by a test case.
81 """
Matthew Treinish16c43792013-09-09 19:55:23 +000082 def decorator(f):
Masayuki Igawa22b30082016-06-27 16:18:59 +090083 services = ['compute', 'image', 'baremetal', 'volume',
84 'network', 'identity', 'object_storage']
Matthew Treinish16c43792013-09-09 19:55:23 +000085 for service in args:
Matthew Treinish3d8c7322014-08-03 23:53:28 -040086 if service not in services:
87 raise exceptions.InvalidServiceTag('%s is not a valid '
88 'service' % service)
Matthew Treinish16c43792013-09-09 19:55:23 +000089 attr(type=list(args))(f)
Matthew Treinish8afbffd2014-01-21 23:56:13 +000090
91 @functools.wraps(f)
92 def wrapper(self, *func_args, **func_kwargs):
Matthew Treinish3d8c7322014-08-03 23:53:28 -040093 service_list = get_service_list()
94
Matthew Treinish8afbffd2014-01-21 23:56:13 +000095 for service in args:
96 if not service_list[service]:
97 msg = 'Skipped because the %s service is not available' % (
98 service)
99 raise testtools.TestCase.skipException(msg)
100 return f(self, *func_args, **func_kwargs)
101 return wrapper
Matthew Treinish16c43792013-09-09 19:55:23 +0000102 return decorator
103
104
Yaroslav Lobankovda999f72015-06-30 20:32:55 +0300105def requires_ext(**kwargs):
Matthew Treinishe3d26142013-11-26 19:14:58 +0000106 """A decorator to skip tests if an extension is not enabled
107
108 @param extension
109 @param service
110 """
111 def decorator(func):
112 @functools.wraps(func)
113 def wrapper(*func_args, **func_kwargs):
114 if not is_extension_enabled(kwargs['extension'],
115 kwargs['service']):
116 msg = "Skipped because %s extension: %s is not enabled" % (
117 kwargs['service'], kwargs['extension'])
118 raise testtools.TestCase.skipException(msg)
119 return func(*func_args, **func_kwargs)
120 return wrapper
121 return decorator
122
123
124def is_extension_enabled(extension_name, service):
125 """A function that will check the list of enabled extensions from config
126
127 """
Matthew Treinishe3d26142013-11-26 19:14:58 +0000128 config_dict = {
Matthew Treinishbc0e03e2014-01-30 16:51:06 +0000129 'compute': CONF.compute_feature_enabled.api_extensions,
Matthew Treinishbc0e03e2014-01-30 16:51:06 +0000130 'volume': CONF.volume_feature_enabled.api_extensions,
131 'network': CONF.network_feature_enabled.api_extensions,
132 'object': CONF.object_storage_feature_enabled.discoverable_apis,
Jane Zadorozhna121576d2015-06-23 12:57:13 +0300133 'identity': CONF.identity_feature_enabled.api_extensions
Matthew Treinishe3d26142013-11-26 19:14:58 +0000134 }
Simeon Monov5d7effe2014-07-16 07:32:38 +0300135 if len(config_dict[service]) == 0:
136 return False
Matthew Treinishe3d26142013-11-26 19:14:58 +0000137 if config_dict[service][0] == 'all':
138 return True
139 if extension_name in config_dict[service]:
140 return True
141 return False
142
Ian Wienand98c35f32013-07-23 20:34:23 +1000143
Yair Fried95914122016-03-03 09:14:40 +0200144def is_scheduler_filter_enabled(filter_name):
Yair Friedca5cfb52016-01-04 15:41:55 +0200145 """Check the list of enabled compute scheduler filters from config. """
146
147 filters = CONF.compute_feature_enabled.scheduler_available_filters
148 if len(filters) == 0:
149 return False
150 if 'all' in filters:
151 return True
152 if filter_name in filters:
153 return True
154 return False
155
156
Attila Fazekasf86fa312013-07-30 19:56:39 +0200157at_exit_set = set()
158
159
160def validate_tearDownClass():
161 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -0400162 LOG.error(
163 "tearDownClass does not call the super's "
164 "tearDownClass in these classes: \n"
165 + str(at_exit_set))
166
Attila Fazekasf86fa312013-07-30 19:56:39 +0200167
168atexit.register(validate_tearDownClass)
169
Attila Fazekas53943322014-02-10 16:07:34 +0100170
Matthew Treinish2474f412014-11-17 18:11:56 -0500171class BaseTestCase(testtools.testcase.WithAttributes,
172 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100173 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000174
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100175 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
176 by subclasses (enforced via hacking rule T105).
177
178 Set-up is split in a series of steps (setup stages), which can be
179 overwritten by test classes. Set-up stages are:
180 - skip_checks
181 - setup_credentials
182 - setup_clients
183 - resource_setup
184
185 Tear-down is also split in a series of steps (teardown stages), which are
186 stacked for execution only if the corresponding setup stage had been
187 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700188 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100189 - resource_cleanup
190 """
Attila Fazekasc43fec82013-04-09 23:17:52 +0200191
Attila Fazekasf86fa312013-07-30 19:56:39 +0200192 setUpClassCalled = False
Marc Koderer24eb89c2014-01-31 11:23:33 +0100193 _service = None
Attila Fazekasf86fa312013-07-30 19:56:39 +0200194
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000195 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100196 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
197 # a list of roles - the first element of the list being a label, and the
198 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000199 credentials = []
nithya-ganesan222efd72015-01-22 12:20:27 +0000200 # Resources required to validate a server using ssh
201 validation_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500202 network_resources = {}
203
Sean Dague2ef32ac2014-06-09 11:32:23 -0400204 # NOTE(sdague): log_format is defined inline here instead of using the oslo
205 # default because going through the config path recouples config to the
206 # stress tests too early, and depending on testr order will fail unit tests
207 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
208 '[%(name)s] %(message)s')
209
Ryota MIBU60687e52015-12-09 18:37:39 +0900210 # Client manager class to use in this test case.
211 client_manager = clients.Manager
212
Sean Dague02620fd2016-03-02 15:52:51 -0500213 # A way to adjust slow test classes
214 TIMEOUT_SCALING_FACTOR = 1
215
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200216 @classmethod
217 def setUpClass(cls):
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100218 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200219 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
220 super(BaseTestCase, cls).setUpClass()
Attila Fazekasf86fa312013-07-30 19:56:39 +0200221 cls.setUpClassCalled = True
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100222 # Stack of (name, callable) to be invoked in reverse order at teardown
223 cls.teardowns = []
224 # All the configuration checks that may generate a skip
225 cls.skip_checks()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100226 try:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100227 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700228 cls.teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100229 cls.setup_credentials()
230 # Shortcuts to clients
231 cls.setup_clients()
232 # Additional class-wide test resources
233 cls.teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100234 cls.resource_setup()
235 except Exception:
236 etype, value, trace = sys.exc_info()
Matthew Treinished2ad4f2014-12-23 15:18:32 -0500237 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass." % (
238 etype, cls.__name__))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100239 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100240 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400241 six.reraise(etype, value, trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100242 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100243 del trace # to avoid circular refs
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200244
Attila Fazekasf86fa312013-07-30 19:56:39 +0200245 @classmethod
246 def tearDownClass(cls):
Attila Fazekas5d275302013-08-29 12:35:12 +0200247 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100248 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200249 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
250 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100251 # Save any existing exception, we always want to re-raise the original
252 # exception only
253 etype, value, trace = sys.exc_info()
254 # If there was no exception during setup we shall re-raise the first
255 # exception in teardown
256 re_raise = (etype is None)
257 while cls.teardowns:
258 name, teardown = cls.teardowns.pop()
259 # Catch any exception in tearDown so we can re-raise the original
260 # exception at the end
261 try:
262 teardown()
263 except Exception as te:
264 sys_exec_info = sys.exc_info()
265 tetype = sys_exec_info[0]
266 # TODO(andreaf): Till we have the ability to cleanup only
267 # resources that were successfully setup in resource_cleanup,
268 # log AttributeError as info instead of exception.
269 if tetype is AttributeError and name == 'resources':
270 LOG.info("tearDownClass of %s failed: %s" % (name, te))
271 else:
272 LOG.exception("teardown of %s failed: %s" % (name, te))
273 if not etype:
274 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800275 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100276 # the first one
277 if re_raise and etype is not None:
278 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400279 six.reraise(etype, value, trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100280 finally:
281 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100282
283 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100284 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000285 """Class level skip checks.
286
287 Subclasses verify in here all conditions that might prevent the
288 execution of the entire test class.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100289 Checks implemented here may not make use API calls, and should rely on
290 configuration alone.
291 In general skip checks that require an API call are discouraged.
292 If one is really needed it may be implemented either in the
293 resource_setup or at test level.
294 """
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100295 identity_version = cls.get_identity_version()
296 if 'admin' in cls.credentials and not credentials.is_admin_available(
297 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000298 msg = "Missing Identity Admin API credentials in configuration."
299 raise cls.skipException(msg)
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100300 if 'alt' in cls.credentials and not credentials.is_alt_available(
301 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000302 msg = "Missing a 2nd set of API credentials in configuration."
303 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100304 if hasattr(cls, 'identity_version'):
305 if cls.identity_version == 'v2':
306 if not CONF.identity_feature_enabled.api_v2:
307 raise cls.skipException("Identity api v2 is not enabled")
308 elif cls.identity_version == 'v3':
309 if not CONF.identity_feature_enabled.api_v3:
310 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100311
312 @classmethod
313 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300314 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000315
edannon6cc6fbc2016-05-03 11:56:12 +0300316 For every element of credentials param function creates tenant/user,
317 Then it creates client manager for that credential.
318
319 Network related tests must override this function with
320 set_network_resources() method, otherwise it will create
321 network resources(network resources are created in a later step).
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000322 """
323 for credentials_type in cls.credentials:
324 # This may raise an exception in case credentials are not available
325 # In that case we want to let the exception through and the test
326 # fail accordingly
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100327 if isinstance(credentials_type, six.string_types):
328 manager = cls.get_client_manager(
329 credential_type=credentials_type)
330 setattr(cls, 'os_%s' % credentials_type, manager)
331 # Setup some common aliases
332 # TODO(andreaf) The aliases below are a temporary hack
333 # to avoid changing too much code in one patch. They should
334 # be removed eventually
335 if credentials_type == 'primary':
336 cls.os = cls.manager = cls.os_primary
337 if credentials_type == 'admin':
338 cls.os_adm = cls.admin_manager = cls.os_admin
339 if credentials_type == 'alt':
340 cls.alt_manager = cls.os_alt
341 elif isinstance(credentials_type, list):
342 manager = cls.get_client_manager(roles=credentials_type[1:],
343 force_new=True)
344 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100345
346 @classmethod
347 def setup_clients(cls):
348 """Create links to the clients into the test object."""
349 # TODO(andreaf) There is a fair amount of code that could me moved from
350 # base / test classes in here. Ideally tests should be able to only
351 # specify which client is `client` and nothing else.
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100352 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200353
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000354 @classmethod
355 def resource_setup(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000356 """Class level resource setup for test cases."""
nithya-ganesan222efd72015-01-22 12:20:27 +0000357 if hasattr(cls, "os"):
358 cls.validation_resources = vresources.create_validation_resources(
359 cls.os, cls.validation_resources)
360 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000361 LOG.warning("Client manager not found, validation resources not"
362 " created")
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000363
364 @classmethod
365 def resource_cleanup(cls):
366 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000367
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000368 Resource cleanup must be able to handle the case of partially setup
369 resources, in case a failure during `resource_setup` should happen.
370 """
nithya-ganesan222efd72015-01-22 12:20:27 +0000371 if cls.validation_resources:
372 if hasattr(cls, "os"):
373 vresources.clear_validation_resources(cls.os,
374 cls.validation_resources)
375 cls.validation_resources = {}
376 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000377 LOG.warning("Client manager not found, validation resources "
378 "not deleted")
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000379
Attila Fazekasf86fa312013-07-30 19:56:39 +0200380 def setUp(self):
381 super(BaseTestCase, self).setUp()
382 if not self.setUpClassCalled:
383 raise RuntimeError("setUpClass does not calls the super's"
384 "setUpClass in the "
385 + self.__class__.__name__)
386 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400387 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
388 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500389 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400390 except ValueError:
391 test_timeout = 0
392 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200393 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400394
395 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
396 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200397 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
398 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400399 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
400 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200401 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
402 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200403 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
404 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200405 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400406 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200407 level=None))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400408
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100409 @property
410 def credentials_provider(self):
411 return self._get_credentials_provider()
412
Jamie Lennox15350172015-08-17 10:54:25 +1000413 @property
414 def identity_utils(self):
415 """A client that abstracts v2 and v3 identity operations.
416
417 This can be used for creating and tearing down projects in tests. It
418 should not be used for testing identity features.
419 """
420 if CONF.identity.auth_version == 'v2':
421 client = self.os_admin.identity_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000422 users_client = self.os_admin.users_client
Daniel Melladob04da902015-11-20 17:43:12 +0100423 project_client = self.os_admin.tenants_client
Daniel Mellado6b16b922015-12-07 12:43:08 +0000424 roles_client = self.os_admin.roles_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000425 domains_client = None
Jamie Lennox15350172015-08-17 10:54:25 +1000426 else:
427 client = self.os_admin.identity_v3_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000428 users_client = self.os_admin.users_v3_client
Arx Cruz24bcb882016-02-10 15:20:16 +0100429 project_client = self.os_admin.projects_client
430 roles_client = self.os_admin.roles_v3_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000431 domains_client = self.os_admin.domains_client
Jamie Lennox15350172015-08-17 10:54:25 +1000432
433 try:
434 domain = client.auth_provider.credentials.project_domain_name
435 except AttributeError:
436 domain = 'Default'
437
Daniel Melladob04da902015-11-20 17:43:12 +0100438 return cred_client.get_creds_client(client, project_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +0000439 users_client,
Daniel Mellado7aea5342016-02-09 09:10:12 +0000440 roles_client,
Daniel Mellado91a26b62016-02-11 11:13:04 +0000441 domains_client,
Daniel Melladob04da902015-11-20 17:43:12 +0100442 project_domain_name=domain)
Jamie Lennox15350172015-08-17 10:54:25 +1000443
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100444 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100445 def get_identity_version(cls):
446 """Returns the identity version used by the test class"""
447 identity_version = getattr(cls, 'identity_version', None)
448 return identity_version or CONF.identity.auth_version
449
450 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100451 def _get_credentials_provider(cls):
452 """Returns a credentials provider
453
454 If no credential provider exists yet creates one.
455 It uses self.identity_version if defined, or the configuration value
456 """
457 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
458 not cls._creds_provider.name == cls.__name__):
459 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
460 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100461
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700462 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100463 name=cls.__name__, network_resources=cls.network_resources,
464 force_tenant_isolation=force_tenant_isolation,
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100465 identity_version=cls.get_identity_version())
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100466 return cls._creds_provider
467
Matthew Treinish3e046852013-07-23 16:00:24 -0400468 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100469 def get_client_manager(cls, credential_type=None, roles=None,
470 force_new=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100471 """Returns an OpenStack client manager
472
473 Returns an OpenStack client manager based on either credential_type
474 or a list of roles. If neither is specified, it defaults to
475 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100476 :param credential_type: string - primary, alt or admin
477 :param roles: list of roles
478
lei zhangdd552b22015-11-25 20:41:48 +0800479 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100480 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700481 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100482 if all([roles, credential_type]):
483 msg = "Cannot get credentials by type and roles at the same time"
484 raise ValueError(msg)
485 if not any([roles, credential_type]):
486 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100487 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100488 if roles:
489 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100490 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100491 skip_msg = (
492 "%s skipped because the configured credential provider"
493 " is not able to provide credentials with the %s role "
494 "assigned." % (cls.__name__, role))
495 raise cls.skipException(skip_msg)
496 params = dict(roles=roles)
497 if force_new is not None:
498 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100499 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000500 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100501 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100502 if hasattr(cred_provider, credentials_method):
503 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100504 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100505 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100506 "Invalid credentials type %s" % credential_type)
Andrea Frittoli73224672016-12-09 21:08:19 +0000507 manager = cls.client_manager(credentials=creds.credentials,
508 service=cls._service)
509 # NOTE(andreaf) Ensure credentials have user and project id fields.
510 # It may not be the case when using pre-provisioned credentials.
511 manager.auth_provider.set_auth()
512 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700513
514 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700515 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000516 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200517 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700518 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700519
520 @classmethod
nithya-ganesan222efd72015-01-22 12:20:27 +0000521 def set_validation_resources(cls, keypair=None, floating_ip=None,
522 security_group=None,
523 security_group_rules=None):
524 """Specify which ssh server validation resources should be created.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000525
nithya-ganesan222efd72015-01-22 12:20:27 +0000526 Each of the argument must be set to either None, True or False, with
527 None - use default from config (security groups and security group
528 rules get created when set to None)
529 False - Do not create the validation resource
530 True - create the validation resource
531
532 @param keypair
533 @param security_group
534 @param security_group_rules
535 @param floating_ip
536 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400537 if not CONF.validation.run_validation:
538 return
nithya-ganesan222efd72015-01-22 12:20:27 +0000539 if keypair is None:
540 if CONF.validation.auth_method.lower() == "keypair":
541 keypair = True
542 else:
543 keypair = False
544 if floating_ip is None:
545 if CONF.validation.connect_method.lower() == "floating":
546 floating_ip = True
547 else:
548 floating_ip = False
549 if security_group is None:
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500550 security_group = CONF.validation.security_group
nithya-ganesan222efd72015-01-22 12:20:27 +0000551 if security_group_rules is None:
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500552 security_group_rules = CONF.validation.security_group_rules
553
nithya-ganesan222efd72015-01-22 12:20:27 +0000554 if not cls.validation_resources:
555 cls.validation_resources = {
556 'keypair': keypair,
557 'security_group': security_group,
558 'security_group_rules': security_group_rules,
559 'floating_ip': floating_ip}
560
561 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000562 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500563 dhcp=False):
564 """Specify which network resources should be created
565
566 @param network
567 @param router
568 @param subnet
569 @param dhcp
570 """
Salvatore Orlando5a337242014-01-15 22:49:22 +0000571 # network resources should be set only once from callers
572 # in order to ensure that even if it's called multiple times in
573 # a chain of overloaded methods, the attribute is set only
574 # in the leaf class
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000575 if not cls.network_resources:
576 cls.network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000577 'network': network,
578 'router': router,
579 'subnet': subnet,
580 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500581
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530582 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000583 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530584 """Get the network to be used in testing
585
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000586 :param credentials_type: The type of credentials for which to get the
587 tenant network
588
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530589 :return: network dict including 'id' and 'name'
590 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000591 # Get a manager for the given credentials_type, but at least
592 # always fall back on getting the manager for primary credentials
593 if isinstance(credentials_type, six.string_types):
594 manager = cls.get_client_manager(credential_type=credentials_type)
595 elif isinstance(credentials_type, list):
596 manager = cls.get_client_manager(roles=credentials_type[1:])
597 else:
598 manager = cls.get_client_manager()
599
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700600 # Make sure cred_provider exists and get a network client
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000601 networks_client = manager.compute_networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100602 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100603 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800604 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100605 # for their servers, so using an admin network client to validate
606 # the network name
607 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100608 credentials.is_admin_available(
609 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100610 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100611 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400612 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900613 return fixed_network.get_tenant_network(
614 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530615
Mark Maglana5885eb32014-02-28 10:57:34 -0800616 def assertEmpty(self, list, msg=None):
Béla Vancsics64862f72016-11-08 09:12:31 +0100617 self.assertEqual(0, len(list), msg)
Mark Maglana5885eb32014-02-28 10:57:34 -0800618
619 def assertNotEmpty(self, list, msg=None):
Béla Vancsics64862f72016-11-08 09:12:31 +0100620 self.assertGreater(len(list), 0, msg)
Mark Maglana5885eb32014-02-28 10:57:34 -0800621
Attila Fazekasdc216422013-01-29 15:12:14 +0100622
Jordan Pittier35a63752016-08-30 13:09:12 +0200623call_until_true = debtcollector.moves.moved_function(
624 test_utils.call_until_true, 'call_until_true', __name__,
625 version='Newton', removal_version='Ocata')