blob: 2dfedeb3a43581f8a3545928549a1500c5794ffb [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
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
Andrea Frittolicd368412017-08-14 21:37:56 +010047services = debtcollector.moves.moved_function(
48 utils.services, 'services', __name__,
49 version='Pike', removal_version='?')
Andrea Frittoli07acf262017-04-09 19:36:37 +020050
51
Andrea Frittolicd368412017-08-14 21:37:56 +010052requires_ext = debtcollector.moves.moved_function(
53 utils.requires_ext, 'requires_ext', __name__,
54 version='Pike', removal_version='?')
Matthew Treinish16c43792013-09-09 19:55:23 +000055
Matthew Treinish3d8c7322014-08-03 23:53:28 -040056
Andrea Frittolicd368412017-08-14 21:37:56 +010057is_extension_enabled = debtcollector.moves.moved_function(
58 utils.is_extension_enabled, 'is_extension_enabled', __name__,
59 version='Pike', removal_version='?')
Ian Wienand98c35f32013-07-23 20:34:23 +100060
Attila Fazekasf86fa312013-07-30 19:56:39 +020061at_exit_set = set()
62
63
64def validate_tearDownClass():
65 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -040066 LOG.error(
Federico Ressi2d6bcaa2018-04-11 12:37:36 +020067 "tearDownClass does not call the super's tearDownClass in "
68 "these classes:\n"
69 " %s", at_exit_set)
Sean Dagueeb1523b2014-03-10 10:17:44 -040070
Attila Fazekasf86fa312013-07-30 19:56:39 +020071
72atexit.register(validate_tearDownClass)
73
Attila Fazekas53943322014-02-10 16:07:34 +010074
Matthew Treinish2474f412014-11-17 18:11:56 -050075class BaseTestCase(testtools.testcase.WithAttributes,
76 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +010077 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000078
Andrea Frittolia5ddd552014-08-19 18:30:00 +010079 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
80 by subclasses (enforced via hacking rule T105).
81
82 Set-up is split in a series of steps (setup stages), which can be
83 overwritten by test classes. Set-up stages are:
84 - skip_checks
85 - setup_credentials
86 - setup_clients
87 - resource_setup
88
89 Tear-down is also split in a series of steps (teardown stages), which are
90 stacked for execution only if the corresponding setup stage had been
91 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -070092 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +010093 - resource_cleanup
94 """
Attila Fazekasc43fec82013-04-09 23:17:52 +020095
Andrea Frittolib21de6c2015-02-06 20:12:38 +000096 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +010097 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
98 # a list of roles - the first element of the list being a label, and the
99 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000100 credentials = []
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100101
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600102 # Track if setUpClass was invoked
103 __setupclass_called = False
104
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100105 # Network resources to be provisioned for the requested test credentials.
106 # Only used with the dynamic credentials provider.
107 _network_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500108
Andrea Frittoli3be57482017-08-25 22:41:26 +0100109 # Stack of resource cleanups
110 _class_cleanups = []
111
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100112 # Resources required to validate a server using ssh
113 _validation_resources = {}
114
Sean Dague2ef32ac2014-06-09 11:32:23 -0400115 # NOTE(sdague): log_format is defined inline here instead of using the oslo
116 # default because going through the config path recouples config to the
117 # stress tests too early, and depending on testr order will fail unit tests
118 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
119 '[%(name)s] %(message)s')
120
Ryota MIBU60687e52015-12-09 18:37:39 +0900121 # Client manager class to use in this test case.
122 client_manager = clients.Manager
123
Sean Dague02620fd2016-03-02 15:52:51 -0500124 # A way to adjust slow test classes
125 TIMEOUT_SCALING_FACTOR = 1
126
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200127 @classmethod
Andrea Frittoli3be57482017-08-25 22:41:26 +0100128 def _reset_class(cls):
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100129 cls.__setup_credentials_called = False
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100130 cls.__resource_cleanup_called = False
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100131 cls.__skip_checks_called = False
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600132 # Stack of callable to be invoked in reverse order
Andrea Frittoli3be57482017-08-25 22:41:26 +0100133 cls._class_cleanups = []
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600134 # Stack of (name, callable) to be invoked in reverse order at teardown
135 cls._teardowns = []
Andrea Frittoli3be57482017-08-25 22:41:26 +0100136
137 @classmethod
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200138 def setUpClass(cls):
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600139 cls.__setupclass_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100140 # Reset state
141 cls._reset_class()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100142 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200143 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
144 super(BaseTestCase, cls).setUpClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100145 # All the configuration checks that may generate a skip
Ghanshyam Mann68ddf412019-09-10 19:40:52 +0000146 # TODO(gmann): cls.handle_skip_exception is really workaround for
147 # testtools bug- https://github.com/testing-cabal/testtools/issues/272
148 # stestr which is used by Tempest internally to run the test switch
149 # the customize test runner(which use stdlib unittest) for >=py3.5
150 # else testtools.run.- https://github.com/mtreinish/stestr/pull/265
151 # These two test runner are not compatible due to skip exception
152 # handling(due to unittest2). testtools.run treat unittestt.SkipTest
153 # as error and stdlib unittest treat unittest2.case.SkipTest raised
154 # by testtools.TestCase.skipException.
155 # The below workaround can be removed once testtools fix issue# 272.
Ghanshyam Manne64c78d2019-10-10 22:26:43 +0000156 orig_skip_exception = testtools.TestCase.skipException
157 lib_base._handle_skip_exception()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100158 try:
Ghanshyam Mann68ddf412019-09-10 19:40:52 +0000159 cls.skip_checks()
160
161 if not cls.__skip_checks_called:
162 raise RuntimeError(
163 "skip_checks for %s did not call the super's "
164 "skip_checks" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100165 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100166 cls._teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100167 cls.setup_credentials()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100168 if not cls.__setup_credentials_called:
169 raise RuntimeError("setup_credentials for %s did not call the "
170 "super's setup_credentials" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100171 # Shortcuts to clients
172 cls.setup_clients()
173 # Additional class-wide test resources
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100174 cls._teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100175 cls.resource_setup()
176 except Exception:
177 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100178 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
179 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100180 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100181 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400182 six.reraise(etype, value, trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100183 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100184 del trace # to avoid circular refs
Ghanshyam Manne64c78d2019-10-10 22:26:43 +0000185 finally:
186 testtools.TestCase.skipException = orig_skip_exception
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200187
Attila Fazekasf86fa312013-07-30 19:56:39 +0200188 @classmethod
189 def tearDownClass(cls):
Martin Kopecae155b72017-06-26 09:41:21 +0000190 # insert pdb breakpoint when pause_teardown is enabled
191 if CONF.pause_teardown:
192 cls.insert_pdb_breakpoint()
Attila Fazekas5d275302013-08-29 12:35:12 +0200193 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100194 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200195 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
196 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100197 # Save any existing exception, we always want to re-raise the original
198 # exception only
199 etype, value, trace = sys.exc_info()
200 # If there was no exception during setup we shall re-raise the first
201 # exception in teardown
202 re_raise = (etype is None)
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100203 while cls._teardowns:
204 name, teardown = cls._teardowns.pop()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100205 # Catch any exception in tearDown so we can re-raise the original
206 # exception at the end
207 try:
208 teardown()
Andrea Frittoli3be57482017-08-25 22:41:26 +0100209 if name == 'resources':
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100210 if not cls.__resource_cleanup_called:
Andrea Frittoli3be57482017-08-25 22:41:26 +0100211 raise RuntimeError(
212 "resource_cleanup for %s did not call the "
213 "super's resource_cleanup" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100214 except Exception as te:
215 sys_exec_info = sys.exc_info()
216 tetype = sys_exec_info[0]
Andrea Frittoli3be57482017-08-25 22:41:26 +0100217 # TODO(andreaf): Resource cleanup is often implemented by
218 # storing an array of resources at class level, and cleaning
219 # them up during `resource_cleanup`.
220 # In case of failure during setup, some resource arrays might
221 # not be defined at all, in which case the cleanup code might
222 # trigger an AttributeError. In such cases we log
223 # AttributeError as info instead of exception. Once all
224 # cleanups are migrated to addClassResourceCleanup we can
225 # remove this.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100226 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100227 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100228 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100229 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100230 if not etype:
231 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800232 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100233 # the first one
234 if re_raise and etype is not None:
235 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400236 six.reraise(etype, value, trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100237 finally:
238 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100239
Martin Kopecae155b72017-06-26 09:41:21 +0000240 def tearDown(self):
241 super(BaseTestCase, self).tearDown()
242 # insert pdb breakpoint when pause_teardown is enabled
243 if CONF.pause_teardown:
244 BaseTestCase.insert_pdb_breakpoint()
245
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100246 if CONF.profiler.key:
247 profiler.disable()
248
Martin Kopecae155b72017-06-26 09:41:21 +0000249 @classmethod
250 def insert_pdb_breakpoint(cls):
251 """Add pdb breakpoint.
252
253 This can help in debugging process, cleaning of resources is
254 paused, so they can be examined.
255 """
256 import pdb
257 pdb.set_trace()
258
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100259 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100260 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000261 """Class level skip checks.
262
263 Subclasses verify in here all conditions that might prevent the
Andrea Frittolia5440c82017-08-23 18:11:21 +0100264 execution of the entire test class. Skipping here prevents any other
265 class fixture from being executed i.e. no credentials or other
266 resource allocation will happen.
267
268 Tests defined in the test class will no longer appear in test results.
269 The `setUpClass` for the entire test class will be marked as SKIPPED
270 instead.
271
272 At this stage no test credentials are available, so skip checks
273 should rely on configuration alone. This is deliberate since skips
274 based on the result of an API call are discouraged.
275
276 The following checks are implemented in `test.py` already:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600277
Andrea Frittolia5440c82017-08-23 18:11:21 +0100278 - check that alt credentials are available when requested by the test
279 - check that admin credentials are available when requested by the test
280 - check that the identity version specified by the test is marked as
281 enabled in the configuration
282
283 Overriders of skip_checks must always invoke skip_check on `super`
284 first.
285
286 Example::
287
288 @classmethod
289 def skip_checks(cls):
290 super(Example, cls).skip_checks()
291 if not CONF.service_available.my_service:
292 skip_msg = ("%s skipped as my_service is not available")
293 raise cls.skipException(skip_msg % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100294 """
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100295 cls.__skip_checks_called = True
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100296 identity_version = cls.get_identity_version()
zhufl75498ba2017-08-25 10:49:35 +0800297 # setting force_tenant_isolation to True also needs admin credentials.
298 if ('admin' in cls.credentials or
Ghanshyam Mann420586c2021-01-29 13:23:18 -0600299 'alt_admin' in cls.credentials or
zhufl75498ba2017-08-25 10:49:35 +0800300 getattr(cls, 'force_tenant_isolation', False)):
301 if not credentials.is_admin_available(
302 identity_version=identity_version):
303 raise cls.skipException(
304 "Missing Identity Admin API credentials in configuration.")
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100305 if 'alt' in cls.credentials and not credentials.is_alt_available(
306 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000307 msg = "Missing a 2nd set of API credentials in configuration."
308 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100309 if hasattr(cls, 'identity_version'):
310 if cls.identity_version == 'v2':
311 if not CONF.identity_feature_enabled.api_v2:
312 raise cls.skipException("Identity api v2 is not enabled")
313 elif cls.identity_version == 'v3':
314 if not CONF.identity_feature_enabled.api_v3:
315 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100316
317 @classmethod
318 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300319 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000320
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100321 `setup_credentials` looks for the content of the `credentials`
322 attribute in the test class. If the value is a non-empty collection,
323 a credentials provider is setup, and credentials are provisioned or
324 allocated based on the content of the collection. Every set of
325 credentials is associated to an object of type `cls.client_manager`.
326 The client manager is accessible by tests via class attribute
327 `os_[type]`:
edannon6cc6fbc2016-05-03 11:56:12 +0300328
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100329 Valid values in `credentials` are:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600330
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100331 - 'primary':
332 A normal user is provisioned.
333 It can be used only once. Multiple entries will be ignored.
334 Clients are available at os_primary.
335 - 'alt':
336 A normal user other than 'primary' is provisioned.
337 It can be used only once. Multiple entries will be ignored.
338 Clients are available at os_alt.
339 - 'admin':
340 An admin user is provisioned.
341 It can be used only once. Multiple entries will be ignored.
342 Clients are available at os_admin.
343 - A list in the format ['any_label', 'role1', ... , 'roleN']:
344 A client with roles <list>[1:] is provisioned.
345 It can be used multiple times, with unique labels.
346 Clients are available at os_roles_<list>[0].
347
348 By default network resources are allocated (in case of dynamic
349 credentials). Tests that do not need network or that require a
350 custom network setup must specify which network resources shall
351 be provisioned using the `set_network_resources()` method (note
352 that it must be invoked before the `setup_credentials` is
353 invoked on super).
354
355 Example::
356
357 class TestWithCredentials(test.BaseTestCase):
358
359 credentials = ['primary', 'admin',
360 ['special', 'special_role1']]
361
362 @classmethod
363 def setup_credentials(cls):
364 # set_network_resources must be called first
365 cls.set_network_resources(network=True)
366 super(TestWithCredentials, cls).setup_credentials()
367
368 @classmethod
369 def setup_clients(cls):
370 cls.servers = cls.os_primary.compute.ServersClient()
371 cls.admin_servers = cls.os_admin.compute.ServersClient()
372 # certain API calls may require a user with a specific
373 # role assigned. In this example `special_role1` is
374 # assigned to the user in `cls.os_roles_special`.
375 cls.special_servers = (
376 cls.os_roles_special.compute.ServersClient())
377
378 def test_special_servers(self):
379 # Do something with servers
380 pass
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000381 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100382 cls.__setup_credentials_called = True
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000383 for credentials_type in cls.credentials:
384 # This may raise an exception in case credentials are not available
385 # In that case we want to let the exception through and the test
386 # fail accordingly
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100387 if isinstance(credentials_type, six.string_types):
388 manager = cls.get_client_manager(
389 credential_type=credentials_type)
390 setattr(cls, 'os_%s' % credentials_type, manager)
Jordan Pittier8160d312017-04-18 11:52:23 +0200391 # NOTE(jordanP): Tempest should use os_primary, os_admin
392 # and os_alt throughout its code base but we keep the aliases
393 # around for a while for Tempest plugins. Aliases should be
394 # removed eventually.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100395 # Setup some common aliases
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100396 if credentials_type == 'primary':
Jordan Pittier8160d312017-04-18 11:52:23 +0200397 cls.os = debtcollector.moves.moved_read_only_property(
398 'os', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200399 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200400 cls.manager =\
401 debtcollector.moves.moved_read_only_property(
402 'manager', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200403 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100404 if credentials_type == 'admin':
Jordan Pittier8160d312017-04-18 11:52:23 +0200405 cls.os_adm = debtcollector.moves.moved_read_only_property(
406 'os_adm', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200407 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200408 cls.admin_manager =\
409 debtcollector.moves.moved_read_only_property(
410 'admin_manager', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200411 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100412 if credentials_type == 'alt':
Jordan Pittier8160d312017-04-18 11:52:23 +0200413 cls.alt_manager =\
414 debtcollector.moves.moved_read_only_property(
415 'alt_manager', 'os_alt', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200416 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100417 elif isinstance(credentials_type, list):
418 manager = cls.get_client_manager(roles=credentials_type[1:],
419 force_new=True)
420 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100421
422 @classmethod
423 def setup_clients(cls):
Andrea Frittoli99583672017-08-24 15:39:20 +0100424 """Create aliases to the clients in the client managers.
425
426 `setup_clients` is invoked after the credential provisioning step.
427 Client manager objects are available to tests already. The purpose
428 of this helper is to setup shortcuts to specific clients that are
429 useful for the tests implemented in the test class.
430
431 Its purpose is mostly for code readability, however it should be used
432 carefully to avoid doing exactly the opposite, i.e. making the code
433 unreadable and hard to debug. If aliases are defined in a super class
434 it won't be obvious what they refer to, so it's good practice to define
435 all aliases used in the class. Aliases are meant to be shortcuts to
436 be used in tests, not shortcuts to avoid helper method attributes.
437 If an helper method starts relying on a client alias and a subclass
438 overrides that alias, it will become rather difficult to understand
439 what the helper method actually does.
440
441 Example::
442
443 class TestDoneItRight(test.BaseTestCase):
444
445 credentials = ['primary', 'alt']
446
447 @classmethod
448 def setup_clients(cls):
449 super(TestDoneItRight, cls).setup_clients()
450 cls.servers = cls.os_primary.ServersClient()
451 cls.servers_alt = cls.os_alt.ServersClient()
452
453 def _a_good_helper(self, clients):
454 # Some complex logic we're going to use many times
455 servers = clients.ServersClient()
456 vm = servers.create_server(...)
457
458 def delete_server():
459 test_utils.call_and_ignore_notfound_exc(
460 servers.delete_server, vm['id'])
461
462 self.addCleanup(self.delete_server)
463 return vm
464
465 def test_with_servers(self):
466 vm = self._a_good_helper(os.primary)
467 vm_alt = self._a_good_helper(os.alt)
468 cls.servers.show_server(vm['id'])
469 cls.servers_alt.show_server(vm_alt['id'])
470 """
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100471 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200472
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000473 @classmethod
474 def resource_setup(cls):
Andrea Frittoli3be57482017-08-25 22:41:26 +0100475 """Class level resource setup for test cases.
476
477 `resource_setup` is invoked once all credentials (and related network
478 resources have been provisioned and after client aliases - if any -
479 have been defined.
480
481 The use case for `resource_setup` is test optimization: provisioning
482 of project-specific "expensive" resources that are not dirtied by tests
483 and can thus safely be re-used by multiple tests.
484
485 System wide resources shared by all tests could instead be provisioned
486 only once, before the test run.
487
488 Resources provisioned here must be cleaned up during
489 `resource_cleanup`. This is best achieved by scheduling a cleanup via
490 `addClassResourceCleanup`.
491
492 Some test resources have an asynchronous delete process. It's best
493 practice for them to schedule a wait for delete via
494 `addClassResourceCleanup` to avoid having resources in process of
495 deletion when we reach the credentials cleanup step.
496
497 Example::
498
499 @classmethod
500 def resource_setup(cls):
501 super(MyTest, cls).resource_setup()
502 servers = cls.os_primary.compute.ServersClient()
503 # Schedule delete and wait so that we can first delete the
504 # two servers and then wait for both to delete
505 # Create server 1
506 cls.shared_server = servers.create_server()
507 # Create server 2. If something goes wrong we schedule cleanup
508 # of server 1 anyways.
509 try:
510 cls.shared_server2 = servers.create_server()
511 # Wait server 2
512 cls.addClassResourceCleanup(
513 waiters.wait_for_server_termination,
514 servers, cls.shared_server2['id'],
515 ignore_error=False)
516 finally:
517 # Wait server 1
518 cls.addClassResourceCleanup(
519 waiters.wait_for_server_termination,
520 servers, cls.shared_server['id'],
521 ignore_error=False)
522 # Delete server 1
523 cls.addClassResourceCleanup(
524 test_utils.call_and_ignore_notfound_exc,
525 servers.delete_server,
526 cls.shared_server['id'])
527 # Delete server 2 (if it was created)
528 if hasattr(cls, 'shared_server2'):
529 cls.addClassResourceCleanup(
530 test_utils.call_and_ignore_notfound_exc,
531 servers.delete_server,
532 cls.shared_server2['id'])
533 """
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100534 pass
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000535
536 @classmethod
537 def resource_cleanup(cls):
538 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000539
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100540 Resource cleanup processes the stack of cleanups produced by
Andrea Frittoli3be57482017-08-25 22:41:26 +0100541 `addClassResourceCleanup` and then cleans up validation resources
542 if any were provisioned.
543
544 All cleanups are processed whatever the outcome. Exceptions are
545 accumulated and re-raised as a `MultipleExceptions` at the end.
546
547 In most cases test cases won't need to override `resource_cleanup`,
548 but if they do they must invoke `resource_cleanup` on super.
549
550 Example::
551
552 class TestWithReallyComplexCleanup(test.BaseTestCase):
553
554 @classmethod
555 def resource_setup(cls):
556 # provision resource A
557 cls.addClassResourceCleanup(delete_resource, A)
558 # provision resource B
559 cls.addClassResourceCleanup(delete_resource, B)
560
561 @classmethod
562 def resource_cleanup(cls):
563 # It's possible to override resource_cleanup but in most
564 # cases it shouldn't be required. Nothing that may fail
565 # should be executed before the call to super since it
566 # might cause resource leak in case of error.
567 super(TestWithReallyComplexCleanup, cls).resource_cleanup()
568 # At this point test credentials are still available but
569 # anything from the cleanup stack has been already deleted.
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000570 """
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100571 cls.__resource_cleanup_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100572 cleanup_errors = []
573 while cls._class_cleanups:
574 try:
575 fn, args, kwargs = cls._class_cleanups.pop()
576 fn(*args, **kwargs)
577 except Exception:
578 cleanup_errors.append(sys.exc_info())
Andrea Frittoli3be57482017-08-25 22:41:26 +0100579 if cleanup_errors:
580 raise testtools.MultipleExceptions(*cleanup_errors)
581
582 @classmethod
583 def addClassResourceCleanup(cls, fn, *arguments, **keywordArguments):
584 """Add a cleanup function to be called during resource_cleanup.
585
586 Functions added with addClassResourceCleanup will be called in reverse
587 order of adding at the beginning of resource_cleanup, before any
588 credential, networking or validation resources cleanup is processed.
589
590 If a function added with addClassResourceCleanup raises an exception,
591 the error will be recorded as a test error, and the next cleanup will
592 then be run.
593
594 Cleanup functions are always called during the test class tearDown
595 fixture, even if an exception occured during setUp or tearDown.
596 """
597 cls._class_cleanups.append((fn, arguments, keywordArguments))
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000598
Attila Fazekasf86fa312013-07-30 19:56:39 +0200599 def setUp(self):
600 super(BaseTestCase, self).setUp()
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600601 if not self.__setupclass_called:
zhuflde676372018-11-16 15:34:56 +0800602 raise RuntimeError("setUpClass does not calls the super's "
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200603 "setUpClass in the " +
604 self.__class__.__name__)
Attila Fazekasf86fa312013-07-30 19:56:39 +0200605 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400606 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
607 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500608 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400609 except ValueError:
610 test_timeout = 0
611 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200612 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400613
614 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
615 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200616 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
617 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400618 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
619 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200620 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
621 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200622 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200623 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200624 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400625 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200626 level=None))
Ilya Shakhat1291bb42017-11-29 18:08:16 +0100627 if CONF.profiler.key:
628 profiler.enable(CONF.profiler.key)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400629
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100630 @property
631 def credentials_provider(self):
632 return self._get_credentials_provider()
633
634 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100635 def get_identity_version(cls):
636 """Returns the identity version used by the test class"""
637 identity_version = getattr(cls, 'identity_version', None)
638 return identity_version or CONF.identity.auth_version
639
640 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100641 def _get_credentials_provider(cls):
642 """Returns a credentials provider
643
644 If no credential provider exists yet creates one.
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100645 It always use the configuration value from identity.auth_version,
646 since we always want to provision accounts with the current version
647 of the identity API.
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100648 """
649 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
650 not cls._creds_provider.name == cls.__name__):
651 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
652 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100653
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700654 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100655 name=cls.__name__, network_resources=cls._network_resources,
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100656 force_tenant_isolation=force_tenant_isolation)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100657 return cls._creds_provider
658
Matthew Treinish3e046852013-07-23 16:00:24 -0400659 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100660 def get_client_manager(cls, credential_type=None, roles=None,
661 force_new=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100662 """Returns an OpenStack client manager
663
664 Returns an OpenStack client manager based on either credential_type
665 or a list of roles. If neither is specified, it defaults to
666 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100667 :param credential_type: string - primary, alt or admin
668 :param roles: list of roles
669
lei zhangdd552b22015-11-25 20:41:48 +0800670 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100671 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700672 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100673 if all([roles, credential_type]):
674 msg = "Cannot get credentials by type and roles at the same time"
675 raise ValueError(msg)
676 if not any([roles, credential_type]):
677 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100678 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100679 if roles:
680 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100681 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100682 skip_msg = (
683 "%s skipped because the configured credential provider"
684 " is not able to provide credentials with the %s role "
685 "assigned." % (cls.__name__, role))
686 raise cls.skipException(skip_msg)
687 params = dict(roles=roles)
688 if force_new is not None:
689 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100690 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000691 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100692 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100693 if hasattr(cred_provider, credentials_method):
694 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100695 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100696 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100697 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100698 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000699 # NOTE(andreaf) Ensure credentials have user and project id fields.
700 # It may not be the case when using pre-provisioned credentials.
701 manager.auth_provider.set_auth()
702 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700703
704 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700705 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000706 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200707 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700708 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700709
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100710 @staticmethod
711 def _validation_resources_params_from_conf():
712 return dict(
713 keypair=(CONF.validation.auth_method.lower() == "keypair"),
714 floating_ip=(CONF.validation.connect_method.lower() == "floating"),
715 security_group=CONF.validation.security_group,
716 security_group_rules=CONF.validation.security_group_rules,
717 use_neutron=CONF.service_available.neutron,
718 ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
719 floating_network_id=CONF.network.public_network_id,
720 floating_network_name=CONF.network.floating_network_name)
721
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700722 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100723 def get_class_validation_resources(cls, os_clients):
724 """Provision validation resources according to configuration
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000725
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100726 This is a wrapper around `create_validation_resources` from
727 `tempest.common.validation_resources` that passes parameters from
728 Tempest configuration. Only one instance of class level
729 validation resources is managed by the helper, so If resources
730 were already provisioned before, existing ones will be returned.
nithya-ganesan222efd72015-01-22 12:20:27 +0000731
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100732 Resources are returned as a dictionary. They are also scheduled for
733 automatic cleanup during class teardown using
734 `addClassResourcesCleanup`.
735
736 If `CONF.validation.run_validation` is False no resource will be
737 provisioned at all.
738
739 @param os_clients: Clients to be used to provision the resources.
nithya-ganesan222efd72015-01-22 12:20:27 +0000740 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400741 if not CONF.validation.run_validation:
742 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100743
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100744 if os_clients in cls._validation_resources:
745 return cls._validation_resources[os_clients]
Jordan Pittier79cd1822016-12-08 17:20:35 +0100746
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100747 if (CONF.validation.ip_version_for_ssh not in (4, 6) and
748 CONF.service_available.neutron):
749 msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
750 raise lib_exc.InvalidConfiguration(
751 msg % CONF.validation.ip_version_for_ssh)
Jordan Pittier79cd1822016-12-08 17:20:35 +0100752
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100753 resources = vr.create_validation_resources(
754 os_clients,
755 **cls._validation_resources_params_from_conf())
Jordan Pittier79cd1822016-12-08 17:20:35 +0100756
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100757 cls.addClassResourceCleanup(
758 vr.clear_validation_resources, os_clients,
759 use_neutron=CONF.service_available.neutron,
760 **resources)
761 cls._validation_resources[os_clients] = resources
762 return resources
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500763
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100764 def get_test_validation_resources(self, os_clients):
765 """Returns a dict of validation resources according to configuration
766
767 Initialise a validation resources fixture based on configuration.
768 Start the fixture and returns the validation resources.
769
770 If `CONF.validation.run_validation` is False no resource will be
771 provisioned at all.
772
773 @param os_clients: Clients to be used to provision the resources.
774 """
775
776 params = {}
777 # Test will try to use the fixture, so for this to be useful
778 # we must return a fixture. If validation is disabled though
779 # we don't need to provision anything, which is the default
780 # behavior for the fixture.
781 if CONF.validation.run_validation:
782 params = self._validation_resources_params_from_conf()
783
784 validation = self.useFixture(
785 vr.ValidationResourcesFixture(os_clients, **params))
786 return validation.resources
nithya-ganesan222efd72015-01-22 12:20:27 +0000787
788 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000789 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500790 dhcp=False):
791 """Specify which network resources should be created
792
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100793 The dynamic credentials provider by default provisions network
794 resources for each user/project that is provisioned. This behavior
795 can be altered using this method, which allows tests to define which
796 specific network resources to be provisioned - none if no parameter
797 is specified.
798
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100799 This method is designed so that only the network resources set on the
800 leaf class are honoured.
801
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100802 Credentials are provisioned as part of the class setup fixture,
803 during the `setup_credentials` step. For this to be effective this
804 helper must be invoked before super's `setup_credentials` is executed.
805
Matthew Treinish9f756a02014-01-15 10:26:07 -0500806 @param network
807 @param router
808 @param subnet
809 @param dhcp
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100810
811 Example::
812
813 @classmethod
814 def setup_credentials(cls):
815 # Do not setup network resources for this test
816 cls.set_network_resources()
817 super(MyTest, cls).setup_credentials()
Matthew Treinish9f756a02014-01-15 10:26:07 -0500818 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100819 # If this is invoked after the credentials are setup, it won't take
820 # any effect. To avoid this situation, fail the test in case this was
821 # invoked too late in the test lifecycle.
822 if cls.__setup_credentials_called:
823 raise RuntimeError(
824 "set_network_resources invoked after setup_credentials on the "
825 "super class has been already invoked. For "
826 "set_network_resources to have effect please invoke it before "
827 "the call to super().setup_credentials")
828
829 # Network resources should be set only once from callers
Salvatore Orlando5a337242014-01-15 22:49:22 +0000830 # in order to ensure that even if it's called multiple times in
831 # a chain of overloaded methods, the attribute is set only
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100832 # in the leaf class.
833 if not cls._network_resources:
834 cls._network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000835 'network': network,
836 'router': router,
837 'subnet': subnet,
838 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500839
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530840 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000841 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530842 """Get the network to be used in testing
843
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000844 :param credentials_type: The type of credentials for which to get the
845 tenant network
846
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530847 :return: network dict including 'id' and 'name'
848 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000849 # Get a manager for the given credentials_type, but at least
850 # always fall back on getting the manager for primary credentials
851 if isinstance(credentials_type, six.string_types):
852 manager = cls.get_client_manager(credential_type=credentials_type)
853 elif isinstance(credentials_type, list):
854 manager = cls.get_client_manager(roles=credentials_type[1:])
855 else:
856 manager = cls.get_client_manager()
857
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700858 # Make sure cred_provider exists and get a network client
zhufl33289a22018-01-04 15:02:00 +0800859 networks_client = manager.networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100860 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100861 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800862 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100863 # for their servers, so using an admin network client to validate
864 # the network name
865 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100866 credentials.is_admin_available(
867 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100868 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100869 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400870 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900871 return fixed_network.get_tenant_network(
872 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530873
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100874 def assertEmpty(self, items, msg=None):
875 """Asserts whether a sequence or collection is empty
Mark Maglana5885eb32014-02-28 10:57:34 -0800876
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100877 :param items: sequence or collection to be tested
878 :param msg: message to be passed to the AssertionError
879 :raises AssertionError: when items is not empty
880 """
zhufl92ade4b2017-03-03 15:20:10 +0800881 if msg is None:
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100882 msg = "sequence or collection is not empty: %s" % items
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900883 self.assertFalse(items, msg)
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100884
885 def assertNotEmpty(self, items, msg=None):
886 """Asserts whether a sequence or collection is not empty
887
888 :param items: sequence or collection to be tested
889 :param msg: message to be passed to the AssertionError
890 :raises AssertionError: when items is empty
891 """
892 if msg is None:
893 msg = "sequence or collection is empty."
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900894 self.assertTrue(items, msg)