blob: f383bc174eaa256380d2aad7d3d976c87998595e [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
Chris Hoge296558c2015-02-19 00:29:49 -060023import six
ivan-zhu1feeb382013-01-24 10:14:39 +080024import testtools
Jay Pipes051075a2012-04-28 17:39:37 -040025
Matthew Treinish3e046852013-07-23 16:00:24 -040026from tempest import clients
Andrea Frittoli (andreaf)290b3e12015-10-08 10:25:02 +010027from tempest.common import credentials_factory as credentials
Andrea Frittolicd368412017-08-14 21:37:56 +010028from tempest.common import utils
Attila Fazekasdc216422013-01-29 15:12:14 +010029from tempest import config
Ghanshyam Manne64c78d2019-10-10 22:26:43 +000030from tempest.lib import base as lib_base
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
Ken'ichi Ohmichi44f01272017-01-27 18:44:14 -080041# TODO(oomichi): This test.idempotent_id should be removed after all projects
42# switch to use decorators.idempotent_id.
43idempotent_id = debtcollector.moves.moved_function(
44 decorators.idempotent_id, 'idempotent_id', __name__,
45 version='Mitaka', removal_version='?')
Matthew Treinishc1802bc2015-12-03 18:48:11 -050046
Jay Pipes051075a2012-04-28 17:39:37 -040047
Jordan Pittier3b46d272017-04-12 16:17:28 +020048attr = debtcollector.moves.moved_function(
49 decorators.attr, 'attr', __name__,
50 version='Pike', removal_version='?')
Chris Yeoh55530bb2013-02-08 16:04:27 +103051
52
Andrea Frittolicd368412017-08-14 21:37:56 +010053services = debtcollector.moves.moved_function(
54 utils.services, 'services', __name__,
55 version='Pike', removal_version='?')
Andrea Frittoli07acf262017-04-09 19:36:37 +020056
57
Andrea Frittolicd368412017-08-14 21:37:56 +010058requires_ext = debtcollector.moves.moved_function(
59 utils.requires_ext, 'requires_ext', __name__,
60 version='Pike', removal_version='?')
Matthew Treinish16c43792013-09-09 19:55:23 +000061
Matthew Treinish3d8c7322014-08-03 23:53:28 -040062
Andrea Frittolicd368412017-08-14 21:37:56 +010063is_extension_enabled = debtcollector.moves.moved_function(
64 utils.is_extension_enabled, 'is_extension_enabled', __name__,
65 version='Pike', removal_version='?')
Ian Wienand98c35f32013-07-23 20:34:23 +100066
Attila Fazekasf86fa312013-07-30 19:56:39 +020067at_exit_set = set()
68
69
70def validate_tearDownClass():
71 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -040072 LOG.error(
Federico Ressi2d6bcaa2018-04-11 12:37:36 +020073 "tearDownClass does not call the super's tearDownClass in "
74 "these classes:\n"
75 " %s", at_exit_set)
Sean Dagueeb1523b2014-03-10 10:17:44 -040076
Attila Fazekasf86fa312013-07-30 19:56:39 +020077
78atexit.register(validate_tearDownClass)
79
Attila Fazekas53943322014-02-10 16:07:34 +010080
Matthew Treinish2474f412014-11-17 18:11:56 -050081class BaseTestCase(testtools.testcase.WithAttributes,
82 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +010083 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000084
Andrea Frittolia5ddd552014-08-19 18:30:00 +010085 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
86 by subclasses (enforced via hacking rule T105).
87
88 Set-up is split in a series of steps (setup stages), which can be
89 overwritten by test classes. Set-up stages are:
90 - skip_checks
91 - setup_credentials
92 - setup_clients
93 - resource_setup
94
95 Tear-down is also split in a series of steps (teardown stages), which are
96 stacked for execution only if the corresponding setup stage had been
97 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -070098 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +010099 - resource_cleanup
100 """
Attila Fazekasc43fec82013-04-09 23:17:52 +0200101
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000102 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100103 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
104 # a list of roles - the first element of the list being a label, and the
105 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000106 credentials = []
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100107
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600108 # Track if setUpClass was invoked
109 __setupclass_called = False
110
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100111 # Network resources to be provisioned for the requested test credentials.
112 # Only used with the dynamic credentials provider.
113 _network_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500114
Andrea Frittoli3be57482017-08-25 22:41:26 +0100115 # Stack of resource cleanups
116 _class_cleanups = []
117
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100118 # Resources required to validate a server using ssh
119 _validation_resources = {}
120
Sean Dague2ef32ac2014-06-09 11:32:23 -0400121 # NOTE(sdague): log_format is defined inline here instead of using the oslo
122 # default because going through the config path recouples config to the
123 # stress tests too early, and depending on testr order will fail unit tests
124 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
125 '[%(name)s] %(message)s')
126
Ryota MIBU60687e52015-12-09 18:37:39 +0900127 # Client manager class to use in this test case.
128 client_manager = clients.Manager
129
Sean Dague02620fd2016-03-02 15:52:51 -0500130 # A way to adjust slow test classes
131 TIMEOUT_SCALING_FACTOR = 1
132
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200133 @classmethod
Andrea Frittoli3be57482017-08-25 22:41:26 +0100134 def _reset_class(cls):
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100135 cls.__setup_credentials_called = False
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100136 cls.__resource_cleanup_called = False
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100137 cls.__skip_checks_called = False
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600138 # Stack of callable to be invoked in reverse order
Andrea Frittoli3be57482017-08-25 22:41:26 +0100139 cls._class_cleanups = []
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600140 # Stack of (name, callable) to be invoked in reverse order at teardown
141 cls._teardowns = []
Andrea Frittoli3be57482017-08-25 22:41:26 +0100142
143 @classmethod
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200144 def setUpClass(cls):
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600145 cls.__setupclass_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100146 # Reset state
147 cls._reset_class()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100148 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200149 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
150 super(BaseTestCase, cls).setUpClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100151 # All the configuration checks that may generate a skip
Ghanshyam Mann68ddf412019-09-10 19:40:52 +0000152 # TODO(gmann): cls.handle_skip_exception is really workaround for
153 # testtools bug- https://github.com/testing-cabal/testtools/issues/272
154 # stestr which is used by Tempest internally to run the test switch
155 # the customize test runner(which use stdlib unittest) for >=py3.5
156 # else testtools.run.- https://github.com/mtreinish/stestr/pull/265
157 # These two test runner are not compatible due to skip exception
158 # handling(due to unittest2). testtools.run treat unittestt.SkipTest
159 # as error and stdlib unittest treat unittest2.case.SkipTest raised
160 # by testtools.TestCase.skipException.
161 # The below workaround can be removed once testtools fix issue# 272.
Ghanshyam Manne64c78d2019-10-10 22:26:43 +0000162 orig_skip_exception = testtools.TestCase.skipException
163 lib_base._handle_skip_exception()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100164 try:
Ghanshyam Mann68ddf412019-09-10 19:40:52 +0000165 cls.skip_checks()
166
167 if not cls.__skip_checks_called:
168 raise RuntimeError(
169 "skip_checks for %s did not call the super's "
170 "skip_checks" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100171 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100172 cls._teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100173 cls.setup_credentials()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100174 if not cls.__setup_credentials_called:
175 raise RuntimeError("setup_credentials for %s did not call the "
176 "super's setup_credentials" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100177 # Shortcuts to clients
178 cls.setup_clients()
179 # Additional class-wide test resources
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100180 cls._teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100181 cls.resource_setup()
182 except Exception:
183 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100184 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
185 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100186 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100187 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400188 six.reraise(etype, value, trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100189 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100190 del trace # to avoid circular refs
Ghanshyam Manne64c78d2019-10-10 22:26:43 +0000191 finally:
192 testtools.TestCase.skipException = orig_skip_exception
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200193
Attila Fazekasf86fa312013-07-30 19:56:39 +0200194 @classmethod
195 def tearDownClass(cls):
Martin Kopecae155b72017-06-26 09:41:21 +0000196 # insert pdb breakpoint when pause_teardown is enabled
197 if CONF.pause_teardown:
198 cls.insert_pdb_breakpoint()
Attila Fazekas5d275302013-08-29 12:35:12 +0200199 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100200 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200201 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
202 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100203 # Save any existing exception, we always want to re-raise the original
204 # exception only
205 etype, value, trace = sys.exc_info()
206 # If there was no exception during setup we shall re-raise the first
207 # exception in teardown
208 re_raise = (etype is None)
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100209 while cls._teardowns:
210 name, teardown = cls._teardowns.pop()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100211 # Catch any exception in tearDown so we can re-raise the original
212 # exception at the end
213 try:
214 teardown()
Andrea Frittoli3be57482017-08-25 22:41:26 +0100215 if name == 'resources':
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100216 if not cls.__resource_cleanup_called:
Andrea Frittoli3be57482017-08-25 22:41:26 +0100217 raise RuntimeError(
218 "resource_cleanup for %s did not call the "
219 "super's resource_cleanup" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100220 except Exception as te:
221 sys_exec_info = sys.exc_info()
222 tetype = sys_exec_info[0]
Andrea Frittoli3be57482017-08-25 22:41:26 +0100223 # TODO(andreaf): Resource cleanup is often implemented by
224 # storing an array of resources at class level, and cleaning
225 # them up during `resource_cleanup`.
226 # In case of failure during setup, some resource arrays might
227 # not be defined at all, in which case the cleanup code might
228 # trigger an AttributeError. In such cases we log
229 # AttributeError as info instead of exception. Once all
230 # cleanups are migrated to addClassResourceCleanup we can
231 # remove this.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100232 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100233 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100234 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100235 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100236 if not etype:
237 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800238 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100239 # the first one
240 if re_raise and etype is not None:
241 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400242 six.reraise(etype, value, trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100243 finally:
244 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100245
Martin Kopecae155b72017-06-26 09:41:21 +0000246 def tearDown(self):
247 super(BaseTestCase, self).tearDown()
248 # insert pdb breakpoint when pause_teardown is enabled
249 if CONF.pause_teardown:
250 BaseTestCase.insert_pdb_breakpoint()
251
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100252 if CONF.profiler.key:
253 profiler.disable()
254
Martin Kopecae155b72017-06-26 09:41:21 +0000255 @classmethod
256 def insert_pdb_breakpoint(cls):
257 """Add pdb breakpoint.
258
259 This can help in debugging process, cleaning of resources is
260 paused, so they can be examined.
261 """
262 import pdb
263 pdb.set_trace()
264
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100265 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100266 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000267 """Class level skip checks.
268
269 Subclasses verify in here all conditions that might prevent the
Andrea Frittolia5440c82017-08-23 18:11:21 +0100270 execution of the entire test class. Skipping here prevents any other
271 class fixture from being executed i.e. no credentials or other
272 resource allocation will happen.
273
274 Tests defined in the test class will no longer appear in test results.
275 The `setUpClass` for the entire test class will be marked as SKIPPED
276 instead.
277
278 At this stage no test credentials are available, so skip checks
279 should rely on configuration alone. This is deliberate since skips
280 based on the result of an API call are discouraged.
281
282 The following checks are implemented in `test.py` already:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600283
Andrea Frittolia5440c82017-08-23 18:11:21 +0100284 - check that alt credentials are available when requested by the test
285 - check that admin credentials are available when requested by the test
286 - check that the identity version specified by the test is marked as
287 enabled in the configuration
288
289 Overriders of skip_checks must always invoke skip_check on `super`
290 first.
291
292 Example::
293
294 @classmethod
295 def skip_checks(cls):
296 super(Example, cls).skip_checks()
297 if not CONF.service_available.my_service:
298 skip_msg = ("%s skipped as my_service is not available")
299 raise cls.skipException(skip_msg % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100300 """
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100301 cls.__skip_checks_called = True
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100302 identity_version = cls.get_identity_version()
zhufl75498ba2017-08-25 10:49:35 +0800303 # setting force_tenant_isolation to True also needs admin credentials.
304 if ('admin' in cls.credentials or
305 getattr(cls, 'force_tenant_isolation', False)):
306 if not credentials.is_admin_available(
307 identity_version=identity_version):
308 raise cls.skipException(
309 "Missing Identity Admin API credentials in configuration.")
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100310 if 'alt' in cls.credentials and not credentials.is_alt_available(
311 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000312 msg = "Missing a 2nd set of API credentials in configuration."
313 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100314 if hasattr(cls, 'identity_version'):
315 if cls.identity_version == 'v2':
316 if not CONF.identity_feature_enabled.api_v2:
317 raise cls.skipException("Identity api v2 is not enabled")
318 elif cls.identity_version == 'v3':
319 if not CONF.identity_feature_enabled.api_v3:
320 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100321
322 @classmethod
323 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300324 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000325
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100326 `setup_credentials` looks for the content of the `credentials`
327 attribute in the test class. If the value is a non-empty collection,
328 a credentials provider is setup, and credentials are provisioned or
329 allocated based on the content of the collection. Every set of
330 credentials is associated to an object of type `cls.client_manager`.
331 The client manager is accessible by tests via class attribute
332 `os_[type]`:
edannon6cc6fbc2016-05-03 11:56:12 +0300333
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100334 Valid values in `credentials` are:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600335
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100336 - 'primary':
337 A normal user is provisioned.
338 It can be used only once. Multiple entries will be ignored.
339 Clients are available at os_primary.
340 - 'alt':
341 A normal user other than 'primary' is provisioned.
342 It can be used only once. Multiple entries will be ignored.
343 Clients are available at os_alt.
344 - 'admin':
345 An admin user is provisioned.
346 It can be used only once. Multiple entries will be ignored.
347 Clients are available at os_admin.
348 - A list in the format ['any_label', 'role1', ... , 'roleN']:
349 A client with roles <list>[1:] is provisioned.
350 It can be used multiple times, with unique labels.
351 Clients are available at os_roles_<list>[0].
352
353 By default network resources are allocated (in case of dynamic
354 credentials). Tests that do not need network or that require a
355 custom network setup must specify which network resources shall
356 be provisioned using the `set_network_resources()` method (note
357 that it must be invoked before the `setup_credentials` is
358 invoked on super).
359
360 Example::
361
362 class TestWithCredentials(test.BaseTestCase):
363
364 credentials = ['primary', 'admin',
365 ['special', 'special_role1']]
366
367 @classmethod
368 def setup_credentials(cls):
369 # set_network_resources must be called first
370 cls.set_network_resources(network=True)
371 super(TestWithCredentials, cls).setup_credentials()
372
373 @classmethod
374 def setup_clients(cls):
375 cls.servers = cls.os_primary.compute.ServersClient()
376 cls.admin_servers = cls.os_admin.compute.ServersClient()
377 # certain API calls may require a user with a specific
378 # role assigned. In this example `special_role1` is
379 # assigned to the user in `cls.os_roles_special`.
380 cls.special_servers = (
381 cls.os_roles_special.compute.ServersClient())
382
383 def test_special_servers(self):
384 # Do something with servers
385 pass
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000386 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100387 cls.__setup_credentials_called = True
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000388 for credentials_type in cls.credentials:
389 # This may raise an exception in case credentials are not available
390 # In that case we want to let the exception through and the test
391 # fail accordingly
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100392 if isinstance(credentials_type, six.string_types):
393 manager = cls.get_client_manager(
394 credential_type=credentials_type)
395 setattr(cls, 'os_%s' % credentials_type, manager)
Jordan Pittier8160d312017-04-18 11:52:23 +0200396 # NOTE(jordanP): Tempest should use os_primary, os_admin
397 # and os_alt throughout its code base but we keep the aliases
398 # around for a while for Tempest plugins. Aliases should be
399 # removed eventually.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100400 # Setup some common aliases
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100401 if credentials_type == 'primary':
Jordan Pittier8160d312017-04-18 11:52:23 +0200402 cls.os = debtcollector.moves.moved_read_only_property(
403 'os', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200404 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200405 cls.manager =\
406 debtcollector.moves.moved_read_only_property(
407 'manager', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200408 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100409 if credentials_type == 'admin':
Jordan Pittier8160d312017-04-18 11:52:23 +0200410 cls.os_adm = debtcollector.moves.moved_read_only_property(
411 'os_adm', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200412 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200413 cls.admin_manager =\
414 debtcollector.moves.moved_read_only_property(
415 'admin_manager', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200416 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100417 if credentials_type == 'alt':
Jordan Pittier8160d312017-04-18 11:52:23 +0200418 cls.alt_manager =\
419 debtcollector.moves.moved_read_only_property(
420 'alt_manager', 'os_alt', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200421 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100422 elif isinstance(credentials_type, list):
423 manager = cls.get_client_manager(roles=credentials_type[1:],
424 force_new=True)
425 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100426
427 @classmethod
428 def setup_clients(cls):
Andrea Frittoli99583672017-08-24 15:39:20 +0100429 """Create aliases to the clients in the client managers.
430
431 `setup_clients` is invoked after the credential provisioning step.
432 Client manager objects are available to tests already. The purpose
433 of this helper is to setup shortcuts to specific clients that are
434 useful for the tests implemented in the test class.
435
436 Its purpose is mostly for code readability, however it should be used
437 carefully to avoid doing exactly the opposite, i.e. making the code
438 unreadable and hard to debug. If aliases are defined in a super class
439 it won't be obvious what they refer to, so it's good practice to define
440 all aliases used in the class. Aliases are meant to be shortcuts to
441 be used in tests, not shortcuts to avoid helper method attributes.
442 If an helper method starts relying on a client alias and a subclass
443 overrides that alias, it will become rather difficult to understand
444 what the helper method actually does.
445
446 Example::
447
448 class TestDoneItRight(test.BaseTestCase):
449
450 credentials = ['primary', 'alt']
451
452 @classmethod
453 def setup_clients(cls):
454 super(TestDoneItRight, cls).setup_clients()
455 cls.servers = cls.os_primary.ServersClient()
456 cls.servers_alt = cls.os_alt.ServersClient()
457
458 def _a_good_helper(self, clients):
459 # Some complex logic we're going to use many times
460 servers = clients.ServersClient()
461 vm = servers.create_server(...)
462
463 def delete_server():
464 test_utils.call_and_ignore_notfound_exc(
465 servers.delete_server, vm['id'])
466
467 self.addCleanup(self.delete_server)
468 return vm
469
470 def test_with_servers(self):
471 vm = self._a_good_helper(os.primary)
472 vm_alt = self._a_good_helper(os.alt)
473 cls.servers.show_server(vm['id'])
474 cls.servers_alt.show_server(vm_alt['id'])
475 """
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100476 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200477
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000478 @classmethod
479 def resource_setup(cls):
Andrea Frittoli3be57482017-08-25 22:41:26 +0100480 """Class level resource setup for test cases.
481
482 `resource_setup` is invoked once all credentials (and related network
483 resources have been provisioned and after client aliases - if any -
484 have been defined.
485
486 The use case for `resource_setup` is test optimization: provisioning
487 of project-specific "expensive" resources that are not dirtied by tests
488 and can thus safely be re-used by multiple tests.
489
490 System wide resources shared by all tests could instead be provisioned
491 only once, before the test run.
492
493 Resources provisioned here must be cleaned up during
494 `resource_cleanup`. This is best achieved by scheduling a cleanup via
495 `addClassResourceCleanup`.
496
497 Some test resources have an asynchronous delete process. It's best
498 practice for them to schedule a wait for delete via
499 `addClassResourceCleanup` to avoid having resources in process of
500 deletion when we reach the credentials cleanup step.
501
502 Example::
503
504 @classmethod
505 def resource_setup(cls):
506 super(MyTest, cls).resource_setup()
507 servers = cls.os_primary.compute.ServersClient()
508 # Schedule delete and wait so that we can first delete the
509 # two servers and then wait for both to delete
510 # Create server 1
511 cls.shared_server = servers.create_server()
512 # Create server 2. If something goes wrong we schedule cleanup
513 # of server 1 anyways.
514 try:
515 cls.shared_server2 = servers.create_server()
516 # Wait server 2
517 cls.addClassResourceCleanup(
518 waiters.wait_for_server_termination,
519 servers, cls.shared_server2['id'],
520 ignore_error=False)
521 finally:
522 # Wait server 1
523 cls.addClassResourceCleanup(
524 waiters.wait_for_server_termination,
525 servers, cls.shared_server['id'],
526 ignore_error=False)
527 # Delete server 1
528 cls.addClassResourceCleanup(
529 test_utils.call_and_ignore_notfound_exc,
530 servers.delete_server,
531 cls.shared_server['id'])
532 # Delete server 2 (if it was created)
533 if hasattr(cls, 'shared_server2'):
534 cls.addClassResourceCleanup(
535 test_utils.call_and_ignore_notfound_exc,
536 servers.delete_server,
537 cls.shared_server2['id'])
538 """
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100539 pass
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000540
541 @classmethod
542 def resource_cleanup(cls):
543 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000544
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100545 Resource cleanup processes the stack of cleanups produced by
Andrea Frittoli3be57482017-08-25 22:41:26 +0100546 `addClassResourceCleanup` and then cleans up validation resources
547 if any were provisioned.
548
549 All cleanups are processed whatever the outcome. Exceptions are
550 accumulated and re-raised as a `MultipleExceptions` at the end.
551
552 In most cases test cases won't need to override `resource_cleanup`,
553 but if they do they must invoke `resource_cleanup` on super.
554
555 Example::
556
557 class TestWithReallyComplexCleanup(test.BaseTestCase):
558
559 @classmethod
560 def resource_setup(cls):
561 # provision resource A
562 cls.addClassResourceCleanup(delete_resource, A)
563 # provision resource B
564 cls.addClassResourceCleanup(delete_resource, B)
565
566 @classmethod
567 def resource_cleanup(cls):
568 # It's possible to override resource_cleanup but in most
569 # cases it shouldn't be required. Nothing that may fail
570 # should be executed before the call to super since it
571 # might cause resource leak in case of error.
572 super(TestWithReallyComplexCleanup, cls).resource_cleanup()
573 # At this point test credentials are still available but
574 # anything from the cleanup stack has been already deleted.
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000575 """
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100576 cls.__resource_cleanup_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100577 cleanup_errors = []
578 while cls._class_cleanups:
579 try:
580 fn, args, kwargs = cls._class_cleanups.pop()
581 fn(*args, **kwargs)
582 except Exception:
583 cleanup_errors.append(sys.exc_info())
Andrea Frittoli3be57482017-08-25 22:41:26 +0100584 if cleanup_errors:
585 raise testtools.MultipleExceptions(*cleanup_errors)
586
587 @classmethod
588 def addClassResourceCleanup(cls, fn, *arguments, **keywordArguments):
589 """Add a cleanup function to be called during resource_cleanup.
590
591 Functions added with addClassResourceCleanup will be called in reverse
592 order of adding at the beginning of resource_cleanup, before any
593 credential, networking or validation resources cleanup is processed.
594
595 If a function added with addClassResourceCleanup raises an exception,
596 the error will be recorded as a test error, and the next cleanup will
597 then be run.
598
599 Cleanup functions are always called during the test class tearDown
600 fixture, even if an exception occured during setUp or tearDown.
601 """
602 cls._class_cleanups.append((fn, arguments, keywordArguments))
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000603
Attila Fazekasf86fa312013-07-30 19:56:39 +0200604 def setUp(self):
605 super(BaseTestCase, self).setUp()
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600606 if not self.__setupclass_called:
zhuflde676372018-11-16 15:34:56 +0800607 raise RuntimeError("setUpClass does not calls the super's "
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200608 "setUpClass in the " +
609 self.__class__.__name__)
Attila Fazekasf86fa312013-07-30 19:56:39 +0200610 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400611 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
612 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500613 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400614 except ValueError:
615 test_timeout = 0
616 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200617 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400618
619 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
620 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200621 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
622 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400623 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
624 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200625 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
626 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200627 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200628 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200629 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400630 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200631 level=None))
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100632 if CONF.profiler.key:
633 profiler.enable(CONF.profiler.key)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400634
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100635 @property
636 def credentials_provider(self):
637 return self._get_credentials_provider()
638
639 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100640 def get_identity_version(cls):
641 """Returns the identity version used by the test class"""
642 identity_version = getattr(cls, 'identity_version', None)
643 return identity_version or CONF.identity.auth_version
644
645 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100646 def _get_credentials_provider(cls):
647 """Returns a credentials provider
648
649 If no credential provider exists yet creates one.
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100650 It always use the configuration value from identity.auth_version,
651 since we always want to provision accounts with the current version
652 of the identity API.
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100653 """
654 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
655 not cls._creds_provider.name == cls.__name__):
656 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
657 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100658
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700659 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100660 name=cls.__name__, network_resources=cls._network_resources,
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100661 force_tenant_isolation=force_tenant_isolation)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100662 return cls._creds_provider
663
Matthew Treinish3e046852013-07-23 16:00:24 -0400664 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100665 def get_client_manager(cls, credential_type=None, roles=None,
666 force_new=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100667 """Returns an OpenStack client manager
668
669 Returns an OpenStack client manager based on either credential_type
670 or a list of roles. If neither is specified, it defaults to
671 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100672 :param credential_type: string - primary, alt or admin
673 :param roles: list of roles
674
lei zhangdd552b22015-11-25 20:41:48 +0800675 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100676 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700677 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100678 if all([roles, credential_type]):
679 msg = "Cannot get credentials by type and roles at the same time"
680 raise ValueError(msg)
681 if not any([roles, credential_type]):
682 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100683 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100684 if roles:
685 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100686 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100687 skip_msg = (
688 "%s skipped because the configured credential provider"
689 " is not able to provide credentials with the %s role "
690 "assigned." % (cls.__name__, role))
691 raise cls.skipException(skip_msg)
692 params = dict(roles=roles)
693 if force_new is not None:
694 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100695 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000696 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100697 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100698 if hasattr(cred_provider, credentials_method):
699 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100700 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100701 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100702 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100703 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000704 # NOTE(andreaf) Ensure credentials have user and project id fields.
705 # It may not be the case when using pre-provisioned credentials.
706 manager.auth_provider.set_auth()
707 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700708
709 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700710 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000711 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200712 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700713 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700714
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100715 @staticmethod
716 def _validation_resources_params_from_conf():
717 return dict(
718 keypair=(CONF.validation.auth_method.lower() == "keypair"),
719 floating_ip=(CONF.validation.connect_method.lower() == "floating"),
720 security_group=CONF.validation.security_group,
721 security_group_rules=CONF.validation.security_group_rules,
722 use_neutron=CONF.service_available.neutron,
723 ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
724 floating_network_id=CONF.network.public_network_id,
725 floating_network_name=CONF.network.floating_network_name)
726
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700727 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100728 def get_class_validation_resources(cls, os_clients):
729 """Provision validation resources according to configuration
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000730
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100731 This is a wrapper around `create_validation_resources` from
732 `tempest.common.validation_resources` that passes parameters from
733 Tempest configuration. Only one instance of class level
734 validation resources is managed by the helper, so If resources
735 were already provisioned before, existing ones will be returned.
nithya-ganesan222efd72015-01-22 12:20:27 +0000736
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100737 Resources are returned as a dictionary. They are also scheduled for
738 automatic cleanup during class teardown using
739 `addClassResourcesCleanup`.
740
741 If `CONF.validation.run_validation` is False no resource will be
742 provisioned at all.
743
744 @param os_clients: Clients to be used to provision the resources.
nithya-ganesan222efd72015-01-22 12:20:27 +0000745 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400746 if not CONF.validation.run_validation:
747 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100748
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100749 if os_clients in cls._validation_resources:
750 return cls._validation_resources[os_clients]
Jordan Pittier79cd1822016-12-08 17:20:35 +0100751
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100752 if (CONF.validation.ip_version_for_ssh not in (4, 6) and
753 CONF.service_available.neutron):
754 msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
755 raise lib_exc.InvalidConfiguration(
756 msg % CONF.validation.ip_version_for_ssh)
Jordan Pittier79cd1822016-12-08 17:20:35 +0100757
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100758 resources = vr.create_validation_resources(
759 os_clients,
760 **cls._validation_resources_params_from_conf())
Jordan Pittier79cd1822016-12-08 17:20:35 +0100761
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100762 cls.addClassResourceCleanup(
763 vr.clear_validation_resources, os_clients,
764 use_neutron=CONF.service_available.neutron,
765 **resources)
766 cls._validation_resources[os_clients] = resources
767 return resources
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500768
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100769 def get_test_validation_resources(self, os_clients):
770 """Returns a dict of validation resources according to configuration
771
772 Initialise a validation resources fixture based on configuration.
773 Start the fixture and returns the validation resources.
774
775 If `CONF.validation.run_validation` is False no resource will be
776 provisioned at all.
777
778 @param os_clients: Clients to be used to provision the resources.
779 """
780
781 params = {}
782 # Test will try to use the fixture, so for this to be useful
783 # we must return a fixture. If validation is disabled though
784 # we don't need to provision anything, which is the default
785 # behavior for the fixture.
786 if CONF.validation.run_validation:
787 params = self._validation_resources_params_from_conf()
788
789 validation = self.useFixture(
790 vr.ValidationResourcesFixture(os_clients, **params))
791 return validation.resources
nithya-ganesan222efd72015-01-22 12:20:27 +0000792
793 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000794 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500795 dhcp=False):
796 """Specify which network resources should be created
797
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100798 The dynamic credentials provider by default provisions network
799 resources for each user/project that is provisioned. This behavior
800 can be altered using this method, which allows tests to define which
801 specific network resources to be provisioned - none if no parameter
802 is specified.
803
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100804 This method is designed so that only the network resources set on the
805 leaf class are honoured.
806
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100807 Credentials are provisioned as part of the class setup fixture,
808 during the `setup_credentials` step. For this to be effective this
809 helper must be invoked before super's `setup_credentials` is executed.
810
Matthew Treinish9f756a02014-01-15 10:26:07 -0500811 @param network
812 @param router
813 @param subnet
814 @param dhcp
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100815
816 Example::
817
818 @classmethod
819 def setup_credentials(cls):
820 # Do not setup network resources for this test
821 cls.set_network_resources()
822 super(MyTest, cls).setup_credentials()
Matthew Treinish9f756a02014-01-15 10:26:07 -0500823 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100824 # If this is invoked after the credentials are setup, it won't take
825 # any effect. To avoid this situation, fail the test in case this was
826 # invoked too late in the test lifecycle.
827 if cls.__setup_credentials_called:
828 raise RuntimeError(
829 "set_network_resources invoked after setup_credentials on the "
830 "super class has been already invoked. For "
831 "set_network_resources to have effect please invoke it before "
832 "the call to super().setup_credentials")
833
834 # Network resources should be set only once from callers
Salvatore Orlando5a337242014-01-15 22:49:22 +0000835 # in order to ensure that even if it's called multiple times in
836 # a chain of overloaded methods, the attribute is set only
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100837 # in the leaf class.
838 if not cls._network_resources:
839 cls._network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000840 'network': network,
841 'router': router,
842 'subnet': subnet,
843 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500844
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530845 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000846 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530847 """Get the network to be used in testing
848
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000849 :param credentials_type: The type of credentials for which to get the
850 tenant network
851
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530852 :return: network dict including 'id' and 'name'
853 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000854 # Get a manager for the given credentials_type, but at least
855 # always fall back on getting the manager for primary credentials
856 if isinstance(credentials_type, six.string_types):
857 manager = cls.get_client_manager(credential_type=credentials_type)
858 elif isinstance(credentials_type, list):
859 manager = cls.get_client_manager(roles=credentials_type[1:])
860 else:
861 manager = cls.get_client_manager()
862
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700863 # Make sure cred_provider exists and get a network client
zhufl33289a22018-01-04 15:02:00 +0800864 networks_client = manager.networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100865 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100866 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800867 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100868 # for their servers, so using an admin network client to validate
869 # the network name
870 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100871 credentials.is_admin_available(
872 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100873 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100874 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400875 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900876 return fixed_network.get_tenant_network(
877 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530878
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100879 def assertEmpty(self, items, msg=None):
880 """Asserts whether a sequence or collection is empty
Mark Maglana5885eb32014-02-28 10:57:34 -0800881
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100882 :param items: sequence or collection to be tested
883 :param msg: message to be passed to the AssertionError
884 :raises AssertionError: when items is not empty
885 """
zhufl92ade4b2017-03-03 15:20:10 +0800886 if msg is None:
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100887 msg = "sequence or collection is not empty: %s" % items
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900888 self.assertFalse(items, msg)
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100889
890 def assertNotEmpty(self, items, msg=None):
891 """Asserts whether a sequence or collection is not empty
892
893 :param items: sequence or collection to be tested
894 :param msg: message to be passed to the AssertionError
895 :raises AssertionError: when items is empty
896 """
897 if msg is None:
898 msg = "sequence or collection is empty."
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900899 self.assertTrue(items, msg)