blob: dba2695138f365457c62a6b99ffc9ce9a25f3981 [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
Ian Wienand98c35f32013-07-23 20:34:23 +100017import os
Attila Fazekas53943322014-02-10 16:07:34 +010018import sys
Jay Pipes051075a2012-04-28 17:39:37 -040019
Jordan Pittier35a63752016-08-30 13:09:12 +020020import debtcollector.moves
Matthew Treinish78561ad2013-07-26 11:41:56 -040021import fixtures
Doug Hellmann583ce2c2015-03-11 14:55:46 +000022from oslo_log import log as logging
ivan-zhu1feeb382013-01-24 10:14:39 +080023import testtools
Jay Pipes051075a2012-04-28 17:39:37 -040024
Matthew Treinish3e046852013-07-23 16:00:24 -040025from tempest import clients
Andrea Frittoli (andreaf)290b3e12015-10-08 10:25:02 +010026from tempest.common import credentials_factory as credentials
Andrea Frittolicd368412017-08-14 21:37:56 +010027from tempest.common import utils
Attila Fazekasdc216422013-01-29 15:12:14 +010028from tempest import config
Ghanshyam Mann18b45d72021-12-07 12:37:29 -060029from tempest.lib.common import api_microversion_fixture
Matthew Treinishb19c55d2017-07-17 12:38:35 -040030from tempest.lib.common import fixed_network
Ilya Shakhat1291bb42017-11-29 18:08:16 +010031from tempest.lib.common import profiler
Andrea Frittoli0477acc2017-08-09 21:14:53 +010032from tempest.lib.common import validation_resources as vr
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050033from tempest.lib import decorators
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +010034from tempest.lib import exceptions as lib_exc
Jay Pipes051075a2012-04-28 17:39:37 -040035
36LOG = logging.getLogger(__name__)
37
Sean Dague86bd8422013-12-20 09:56:44 -050038CONF = config.CONF
39
Jay Pipes051075a2012-04-28 17:39:37 -040040
Jordan Pittier3b46d272017-04-12 16:17:28 +020041attr = debtcollector.moves.moved_function(
42 decorators.attr, 'attr', __name__,
43 version='Pike', removal_version='?')
Chris Yeoh55530bb2013-02-08 16:04:27 +103044
45
Andrea Frittolicd368412017-08-14 21:37:56 +010046services = debtcollector.moves.moved_function(
47 utils.services, 'services', __name__,
48 version='Pike', removal_version='?')
Andrea Frittoli07acf262017-04-09 19:36:37 +020049
50
Andrea Frittolicd368412017-08-14 21:37:56 +010051requires_ext = debtcollector.moves.moved_function(
52 utils.requires_ext, 'requires_ext', __name__,
53 version='Pike', removal_version='?')
Matthew Treinish16c43792013-09-09 19:55:23 +000054
Matthew Treinish3d8c7322014-08-03 23:53:28 -040055
Andrea Frittolicd368412017-08-14 21:37:56 +010056is_extension_enabled = debtcollector.moves.moved_function(
57 utils.is_extension_enabled, 'is_extension_enabled', __name__,
58 version='Pike', removal_version='?')
Ian Wienand98c35f32013-07-23 20:34:23 +100059
Attila Fazekasf86fa312013-07-30 19:56:39 +020060at_exit_set = set()
61
62
63def validate_tearDownClass():
64 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -040065 LOG.error(
Federico Ressi2d6bcaa2018-04-11 12:37:36 +020066 "tearDownClass does not call the super's tearDownClass in "
67 "these classes:\n"
68 " %s", at_exit_set)
Sean Dagueeb1523b2014-03-10 10:17:44 -040069
Attila Fazekasf86fa312013-07-30 19:56:39 +020070
71atexit.register(validate_tearDownClass)
72
Attila Fazekas53943322014-02-10 16:07:34 +010073
Matthew Treinish2474f412014-11-17 18:11:56 -050074class BaseTestCase(testtools.testcase.WithAttributes,
75 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +010076 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000077
Andrea Frittolia5ddd552014-08-19 18:30:00 +010078 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
79 by subclasses (enforced via hacking rule T105).
80
81 Set-up is split in a series of steps (setup stages), which can be
82 overwritten by test classes. Set-up stages are:
83 - skip_checks
84 - setup_credentials
85 - setup_clients
86 - resource_setup
87
88 Tear-down is also split in a series of steps (teardown stages), which are
89 stacked for execution only if the corresponding setup stage had been
90 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -070091 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +010092 - resource_cleanup
93 """
Attila Fazekasc43fec82013-04-09 23:17:52 +020094
Andrea Frittolib21de6c2015-02-06 20:12:38 +000095 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +010096 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
97 # a list of roles - the first element of the list being a label, and the
98 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +000099 credentials = []
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100100
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600101 # Track if setUpClass was invoked
102 __setupclass_called = False
103
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100104 # Network resources to be provisioned for the requested test credentials.
105 # Only used with the dynamic credentials provider.
106 _network_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500107
Andrea Frittoli3be57482017-08-25 22:41:26 +0100108 # Stack of resource cleanups
109 _class_cleanups = []
110
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100111 # Resources required to validate a server using ssh
112 _validation_resources = {}
113
Sean Dague2ef32ac2014-06-09 11:32:23 -0400114 # NOTE(sdague): log_format is defined inline here instead of using the oslo
115 # default because going through the config path recouples config to the
116 # stress tests too early, and depending on testr order will fail unit tests
117 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
118 '[%(name)s] %(message)s')
119
Ryota MIBU60687e52015-12-09 18:37:39 +0900120 # Client manager class to use in this test case.
121 client_manager = clients.Manager
122
Sean Dague02620fd2016-03-02 15:52:51 -0500123 # A way to adjust slow test classes
124 TIMEOUT_SCALING_FACTOR = 1
125
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200126 @classmethod
Andrea Frittoli3be57482017-08-25 22:41:26 +0100127 def _reset_class(cls):
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100128 cls.__setup_credentials_called = False
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100129 cls.__resource_cleanup_called = False
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100130 cls.__skip_checks_called = False
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600131 # Stack of callable to be invoked in reverse order
Andrea Frittoli3be57482017-08-25 22:41:26 +0100132 cls._class_cleanups = []
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600133 # Stack of (name, callable) to be invoked in reverse order at teardown
134 cls._teardowns = []
Andrea Frittoli3be57482017-08-25 22:41:26 +0100135
136 @classmethod
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200137 def setUpClass(cls):
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600138 cls.__setupclass_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100139 # Reset state
140 cls._reset_class()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100141 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200142 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
143 super(BaseTestCase, cls).setUpClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100144 try:
Ghanshyam Mann68ddf412019-09-10 19:40:52 +0000145 cls.skip_checks()
146
147 if not cls.__skip_checks_called:
148 raise RuntimeError(
149 "skip_checks for %s did not call the super's "
150 "skip_checks" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100151 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100152 cls._teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100153 cls.setup_credentials()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100154 if not cls.__setup_credentials_called:
155 raise RuntimeError("setup_credentials for %s did not call the "
156 "super's setup_credentials" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100157 # Shortcuts to clients
158 cls.setup_clients()
159 # Additional class-wide test resources
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100160 cls._teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100161 cls.resource_setup()
162 except Exception:
163 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100164 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
165 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100166 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100167 try:
songwenpinge6623072021-02-22 14:47:34 +0800168 raise value.with_traceback(trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100169 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100170 del trace # to avoid circular refs
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200171
Attila Fazekasf86fa312013-07-30 19:56:39 +0200172 @classmethod
173 def tearDownClass(cls):
Martin Kopecae155b72017-06-26 09:41:21 +0000174 # insert pdb breakpoint when pause_teardown is enabled
175 if CONF.pause_teardown:
176 cls.insert_pdb_breakpoint()
Attila Fazekas5d275302013-08-29 12:35:12 +0200177 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100178 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200179 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
180 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100181 # Save any existing exception, we always want to re-raise the original
182 # exception only
183 etype, value, trace = sys.exc_info()
184 # If there was no exception during setup we shall re-raise the first
185 # exception in teardown
186 re_raise = (etype is None)
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100187 while cls._teardowns:
188 name, teardown = cls._teardowns.pop()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100189 # Catch any exception in tearDown so we can re-raise the original
190 # exception at the end
191 try:
192 teardown()
Andrea Frittoli3be57482017-08-25 22:41:26 +0100193 if name == 'resources':
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100194 if not cls.__resource_cleanup_called:
Andrea Frittoli3be57482017-08-25 22:41:26 +0100195 raise RuntimeError(
196 "resource_cleanup for %s did not call the "
197 "super's resource_cleanup" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100198 except Exception as te:
199 sys_exec_info = sys.exc_info()
200 tetype = sys_exec_info[0]
Andrea Frittoli3be57482017-08-25 22:41:26 +0100201 # TODO(andreaf): Resource cleanup is often implemented by
202 # storing an array of resources at class level, and cleaning
203 # them up during `resource_cleanup`.
204 # In case of failure during setup, some resource arrays might
205 # not be defined at all, in which case the cleanup code might
206 # trigger an AttributeError. In such cases we log
207 # AttributeError as info instead of exception. Once all
208 # cleanups are migrated to addClassResourceCleanup we can
209 # remove this.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100210 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100211 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100212 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100213 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100214 if not etype:
215 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800216 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100217 # the first one
218 if re_raise and etype is not None:
219 try:
songwenpinge6623072021-02-22 14:47:34 +0800220 raise value.with_traceback(trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100221 finally:
222 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100223
Martin Kopecae155b72017-06-26 09:41:21 +0000224 def tearDown(self):
225 super(BaseTestCase, self).tearDown()
226 # insert pdb breakpoint when pause_teardown is enabled
227 if CONF.pause_teardown:
228 BaseTestCase.insert_pdb_breakpoint()
229
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100230 if CONF.profiler.key:
231 profiler.disable()
232
Martin Kopecae155b72017-06-26 09:41:21 +0000233 @classmethod
234 def insert_pdb_breakpoint(cls):
235 """Add pdb breakpoint.
236
237 This can help in debugging process, cleaning of resources is
238 paused, so they can be examined.
239 """
240 import pdb
241 pdb.set_trace()
242
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100243 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100244 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000245 """Class level skip checks.
246
247 Subclasses verify in here all conditions that might prevent the
Andrea Frittolia5440c82017-08-23 18:11:21 +0100248 execution of the entire test class. Skipping here prevents any other
249 class fixture from being executed i.e. no credentials or other
250 resource allocation will happen.
251
252 Tests defined in the test class will no longer appear in test results.
253 The `setUpClass` for the entire test class will be marked as SKIPPED
254 instead.
255
256 At this stage no test credentials are available, so skip checks
257 should rely on configuration alone. This is deliberate since skips
258 based on the result of an API call are discouraged.
259
260 The following checks are implemented in `test.py` already:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600261
Andrea Frittolia5440c82017-08-23 18:11:21 +0100262 - check that alt credentials are available when requested by the test
263 - check that admin credentials are available when requested by the test
264 - check that the identity version specified by the test is marked as
265 enabled in the configuration
266
267 Overriders of skip_checks must always invoke skip_check on `super`
268 first.
269
270 Example::
271
272 @classmethod
273 def skip_checks(cls):
274 super(Example, cls).skip_checks()
275 if not CONF.service_available.my_service:
276 skip_msg = ("%s skipped as my_service is not available")
277 raise cls.skipException(skip_msg % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100278 """
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100279 cls.__skip_checks_called = True
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100280 identity_version = cls.get_identity_version()
zhufl75498ba2017-08-25 10:49:35 +0800281 # setting force_tenant_isolation to True also needs admin credentials.
282 if ('admin' in cls.credentials or
Ghanshyam Mann420586c2021-01-29 13:23:18 -0600283 'alt_admin' in cls.credentials or
zhufl75498ba2017-08-25 10:49:35 +0800284 getattr(cls, 'force_tenant_isolation', False)):
285 if not credentials.is_admin_available(
286 identity_version=identity_version):
287 raise cls.skipException(
288 "Missing Identity Admin API credentials in configuration.")
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100289 if 'alt' in cls.credentials and not credentials.is_alt_available(
290 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000291 msg = "Missing a 2nd set of API credentials in configuration."
292 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100293 if hasattr(cls, 'identity_version'):
294 if cls.identity_version == 'v2':
295 if not CONF.identity_feature_enabled.api_v2:
296 raise cls.skipException("Identity api v2 is not enabled")
297 elif cls.identity_version == 'v3':
298 if not CONF.identity_feature_enabled.api_v3:
299 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100300
301 @classmethod
302 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300303 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000304
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100305 `setup_credentials` looks for the content of the `credentials`
306 attribute in the test class. If the value is a non-empty collection,
307 a credentials provider is setup, and credentials are provisioned or
308 allocated based on the content of the collection. Every set of
309 credentials is associated to an object of type `cls.client_manager`.
310 The client manager is accessible by tests via class attribute
311 `os_[type]`:
edannon6cc6fbc2016-05-03 11:56:12 +0300312
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100313 Valid values in `credentials` are:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600314
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100315 - 'primary':
316 A normal user is provisioned.
317 It can be used only once. Multiple entries will be ignored.
318 Clients are available at os_primary.
319 - 'alt':
320 A normal user other than 'primary' is provisioned.
321 It can be used only once. Multiple entries will be ignored.
322 Clients are available at os_alt.
323 - 'admin':
324 An admin user is provisioned.
325 It can be used only once. Multiple entries will be ignored.
326 Clients are available at os_admin.
327 - A list in the format ['any_label', 'role1', ... , 'roleN']:
328 A client with roles <list>[1:] is provisioned.
329 It can be used multiple times, with unique labels.
330 Clients are available at os_roles_<list>[0].
331
332 By default network resources are allocated (in case of dynamic
333 credentials). Tests that do not need network or that require a
334 custom network setup must specify which network resources shall
335 be provisioned using the `set_network_resources()` method (note
336 that it must be invoked before the `setup_credentials` is
337 invoked on super).
338
339 Example::
340
341 class TestWithCredentials(test.BaseTestCase):
342
343 credentials = ['primary', 'admin',
344 ['special', 'special_role1']]
345
346 @classmethod
347 def setup_credentials(cls):
348 # set_network_resources must be called first
349 cls.set_network_resources(network=True)
350 super(TestWithCredentials, cls).setup_credentials()
351
352 @classmethod
353 def setup_clients(cls):
354 cls.servers = cls.os_primary.compute.ServersClient()
355 cls.admin_servers = cls.os_admin.compute.ServersClient()
356 # certain API calls may require a user with a specific
357 # role assigned. In this example `special_role1` is
358 # assigned to the user in `cls.os_roles_special`.
359 cls.special_servers = (
360 cls.os_roles_special.compute.ServersClient())
361
362 def test_special_servers(self):
363 # Do something with servers
364 pass
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000365 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100366 cls.__setup_credentials_called = True
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000367 for credentials_type in cls.credentials:
368 # This may raise an exception in case credentials are not available
369 # In that case we want to let the exception through and the test
370 # fail accordingly
songwenpinga6ee2d12021-02-22 10:24:16 +0800371 if isinstance(credentials_type, str):
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100372 manager = cls.get_client_manager(
373 credential_type=credentials_type)
374 setattr(cls, 'os_%s' % credentials_type, manager)
Jordan Pittier8160d312017-04-18 11:52:23 +0200375 # NOTE(jordanP): Tempest should use os_primary, os_admin
376 # and os_alt throughout its code base but we keep the aliases
377 # around for a while for Tempest plugins. Aliases should be
378 # removed eventually.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100379 # Setup some common aliases
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100380 if credentials_type == 'primary':
Jordan Pittier8160d312017-04-18 11:52:23 +0200381 cls.os = debtcollector.moves.moved_read_only_property(
382 'os', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200383 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200384 cls.manager =\
385 debtcollector.moves.moved_read_only_property(
386 'manager', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200387 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100388 if credentials_type == 'admin':
Jordan Pittier8160d312017-04-18 11:52:23 +0200389 cls.os_adm = debtcollector.moves.moved_read_only_property(
390 'os_adm', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200391 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200392 cls.admin_manager =\
393 debtcollector.moves.moved_read_only_property(
394 'admin_manager', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200395 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100396 if credentials_type == 'alt':
Jordan Pittier8160d312017-04-18 11:52:23 +0200397 cls.alt_manager =\
398 debtcollector.moves.moved_read_only_property(
399 'alt_manager', 'os_alt', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200400 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100401 elif isinstance(credentials_type, list):
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600402 scope = 'project'
403 if credentials_type[0].startswith('system'):
404 scope = 'system'
405 elif credentials_type[0].startswith('domain'):
406 scope = 'domain'
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100407 manager = cls.get_client_manager(roles=credentials_type[1:],
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600408 force_new=True,
409 scope=scope)
410 setattr(cls, 'os_%s' % credentials_type[0], manager)
411 # TODO(gmann): Setting the old style attribute too for
412 # backward compatibility but at some point we should
413 # remove this.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100414 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100415
416 @classmethod
417 def setup_clients(cls):
Andrea Frittoli99583672017-08-24 15:39:20 +0100418 """Create aliases to the clients in the client managers.
419
420 `setup_clients` is invoked after the credential provisioning step.
421 Client manager objects are available to tests already. The purpose
422 of this helper is to setup shortcuts to specific clients that are
423 useful for the tests implemented in the test class.
424
425 Its purpose is mostly for code readability, however it should be used
426 carefully to avoid doing exactly the opposite, i.e. making the code
427 unreadable and hard to debug. If aliases are defined in a super class
428 it won't be obvious what they refer to, so it's good practice to define
429 all aliases used in the class. Aliases are meant to be shortcuts to
430 be used in tests, not shortcuts to avoid helper method attributes.
431 If an helper method starts relying on a client alias and a subclass
432 overrides that alias, it will become rather difficult to understand
433 what the helper method actually does.
434
435 Example::
436
437 class TestDoneItRight(test.BaseTestCase):
438
439 credentials = ['primary', 'alt']
440
441 @classmethod
442 def setup_clients(cls):
443 super(TestDoneItRight, cls).setup_clients()
444 cls.servers = cls.os_primary.ServersClient()
445 cls.servers_alt = cls.os_alt.ServersClient()
446
447 def _a_good_helper(self, clients):
448 # Some complex logic we're going to use many times
449 servers = clients.ServersClient()
450 vm = servers.create_server(...)
451
452 def delete_server():
453 test_utils.call_and_ignore_notfound_exc(
454 servers.delete_server, vm['id'])
455
456 self.addCleanup(self.delete_server)
457 return vm
458
459 def test_with_servers(self):
460 vm = self._a_good_helper(os.primary)
461 vm_alt = self._a_good_helper(os.alt)
462 cls.servers.show_server(vm['id'])
463 cls.servers_alt.show_server(vm_alt['id'])
464 """
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100465 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200466
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000467 @classmethod
Ghanshyam Mann18b45d72021-12-07 12:37:29 -0600468 def setup_api_microversion_fixture(
469 cls, compute_microversion=None, volume_microversion=None,
470 placement_microversion=None):
471 """Set up api microversion fixture on service clients.
472
473 `setup_api_microversion_fixture` is used to set the api microversion
474 on service clients. This can be invoked from resource_setup() method.
475
476 Example::
477
478 @classmethod
479 def resource_setup(cls):
480 super(MyTest, cls).resource_setup()
481 cls.setup_api_microversion_fixture(
482 compute_microversion=cls.compute_request_microversion,
483 volume_microversion=cls.volume_request_microversion,
484 placement_microversion=cls.placement_request_microversion)
485
486 """
487
488 api_fixture = api_microversion_fixture.APIMicroversionFixture(
489 compute_microversion=compute_microversion,
490 volume_microversion=volume_microversion,
491 placement_microversion=placement_microversion)
492 api_fixture.setUp()
493 cls.addClassResourceCleanup(api_fixture._reset_microversion)
494
495 @classmethod
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000496 def resource_setup(cls):
Andrea Frittoli3be57482017-08-25 22:41:26 +0100497 """Class level resource setup for test cases.
498
499 `resource_setup` is invoked once all credentials (and related network
500 resources have been provisioned and after client aliases - if any -
501 have been defined.
502
503 The use case for `resource_setup` is test optimization: provisioning
504 of project-specific "expensive" resources that are not dirtied by tests
505 and can thus safely be re-used by multiple tests.
506
507 System wide resources shared by all tests could instead be provisioned
508 only once, before the test run.
509
510 Resources provisioned here must be cleaned up during
511 `resource_cleanup`. This is best achieved by scheduling a cleanup via
512 `addClassResourceCleanup`.
513
514 Some test resources have an asynchronous delete process. It's best
515 practice for them to schedule a wait for delete via
516 `addClassResourceCleanup` to avoid having resources in process of
517 deletion when we reach the credentials cleanup step.
518
519 Example::
520
521 @classmethod
522 def resource_setup(cls):
523 super(MyTest, cls).resource_setup()
524 servers = cls.os_primary.compute.ServersClient()
525 # Schedule delete and wait so that we can first delete the
526 # two servers and then wait for both to delete
527 # Create server 1
528 cls.shared_server = servers.create_server()
529 # Create server 2. If something goes wrong we schedule cleanup
530 # of server 1 anyways.
531 try:
532 cls.shared_server2 = servers.create_server()
533 # Wait server 2
534 cls.addClassResourceCleanup(
535 waiters.wait_for_server_termination,
536 servers, cls.shared_server2['id'],
537 ignore_error=False)
538 finally:
539 # Wait server 1
540 cls.addClassResourceCleanup(
541 waiters.wait_for_server_termination,
542 servers, cls.shared_server['id'],
543 ignore_error=False)
544 # Delete server 1
545 cls.addClassResourceCleanup(
546 test_utils.call_and_ignore_notfound_exc,
547 servers.delete_server,
548 cls.shared_server['id'])
549 # Delete server 2 (if it was created)
550 if hasattr(cls, 'shared_server2'):
551 cls.addClassResourceCleanup(
552 test_utils.call_and_ignore_notfound_exc,
553 servers.delete_server,
554 cls.shared_server2['id'])
555 """
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100556 pass
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000557
558 @classmethod
559 def resource_cleanup(cls):
560 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000561
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100562 Resource cleanup processes the stack of cleanups produced by
Andrea Frittoli3be57482017-08-25 22:41:26 +0100563 `addClassResourceCleanup` and then cleans up validation resources
564 if any were provisioned.
565
566 All cleanups are processed whatever the outcome. Exceptions are
567 accumulated and re-raised as a `MultipleExceptions` at the end.
568
569 In most cases test cases won't need to override `resource_cleanup`,
570 but if they do they must invoke `resource_cleanup` on super.
571
572 Example::
573
574 class TestWithReallyComplexCleanup(test.BaseTestCase):
575
576 @classmethod
577 def resource_setup(cls):
578 # provision resource A
579 cls.addClassResourceCleanup(delete_resource, A)
580 # provision resource B
581 cls.addClassResourceCleanup(delete_resource, B)
582
583 @classmethod
584 def resource_cleanup(cls):
585 # It's possible to override resource_cleanup but in most
586 # cases it shouldn't be required. Nothing that may fail
587 # should be executed before the call to super since it
588 # might cause resource leak in case of error.
589 super(TestWithReallyComplexCleanup, cls).resource_cleanup()
590 # At this point test credentials are still available but
591 # anything from the cleanup stack has been already deleted.
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000592 """
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100593 cls.__resource_cleanup_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100594 cleanup_errors = []
595 while cls._class_cleanups:
596 try:
597 fn, args, kwargs = cls._class_cleanups.pop()
598 fn(*args, **kwargs)
599 except Exception:
600 cleanup_errors.append(sys.exc_info())
Andrea Frittoli3be57482017-08-25 22:41:26 +0100601 if cleanup_errors:
602 raise testtools.MultipleExceptions(*cleanup_errors)
603
604 @classmethod
605 def addClassResourceCleanup(cls, fn, *arguments, **keywordArguments):
606 """Add a cleanup function to be called during resource_cleanup.
607
608 Functions added with addClassResourceCleanup will be called in reverse
609 order of adding at the beginning of resource_cleanup, before any
610 credential, networking or validation resources cleanup is processed.
611
612 If a function added with addClassResourceCleanup raises an exception,
613 the error will be recorded as a test error, and the next cleanup will
614 then be run.
615
616 Cleanup functions are always called during the test class tearDown
617 fixture, even if an exception occured during setUp or tearDown.
618 """
619 cls._class_cleanups.append((fn, arguments, keywordArguments))
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000620
Attila Fazekasf86fa312013-07-30 19:56:39 +0200621 def setUp(self):
622 super(BaseTestCase, self).setUp()
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600623 if not self.__setupclass_called:
zhuflde676372018-11-16 15:34:56 +0800624 raise RuntimeError("setUpClass does not calls the super's "
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200625 "setUpClass in the " +
626 self.__class__.__name__)
Attila Fazekasf86fa312013-07-30 19:56:39 +0200627 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400628 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
629 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500630 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400631 except ValueError:
632 test_timeout = 0
633 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200634 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400635
636 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
637 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200638 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
639 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400640 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
641 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200642 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
643 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200644 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200645 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200646 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400647 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200648 level=None))
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100649 if CONF.profiler.key:
650 profiler.enable(CONF.profiler.key)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400651
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100652 @property
653 def credentials_provider(self):
654 return self._get_credentials_provider()
655
656 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100657 def get_identity_version(cls):
658 """Returns the identity version used by the test class"""
659 identity_version = getattr(cls, 'identity_version', None)
660 return identity_version or CONF.identity.auth_version
661
662 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100663 def _get_credentials_provider(cls):
664 """Returns a credentials provider
665
666 If no credential provider exists yet creates one.
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100667 It always use the configuration value from identity.auth_version,
668 since we always want to provision accounts with the current version
669 of the identity API.
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100670 """
671 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
672 not cls._creds_provider.name == cls.__name__):
673 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
674 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100675
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700676 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100677 name=cls.__name__, network_resources=cls._network_resources,
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100678 force_tenant_isolation=force_tenant_isolation)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100679 return cls._creds_provider
680
Matthew Treinish3e046852013-07-23 16:00:24 -0400681 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100682 def get_client_manager(cls, credential_type=None, roles=None,
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600683 force_new=None, scope=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100684 """Returns an OpenStack client manager
685
686 Returns an OpenStack client manager based on either credential_type
687 or a list of roles. If neither is specified, it defaults to
688 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100689 :param credential_type: string - primary, alt or admin
690 :param roles: list of roles
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600691 :param scope: scope for the test user
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100692
lei zhangdd552b22015-11-25 20:41:48 +0800693 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100694 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700695 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100696 if all([roles, credential_type]):
697 msg = "Cannot get credentials by type and roles at the same time"
698 raise ValueError(msg)
699 if not any([roles, credential_type]):
700 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100701 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100702 if roles:
703 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100704 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100705 skip_msg = (
706 "%s skipped because the configured credential provider"
707 " is not able to provide credentials with the %s role "
708 "assigned." % (cls.__name__, role))
709 raise cls.skipException(skip_msg)
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600710 params = dict(roles=roles, scope=scope)
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100711 if force_new is not None:
712 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100713 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000714 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100715 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100716 if hasattr(cred_provider, credentials_method):
717 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100718 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100719 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100720 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100721 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000722 # NOTE(andreaf) Ensure credentials have user and project id fields.
723 # It may not be the case when using pre-provisioned credentials.
724 manager.auth_provider.set_auth()
725 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700726
727 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700728 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000729 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200730 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700731 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700732
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100733 @staticmethod
734 def _validation_resources_params_from_conf():
735 return dict(
736 keypair=(CONF.validation.auth_method.lower() == "keypair"),
737 floating_ip=(CONF.validation.connect_method.lower() == "floating"),
738 security_group=CONF.validation.security_group,
739 security_group_rules=CONF.validation.security_group_rules,
740 use_neutron=CONF.service_available.neutron,
741 ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
742 floating_network_id=CONF.network.public_network_id,
743 floating_network_name=CONF.network.floating_network_name)
744
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700745 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100746 def get_class_validation_resources(cls, os_clients):
747 """Provision validation resources according to configuration
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000748
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100749 This is a wrapper around `create_validation_resources` from
750 `tempest.common.validation_resources` that passes parameters from
751 Tempest configuration. Only one instance of class level
752 validation resources is managed by the helper, so If resources
753 were already provisioned before, existing ones will be returned.
nithya-ganesan222efd72015-01-22 12:20:27 +0000754
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100755 Resources are returned as a dictionary. They are also scheduled for
756 automatic cleanup during class teardown using
757 `addClassResourcesCleanup`.
758
759 If `CONF.validation.run_validation` is False no resource will be
760 provisioned at all.
761
762 @param os_clients: Clients to be used to provision the resources.
nithya-ganesan222efd72015-01-22 12:20:27 +0000763 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400764 if not CONF.validation.run_validation:
765 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100766
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100767 if os_clients in cls._validation_resources:
768 return cls._validation_resources[os_clients]
Jordan Pittier79cd1822016-12-08 17:20:35 +0100769
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100770 if (CONF.validation.ip_version_for_ssh not in (4, 6) and
771 CONF.service_available.neutron):
772 msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
773 raise lib_exc.InvalidConfiguration(
774 msg % CONF.validation.ip_version_for_ssh)
Jordan Pittier79cd1822016-12-08 17:20:35 +0100775
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100776 resources = vr.create_validation_resources(
777 os_clients,
778 **cls._validation_resources_params_from_conf())
Jordan Pittier79cd1822016-12-08 17:20:35 +0100779
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100780 cls.addClassResourceCleanup(
781 vr.clear_validation_resources, os_clients,
782 use_neutron=CONF.service_available.neutron,
783 **resources)
784 cls._validation_resources[os_clients] = resources
785 return resources
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500786
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100787 def get_test_validation_resources(self, os_clients):
788 """Returns a dict of validation resources according to configuration
789
790 Initialise a validation resources fixture based on configuration.
791 Start the fixture and returns the validation resources.
792
793 If `CONF.validation.run_validation` is False no resource will be
794 provisioned at all.
795
796 @param os_clients: Clients to be used to provision the resources.
797 """
798
799 params = {}
800 # Test will try to use the fixture, so for this to be useful
801 # we must return a fixture. If validation is disabled though
802 # we don't need to provision anything, which is the default
803 # behavior for the fixture.
804 if CONF.validation.run_validation:
805 params = self._validation_resources_params_from_conf()
806
807 validation = self.useFixture(
808 vr.ValidationResourcesFixture(os_clients, **params))
809 return validation.resources
nithya-ganesan222efd72015-01-22 12:20:27 +0000810
811 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000812 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500813 dhcp=False):
814 """Specify which network resources should be created
815
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100816 The dynamic credentials provider by default provisions network
817 resources for each user/project that is provisioned. This behavior
818 can be altered using this method, which allows tests to define which
819 specific network resources to be provisioned - none if no parameter
820 is specified.
821
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100822 This method is designed so that only the network resources set on the
823 leaf class are honoured.
824
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100825 Credentials are provisioned as part of the class setup fixture,
826 during the `setup_credentials` step. For this to be effective this
827 helper must be invoked before super's `setup_credentials` is executed.
828
Matthew Treinish9f756a02014-01-15 10:26:07 -0500829 @param network
830 @param router
831 @param subnet
832 @param dhcp
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100833
834 Example::
835
836 @classmethod
837 def setup_credentials(cls):
838 # Do not setup network resources for this test
839 cls.set_network_resources()
840 super(MyTest, cls).setup_credentials()
Matthew Treinish9f756a02014-01-15 10:26:07 -0500841 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100842 # If this is invoked after the credentials are setup, it won't take
843 # any effect. To avoid this situation, fail the test in case this was
844 # invoked too late in the test lifecycle.
845 if cls.__setup_credentials_called:
846 raise RuntimeError(
847 "set_network_resources invoked after setup_credentials on the "
848 "super class has been already invoked. For "
849 "set_network_resources to have effect please invoke it before "
850 "the call to super().setup_credentials")
851
852 # Network resources should be set only once from callers
Salvatore Orlando5a337242014-01-15 22:49:22 +0000853 # in order to ensure that even if it's called multiple times in
854 # a chain of overloaded methods, the attribute is set only
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100855 # in the leaf class.
856 if not cls._network_resources:
857 cls._network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000858 'network': network,
859 'router': router,
860 'subnet': subnet,
861 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500862
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530863 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000864 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530865 """Get the network to be used in testing
866
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000867 :param credentials_type: The type of credentials for which to get the
868 tenant network
869
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530870 :return: network dict including 'id' and 'name'
871 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000872 # Get a manager for the given credentials_type, but at least
873 # always fall back on getting the manager for primary credentials
songwenpinga6ee2d12021-02-22 10:24:16 +0800874 if isinstance(credentials_type, str):
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000875 manager = cls.get_client_manager(credential_type=credentials_type)
876 elif isinstance(credentials_type, list):
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600877 scope = 'project'
878 if credentials_type[0].startswith('system'):
879 scope = 'system'
880 elif credentials_type[0].startswith('domain'):
881 scope = 'domain'
882 manager = cls.get_client_manager(roles=credentials_type[1:],
883 scope=scope)
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000884 else:
885 manager = cls.get_client_manager()
886
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700887 # Make sure cred_provider exists and get a network client
zhufl33289a22018-01-04 15:02:00 +0800888 networks_client = manager.networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100889 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100890 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800891 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100892 # for their servers, so using an admin network client to validate
893 # the network name
894 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100895 credentials.is_admin_available(
896 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100897 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100898 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400899 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900900 return fixed_network.get_tenant_network(
901 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530902
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100903 def assertEmpty(self, items, msg=None):
904 """Asserts whether a sequence or collection is empty
Mark Maglana5885eb32014-02-28 10:57:34 -0800905
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100906 :param items: sequence or collection to be tested
907 :param msg: message to be passed to the AssertionError
908 :raises AssertionError: when items is not empty
909 """
zhufl92ade4b2017-03-03 15:20:10 +0800910 if msg is None:
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100911 msg = "sequence or collection is not empty: %s" % items
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900912 self.assertFalse(items, msg)
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100913
914 def assertNotEmpty(self, items, msg=None):
915 """Asserts whether a sequence or collection is not empty
916
917 :param items: sequence or collection to be tested
918 :param msg: message to be passed to the AssertionError
919 :raises AssertionError: when items is empty
920 """
921 if msg is None:
922 msg = "sequence or collection is empty."
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900923 self.assertTrue(items, msg)