blob: c3c58dc51bb292426b7d4d9f66ac3de8a8248acc [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
Matthew Treinishb19c55d2017-07-17 12:38:35 -040030from tempest.lib.common import fixed_network
Andrea Frittoli0477acc2017-08-09 21:14:53 +010031from tempest.lib.common import validation_resources as vr
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050032from tempest.lib import decorators
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +010033from tempest.lib import exceptions as lib_exc
Jay Pipes051075a2012-04-28 17:39:37 -040034
35LOG = logging.getLogger(__name__)
36
Sean Dague86bd8422013-12-20 09:56:44 -050037CONF = config.CONF
38
Ken'ichi Ohmichi44f01272017-01-27 18:44:14 -080039# TODO(oomichi): This test.idempotent_id should be removed after all projects
40# switch to use decorators.idempotent_id.
41idempotent_id = debtcollector.moves.moved_function(
42 decorators.idempotent_id, 'idempotent_id', __name__,
43 version='Mitaka', removal_version='?')
Matthew Treinishc1802bc2015-12-03 18:48:11 -050044
Jay Pipes051075a2012-04-28 17:39:37 -040045
Jordan Pittier3b46d272017-04-12 16:17:28 +020046attr = debtcollector.moves.moved_function(
47 decorators.attr, 'attr', __name__,
48 version='Pike', removal_version='?')
Chris Yeoh55530bb2013-02-08 16:04:27 +103049
50
Andrea Frittolicd368412017-08-14 21:37:56 +010051services = debtcollector.moves.moved_function(
52 utils.services, 'services', __name__,
53 version='Pike', removal_version='?')
Andrea Frittoli07acf262017-04-09 19:36:37 +020054
55
Andrea Frittolicd368412017-08-14 21:37:56 +010056requires_ext = debtcollector.moves.moved_function(
57 utils.requires_ext, 'requires_ext', __name__,
58 version='Pike', removal_version='?')
Matthew Treinish16c43792013-09-09 19:55:23 +000059
Matthew Treinish3d8c7322014-08-03 23:53:28 -040060
Andrea Frittolicd368412017-08-14 21:37:56 +010061is_extension_enabled = debtcollector.moves.moved_function(
62 utils.is_extension_enabled, 'is_extension_enabled', __name__,
63 version='Pike', removal_version='?')
Ian Wienand98c35f32013-07-23 20:34:23 +100064
Attila Fazekasf86fa312013-07-30 19:56:39 +020065at_exit_set = set()
66
67
68def validate_tearDownClass():
69 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -040070 LOG.error(
Federico Ressi2d6bcaa2018-04-11 12:37:36 +020071 "tearDownClass does not call the super's tearDownClass in "
72 "these classes:\n"
73 " %s", at_exit_set)
Sean Dagueeb1523b2014-03-10 10:17:44 -040074
Attila Fazekasf86fa312013-07-30 19:56:39 +020075
76atexit.register(validate_tearDownClass)
77
Attila Fazekas53943322014-02-10 16:07:34 +010078
Matthew Treinish2474f412014-11-17 18:11:56 -050079class BaseTestCase(testtools.testcase.WithAttributes,
80 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +010081 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000082
Andrea Frittolia5ddd552014-08-19 18:30:00 +010083 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
84 by subclasses (enforced via hacking rule T105).
85
86 Set-up is split in a series of steps (setup stages), which can be
87 overwritten by test classes. Set-up stages are:
88 - skip_checks
89 - setup_credentials
90 - setup_clients
91 - resource_setup
92
93 Tear-down is also split in a series of steps (teardown stages), which are
94 stacked for execution only if the corresponding setup stage had been
95 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -070096 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +010097 - resource_cleanup
98 """
Attila Fazekasc43fec82013-04-09 23:17:52 +020099
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000100 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100101 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
102 # a list of roles - the first element of the list being a label, and the
103 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000104 credentials = []
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100105
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600106 # Track if setUpClass was invoked
107 __setupclass_called = False
108
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100109 # Network resources to be provisioned for the requested test credentials.
110 # Only used with the dynamic credentials provider.
111 _network_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500112
Andrea Frittoli3be57482017-08-25 22:41:26 +0100113 # Stack of resource cleanups
114 _class_cleanups = []
115
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100116 # Resources required to validate a server using ssh
117 _validation_resources = {}
118
Sean Dague2ef32ac2014-06-09 11:32:23 -0400119 # NOTE(sdague): log_format is defined inline here instead of using the oslo
120 # default because going through the config path recouples config to the
121 # stress tests too early, and depending on testr order will fail unit tests
122 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
123 '[%(name)s] %(message)s')
124
Ryota MIBU60687e52015-12-09 18:37:39 +0900125 # Client manager class to use in this test case.
126 client_manager = clients.Manager
127
Sean Dague02620fd2016-03-02 15:52:51 -0500128 # A way to adjust slow test classes
129 TIMEOUT_SCALING_FACTOR = 1
130
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200131 @classmethod
Andrea Frittoli3be57482017-08-25 22:41:26 +0100132 def _reset_class(cls):
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100133 cls.__setup_credentials_called = False
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100134 cls.__resource_cleanup_called = False
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100135 cls.__skip_checks_called = False
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600136 # Stack of callable to be invoked in reverse order
Andrea Frittoli3be57482017-08-25 22:41:26 +0100137 cls._class_cleanups = []
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600138 # Stack of (name, callable) to be invoked in reverse order at teardown
139 cls._teardowns = []
Andrea Frittoli3be57482017-08-25 22:41:26 +0100140
141 @classmethod
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200142 def setUpClass(cls):
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600143 cls.__setupclass_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100144 # Reset state
145 cls._reset_class()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100146 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200147 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
148 super(BaseTestCase, cls).setUpClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100149 # All the configuration checks that may generate a skip
150 cls.skip_checks()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100151 if not cls.__skip_checks_called:
152 raise RuntimeError("skip_checks for %s did not call the super's "
153 "skip_checks" % cls.__name__)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100154 try:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100155 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100156 cls._teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100157 cls.setup_credentials()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100158 if not cls.__setup_credentials_called:
159 raise RuntimeError("setup_credentials for %s did not call the "
160 "super's setup_credentials" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100161 # Shortcuts to clients
162 cls.setup_clients()
163 # Additional class-wide test resources
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100164 cls._teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100165 cls.resource_setup()
166 except Exception:
167 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100168 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
169 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100170 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100171 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400172 six.reraise(etype, value, trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100173 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100174 del trace # to avoid circular refs
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200175
Attila Fazekasf86fa312013-07-30 19:56:39 +0200176 @classmethod
177 def tearDownClass(cls):
Martin Kopecae155b72017-06-26 09:41:21 +0000178 # insert pdb breakpoint when pause_teardown is enabled
179 if CONF.pause_teardown:
180 cls.insert_pdb_breakpoint()
Attila Fazekas5d275302013-08-29 12:35:12 +0200181 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100182 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200183 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
184 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100185 # Save any existing exception, we always want to re-raise the original
186 # exception only
187 etype, value, trace = sys.exc_info()
188 # If there was no exception during setup we shall re-raise the first
189 # exception in teardown
190 re_raise = (etype is None)
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100191 while cls._teardowns:
192 name, teardown = cls._teardowns.pop()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100193 # Catch any exception in tearDown so we can re-raise the original
194 # exception at the end
195 try:
196 teardown()
Andrea Frittoli3be57482017-08-25 22:41:26 +0100197 if name == 'resources':
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100198 if not cls.__resource_cleanup_called:
Andrea Frittoli3be57482017-08-25 22:41:26 +0100199 raise RuntimeError(
200 "resource_cleanup for %s did not call the "
201 "super's resource_cleanup" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100202 except Exception as te:
203 sys_exec_info = sys.exc_info()
204 tetype = sys_exec_info[0]
Andrea Frittoli3be57482017-08-25 22:41:26 +0100205 # TODO(andreaf): Resource cleanup is often implemented by
206 # storing an array of resources at class level, and cleaning
207 # them up during `resource_cleanup`.
208 # In case of failure during setup, some resource arrays might
209 # not be defined at all, in which case the cleanup code might
210 # trigger an AttributeError. In such cases we log
211 # AttributeError as info instead of exception. Once all
212 # cleanups are migrated to addClassResourceCleanup we can
213 # remove this.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100214 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100215 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100216 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100217 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100218 if not etype:
219 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800220 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100221 # the first one
222 if re_raise and etype is not None:
223 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400224 six.reraise(etype, value, trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100225 finally:
226 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100227
Martin Kopecae155b72017-06-26 09:41:21 +0000228 def tearDown(self):
229 super(BaseTestCase, self).tearDown()
230 # insert pdb breakpoint when pause_teardown is enabled
231 if CONF.pause_teardown:
232 BaseTestCase.insert_pdb_breakpoint()
233
234 @classmethod
235 def insert_pdb_breakpoint(cls):
236 """Add pdb breakpoint.
237
238 This can help in debugging process, cleaning of resources is
239 paused, so they can be examined.
240 """
241 import pdb
242 pdb.set_trace()
243
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100244 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100245 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000246 """Class level skip checks.
247
248 Subclasses verify in here all conditions that might prevent the
Andrea Frittolia5440c82017-08-23 18:11:21 +0100249 execution of the entire test class. Skipping here prevents any other
250 class fixture from being executed i.e. no credentials or other
251 resource allocation will happen.
252
253 Tests defined in the test class will no longer appear in test results.
254 The `setUpClass` for the entire test class will be marked as SKIPPED
255 instead.
256
257 At this stage no test credentials are available, so skip checks
258 should rely on configuration alone. This is deliberate since skips
259 based on the result of an API call are discouraged.
260
261 The following checks are implemented in `test.py` already:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600262
Andrea Frittolia5440c82017-08-23 18:11:21 +0100263 - check that alt credentials are available when requested by the test
264 - check that admin credentials are available when requested by the test
265 - check that the identity version specified by the test is marked as
266 enabled in the configuration
267
268 Overriders of skip_checks must always invoke skip_check on `super`
269 first.
270
271 Example::
272
273 @classmethod
274 def skip_checks(cls):
275 super(Example, cls).skip_checks()
276 if not CONF.service_available.my_service:
277 skip_msg = ("%s skipped as my_service is not available")
278 raise cls.skipException(skip_msg % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100279 """
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100280 cls.__skip_checks_called = True
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100281 identity_version = cls.get_identity_version()
zhufl75498ba2017-08-25 10:49:35 +0800282 # setting force_tenant_isolation to True also needs admin credentials.
283 if ('admin' in cls.credentials or
284 getattr(cls, 'force_tenant_isolation', False)):
285 if not credentials.is_admin_available(
286 identity_version=identity_version):
287 raise cls.skipException(
288 "Missing Identity Admin API credentials in configuration.")
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100289 if 'alt' in cls.credentials and not credentials.is_alt_available(
290 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000291 msg = "Missing a 2nd set of API credentials in configuration."
292 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100293 if hasattr(cls, 'identity_version'):
294 if cls.identity_version == 'v2':
295 if not CONF.identity_feature_enabled.api_v2:
296 raise cls.skipException("Identity api v2 is not enabled")
297 elif cls.identity_version == 'v3':
298 if not CONF.identity_feature_enabled.api_v3:
299 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100300
301 @classmethod
302 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300303 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000304
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100305 `setup_credentials` looks for the content of the `credentials`
306 attribute in the test class. If the value is a non-empty collection,
307 a credentials provider is setup, and credentials are provisioned or
308 allocated based on the content of the collection. Every set of
309 credentials is associated to an object of type `cls.client_manager`.
310 The client manager is accessible by tests via class attribute
311 `os_[type]`:
edannon6cc6fbc2016-05-03 11:56:12 +0300312
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100313 Valid values in `credentials` are:
Sergey Vilgelmeac094a2018-11-21 18:27:51 -0600314
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100315 - 'primary':
316 A normal user is provisioned.
317 It can be used only once. Multiple entries will be ignored.
318 Clients are available at os_primary.
319 - 'alt':
320 A normal user other than 'primary' is provisioned.
321 It can be used only once. Multiple entries will be ignored.
322 Clients are available at os_alt.
323 - 'admin':
324 An admin user is provisioned.
325 It can be used only once. Multiple entries will be ignored.
326 Clients are available at os_admin.
327 - A list in the format ['any_label', 'role1', ... , 'roleN']:
328 A client with roles <list>[1:] is provisioned.
329 It can be used multiple times, with unique labels.
330 Clients are available at os_roles_<list>[0].
331
332 By default network resources are allocated (in case of dynamic
333 credentials). Tests that do not need network or that require a
334 custom network setup must specify which network resources shall
335 be provisioned using the `set_network_resources()` method (note
336 that it must be invoked before the `setup_credentials` is
337 invoked on super).
338
339 Example::
340
341 class TestWithCredentials(test.BaseTestCase):
342
343 credentials = ['primary', 'admin',
344 ['special', 'special_role1']]
345
346 @classmethod
347 def setup_credentials(cls):
348 # set_network_resources must be called first
349 cls.set_network_resources(network=True)
350 super(TestWithCredentials, cls).setup_credentials()
351
352 @classmethod
353 def setup_clients(cls):
354 cls.servers = cls.os_primary.compute.ServersClient()
355 cls.admin_servers = cls.os_admin.compute.ServersClient()
356 # certain API calls may require a user with a specific
357 # role assigned. In this example `special_role1` is
358 # assigned to the user in `cls.os_roles_special`.
359 cls.special_servers = (
360 cls.os_roles_special.compute.ServersClient())
361
362 def test_special_servers(self):
363 # Do something with servers
364 pass
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000365 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100366 cls.__setup_credentials_called = True
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000367 for credentials_type in cls.credentials:
368 # This may raise an exception in case credentials are not available
369 # In that case we want to let the exception through and the test
370 # fail accordingly
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100371 if isinstance(credentials_type, six.string_types):
372 manager = cls.get_client_manager(
373 credential_type=credentials_type)
374 setattr(cls, 'os_%s' % credentials_type, manager)
Jordan Pittier8160d312017-04-18 11:52:23 +0200375 # NOTE(jordanP): Tempest should use os_primary, os_admin
376 # and os_alt throughout its code base but we keep the aliases
377 # around for a while for Tempest plugins. Aliases should be
378 # removed eventually.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100379 # Setup some common aliases
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100380 if credentials_type == 'primary':
Jordan Pittier8160d312017-04-18 11:52:23 +0200381 cls.os = debtcollector.moves.moved_read_only_property(
382 'os', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200383 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200384 cls.manager =\
385 debtcollector.moves.moved_read_only_property(
386 'manager', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200387 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100388 if credentials_type == 'admin':
Jordan Pittier8160d312017-04-18 11:52:23 +0200389 cls.os_adm = debtcollector.moves.moved_read_only_property(
390 'os_adm', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200391 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200392 cls.admin_manager =\
393 debtcollector.moves.moved_read_only_property(
394 'admin_manager', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200395 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100396 if credentials_type == 'alt':
Jordan Pittier8160d312017-04-18 11:52:23 +0200397 cls.alt_manager =\
398 debtcollector.moves.moved_read_only_property(
399 'alt_manager', 'os_alt', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200400 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100401 elif isinstance(credentials_type, list):
402 manager = cls.get_client_manager(roles=credentials_type[1:],
403 force_new=True)
404 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100405
406 @classmethod
407 def setup_clients(cls):
Andrea Frittoli99583672017-08-24 15:39:20 +0100408 """Create aliases to the clients in the client managers.
409
410 `setup_clients` is invoked after the credential provisioning step.
411 Client manager objects are available to tests already. The purpose
412 of this helper is to setup shortcuts to specific clients that are
413 useful for the tests implemented in the test class.
414
415 Its purpose is mostly for code readability, however it should be used
416 carefully to avoid doing exactly the opposite, i.e. making the code
417 unreadable and hard to debug. If aliases are defined in a super class
418 it won't be obvious what they refer to, so it's good practice to define
419 all aliases used in the class. Aliases are meant to be shortcuts to
420 be used in tests, not shortcuts to avoid helper method attributes.
421 If an helper method starts relying on a client alias and a subclass
422 overrides that alias, it will become rather difficult to understand
423 what the helper method actually does.
424
425 Example::
426
427 class TestDoneItRight(test.BaseTestCase):
428
429 credentials = ['primary', 'alt']
430
431 @classmethod
432 def setup_clients(cls):
433 super(TestDoneItRight, cls).setup_clients()
434 cls.servers = cls.os_primary.ServersClient()
435 cls.servers_alt = cls.os_alt.ServersClient()
436
437 def _a_good_helper(self, clients):
438 # Some complex logic we're going to use many times
439 servers = clients.ServersClient()
440 vm = servers.create_server(...)
441
442 def delete_server():
443 test_utils.call_and_ignore_notfound_exc(
444 servers.delete_server, vm['id'])
445
446 self.addCleanup(self.delete_server)
447 return vm
448
449 def test_with_servers(self):
450 vm = self._a_good_helper(os.primary)
451 vm_alt = self._a_good_helper(os.alt)
452 cls.servers.show_server(vm['id'])
453 cls.servers_alt.show_server(vm_alt['id'])
454 """
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100455 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200456
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000457 @classmethod
458 def resource_setup(cls):
Andrea Frittoli3be57482017-08-25 22:41:26 +0100459 """Class level resource setup for test cases.
460
461 `resource_setup` is invoked once all credentials (and related network
462 resources have been provisioned and after client aliases - if any -
463 have been defined.
464
465 The use case for `resource_setup` is test optimization: provisioning
466 of project-specific "expensive" resources that are not dirtied by tests
467 and can thus safely be re-used by multiple tests.
468
469 System wide resources shared by all tests could instead be provisioned
470 only once, before the test run.
471
472 Resources provisioned here must be cleaned up during
473 `resource_cleanup`. This is best achieved by scheduling a cleanup via
474 `addClassResourceCleanup`.
475
476 Some test resources have an asynchronous delete process. It's best
477 practice for them to schedule a wait for delete via
478 `addClassResourceCleanup` to avoid having resources in process of
479 deletion when we reach the credentials cleanup step.
480
481 Example::
482
483 @classmethod
484 def resource_setup(cls):
485 super(MyTest, cls).resource_setup()
486 servers = cls.os_primary.compute.ServersClient()
487 # Schedule delete and wait so that we can first delete the
488 # two servers and then wait for both to delete
489 # Create server 1
490 cls.shared_server = servers.create_server()
491 # Create server 2. If something goes wrong we schedule cleanup
492 # of server 1 anyways.
493 try:
494 cls.shared_server2 = servers.create_server()
495 # Wait server 2
496 cls.addClassResourceCleanup(
497 waiters.wait_for_server_termination,
498 servers, cls.shared_server2['id'],
499 ignore_error=False)
500 finally:
501 # Wait server 1
502 cls.addClassResourceCleanup(
503 waiters.wait_for_server_termination,
504 servers, cls.shared_server['id'],
505 ignore_error=False)
506 # Delete server 1
507 cls.addClassResourceCleanup(
508 test_utils.call_and_ignore_notfound_exc,
509 servers.delete_server,
510 cls.shared_server['id'])
511 # Delete server 2 (if it was created)
512 if hasattr(cls, 'shared_server2'):
513 cls.addClassResourceCleanup(
514 test_utils.call_and_ignore_notfound_exc,
515 servers.delete_server,
516 cls.shared_server2['id'])
517 """
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100518 pass
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000519
520 @classmethod
521 def resource_cleanup(cls):
522 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000523
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100524 Resource cleanup processes the stack of cleanups produced by
Andrea Frittoli3be57482017-08-25 22:41:26 +0100525 `addClassResourceCleanup` and then cleans up validation resources
526 if any were provisioned.
527
528 All cleanups are processed whatever the outcome. Exceptions are
529 accumulated and re-raised as a `MultipleExceptions` at the end.
530
531 In most cases test cases won't need to override `resource_cleanup`,
532 but if they do they must invoke `resource_cleanup` on super.
533
534 Example::
535
536 class TestWithReallyComplexCleanup(test.BaseTestCase):
537
538 @classmethod
539 def resource_setup(cls):
540 # provision resource A
541 cls.addClassResourceCleanup(delete_resource, A)
542 # provision resource B
543 cls.addClassResourceCleanup(delete_resource, B)
544
545 @classmethod
546 def resource_cleanup(cls):
547 # It's possible to override resource_cleanup but in most
548 # cases it shouldn't be required. Nothing that may fail
549 # should be executed before the call to super since it
550 # might cause resource leak in case of error.
551 super(TestWithReallyComplexCleanup, cls).resource_cleanup()
552 # At this point test credentials are still available but
553 # anything from the cleanup stack has been already deleted.
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000554 """
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100555 cls.__resource_cleanup_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100556 cleanup_errors = []
557 while cls._class_cleanups:
558 try:
559 fn, args, kwargs = cls._class_cleanups.pop()
560 fn(*args, **kwargs)
561 except Exception:
562 cleanup_errors.append(sys.exc_info())
Andrea Frittoli3be57482017-08-25 22:41:26 +0100563 if cleanup_errors:
564 raise testtools.MultipleExceptions(*cleanup_errors)
565
566 @classmethod
567 def addClassResourceCleanup(cls, fn, *arguments, **keywordArguments):
568 """Add a cleanup function to be called during resource_cleanup.
569
570 Functions added with addClassResourceCleanup will be called in reverse
571 order of adding at the beginning of resource_cleanup, before any
572 credential, networking or validation resources cleanup is processed.
573
574 If a function added with addClassResourceCleanup raises an exception,
575 the error will be recorded as a test error, and the next cleanup will
576 then be run.
577
578 Cleanup functions are always called during the test class tearDown
579 fixture, even if an exception occured during setUp or tearDown.
580 """
581 cls._class_cleanups.append((fn, arguments, keywordArguments))
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000582
Attila Fazekasf86fa312013-07-30 19:56:39 +0200583 def setUp(self):
584 super(BaseTestCase, self).setUp()
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600585 if not self.__setupclass_called:
zhuflde676372018-11-16 15:34:56 +0800586 raise RuntimeError("setUpClass does not calls the super's "
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200587 "setUpClass in the " +
588 self.__class__.__name__)
Attila Fazekasf86fa312013-07-30 19:56:39 +0200589 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400590 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
591 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500592 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400593 except ValueError:
594 test_timeout = 0
595 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200596 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400597
598 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
599 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200600 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
601 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400602 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
603 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200604 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
605 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200606 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200607 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200608 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400609 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200610 level=None))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400611
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100612 @property
613 def credentials_provider(self):
614 return self._get_credentials_provider()
615
616 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100617 def get_identity_version(cls):
618 """Returns the identity version used by the test class"""
619 identity_version = getattr(cls, 'identity_version', None)
620 return identity_version or CONF.identity.auth_version
621
622 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100623 def _get_credentials_provider(cls):
624 """Returns a credentials provider
625
626 If no credential provider exists yet creates one.
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100627 It always use the configuration value from identity.auth_version,
628 since we always want to provision accounts with the current version
629 of the identity API.
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100630 """
631 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
632 not cls._creds_provider.name == cls.__name__):
633 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
634 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100635
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700636 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100637 name=cls.__name__, network_resources=cls._network_resources,
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100638 force_tenant_isolation=force_tenant_isolation)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100639 return cls._creds_provider
640
Matthew Treinish3e046852013-07-23 16:00:24 -0400641 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100642 def get_client_manager(cls, credential_type=None, roles=None,
643 force_new=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100644 """Returns an OpenStack client manager
645
646 Returns an OpenStack client manager based on either credential_type
647 or a list of roles. If neither is specified, it defaults to
648 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100649 :param credential_type: string - primary, alt or admin
650 :param roles: list of roles
651
lei zhangdd552b22015-11-25 20:41:48 +0800652 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100653 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700654 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100655 if all([roles, credential_type]):
656 msg = "Cannot get credentials by type and roles at the same time"
657 raise ValueError(msg)
658 if not any([roles, credential_type]):
659 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100660 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100661 if roles:
662 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100663 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100664 skip_msg = (
665 "%s skipped because the configured credential provider"
666 " is not able to provide credentials with the %s role "
667 "assigned." % (cls.__name__, role))
668 raise cls.skipException(skip_msg)
669 params = dict(roles=roles)
670 if force_new is not None:
671 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100672 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000673 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100674 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100675 if hasattr(cred_provider, credentials_method):
676 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100677 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100678 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100679 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100680 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000681 # NOTE(andreaf) Ensure credentials have user and project id fields.
682 # It may not be the case when using pre-provisioned credentials.
683 manager.auth_provider.set_auth()
684 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700685
686 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700687 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000688 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200689 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700690 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700691
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100692 @staticmethod
693 def _validation_resources_params_from_conf():
694 return dict(
695 keypair=(CONF.validation.auth_method.lower() == "keypair"),
696 floating_ip=(CONF.validation.connect_method.lower() == "floating"),
697 security_group=CONF.validation.security_group,
698 security_group_rules=CONF.validation.security_group_rules,
699 use_neutron=CONF.service_available.neutron,
700 ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
701 floating_network_id=CONF.network.public_network_id,
702 floating_network_name=CONF.network.floating_network_name)
703
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700704 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100705 def get_class_validation_resources(cls, os_clients):
706 """Provision validation resources according to configuration
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000707
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100708 This is a wrapper around `create_validation_resources` from
709 `tempest.common.validation_resources` that passes parameters from
710 Tempest configuration. Only one instance of class level
711 validation resources is managed by the helper, so If resources
712 were already provisioned before, existing ones will be returned.
nithya-ganesan222efd72015-01-22 12:20:27 +0000713
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100714 Resources are returned as a dictionary. They are also scheduled for
715 automatic cleanup during class teardown using
716 `addClassResourcesCleanup`.
717
718 If `CONF.validation.run_validation` is False no resource will be
719 provisioned at all.
720
721 @param os_clients: Clients to be used to provision the resources.
nithya-ganesan222efd72015-01-22 12:20:27 +0000722 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400723 if not CONF.validation.run_validation:
724 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100725
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100726 if os_clients in cls._validation_resources:
727 return cls._validation_resources[os_clients]
Jordan Pittier79cd1822016-12-08 17:20:35 +0100728
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100729 if (CONF.validation.ip_version_for_ssh not in (4, 6) and
730 CONF.service_available.neutron):
731 msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
732 raise lib_exc.InvalidConfiguration(
733 msg % CONF.validation.ip_version_for_ssh)
Jordan Pittier79cd1822016-12-08 17:20:35 +0100734
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100735 resources = vr.create_validation_resources(
736 os_clients,
737 **cls._validation_resources_params_from_conf())
Jordan Pittier79cd1822016-12-08 17:20:35 +0100738
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100739 cls.addClassResourceCleanup(
740 vr.clear_validation_resources, os_clients,
741 use_neutron=CONF.service_available.neutron,
742 **resources)
743 cls._validation_resources[os_clients] = resources
744 return resources
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500745
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100746 def get_test_validation_resources(self, os_clients):
747 """Returns a dict of validation resources according to configuration
748
749 Initialise a validation resources fixture based on configuration.
750 Start the fixture and returns the validation resources.
751
752 If `CONF.validation.run_validation` is False no resource will be
753 provisioned at all.
754
755 @param os_clients: Clients to be used to provision the resources.
756 """
757
758 params = {}
759 # Test will try to use the fixture, so for this to be useful
760 # we must return a fixture. If validation is disabled though
761 # we don't need to provision anything, which is the default
762 # behavior for the fixture.
763 if CONF.validation.run_validation:
764 params = self._validation_resources_params_from_conf()
765
766 validation = self.useFixture(
767 vr.ValidationResourcesFixture(os_clients, **params))
768 return validation.resources
nithya-ganesan222efd72015-01-22 12:20:27 +0000769
770 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000771 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500772 dhcp=False):
773 """Specify which network resources should be created
774
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100775 The dynamic credentials provider by default provisions network
776 resources for each user/project that is provisioned. This behavior
777 can be altered using this method, which allows tests to define which
778 specific network resources to be provisioned - none if no parameter
779 is specified.
780
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100781 This method is designed so that only the network resources set on the
782 leaf class are honoured.
783
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100784 Credentials are provisioned as part of the class setup fixture,
785 during the `setup_credentials` step. For this to be effective this
786 helper must be invoked before super's `setup_credentials` is executed.
787
Matthew Treinish9f756a02014-01-15 10:26:07 -0500788 @param network
789 @param router
790 @param subnet
791 @param dhcp
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100792
793 Example::
794
795 @classmethod
796 def setup_credentials(cls):
797 # Do not setup network resources for this test
798 cls.set_network_resources()
799 super(MyTest, cls).setup_credentials()
Matthew Treinish9f756a02014-01-15 10:26:07 -0500800 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100801 # If this is invoked after the credentials are setup, it won't take
802 # any effect. To avoid this situation, fail the test in case this was
803 # invoked too late in the test lifecycle.
804 if cls.__setup_credentials_called:
805 raise RuntimeError(
806 "set_network_resources invoked after setup_credentials on the "
807 "super class has been already invoked. For "
808 "set_network_resources to have effect please invoke it before "
809 "the call to super().setup_credentials")
810
811 # Network resources should be set only once from callers
Salvatore Orlando5a337242014-01-15 22:49:22 +0000812 # in order to ensure that even if it's called multiple times in
813 # a chain of overloaded methods, the attribute is set only
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100814 # in the leaf class.
815 if not cls._network_resources:
816 cls._network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000817 'network': network,
818 'router': router,
819 'subnet': subnet,
820 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500821
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530822 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000823 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530824 """Get the network to be used in testing
825
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000826 :param credentials_type: The type of credentials for which to get the
827 tenant network
828
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530829 :return: network dict including 'id' and 'name'
830 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000831 # Get a manager for the given credentials_type, but at least
832 # always fall back on getting the manager for primary credentials
833 if isinstance(credentials_type, six.string_types):
834 manager = cls.get_client_manager(credential_type=credentials_type)
835 elif isinstance(credentials_type, list):
836 manager = cls.get_client_manager(roles=credentials_type[1:])
837 else:
838 manager = cls.get_client_manager()
839
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700840 # Make sure cred_provider exists and get a network client
zhufl33289a22018-01-04 15:02:00 +0800841 networks_client = manager.networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100842 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100843 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800844 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100845 # for their servers, so using an admin network client to validate
846 # the network name
847 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100848 credentials.is_admin_available(
849 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100850 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100851 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400852 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900853 return fixed_network.get_tenant_network(
854 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530855
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100856 def assertEmpty(self, items, msg=None):
857 """Asserts whether a sequence or collection is empty
Mark Maglana5885eb32014-02-28 10:57:34 -0800858
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100859 :param items: sequence or collection to be tested
860 :param msg: message to be passed to the AssertionError
861 :raises AssertionError: when items is not empty
862 """
zhufl92ade4b2017-03-03 15:20:10 +0800863 if msg is None:
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100864 msg = "sequence or collection is not empty: %s" % items
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900865 self.assertFalse(items, msg)
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100866
867 def assertNotEmpty(self, items, msg=None):
868 """Asserts whether a sequence or collection is not empty
869
870 :param items: sequence or collection to be tested
871 :param msg: message to be passed to the AssertionError
872 :raises AssertionError: when items is empty
873 """
874 if msg is None:
875 msg = "sequence or collection is empty."
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900876 self.assertTrue(items, msg)