blob: 173bfab0035f8487a09f7f137dc8b7b3342abdba [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
Balazs Gibizerdfb30432021-12-14 17:25:16 +010021from fasteners import process_lock
Matthew Treinish78561ad2013-07-26 11:41:56 -040022import fixtures
Balazs Gibizerdfb30432021-12-14 17:25:16 +010023from oslo_concurrency import lockutils
Doug Hellmann583ce2c2015-03-11 14:55:46 +000024from oslo_log import log as logging
ivan-zhu1feeb382013-01-24 10:14:39 +080025import testtools
Jay Pipes051075a2012-04-28 17:39:37 -040026
Matthew Treinish3e046852013-07-23 16:00:24 -040027from tempest import clients
Andrea Frittoli (andreaf)290b3e12015-10-08 10:25:02 +010028from tempest.common import credentials_factory as credentials
Attila Fazekasdc216422013-01-29 15:12:14 +010029from tempest import config
Ghanshyam Mann18b45d72021-12-07 12:37:29 -060030from tempest.lib.common import api_microversion_fixture
Matthew Treinishb19c55d2017-07-17 12:38:35 -040031from tempest.lib.common import fixed_network
Ilya Shakhat1291bb42017-11-29 18:08:16 +010032from tempest.lib.common import profiler
Andrea Frittoli0477acc2017-08-09 21:14:53 +010033from tempest.lib.common import validation_resources as vr
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050034from tempest.lib import decorators
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +010035from tempest.lib import exceptions as lib_exc
Jay Pipes051075a2012-04-28 17:39:37 -040036
37LOG = logging.getLogger(__name__)
38
Sean Dague86bd8422013-12-20 09:56:44 -050039CONF = config.CONF
40
Jay Pipes051075a2012-04-28 17:39:37 -040041
Jordan Pittier3b46d272017-04-12 16:17:28 +020042attr = debtcollector.moves.moved_function(
43 decorators.attr, 'attr', __name__,
44 version='Pike', removal_version='?')
Chris Yeoh55530bb2013-02-08 16:04:27 +103045
46
Attila Fazekasf86fa312013-07-30 19:56:39 +020047at_exit_set = set()
48
49
50def validate_tearDownClass():
51 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -040052 LOG.error(
Federico Ressi2d6bcaa2018-04-11 12:37:36 +020053 "tearDownClass does not call the super's tearDownClass in "
54 "these classes:\n"
55 " %s", at_exit_set)
Sean Dagueeb1523b2014-03-10 10:17:44 -040056
Attila Fazekasf86fa312013-07-30 19:56:39 +020057
58atexit.register(validate_tearDownClass)
59
Attila Fazekas53943322014-02-10 16:07:34 +010060
Matthew Treinish2474f412014-11-17 18:11:56 -050061class BaseTestCase(testtools.testcase.WithAttributes,
62 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +010063 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000064
Andrea Frittolia5ddd552014-08-19 18:30:00 +010065 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
66 by subclasses (enforced via hacking rule T105).
67
68 Set-up is split in a series of steps (setup stages), which can be
69 overwritten by test classes. Set-up stages are:
70 - skip_checks
71 - setup_credentials
72 - setup_clients
73 - resource_setup
74
75 Tear-down is also split in a series of steps (teardown stages), which are
76 stacked for execution only if the corresponding setup stage had been
77 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -070078 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +010079 - resource_cleanup
80 """
Attila Fazekasc43fec82013-04-09 23:17:52 +020081
Andrea Frittolib21de6c2015-02-06 20:12:38 +000082 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +010083 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
84 # a list of roles - the first element of the list being a label, and the
85 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +000086 credentials = []
Andrea Frittolibcbf1af12017-08-14 11:53:35 +010087
Andrea Frittoliba712ac2017-09-13 16:54:47 -060088 # Track if setUpClass was invoked
89 __setupclass_called = False
90
Andrea Frittolibcbf1af12017-08-14 11:53:35 +010091 # Network resources to be provisioned for the requested test credentials.
92 # Only used with the dynamic credentials provider.
93 _network_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -050094
Andrea Frittoli3be57482017-08-25 22:41:26 +010095 # Stack of resource cleanups
96 _class_cleanups = []
97
Andrea Frittoli9f416dd2017-08-10 15:38:00 +010098 # Resources required to validate a server using ssh
99 _validation_resources = {}
100
Sean Dague2ef32ac2014-06-09 11:32:23 -0400101 # NOTE(sdague): log_format is defined inline here instead of using the oslo
102 # default because going through the config path recouples config to the
103 # stress tests too early, and depending on testr order will fail unit tests
104 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
105 '[%(name)s] %(message)s')
106
Ryota MIBU60687e52015-12-09 18:37:39 +0900107 # Client manager class to use in this test case.
108 client_manager = clients.Manager
109
Sean Dague02620fd2016-03-02 15:52:51 -0500110 # A way to adjust slow test classes
111 TIMEOUT_SCALING_FACTOR = 1
112
Balazs Gibizerdfb30432021-12-14 17:25:16 +0100113 # An interprocess lock to implement serial test execution if requested.
114 # The serial test classes are the writers as only one of them can be
115 # executed. The rest of the test classes are the readers as many of them
116 # can be run in parallel.
117 # Only classes can be decorated with @serial decorator not individual test
118 # cases as tempest allows test class level resource setup which could
119 # interfere with serialized execution on test cases level. I.e. the class
120 # setup of one of the test cases could run before taking a test case level
121 # lock.
122 # We cannot init the lock here as external lock needs oslo configuration
123 # to be loaded first to get the lock_path
124 serial_rw_lock = None
125
126 # Defines if the tests in this class should be run without any parallelism
127 # Use the @serial decorator on your test class to indicate such requirement
128 _serial = False
129
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200130 @classmethod
Andrea Frittoli3be57482017-08-25 22:41:26 +0100131 def _reset_class(cls):
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100132 cls.__setup_credentials_called = False
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100133 cls.__resource_cleanup_called = False
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100134 cls.__skip_checks_called = False
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600135 # Stack of callable to be invoked in reverse order
Andrea Frittoli3be57482017-08-25 22:41:26 +0100136 cls._class_cleanups = []
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600137 # Stack of (name, callable) to be invoked in reverse order at teardown
138 cls._teardowns = []
Andrea Frittoli3be57482017-08-25 22:41:26 +0100139
140 @classmethod
Balazs Gibizerdfb30432021-12-14 17:25:16 +0100141 def is_serial_execution_requested(cls):
142 return cls._serial
143
144 @classmethod
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200145 def setUpClass(cls):
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600146 cls.__setupclass_called = True
Balazs Gibizerdfb30432021-12-14 17:25:16 +0100147
148 if cls.serial_rw_lock is None:
149 path = os.path.join(
150 lockutils.get_lock_path(CONF), 'tempest-serial-rw-lock')
151 cls.serial_rw_lock = (
152 process_lock.InterProcessReaderWriterLock(path)
153 )
154
Andrea Frittoli3be57482017-08-25 22:41:26 +0100155 # Reset state
156 cls._reset_class()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100157 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200158 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
159 super(BaseTestCase, cls).setUpClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100160 try:
Balazs Gibizerdfb30432021-12-14 17:25:16 +0100161 if cls.is_serial_execution_requested():
162 LOG.debug('%s taking the write lock', cls.__name__)
163 cls.serial_rw_lock.acquire_write_lock()
164 LOG.debug('%s took the write lock', cls.__name__)
165 else:
166 cls.serial_rw_lock.acquire_read_lock()
167
Ghanshyam Mann68ddf412019-09-10 19:40:52 +0000168 cls.skip_checks()
169
170 if not cls.__skip_checks_called:
171 raise RuntimeError(
172 "skip_checks for %s did not call the super's "
173 "skip_checks" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100174 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100175 cls._teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100176 cls.setup_credentials()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100177 if not cls.__setup_credentials_called:
178 raise RuntimeError("setup_credentials for %s did not call the "
179 "super's setup_credentials" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100180 # Shortcuts to clients
181 cls.setup_clients()
182 # Additional class-wide test resources
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100183 cls._teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100184 cls.resource_setup()
185 except Exception:
186 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100187 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
188 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100189 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100190 try:
songwenpinge6623072021-02-22 14:47:34 +0800191 raise value.with_traceback(trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100192 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100193 del trace # to avoid circular refs
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200194
Attila Fazekasf86fa312013-07-30 19:56:39 +0200195 @classmethod
196 def tearDownClass(cls):
Martin Kopecae155b72017-06-26 09:41:21 +0000197 # insert pdb breakpoint when pause_teardown is enabled
198 if CONF.pause_teardown:
199 cls.insert_pdb_breakpoint()
Attila Fazekas5d275302013-08-29 12:35:12 +0200200 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100201 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200202 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
203 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100204 # Save any existing exception, we always want to re-raise the original
205 # exception only
206 etype, value, trace = sys.exc_info()
207 # If there was no exception during setup we shall re-raise the first
208 # exception in teardown
209 re_raise = (etype is None)
Balazs Gibizerdfb30432021-12-14 17:25:16 +0100210 try:
211 while cls._teardowns:
212 name, teardown = cls._teardowns.pop()
213 # Catch any exception in tearDown so we can re-raise the
214 # original exception at the end
215 try:
216 teardown()
217 if name == 'resources':
218 if not cls.__resource_cleanup_called:
219 raise RuntimeError(
220 "resource_cleanup for %s did not call the "
221 "super's resource_cleanup" % cls.__name__)
222 except Exception as te:
223 sys_exec_info = sys.exc_info()
224 tetype = sys_exec_info[0]
225 # TODO(andreaf): Resource cleanup is often implemented by
226 # storing an array of resources at class level, and
227 # cleaning them up during `resource_cleanup`.
228 # In case of failure during setup, some resource arrays
229 # might not be defined at all, in which case the cleanup
230 # code might trigger an AttributeError. In such cases we
231 # log AttributeError as info instead of exception. Once all
232 # cleanups are migrated to addClassResourceCleanup we can
233 # remove this.
234 if tetype is AttributeError and name == 'resources':
235 LOG.info("tearDownClass of %s failed: %s", name, te)
236 else:
237 LOG.exception("teardown of %s failed: %s", name, te)
238 if not etype:
239 etype, value, trace = sys_exec_info
240 finally:
241 if cls.is_serial_execution_requested():
242 LOG.debug('%s releasing the write lock', cls.__name__)
243 cls.serial_rw_lock.release_write_lock()
244 LOG.debug('%s released the write lock', cls.__name__)
245 else:
246 cls.serial_rw_lock.release_read_lock()
247
Joshua Whitebd769602016-02-02 09:30:11 -0800248 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100249 # the first one
250 if re_raise and etype is not None:
251 try:
songwenpinge6623072021-02-22 14:47:34 +0800252 raise value.with_traceback(trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100253 finally:
254 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100255
Martin Kopecae155b72017-06-26 09:41:21 +0000256 def tearDown(self):
257 super(BaseTestCase, self).tearDown()
258 # insert pdb breakpoint when pause_teardown is enabled
259 if CONF.pause_teardown:
260 BaseTestCase.insert_pdb_breakpoint()
261
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100262 if CONF.profiler.key:
263 profiler.disable()
264
Martin Kopecae155b72017-06-26 09:41:21 +0000265 @classmethod
266 def insert_pdb_breakpoint(cls):
267 """Add pdb breakpoint.
268
269 This can help in debugging process, cleaning of resources is
270 paused, so they can be examined.
271 """
272 import pdb
273 pdb.set_trace()
274
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100275 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100276 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000277 """Class level skip checks.
278
279 Subclasses verify in here all conditions that might prevent the
Andrea Frittolia5440c82017-08-23 18:11:21 +0100280 execution of the entire test class. Skipping here prevents any other
281 class fixture from being executed i.e. no credentials or other
282 resource allocation will happen.
283
284 Tests defined in the test class will no longer appear in test results.
285 The `setUpClass` for the entire test class will be marked as SKIPPED
286 instead.
287
288 At this stage no test credentials are available, so skip checks
289 should rely on configuration alone. This is deliberate since skips
290 based on the result of an API call are discouraged.
291
292 The following checks are implemented in `test.py` already:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600293
Andrea Frittolia5440c82017-08-23 18:11:21 +0100294 - check that alt credentials are available when requested by the test
295 - check that admin credentials are available when requested by the test
296 - check that the identity version specified by the test is marked as
297 enabled in the configuration
298
299 Overriders of skip_checks must always invoke skip_check on `super`
300 first.
301
302 Example::
303
304 @classmethod
305 def skip_checks(cls):
306 super(Example, cls).skip_checks()
307 if not CONF.service_available.my_service:
308 skip_msg = ("%s skipped as my_service is not available")
309 raise cls.skipException(skip_msg % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100310 """
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100311 cls.__skip_checks_called = True
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100312 identity_version = cls.get_identity_version()
zhufl75498ba2017-08-25 10:49:35 +0800313 # setting force_tenant_isolation to True also needs admin credentials.
314 if ('admin' in cls.credentials or
Ghanshyam Mann420586c2021-01-29 13:23:18 -0600315 'alt_admin' in cls.credentials or
zhufl75498ba2017-08-25 10:49:35 +0800316 getattr(cls, 'force_tenant_isolation', False)):
317 if not credentials.is_admin_available(
318 identity_version=identity_version):
319 raise cls.skipException(
320 "Missing Identity Admin API credentials in configuration.")
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100321 if 'alt' in cls.credentials and not credentials.is_alt_available(
322 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000323 msg = "Missing a 2nd set of API credentials in configuration."
324 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100325 if hasattr(cls, 'identity_version'):
326 if cls.identity_version == 'v2':
327 if not CONF.identity_feature_enabled.api_v2:
328 raise cls.skipException("Identity api v2 is not enabled")
329 elif cls.identity_version == 'v3':
330 if not CONF.identity_feature_enabled.api_v3:
331 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100332
333 @classmethod
334 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300335 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000336
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100337 `setup_credentials` looks for the content of the `credentials`
338 attribute in the test class. If the value is a non-empty collection,
339 a credentials provider is setup, and credentials are provisioned or
340 allocated based on the content of the collection. Every set of
341 credentials is associated to an object of type `cls.client_manager`.
342 The client manager is accessible by tests via class attribute
343 `os_[type]`:
edannon6cc6fbc2016-05-03 11:56:12 +0300344
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100345 Valid values in `credentials` are:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600346
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100347 - 'primary':
348 A normal user is provisioned.
349 It can be used only once. Multiple entries will be ignored.
350 Clients are available at os_primary.
351 - 'alt':
352 A normal user other than 'primary' is provisioned.
353 It can be used only once. Multiple entries will be ignored.
354 Clients are available at os_alt.
355 - 'admin':
356 An admin user is provisioned.
357 It can be used only once. Multiple entries will be ignored.
358 Clients are available at os_admin.
359 - A list in the format ['any_label', 'role1', ... , 'roleN']:
360 A client with roles <list>[1:] is provisioned.
361 It can be used multiple times, with unique labels.
362 Clients are available at os_roles_<list>[0].
363
364 By default network resources are allocated (in case of dynamic
365 credentials). Tests that do not need network or that require a
366 custom network setup must specify which network resources shall
367 be provisioned using the `set_network_resources()` method (note
368 that it must be invoked before the `setup_credentials` is
369 invoked on super).
370
371 Example::
372
373 class TestWithCredentials(test.BaseTestCase):
374
375 credentials = ['primary', 'admin',
376 ['special', 'special_role1']]
377
378 @classmethod
379 def setup_credentials(cls):
380 # set_network_resources must be called first
381 cls.set_network_resources(network=True)
382 super(TestWithCredentials, cls).setup_credentials()
383
384 @classmethod
385 def setup_clients(cls):
386 cls.servers = cls.os_primary.compute.ServersClient()
387 cls.admin_servers = cls.os_admin.compute.ServersClient()
388 # certain API calls may require a user with a specific
389 # role assigned. In this example `special_role1` is
390 # assigned to the user in `cls.os_roles_special`.
391 cls.special_servers = (
392 cls.os_roles_special.compute.ServersClient())
393
394 def test_special_servers(self):
395 # Do something with servers
396 pass
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000397 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100398 cls.__setup_credentials_called = True
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000399 for credentials_type in cls.credentials:
400 # This may raise an exception in case credentials are not available
401 # In that case we want to let the exception through and the test
402 # fail accordingly
songwenpinga6ee2d12021-02-22 10:24:16 +0800403 if isinstance(credentials_type, str):
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100404 manager = cls.get_client_manager(
405 credential_type=credentials_type)
406 setattr(cls, 'os_%s' % credentials_type, manager)
Jordan Pittier8160d312017-04-18 11:52:23 +0200407 # NOTE(jordanP): Tempest should use os_primary, os_admin
408 # and os_alt throughout its code base but we keep the aliases
409 # around for a while for Tempest plugins. Aliases should be
410 # removed eventually.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100411 # Setup some common aliases
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100412 if credentials_type == 'primary':
Jordan Pittier8160d312017-04-18 11:52:23 +0200413 cls.os = debtcollector.moves.moved_read_only_property(
414 'os', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200415 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200416 cls.manager =\
417 debtcollector.moves.moved_read_only_property(
418 'manager', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200419 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100420 if credentials_type == 'admin':
Jordan Pittier8160d312017-04-18 11:52:23 +0200421 cls.os_adm = debtcollector.moves.moved_read_only_property(
422 'os_adm', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200423 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200424 cls.admin_manager =\
425 debtcollector.moves.moved_read_only_property(
426 'admin_manager', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200427 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100428 if credentials_type == 'alt':
Jordan Pittier8160d312017-04-18 11:52:23 +0200429 cls.alt_manager =\
430 debtcollector.moves.moved_read_only_property(
431 'alt_manager', 'os_alt', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200432 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100433 elif isinstance(credentials_type, list):
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600434 scope = 'project'
435 if credentials_type[0].startswith('system'):
436 scope = 'system'
437 elif credentials_type[0].startswith('domain'):
438 scope = 'domain'
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100439 manager = cls.get_client_manager(roles=credentials_type[1:],
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600440 force_new=True,
441 scope=scope)
442 setattr(cls, 'os_%s' % credentials_type[0], manager)
443 # TODO(gmann): Setting the old style attribute too for
444 # backward compatibility but at some point we should
445 # remove this.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100446 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100447
448 @classmethod
449 def setup_clients(cls):
Andrea Frittoli99583672017-08-24 15:39:20 +0100450 """Create aliases to the clients in the client managers.
451
452 `setup_clients` is invoked after the credential provisioning step.
453 Client manager objects are available to tests already. The purpose
454 of this helper is to setup shortcuts to specific clients that are
455 useful for the tests implemented in the test class.
456
457 Its purpose is mostly for code readability, however it should be used
458 carefully to avoid doing exactly the opposite, i.e. making the code
459 unreadable and hard to debug. If aliases are defined in a super class
460 it won't be obvious what they refer to, so it's good practice to define
461 all aliases used in the class. Aliases are meant to be shortcuts to
462 be used in tests, not shortcuts to avoid helper method attributes.
463 If an helper method starts relying on a client alias and a subclass
464 overrides that alias, it will become rather difficult to understand
465 what the helper method actually does.
466
467 Example::
468
469 class TestDoneItRight(test.BaseTestCase):
470
471 credentials = ['primary', 'alt']
472
473 @classmethod
474 def setup_clients(cls):
475 super(TestDoneItRight, cls).setup_clients()
476 cls.servers = cls.os_primary.ServersClient()
477 cls.servers_alt = cls.os_alt.ServersClient()
478
479 def _a_good_helper(self, clients):
480 # Some complex logic we're going to use many times
481 servers = clients.ServersClient()
482 vm = servers.create_server(...)
483
484 def delete_server():
485 test_utils.call_and_ignore_notfound_exc(
486 servers.delete_server, vm['id'])
487
488 self.addCleanup(self.delete_server)
489 return vm
490
491 def test_with_servers(self):
492 vm = self._a_good_helper(os.primary)
493 vm_alt = self._a_good_helper(os.alt)
494 cls.servers.show_server(vm['id'])
495 cls.servers_alt.show_server(vm_alt['id'])
496 """
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100497 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200498
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000499 @classmethod
Ghanshyam Mann18b45d72021-12-07 12:37:29 -0600500 def setup_api_microversion_fixture(
501 cls, compute_microversion=None, volume_microversion=None,
502 placement_microversion=None):
503 """Set up api microversion fixture on service clients.
504
505 `setup_api_microversion_fixture` is used to set the api microversion
506 on service clients. This can be invoked from resource_setup() method.
507
508 Example::
509
510 @classmethod
511 def resource_setup(cls):
512 super(MyTest, cls).resource_setup()
513 cls.setup_api_microversion_fixture(
514 compute_microversion=cls.compute_request_microversion,
515 volume_microversion=cls.volume_request_microversion,
516 placement_microversion=cls.placement_request_microversion)
517
518 """
519
520 api_fixture = api_microversion_fixture.APIMicroversionFixture(
521 compute_microversion=compute_microversion,
522 volume_microversion=volume_microversion,
523 placement_microversion=placement_microversion)
524 api_fixture.setUp()
525 cls.addClassResourceCleanup(api_fixture._reset_microversion)
526
527 @classmethod
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000528 def resource_setup(cls):
Andrea Frittoli3be57482017-08-25 22:41:26 +0100529 """Class level resource setup for test cases.
530
531 `resource_setup` is invoked once all credentials (and related network
532 resources have been provisioned and after client aliases - if any -
533 have been defined.
534
535 The use case for `resource_setup` is test optimization: provisioning
536 of project-specific "expensive" resources that are not dirtied by tests
537 and can thus safely be re-used by multiple tests.
538
539 System wide resources shared by all tests could instead be provisioned
540 only once, before the test run.
541
542 Resources provisioned here must be cleaned up during
543 `resource_cleanup`. This is best achieved by scheduling a cleanup via
544 `addClassResourceCleanup`.
545
546 Some test resources have an asynchronous delete process. It's best
547 practice for them to schedule a wait for delete via
548 `addClassResourceCleanup` to avoid having resources in process of
549 deletion when we reach the credentials cleanup step.
550
551 Example::
552
553 @classmethod
554 def resource_setup(cls):
555 super(MyTest, cls).resource_setup()
556 servers = cls.os_primary.compute.ServersClient()
557 # Schedule delete and wait so that we can first delete the
558 # two servers and then wait for both to delete
559 # Create server 1
560 cls.shared_server = servers.create_server()
561 # Create server 2. If something goes wrong we schedule cleanup
562 # of server 1 anyways.
563 try:
564 cls.shared_server2 = servers.create_server()
565 # Wait server 2
566 cls.addClassResourceCleanup(
567 waiters.wait_for_server_termination,
568 servers, cls.shared_server2['id'],
569 ignore_error=False)
570 finally:
571 # Wait server 1
572 cls.addClassResourceCleanup(
573 waiters.wait_for_server_termination,
574 servers, cls.shared_server['id'],
575 ignore_error=False)
576 # Delete server 1
577 cls.addClassResourceCleanup(
578 test_utils.call_and_ignore_notfound_exc,
579 servers.delete_server,
580 cls.shared_server['id'])
581 # Delete server 2 (if it was created)
582 if hasattr(cls, 'shared_server2'):
583 cls.addClassResourceCleanup(
584 test_utils.call_and_ignore_notfound_exc,
585 servers.delete_server,
586 cls.shared_server2['id'])
587 """
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100588 pass
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000589
590 @classmethod
591 def resource_cleanup(cls):
592 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000593
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100594 Resource cleanup processes the stack of cleanups produced by
Andrea Frittoli3be57482017-08-25 22:41:26 +0100595 `addClassResourceCleanup` and then cleans up validation resources
596 if any were provisioned.
597
598 All cleanups are processed whatever the outcome. Exceptions are
599 accumulated and re-raised as a `MultipleExceptions` at the end.
600
601 In most cases test cases won't need to override `resource_cleanup`,
602 but if they do they must invoke `resource_cleanup` on super.
603
604 Example::
605
606 class TestWithReallyComplexCleanup(test.BaseTestCase):
607
608 @classmethod
609 def resource_setup(cls):
610 # provision resource A
611 cls.addClassResourceCleanup(delete_resource, A)
612 # provision resource B
613 cls.addClassResourceCleanup(delete_resource, B)
614
615 @classmethod
616 def resource_cleanup(cls):
617 # It's possible to override resource_cleanup but in most
618 # cases it shouldn't be required. Nothing that may fail
619 # should be executed before the call to super since it
620 # might cause resource leak in case of error.
621 super(TestWithReallyComplexCleanup, cls).resource_cleanup()
622 # At this point test credentials are still available but
623 # anything from the cleanup stack has been already deleted.
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000624 """
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100625 cls.__resource_cleanup_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100626 cleanup_errors = []
627 while cls._class_cleanups:
628 try:
629 fn, args, kwargs = cls._class_cleanups.pop()
630 fn(*args, **kwargs)
631 except Exception:
632 cleanup_errors.append(sys.exc_info())
Andrea Frittoli3be57482017-08-25 22:41:26 +0100633 if cleanup_errors:
634 raise testtools.MultipleExceptions(*cleanup_errors)
635
636 @classmethod
637 def addClassResourceCleanup(cls, fn, *arguments, **keywordArguments):
638 """Add a cleanup function to be called during resource_cleanup.
639
640 Functions added with addClassResourceCleanup will be called in reverse
641 order of adding at the beginning of resource_cleanup, before any
642 credential, networking or validation resources cleanup is processed.
643
644 If a function added with addClassResourceCleanup raises an exception,
645 the error will be recorded as a test error, and the next cleanup will
646 then be run.
647
648 Cleanup functions are always called during the test class tearDown
Rajesh Tailora85bdb42024-04-02 12:01:53 +0530649 fixture, even if an exception occurred during setUp or tearDown.
Andrea Frittoli3be57482017-08-25 22:41:26 +0100650 """
651 cls._class_cleanups.append((fn, arguments, keywordArguments))
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000652
Attila Fazekasf86fa312013-07-30 19:56:39 +0200653 def setUp(self):
654 super(BaseTestCase, self).setUp()
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600655 if not self.__setupclass_called:
zhuflde676372018-11-16 15:34:56 +0800656 raise RuntimeError("setUpClass does not calls the super's "
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200657 "setUpClass in the " +
658 self.__class__.__name__)
Attila Fazekasf86fa312013-07-30 19:56:39 +0200659 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400660 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
661 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500662 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400663 except ValueError:
664 test_timeout = 0
665 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200666 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400667
668 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
669 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200670 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
671 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400672 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
673 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200674 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
675 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200676 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200677 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200678 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400679 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200680 level=None))
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100681 if CONF.profiler.key:
682 profiler.enable(CONF.profiler.key)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400683
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100684 @property
685 def credentials_provider(self):
686 return self._get_credentials_provider()
687
688 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100689 def get_identity_version(cls):
690 """Returns the identity version used by the test class"""
691 identity_version = getattr(cls, 'identity_version', None)
692 return identity_version or CONF.identity.auth_version
693
694 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100695 def _get_credentials_provider(cls):
696 """Returns a credentials provider
697
698 If no credential provider exists yet creates one.
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100699 It always use the configuration value from identity.auth_version,
700 since we always want to provision accounts with the current version
701 of the identity API.
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100702 """
703 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
704 not cls._creds_provider.name == cls.__name__):
705 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
706 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100707
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700708 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100709 name=cls.__name__, network_resources=cls._network_resources,
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100710 force_tenant_isolation=force_tenant_isolation)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100711 return cls._creds_provider
712
Matthew Treinish3e046852013-07-23 16:00:24 -0400713 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100714 def get_client_manager(cls, credential_type=None, roles=None,
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600715 force_new=None, scope=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100716 """Returns an OpenStack client manager
717
718 Returns an OpenStack client manager based on either credential_type
719 or a list of roles. If neither is specified, it defaults to
720 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100721 :param credential_type: string - primary, alt or admin
722 :param roles: list of roles
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600723 :param scope: scope for the test user
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100724
lei zhangdd552b22015-11-25 20:41:48 +0800725 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100726 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700727 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100728 if all([roles, credential_type]):
729 msg = "Cannot get credentials by type and roles at the same time"
730 raise ValueError(msg)
731 if not any([roles, credential_type]):
732 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100733 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100734 if roles:
735 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100736 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100737 skip_msg = (
738 "%s skipped because the configured credential provider"
739 " is not able to provide credentials with the %s role "
740 "assigned." % (cls.__name__, role))
741 raise cls.skipException(skip_msg)
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600742 params = dict(roles=roles, scope=scope)
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100743 if force_new is not None:
744 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100745 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000746 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100747 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100748 if hasattr(cred_provider, credentials_method):
749 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100750 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100751 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100752 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100753 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000754 # NOTE(andreaf) Ensure credentials have user and project id fields.
755 # It may not be the case when using pre-provisioned credentials.
756 manager.auth_provider.set_auth()
757 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700758
759 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700760 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000761 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200762 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700763 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700764
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100765 @staticmethod
766 def _validation_resources_params_from_conf():
767 return dict(
768 keypair=(CONF.validation.auth_method.lower() == "keypair"),
769 floating_ip=(CONF.validation.connect_method.lower() == "floating"),
770 security_group=CONF.validation.security_group,
771 security_group_rules=CONF.validation.security_group_rules,
772 use_neutron=CONF.service_available.neutron,
773 ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
774 floating_network_id=CONF.network.public_network_id,
775 floating_network_name=CONF.network.floating_network_name)
776
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700777 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100778 def get_class_validation_resources(cls, os_clients):
779 """Provision validation resources according to configuration
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000780
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100781 This is a wrapper around `create_validation_resources` from
782 `tempest.common.validation_resources` that passes parameters from
783 Tempest configuration. Only one instance of class level
784 validation resources is managed by the helper, so If resources
785 were already provisioned before, existing ones will be returned.
nithya-ganesan222efd72015-01-22 12:20:27 +0000786
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100787 Resources are returned as a dictionary. They are also scheduled for
788 automatic cleanup during class teardown using
789 `addClassResourcesCleanup`.
790
791 If `CONF.validation.run_validation` is False no resource will be
792 provisioned at all.
793
794 @param os_clients: Clients to be used to provision the resources.
nithya-ganesan222efd72015-01-22 12:20:27 +0000795 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400796 if not CONF.validation.run_validation:
Dan Smith8f9c77b2023-05-01 14:02:46 -0700797 return {}
Jordan Pittier79cd1822016-12-08 17:20:35 +0100798
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100799 if os_clients in cls._validation_resources:
800 return cls._validation_resources[os_clients]
Jordan Pittier79cd1822016-12-08 17:20:35 +0100801
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100802 if (CONF.validation.ip_version_for_ssh not in (4, 6) and
803 CONF.service_available.neutron):
804 msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
805 raise lib_exc.InvalidConfiguration(
806 msg % CONF.validation.ip_version_for_ssh)
Jordan Pittier79cd1822016-12-08 17:20:35 +0100807
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100808 resources = vr.create_validation_resources(
809 os_clients,
810 **cls._validation_resources_params_from_conf())
Jordan Pittier79cd1822016-12-08 17:20:35 +0100811
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100812 cls.addClassResourceCleanup(
813 vr.clear_validation_resources, os_clients,
814 use_neutron=CONF.service_available.neutron,
815 **resources)
816 cls._validation_resources[os_clients] = resources
817 return resources
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500818
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100819 def get_test_validation_resources(self, os_clients):
820 """Returns a dict of validation resources according to configuration
821
822 Initialise a validation resources fixture based on configuration.
823 Start the fixture and returns the validation resources.
824
825 If `CONF.validation.run_validation` is False no resource will be
826 provisioned at all.
827
828 @param os_clients: Clients to be used to provision the resources.
829 """
830
831 params = {}
832 # Test will try to use the fixture, so for this to be useful
833 # we must return a fixture. If validation is disabled though
834 # we don't need to provision anything, which is the default
835 # behavior for the fixture.
836 if CONF.validation.run_validation:
837 params = self._validation_resources_params_from_conf()
838
839 validation = self.useFixture(
840 vr.ValidationResourcesFixture(os_clients, **params))
841 return validation.resources
nithya-ganesan222efd72015-01-22 12:20:27 +0000842
843 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000844 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500845 dhcp=False):
846 """Specify which network resources should be created
847
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100848 The dynamic credentials provider by default provisions network
849 resources for each user/project that is provisioned. This behavior
850 can be altered using this method, which allows tests to define which
851 specific network resources to be provisioned - none if no parameter
852 is specified.
853
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100854 This method is designed so that only the network resources set on the
855 leaf class are honoured.
856
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100857 Credentials are provisioned as part of the class setup fixture,
858 during the `setup_credentials` step. For this to be effective this
859 helper must be invoked before super's `setup_credentials` is executed.
860
Matthew Treinish9f756a02014-01-15 10:26:07 -0500861 @param network
862 @param router
863 @param subnet
864 @param dhcp
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100865
866 Example::
867
868 @classmethod
869 def setup_credentials(cls):
870 # Do not setup network resources for this test
871 cls.set_network_resources()
872 super(MyTest, cls).setup_credentials()
Matthew Treinish9f756a02014-01-15 10:26:07 -0500873 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100874 # If this is invoked after the credentials are setup, it won't take
875 # any effect. To avoid this situation, fail the test in case this was
876 # invoked too late in the test lifecycle.
877 if cls.__setup_credentials_called:
878 raise RuntimeError(
879 "set_network_resources invoked after setup_credentials on the "
880 "super class has been already invoked. For "
881 "set_network_resources to have effect please invoke it before "
882 "the call to super().setup_credentials")
883
884 # Network resources should be set only once from callers
Salvatore Orlando5a337242014-01-15 22:49:22 +0000885 # in order to ensure that even if it's called multiple times in
886 # a chain of overloaded methods, the attribute is set only
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100887 # in the leaf class.
888 if not cls._network_resources:
889 cls._network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000890 'network': network,
891 'router': router,
892 'subnet': subnet,
893 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500894
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530895 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000896 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530897 """Get the network to be used in testing
898
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000899 :param credentials_type: The type of credentials for which to get the
900 tenant network
901
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530902 :return: network dict including 'id' and 'name'
903 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000904 # Get a manager for the given credentials_type, but at least
905 # always fall back on getting the manager for primary credentials
songwenpinga6ee2d12021-02-22 10:24:16 +0800906 if isinstance(credentials_type, str):
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000907 manager = cls.get_client_manager(credential_type=credentials_type)
908 elif isinstance(credentials_type, list):
Ghanshyam Mann2d0da042021-03-05 09:09:30 -0600909 scope = 'project'
910 if credentials_type[0].startswith('system'):
911 scope = 'system'
912 elif credentials_type[0].startswith('domain'):
913 scope = 'domain'
914 manager = cls.get_client_manager(roles=credentials_type[1:],
915 scope=scope)
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000916 else:
917 manager = cls.get_client_manager()
918
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700919 # Make sure cred_provider exists and get a network client
zhufl33289a22018-01-04 15:02:00 +0800920 networks_client = manager.networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100921 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100922 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800923 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100924 # for their servers, so using an admin network client to validate
925 # the network name
926 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100927 credentials.is_admin_available(
928 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100929 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100930 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400931 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900932 return fixed_network.get_tenant_network(
933 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530934
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100935 def assertEmpty(self, items, msg=None):
936 """Asserts whether a sequence or collection is empty
Mark Maglana5885eb32014-02-28 10:57:34 -0800937
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100938 :param items: sequence or collection to be tested
939 :param msg: message to be passed to the AssertionError
940 :raises AssertionError: when items is not empty
941 """
zhufl92ade4b2017-03-03 15:20:10 +0800942 if msg is None:
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100943 msg = "sequence or collection is not empty: %s" % items
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900944 self.assertFalse(items, msg)
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100945
946 def assertNotEmpty(self, items, msg=None):
947 """Asserts whether a sequence or collection is not empty
948
949 :param items: sequence or collection to be tested
950 :param msg: message to be passed to the AssertionError
951 :raises AssertionError: when items is empty
952 """
953 if msg is None:
954 msg = "sequence or collection is empty."
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900955 self.assertTrue(items, msg)