blob: 8ea3b16538b1b59586dd392e95d8749d19dd8d39 [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 Manne64c78d2019-10-10 22:26:43 +000029from tempest.lib import base as lib_base
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 Frittolia5ddd552014-08-19 18:30:00 +0100144 # All the configuration checks that may generate a skip
Ghanshyam Mann68ddf412019-09-10 19:40:52 +0000145 # TODO(gmann): cls.handle_skip_exception is really workaround for
146 # testtools bug- https://github.com/testing-cabal/testtools/issues/272
147 # stestr which is used by Tempest internally to run the test switch
148 # the customize test runner(which use stdlib unittest) for >=py3.5
149 # else testtools.run.- https://github.com/mtreinish/stestr/pull/265
150 # These two test runner are not compatible due to skip exception
151 # handling(due to unittest2). testtools.run treat unittestt.SkipTest
152 # as error and stdlib unittest treat unittest2.case.SkipTest raised
153 # by testtools.TestCase.skipException.
154 # The below workaround can be removed once testtools fix issue# 272.
Ghanshyam Manne64c78d2019-10-10 22:26:43 +0000155 orig_skip_exception = testtools.TestCase.skipException
156 lib_base._handle_skip_exception()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100157 try:
Ghanshyam Mann68ddf412019-09-10 19:40:52 +0000158 cls.skip_checks()
159
160 if not cls.__skip_checks_called:
161 raise RuntimeError(
162 "skip_checks for %s did not call the super's "
163 "skip_checks" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100164 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100165 cls._teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100166 cls.setup_credentials()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100167 if not cls.__setup_credentials_called:
168 raise RuntimeError("setup_credentials for %s did not call the "
169 "super's setup_credentials" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100170 # Shortcuts to clients
171 cls.setup_clients()
172 # Additional class-wide test resources
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100173 cls._teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100174 cls.resource_setup()
175 except Exception:
176 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100177 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
178 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100179 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100180 try:
songwenpinge6623072021-02-22 14:47:34 +0800181 raise value.with_traceback(trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100182 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100183 del trace # to avoid circular refs
Ghanshyam Manne64c78d2019-10-10 22:26:43 +0000184 finally:
185 testtools.TestCase.skipException = orig_skip_exception
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200186
Attila Fazekasf86fa312013-07-30 19:56:39 +0200187 @classmethod
188 def tearDownClass(cls):
Martin Kopecae155b72017-06-26 09:41:21 +0000189 # insert pdb breakpoint when pause_teardown is enabled
190 if CONF.pause_teardown:
191 cls.insert_pdb_breakpoint()
Attila Fazekas5d275302013-08-29 12:35:12 +0200192 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100193 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200194 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
195 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100196 # Save any existing exception, we always want to re-raise the original
197 # exception only
198 etype, value, trace = sys.exc_info()
199 # If there was no exception during setup we shall re-raise the first
200 # exception in teardown
201 re_raise = (etype is None)
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100202 while cls._teardowns:
203 name, teardown = cls._teardowns.pop()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100204 # Catch any exception in tearDown so we can re-raise the original
205 # exception at the end
206 try:
207 teardown()
Andrea Frittoli3be57482017-08-25 22:41:26 +0100208 if name == 'resources':
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100209 if not cls.__resource_cleanup_called:
Andrea Frittoli3be57482017-08-25 22:41:26 +0100210 raise RuntimeError(
211 "resource_cleanup for %s did not call the "
212 "super's resource_cleanup" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100213 except Exception as te:
214 sys_exec_info = sys.exc_info()
215 tetype = sys_exec_info[0]
Andrea Frittoli3be57482017-08-25 22:41:26 +0100216 # TODO(andreaf): Resource cleanup is often implemented by
217 # storing an array of resources at class level, and cleaning
218 # them up during `resource_cleanup`.
219 # In case of failure during setup, some resource arrays might
220 # not be defined at all, in which case the cleanup code might
221 # trigger an AttributeError. In such cases we log
222 # AttributeError as info instead of exception. Once all
223 # cleanups are migrated to addClassResourceCleanup we can
224 # remove this.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100225 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100226 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100227 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100228 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100229 if not etype:
230 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800231 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100232 # the first one
233 if re_raise and etype is not None:
234 try:
songwenpinge6623072021-02-22 14:47:34 +0800235 raise value.with_traceback(trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100236 finally:
237 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100238
Martin Kopecae155b72017-06-26 09:41:21 +0000239 def tearDown(self):
240 super(BaseTestCase, self).tearDown()
241 # insert pdb breakpoint when pause_teardown is enabled
242 if CONF.pause_teardown:
243 BaseTestCase.insert_pdb_breakpoint()
244
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100245 if CONF.profiler.key:
246 profiler.disable()
247
Martin Kopecae155b72017-06-26 09:41:21 +0000248 @classmethod
249 def insert_pdb_breakpoint(cls):
250 """Add pdb breakpoint.
251
252 This can help in debugging process, cleaning of resources is
253 paused, so they can be examined.
254 """
255 import pdb
256 pdb.set_trace()
257
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100258 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100259 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000260 """Class level skip checks.
261
262 Subclasses verify in here all conditions that might prevent the
Andrea Frittolia5440c82017-08-23 18:11:21 +0100263 execution of the entire test class. Skipping here prevents any other
264 class fixture from being executed i.e. no credentials or other
265 resource allocation will happen.
266
267 Tests defined in the test class will no longer appear in test results.
268 The `setUpClass` for the entire test class will be marked as SKIPPED
269 instead.
270
271 At this stage no test credentials are available, so skip checks
272 should rely on configuration alone. This is deliberate since skips
273 based on the result of an API call are discouraged.
274
275 The following checks are implemented in `test.py` already:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600276
Andrea Frittolia5440c82017-08-23 18:11:21 +0100277 - check that alt credentials are available when requested by the test
278 - check that admin credentials are available when requested by the test
279 - check that the identity version specified by the test is marked as
280 enabled in the configuration
281
282 Overriders of skip_checks must always invoke skip_check on `super`
283 first.
284
285 Example::
286
287 @classmethod
288 def skip_checks(cls):
289 super(Example, cls).skip_checks()
290 if not CONF.service_available.my_service:
291 skip_msg = ("%s skipped as my_service is not available")
292 raise cls.skipException(skip_msg % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100293 """
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100294 cls.__skip_checks_called = True
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100295 identity_version = cls.get_identity_version()
zhufl75498ba2017-08-25 10:49:35 +0800296 # setting force_tenant_isolation to True also needs admin credentials.
297 if ('admin' in cls.credentials or
Ghanshyam Mann420586c2021-01-29 13:23:18 -0600298 'alt_admin' in cls.credentials or
zhufl75498ba2017-08-25 10:49:35 +0800299 getattr(cls, 'force_tenant_isolation', False)):
300 if not credentials.is_admin_available(
301 identity_version=identity_version):
302 raise cls.skipException(
303 "Missing Identity Admin API credentials in configuration.")
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100304 if 'alt' in cls.credentials and not credentials.is_alt_available(
305 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000306 msg = "Missing a 2nd set of API credentials in configuration."
307 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100308 if hasattr(cls, 'identity_version'):
309 if cls.identity_version == 'v2':
310 if not CONF.identity_feature_enabled.api_v2:
311 raise cls.skipException("Identity api v2 is not enabled")
312 elif cls.identity_version == 'v3':
313 if not CONF.identity_feature_enabled.api_v3:
314 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100315
316 @classmethod
317 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300318 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000319
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100320 `setup_credentials` looks for the content of the `credentials`
321 attribute in the test class. If the value is a non-empty collection,
322 a credentials provider is setup, and credentials are provisioned or
323 allocated based on the content of the collection. Every set of
324 credentials is associated to an object of type `cls.client_manager`.
325 The client manager is accessible by tests via class attribute
326 `os_[type]`:
edannon6cc6fbc2016-05-03 11:56:12 +0300327
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100328 Valid values in `credentials` are:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600329
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100330 - 'primary':
331 A normal user is provisioned.
332 It can be used only once. Multiple entries will be ignored.
333 Clients are available at os_primary.
334 - 'alt':
335 A normal user other than 'primary' is provisioned.
336 It can be used only once. Multiple entries will be ignored.
337 Clients are available at os_alt.
338 - 'admin':
339 An admin user is provisioned.
340 It can be used only once. Multiple entries will be ignored.
341 Clients are available at os_admin.
342 - A list in the format ['any_label', 'role1', ... , 'roleN']:
343 A client with roles <list>[1:] is provisioned.
344 It can be used multiple times, with unique labels.
345 Clients are available at os_roles_<list>[0].
346
347 By default network resources are allocated (in case of dynamic
348 credentials). Tests that do not need network or that require a
349 custom network setup must specify which network resources shall
350 be provisioned using the `set_network_resources()` method (note
351 that it must be invoked before the `setup_credentials` is
352 invoked on super).
353
354 Example::
355
356 class TestWithCredentials(test.BaseTestCase):
357
358 credentials = ['primary', 'admin',
359 ['special', 'special_role1']]
360
361 @classmethod
362 def setup_credentials(cls):
363 # set_network_resources must be called first
364 cls.set_network_resources(network=True)
365 super(TestWithCredentials, cls).setup_credentials()
366
367 @classmethod
368 def setup_clients(cls):
369 cls.servers = cls.os_primary.compute.ServersClient()
370 cls.admin_servers = cls.os_admin.compute.ServersClient()
371 # certain API calls may require a user with a specific
372 # role assigned. In this example `special_role1` is
373 # assigned to the user in `cls.os_roles_special`.
374 cls.special_servers = (
375 cls.os_roles_special.compute.ServersClient())
376
377 def test_special_servers(self):
378 # Do something with servers
379 pass
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000380 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100381 cls.__setup_credentials_called = True
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000382 for credentials_type in cls.credentials:
383 # This may raise an exception in case credentials are not available
384 # In that case we want to let the exception through and the test
385 # fail accordingly
songwenpinga6ee2d12021-02-22 10:24:16 +0800386 if isinstance(credentials_type, str):
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100387 manager = cls.get_client_manager(
388 credential_type=credentials_type)
389 setattr(cls, 'os_%s' % credentials_type, manager)
Jordan Pittier8160d312017-04-18 11:52:23 +0200390 # NOTE(jordanP): Tempest should use os_primary, os_admin
391 # and os_alt throughout its code base but we keep the aliases
392 # around for a while for Tempest plugins. Aliases should be
393 # removed eventually.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100394 # Setup some common aliases
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100395 if credentials_type == 'primary':
Jordan Pittier8160d312017-04-18 11:52:23 +0200396 cls.os = debtcollector.moves.moved_read_only_property(
397 'os', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200398 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200399 cls.manager =\
400 debtcollector.moves.moved_read_only_property(
401 'manager', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200402 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100403 if credentials_type == 'admin':
Jordan Pittier8160d312017-04-18 11:52:23 +0200404 cls.os_adm = debtcollector.moves.moved_read_only_property(
405 'os_adm', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200406 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200407 cls.admin_manager =\
408 debtcollector.moves.moved_read_only_property(
409 'admin_manager', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200410 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100411 if credentials_type == 'alt':
Jordan Pittier8160d312017-04-18 11:52:23 +0200412 cls.alt_manager =\
413 debtcollector.moves.moved_read_only_property(
414 'alt_manager', 'os_alt', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200415 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100416 elif isinstance(credentials_type, list):
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600417 scope = 'project'
418 if credentials_type[0].startswith('system'):
419 scope = 'system'
420 elif credentials_type[0].startswith('domain'):
421 scope = 'domain'
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100422 manager = cls.get_client_manager(roles=credentials_type[1:],
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600423 force_new=True,
424 scope=scope)
425 setattr(cls, 'os_%s' % credentials_type[0], manager)
426 # TODO(gmann): Setting the old style attribute too for
427 # backward compatibility but at some point we should
428 # remove this.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100429 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100430
431 @classmethod
432 def setup_clients(cls):
Andrea Frittoli99583672017-08-24 15:39:20 +0100433 """Create aliases to the clients in the client managers.
434
435 `setup_clients` is invoked after the credential provisioning step.
436 Client manager objects are available to tests already. The purpose
437 of this helper is to setup shortcuts to specific clients that are
438 useful for the tests implemented in the test class.
439
440 Its purpose is mostly for code readability, however it should be used
441 carefully to avoid doing exactly the opposite, i.e. making the code
442 unreadable and hard to debug. If aliases are defined in a super class
443 it won't be obvious what they refer to, so it's good practice to define
444 all aliases used in the class. Aliases are meant to be shortcuts to
445 be used in tests, not shortcuts to avoid helper method attributes.
446 If an helper method starts relying on a client alias and a subclass
447 overrides that alias, it will become rather difficult to understand
448 what the helper method actually does.
449
450 Example::
451
452 class TestDoneItRight(test.BaseTestCase):
453
454 credentials = ['primary', 'alt']
455
456 @classmethod
457 def setup_clients(cls):
458 super(TestDoneItRight, cls).setup_clients()
459 cls.servers = cls.os_primary.ServersClient()
460 cls.servers_alt = cls.os_alt.ServersClient()
461
462 def _a_good_helper(self, clients):
463 # Some complex logic we're going to use many times
464 servers = clients.ServersClient()
465 vm = servers.create_server(...)
466
467 def delete_server():
468 test_utils.call_and_ignore_notfound_exc(
469 servers.delete_server, vm['id'])
470
471 self.addCleanup(self.delete_server)
472 return vm
473
474 def test_with_servers(self):
475 vm = self._a_good_helper(os.primary)
476 vm_alt = self._a_good_helper(os.alt)
477 cls.servers.show_server(vm['id'])
478 cls.servers_alt.show_server(vm_alt['id'])
479 """
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100480 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200481
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000482 @classmethod
483 def resource_setup(cls):
Andrea Frittoli3be57482017-08-25 22:41:26 +0100484 """Class level resource setup for test cases.
485
486 `resource_setup` is invoked once all credentials (and related network
487 resources have been provisioned and after client aliases - if any -
488 have been defined.
489
490 The use case for `resource_setup` is test optimization: provisioning
491 of project-specific "expensive" resources that are not dirtied by tests
492 and can thus safely be re-used by multiple tests.
493
494 System wide resources shared by all tests could instead be provisioned
495 only once, before the test run.
496
497 Resources provisioned here must be cleaned up during
498 `resource_cleanup`. This is best achieved by scheduling a cleanup via
499 `addClassResourceCleanup`.
500
501 Some test resources have an asynchronous delete process. It's best
502 practice for them to schedule a wait for delete via
503 `addClassResourceCleanup` to avoid having resources in process of
504 deletion when we reach the credentials cleanup step.
505
506 Example::
507
508 @classmethod
509 def resource_setup(cls):
510 super(MyTest, cls).resource_setup()
511 servers = cls.os_primary.compute.ServersClient()
512 # Schedule delete and wait so that we can first delete the
513 # two servers and then wait for both to delete
514 # Create server 1
515 cls.shared_server = servers.create_server()
516 # Create server 2. If something goes wrong we schedule cleanup
517 # of server 1 anyways.
518 try:
519 cls.shared_server2 = servers.create_server()
520 # Wait server 2
521 cls.addClassResourceCleanup(
522 waiters.wait_for_server_termination,
523 servers, cls.shared_server2['id'],
524 ignore_error=False)
525 finally:
526 # Wait server 1
527 cls.addClassResourceCleanup(
528 waiters.wait_for_server_termination,
529 servers, cls.shared_server['id'],
530 ignore_error=False)
531 # Delete server 1
532 cls.addClassResourceCleanup(
533 test_utils.call_and_ignore_notfound_exc,
534 servers.delete_server,
535 cls.shared_server['id'])
536 # Delete server 2 (if it was created)
537 if hasattr(cls, 'shared_server2'):
538 cls.addClassResourceCleanup(
539 test_utils.call_and_ignore_notfound_exc,
540 servers.delete_server,
541 cls.shared_server2['id'])
542 """
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100543 pass
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000544
545 @classmethod
546 def resource_cleanup(cls):
547 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000548
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100549 Resource cleanup processes the stack of cleanups produced by
Andrea Frittoli3be57482017-08-25 22:41:26 +0100550 `addClassResourceCleanup` and then cleans up validation resources
551 if any were provisioned.
552
553 All cleanups are processed whatever the outcome. Exceptions are
554 accumulated and re-raised as a `MultipleExceptions` at the end.
555
556 In most cases test cases won't need to override `resource_cleanup`,
557 but if they do they must invoke `resource_cleanup` on super.
558
559 Example::
560
561 class TestWithReallyComplexCleanup(test.BaseTestCase):
562
563 @classmethod
564 def resource_setup(cls):
565 # provision resource A
566 cls.addClassResourceCleanup(delete_resource, A)
567 # provision resource B
568 cls.addClassResourceCleanup(delete_resource, B)
569
570 @classmethod
571 def resource_cleanup(cls):
572 # It's possible to override resource_cleanup but in most
573 # cases it shouldn't be required. Nothing that may fail
574 # should be executed before the call to super since it
575 # might cause resource leak in case of error.
576 super(TestWithReallyComplexCleanup, cls).resource_cleanup()
577 # At this point test credentials are still available but
578 # anything from the cleanup stack has been already deleted.
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000579 """
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100580 cls.__resource_cleanup_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100581 cleanup_errors = []
582 while cls._class_cleanups:
583 try:
584 fn, args, kwargs = cls._class_cleanups.pop()
585 fn(*args, **kwargs)
586 except Exception:
587 cleanup_errors.append(sys.exc_info())
Andrea Frittoli3be57482017-08-25 22:41:26 +0100588 if cleanup_errors:
589 raise testtools.MultipleExceptions(*cleanup_errors)
590
591 @classmethod
592 def addClassResourceCleanup(cls, fn, *arguments, **keywordArguments):
593 """Add a cleanup function to be called during resource_cleanup.
594
595 Functions added with addClassResourceCleanup will be called in reverse
596 order of adding at the beginning of resource_cleanup, before any
597 credential, networking or validation resources cleanup is processed.
598
599 If a function added with addClassResourceCleanup raises an exception,
600 the error will be recorded as a test error, and the next cleanup will
601 then be run.
602
603 Cleanup functions are always called during the test class tearDown
604 fixture, even if an exception occured during setUp or tearDown.
605 """
606 cls._class_cleanups.append((fn, arguments, keywordArguments))
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000607
Attila Fazekasf86fa312013-07-30 19:56:39 +0200608 def setUp(self):
609 super(BaseTestCase, self).setUp()
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600610 if not self.__setupclass_called:
zhuflde676372018-11-16 15:34:56 +0800611 raise RuntimeError("setUpClass does not calls the super's "
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200612 "setUpClass in the " +
613 self.__class__.__name__)
Attila Fazekasf86fa312013-07-30 19:56:39 +0200614 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400615 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
616 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500617 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400618 except ValueError:
619 test_timeout = 0
620 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200621 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400622
623 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
624 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200625 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
626 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400627 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
628 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200629 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
630 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200631 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200632 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200633 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400634 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200635 level=None))
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100636 if CONF.profiler.key:
637 profiler.enable(CONF.profiler.key)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400638
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100639 @property
640 def credentials_provider(self):
641 return self._get_credentials_provider()
642
643 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100644 def get_identity_version(cls):
645 """Returns the identity version used by the test class"""
646 identity_version = getattr(cls, 'identity_version', None)
647 return identity_version or CONF.identity.auth_version
648
649 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100650 def _get_credentials_provider(cls):
651 """Returns a credentials provider
652
653 If no credential provider exists yet creates one.
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100654 It always use the configuration value from identity.auth_version,
655 since we always want to provision accounts with the current version
656 of the identity API.
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100657 """
658 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
659 not cls._creds_provider.name == cls.__name__):
660 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
661 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100662
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700663 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100664 name=cls.__name__, network_resources=cls._network_resources,
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100665 force_tenant_isolation=force_tenant_isolation)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100666 return cls._creds_provider
667
Matthew Treinish3e046852013-07-23 16:00:24 -0400668 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100669 def get_client_manager(cls, credential_type=None, roles=None,
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600670 force_new=None, scope=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100671 """Returns an OpenStack client manager
672
673 Returns an OpenStack client manager based on either credential_type
674 or a list of roles. If neither is specified, it defaults to
675 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100676 :param credential_type: string - primary, alt or admin
677 :param roles: list of roles
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600678 :param scope: scope for the test user
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100679
lei zhangdd552b22015-11-25 20:41:48 +0800680 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100681 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700682 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100683 if all([roles, credential_type]):
684 msg = "Cannot get credentials by type and roles at the same time"
685 raise ValueError(msg)
686 if not any([roles, credential_type]):
687 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100688 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100689 if roles:
690 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100691 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100692 skip_msg = (
693 "%s skipped because the configured credential provider"
694 " is not able to provide credentials with the %s role "
695 "assigned." % (cls.__name__, role))
696 raise cls.skipException(skip_msg)
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600697 params = dict(roles=roles, scope=scope)
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100698 if force_new is not None:
699 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100700 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000701 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100702 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100703 if hasattr(cred_provider, credentials_method):
704 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100705 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100706 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100707 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100708 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000709 # NOTE(andreaf) Ensure credentials have user and project id fields.
710 # It may not be the case when using pre-provisioned credentials.
711 manager.auth_provider.set_auth()
712 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700713
714 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700715 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000716 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200717 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700718 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700719
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100720 @staticmethod
721 def _validation_resources_params_from_conf():
722 return dict(
723 keypair=(CONF.validation.auth_method.lower() == "keypair"),
724 floating_ip=(CONF.validation.connect_method.lower() == "floating"),
725 security_group=CONF.validation.security_group,
726 security_group_rules=CONF.validation.security_group_rules,
727 use_neutron=CONF.service_available.neutron,
728 ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
729 floating_network_id=CONF.network.public_network_id,
730 floating_network_name=CONF.network.floating_network_name)
731
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700732 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100733 def get_class_validation_resources(cls, os_clients):
734 """Provision validation resources according to configuration
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000735
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100736 This is a wrapper around `create_validation_resources` from
737 `tempest.common.validation_resources` that passes parameters from
738 Tempest configuration. Only one instance of class level
739 validation resources is managed by the helper, so If resources
740 were already provisioned before, existing ones will be returned.
nithya-ganesan222efd72015-01-22 12:20:27 +0000741
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100742 Resources are returned as a dictionary. They are also scheduled for
743 automatic cleanup during class teardown using
744 `addClassResourcesCleanup`.
745
746 If `CONF.validation.run_validation` is False no resource will be
747 provisioned at all.
748
749 @param os_clients: Clients to be used to provision the resources.
nithya-ganesan222efd72015-01-22 12:20:27 +0000750 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400751 if not CONF.validation.run_validation:
752 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100753
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100754 if os_clients in cls._validation_resources:
755 return cls._validation_resources[os_clients]
Jordan Pittier79cd1822016-12-08 17:20:35 +0100756
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100757 if (CONF.validation.ip_version_for_ssh not in (4, 6) and
758 CONF.service_available.neutron):
759 msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
760 raise lib_exc.InvalidConfiguration(
761 msg % CONF.validation.ip_version_for_ssh)
Jordan Pittier79cd1822016-12-08 17:20:35 +0100762
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100763 resources = vr.create_validation_resources(
764 os_clients,
765 **cls._validation_resources_params_from_conf())
Jordan Pittier79cd1822016-12-08 17:20:35 +0100766
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100767 cls.addClassResourceCleanup(
768 vr.clear_validation_resources, os_clients,
769 use_neutron=CONF.service_available.neutron,
770 **resources)
771 cls._validation_resources[os_clients] = resources
772 return resources
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500773
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100774 def get_test_validation_resources(self, os_clients):
775 """Returns a dict of validation resources according to configuration
776
777 Initialise a validation resources fixture based on configuration.
778 Start the fixture and returns the validation resources.
779
780 If `CONF.validation.run_validation` is False no resource will be
781 provisioned at all.
782
783 @param os_clients: Clients to be used to provision the resources.
784 """
785
786 params = {}
787 # Test will try to use the fixture, so for this to be useful
788 # we must return a fixture. If validation is disabled though
789 # we don't need to provision anything, which is the default
790 # behavior for the fixture.
791 if CONF.validation.run_validation:
792 params = self._validation_resources_params_from_conf()
793
794 validation = self.useFixture(
795 vr.ValidationResourcesFixture(os_clients, **params))
796 return validation.resources
nithya-ganesan222efd72015-01-22 12:20:27 +0000797
798 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000799 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500800 dhcp=False):
801 """Specify which network resources should be created
802
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100803 The dynamic credentials provider by default provisions network
804 resources for each user/project that is provisioned. This behavior
805 can be altered using this method, which allows tests to define which
806 specific network resources to be provisioned - none if no parameter
807 is specified.
808
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100809 This method is designed so that only the network resources set on the
810 leaf class are honoured.
811
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100812 Credentials are provisioned as part of the class setup fixture,
813 during the `setup_credentials` step. For this to be effective this
814 helper must be invoked before super's `setup_credentials` is executed.
815
Matthew Treinish9f756a02014-01-15 10:26:07 -0500816 @param network
817 @param router
818 @param subnet
819 @param dhcp
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100820
821 Example::
822
823 @classmethod
824 def setup_credentials(cls):
825 # Do not setup network resources for this test
826 cls.set_network_resources()
827 super(MyTest, cls).setup_credentials()
Matthew Treinish9f756a02014-01-15 10:26:07 -0500828 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100829 # If this is invoked after the credentials are setup, it won't take
830 # any effect. To avoid this situation, fail the test in case this was
831 # invoked too late in the test lifecycle.
832 if cls.__setup_credentials_called:
833 raise RuntimeError(
834 "set_network_resources invoked after setup_credentials on the "
835 "super class has been already invoked. For "
836 "set_network_resources to have effect please invoke it before "
837 "the call to super().setup_credentials")
838
839 # Network resources should be set only once from callers
Salvatore Orlando5a337242014-01-15 22:49:22 +0000840 # in order to ensure that even if it's called multiple times in
841 # a chain of overloaded methods, the attribute is set only
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100842 # in the leaf class.
843 if not cls._network_resources:
844 cls._network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000845 'network': network,
846 'router': router,
847 'subnet': subnet,
848 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500849
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530850 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000851 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530852 """Get the network to be used in testing
853
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000854 :param credentials_type: The type of credentials for which to get the
855 tenant network
856
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530857 :return: network dict including 'id' and 'name'
858 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000859 # Get a manager for the given credentials_type, but at least
860 # always fall back on getting the manager for primary credentials
songwenpinga6ee2d12021-02-22 10:24:16 +0800861 if isinstance(credentials_type, str):
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000862 manager = cls.get_client_manager(credential_type=credentials_type)
863 elif isinstance(credentials_type, list):
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600864 scope = 'project'
865 if credentials_type[0].startswith('system'):
866 scope = 'system'
867 elif credentials_type[0].startswith('domain'):
868 scope = 'domain'
869 manager = cls.get_client_manager(roles=credentials_type[1:],
870 scope=scope)
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000871 else:
872 manager = cls.get_client_manager()
873
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700874 # Make sure cred_provider exists and get a network client
zhufl33289a22018-01-04 15:02:00 +0800875 networks_client = manager.networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100876 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100877 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800878 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100879 # for their servers, so using an admin network client to validate
880 # the network name
881 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100882 credentials.is_admin_available(
883 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100884 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100885 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400886 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900887 return fixed_network.get_tenant_network(
888 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530889
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100890 def assertEmpty(self, items, msg=None):
891 """Asserts whether a sequence or collection is empty
Mark Maglana5885eb32014-02-28 10:57:34 -0800892
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100893 :param items: sequence or collection to be tested
894 :param msg: message to be passed to the AssertionError
895 :raises AssertionError: when items is not empty
896 """
zhufl92ade4b2017-03-03 15:20:10 +0800897 if msg is None:
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100898 msg = "sequence or collection is not empty: %s" % items
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900899 self.assertFalse(items, msg)
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100900
901 def assertNotEmpty(self, items, msg=None):
902 """Asserts whether a sequence or collection is not empty
903
904 :param items: sequence or collection to be tested
905 :param msg: message to be passed to the AssertionError
906 :raises AssertionError: when items is empty
907 """
908 if msg is None:
909 msg = "sequence or collection is empty."
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900910 self.assertTrue(items, msg)