blob: 1a97502632899543107aa4a22a11d1ff562c0f6d [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 Treinish3787e4c2016-10-07 21:25:33 -040030from tempest.lib.common import cred_client
Matthew Treinishb19c55d2017-07-17 12:38:35 -040031from tempest.lib.common import fixed_network
Andrea Frittoli0477acc2017-08-09 21:14:53 +010032from tempest.lib.common import validation_resources as vr
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050033from tempest.lib import decorators
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +010034from tempest.lib import exceptions as lib_exc
Jay Pipes051075a2012-04-28 17:39:37 -040035
36LOG = logging.getLogger(__name__)
37
Sean Dague86bd8422013-12-20 09:56:44 -050038CONF = config.CONF
39
Ken'ichi Ohmichi44f01272017-01-27 18:44:14 -080040# TODO(oomichi): This test.idempotent_id should be removed after all projects
41# switch to use decorators.idempotent_id.
42idempotent_id = debtcollector.moves.moved_function(
43 decorators.idempotent_id, 'idempotent_id', __name__,
44 version='Mitaka', removal_version='?')
Matthew Treinishc1802bc2015-12-03 18:48:11 -050045
Jay Pipes051075a2012-04-28 17:39:37 -040046
Jordan Pittier3b46d272017-04-12 16:17:28 +020047attr = debtcollector.moves.moved_function(
48 decorators.attr, 'attr', __name__,
49 version='Pike', removal_version='?')
Chris Yeoh55530bb2013-02-08 16:04:27 +103050
51
Andrea Frittolicd368412017-08-14 21:37:56 +010052services = debtcollector.moves.moved_function(
53 utils.services, 'services', __name__,
54 version='Pike', removal_version='?')
Andrea Frittoli07acf262017-04-09 19:36:37 +020055
56
Andrea Frittolicd368412017-08-14 21:37:56 +010057requires_ext = debtcollector.moves.moved_function(
58 utils.requires_ext, 'requires_ext', __name__,
59 version='Pike', removal_version='?')
Matthew Treinish16c43792013-09-09 19:55:23 +000060
Matthew Treinish3d8c7322014-08-03 23:53:28 -040061
Andrea Frittolicd368412017-08-14 21:37:56 +010062is_extension_enabled = debtcollector.moves.moved_function(
63 utils.is_extension_enabled, 'is_extension_enabled', __name__,
64 version='Pike', removal_version='?')
Ian Wienand98c35f32013-07-23 20:34:23 +100065
Attila Fazekasf86fa312013-07-30 19:56:39 +020066at_exit_set = set()
67
68
69def validate_tearDownClass():
70 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -040071 LOG.error(
72 "tearDownClass does not call the super's "
73 "tearDownClass in these classes: \n"
74 + str(at_exit_set))
75
Attila Fazekasf86fa312013-07-30 19:56:39 +020076
77atexit.register(validate_tearDownClass)
78
Attila Fazekas53943322014-02-10 16:07:34 +010079
Matthew Treinish2474f412014-11-17 18:11:56 -050080class BaseTestCase(testtools.testcase.WithAttributes,
81 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +010082 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000083
Andrea Frittolia5ddd552014-08-19 18:30:00 +010084 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
85 by subclasses (enforced via hacking rule T105).
86
87 Set-up is split in a series of steps (setup stages), which can be
88 overwritten by test classes. Set-up stages are:
89 - skip_checks
90 - setup_credentials
91 - setup_clients
92 - resource_setup
93
94 Tear-down is also split in a series of steps (teardown stages), which are
95 stacked for execution only if the corresponding setup stage had been
96 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -070097 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +010098 - resource_cleanup
99 """
Attila Fazekasc43fec82013-04-09 23:17:52 +0200100
Attila Fazekasf86fa312013-07-30 19:56:39 +0200101 setUpClassCalled = False
102
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000103 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100104 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
105 # a list of roles - the first element of the list being a label, and the
106 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000107 credentials = []
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100108
109 # 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 Frittoli3be57482017-08-25 22:41:26 +0100134 cls.__resource_cleaup_called = False
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100135 cls.__skip_checks_called = False
Andrea Frittoli3be57482017-08-25 22:41:26 +0100136 cls._class_cleanups = []
137
138 @classmethod
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200139 def setUpClass(cls):
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()
Attila Fazekasf86fa312013-07-30 19:56:39 +0200145 cls.setUpClassCalled = True
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100146 # Stack of (name, callable) to be invoked in reverse order at teardown
147 cls.teardowns = []
148 # All the configuration checks that may generate a skip
149 cls.skip_checks()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100150 if not cls.__skip_checks_called:
151 raise RuntimeError("skip_checks for %s did not call the super's "
152 "skip_checks" % cls.__name__)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100153 try:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100154 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700155 cls.teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100156 cls.setup_credentials()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100157 if not cls.__setup_credentials_called:
158 raise RuntimeError("setup_credentials for %s did not call the "
159 "super's setup_credentials" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100160 # Shortcuts to clients
161 cls.setup_clients()
162 # Additional class-wide test resources
163 cls.teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100164 cls.resource_setup()
165 except Exception:
166 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100167 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
168 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100169 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100170 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400171 six.reraise(etype, value, trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100172 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100173 del trace # to avoid circular refs
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200174
Attila Fazekasf86fa312013-07-30 19:56:39 +0200175 @classmethod
176 def tearDownClass(cls):
Martin Kopecae155b72017-06-26 09:41:21 +0000177 # insert pdb breakpoint when pause_teardown is enabled
178 if CONF.pause_teardown:
179 cls.insert_pdb_breakpoint()
Attila Fazekas5d275302013-08-29 12:35:12 +0200180 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100181 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200182 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
183 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100184 # Save any existing exception, we always want to re-raise the original
185 # exception only
186 etype, value, trace = sys.exc_info()
187 # If there was no exception during setup we shall re-raise the first
188 # exception in teardown
189 re_raise = (etype is None)
190 while cls.teardowns:
191 name, teardown = cls.teardowns.pop()
192 # Catch any exception in tearDown so we can re-raise the original
193 # exception at the end
194 try:
195 teardown()
Andrea Frittoli3be57482017-08-25 22:41:26 +0100196 if name == 'resources':
197 if not cls.__resource_cleaup_called:
198 raise RuntimeError(
199 "resource_cleanup for %s did not call the "
200 "super's resource_cleanup" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100201 except Exception as te:
202 sys_exec_info = sys.exc_info()
203 tetype = sys_exec_info[0]
Andrea Frittoli3be57482017-08-25 22:41:26 +0100204 # TODO(andreaf): Resource cleanup is often implemented by
205 # storing an array of resources at class level, and cleaning
206 # them up during `resource_cleanup`.
207 # In case of failure during setup, some resource arrays might
208 # not be defined at all, in which case the cleanup code might
209 # trigger an AttributeError. In such cases we log
210 # AttributeError as info instead of exception. Once all
211 # cleanups are migrated to addClassResourceCleanup we can
212 # remove this.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100213 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100214 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100215 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100216 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100217 if not etype:
218 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800219 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100220 # the first one
221 if re_raise and etype is not None:
222 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400223 six.reraise(etype, value, trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100224 finally:
225 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100226
Martin Kopecae155b72017-06-26 09:41:21 +0000227 def tearDown(self):
228 super(BaseTestCase, self).tearDown()
229 # insert pdb breakpoint when pause_teardown is enabled
230 if CONF.pause_teardown:
231 BaseTestCase.insert_pdb_breakpoint()
232
233 @classmethod
234 def insert_pdb_breakpoint(cls):
235 """Add pdb breakpoint.
236
237 This can help in debugging process, cleaning of resources is
238 paused, so they can be examined.
239 """
240 import pdb
241 pdb.set_trace()
242
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100243 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100244 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000245 """Class level skip checks.
246
247 Subclasses verify in here all conditions that might prevent the
Andrea Frittolia5440c82017-08-23 18:11:21 +0100248 execution of the entire test class. Skipping here prevents any other
249 class fixture from being executed i.e. no credentials or other
250 resource allocation will happen.
251
252 Tests defined in the test class will no longer appear in test results.
253 The `setUpClass` for the entire test class will be marked as SKIPPED
254 instead.
255
256 At this stage no test credentials are available, so skip checks
257 should rely on configuration alone. This is deliberate since skips
258 based on the result of an API call are discouraged.
259
260 The following checks are implemented in `test.py` already:
261 - check that alt credentials are available when requested by the test
262 - check that admin credentials are available when requested by the test
263 - check that the identity version specified by the test is marked as
264 enabled in the configuration
265
266 Overriders of skip_checks must always invoke skip_check on `super`
267 first.
268
269 Example::
270
271 @classmethod
272 def skip_checks(cls):
273 super(Example, cls).skip_checks()
274 if not CONF.service_available.my_service:
275 skip_msg = ("%s skipped as my_service is not available")
276 raise cls.skipException(skip_msg % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100277 """
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100278 cls.__skip_checks_called = True
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100279 identity_version = cls.get_identity_version()
zhufl75498ba2017-08-25 10:49:35 +0800280 # setting force_tenant_isolation to True also needs admin credentials.
281 if ('admin' in cls.credentials or
282 getattr(cls, 'force_tenant_isolation', False)):
283 if not credentials.is_admin_available(
284 identity_version=identity_version):
285 raise cls.skipException(
286 "Missing Identity Admin API credentials in configuration.")
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100287 if 'alt' in cls.credentials and not credentials.is_alt_available(
288 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000289 msg = "Missing a 2nd set of API credentials in configuration."
290 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100291 if hasattr(cls, 'identity_version'):
292 if cls.identity_version == 'v2':
293 if not CONF.identity_feature_enabled.api_v2:
294 raise cls.skipException("Identity api v2 is not enabled")
295 elif cls.identity_version == 'v3':
296 if not CONF.identity_feature_enabled.api_v3:
297 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100298
299 @classmethod
300 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300301 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000302
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100303 `setup_credentials` looks for the content of the `credentials`
304 attribute in the test class. If the value is a non-empty collection,
305 a credentials provider is setup, and credentials are provisioned or
306 allocated based on the content of the collection. Every set of
307 credentials is associated to an object of type `cls.client_manager`.
308 The client manager is accessible by tests via class attribute
309 `os_[type]`:
edannon6cc6fbc2016-05-03 11:56:12 +0300310
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100311 Valid values in `credentials` are:
312 - 'primary':
313 A normal user is provisioned.
314 It can be used only once. Multiple entries will be ignored.
315 Clients are available at os_primary.
316 - 'alt':
317 A normal user other than 'primary' is provisioned.
318 It can be used only once. Multiple entries will be ignored.
319 Clients are available at os_alt.
320 - 'admin':
321 An admin user is provisioned.
322 It can be used only once. Multiple entries will be ignored.
323 Clients are available at os_admin.
324 - A list in the format ['any_label', 'role1', ... , 'roleN']:
325 A client with roles <list>[1:] is provisioned.
326 It can be used multiple times, with unique labels.
327 Clients are available at os_roles_<list>[0].
328
329 By default network resources are allocated (in case of dynamic
330 credentials). Tests that do not need network or that require a
331 custom network setup must specify which network resources shall
332 be provisioned using the `set_network_resources()` method (note
333 that it must be invoked before the `setup_credentials` is
334 invoked on super).
335
336 Example::
337
338 class TestWithCredentials(test.BaseTestCase):
339
340 credentials = ['primary', 'admin',
341 ['special', 'special_role1']]
342
343 @classmethod
344 def setup_credentials(cls):
345 # set_network_resources must be called first
346 cls.set_network_resources(network=True)
347 super(TestWithCredentials, cls).setup_credentials()
348
349 @classmethod
350 def setup_clients(cls):
351 cls.servers = cls.os_primary.compute.ServersClient()
352 cls.admin_servers = cls.os_admin.compute.ServersClient()
353 # certain API calls may require a user with a specific
354 # role assigned. In this example `special_role1` is
355 # assigned to the user in `cls.os_roles_special`.
356 cls.special_servers = (
357 cls.os_roles_special.compute.ServersClient())
358
359 def test_special_servers(self):
360 # Do something with servers
361 pass
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000362 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100363 cls.__setup_credentials_called = True
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000364 for credentials_type in cls.credentials:
365 # This may raise an exception in case credentials are not available
366 # In that case we want to let the exception through and the test
367 # fail accordingly
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100368 if isinstance(credentials_type, six.string_types):
369 manager = cls.get_client_manager(
370 credential_type=credentials_type)
371 setattr(cls, 'os_%s' % credentials_type, manager)
Jordan Pittier8160d312017-04-18 11:52:23 +0200372 # NOTE(jordanP): Tempest should use os_primary, os_admin
373 # and os_alt throughout its code base but we keep the aliases
374 # around for a while for Tempest plugins. Aliases should be
375 # removed eventually.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100376 # Setup some common aliases
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100377 if credentials_type == 'primary':
Jordan Pittier8160d312017-04-18 11:52:23 +0200378 cls.os = debtcollector.moves.moved_read_only_property(
379 'os', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200380 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200381 cls.manager =\
382 debtcollector.moves.moved_read_only_property(
383 'manager', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200384 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100385 if credentials_type == 'admin':
Jordan Pittier8160d312017-04-18 11:52:23 +0200386 cls.os_adm = debtcollector.moves.moved_read_only_property(
387 'os_adm', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200388 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200389 cls.admin_manager =\
390 debtcollector.moves.moved_read_only_property(
391 'admin_manager', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200392 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100393 if credentials_type == 'alt':
Jordan Pittier8160d312017-04-18 11:52:23 +0200394 cls.alt_manager =\
395 debtcollector.moves.moved_read_only_property(
396 'alt_manager', 'os_alt', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200397 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100398 elif isinstance(credentials_type, list):
399 manager = cls.get_client_manager(roles=credentials_type[1:],
400 force_new=True)
401 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100402
403 @classmethod
404 def setup_clients(cls):
Andrea Frittoli99583672017-08-24 15:39:20 +0100405 """Create aliases to the clients in the client managers.
406
407 `setup_clients` is invoked after the credential provisioning step.
408 Client manager objects are available to tests already. The purpose
409 of this helper is to setup shortcuts to specific clients that are
410 useful for the tests implemented in the test class.
411
412 Its purpose is mostly for code readability, however it should be used
413 carefully to avoid doing exactly the opposite, i.e. making the code
414 unreadable and hard to debug. If aliases are defined in a super class
415 it won't be obvious what they refer to, so it's good practice to define
416 all aliases used in the class. Aliases are meant to be shortcuts to
417 be used in tests, not shortcuts to avoid helper method attributes.
418 If an helper method starts relying on a client alias and a subclass
419 overrides that alias, it will become rather difficult to understand
420 what the helper method actually does.
421
422 Example::
423
424 class TestDoneItRight(test.BaseTestCase):
425
426 credentials = ['primary', 'alt']
427
428 @classmethod
429 def setup_clients(cls):
430 super(TestDoneItRight, cls).setup_clients()
431 cls.servers = cls.os_primary.ServersClient()
432 cls.servers_alt = cls.os_alt.ServersClient()
433
434 def _a_good_helper(self, clients):
435 # Some complex logic we're going to use many times
436 servers = clients.ServersClient()
437 vm = servers.create_server(...)
438
439 def delete_server():
440 test_utils.call_and_ignore_notfound_exc(
441 servers.delete_server, vm['id'])
442
443 self.addCleanup(self.delete_server)
444 return vm
445
446 def test_with_servers(self):
447 vm = self._a_good_helper(os.primary)
448 vm_alt = self._a_good_helper(os.alt)
449 cls.servers.show_server(vm['id'])
450 cls.servers_alt.show_server(vm_alt['id'])
451 """
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100452 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200453
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000454 @classmethod
455 def resource_setup(cls):
Andrea Frittoli3be57482017-08-25 22:41:26 +0100456 """Class level resource setup for test cases.
457
458 `resource_setup` is invoked once all credentials (and related network
459 resources have been provisioned and after client aliases - if any -
460 have been defined.
461
462 The use case for `resource_setup` is test optimization: provisioning
463 of project-specific "expensive" resources that are not dirtied by tests
464 and can thus safely be re-used by multiple tests.
465
466 System wide resources shared by all tests could instead be provisioned
467 only once, before the test run.
468
469 Resources provisioned here must be cleaned up during
470 `resource_cleanup`. This is best achieved by scheduling a cleanup via
471 `addClassResourceCleanup`.
472
473 Some test resources have an asynchronous delete process. It's best
474 practice for them to schedule a wait for delete via
475 `addClassResourceCleanup` to avoid having resources in process of
476 deletion when we reach the credentials cleanup step.
477
478 Example::
479
480 @classmethod
481 def resource_setup(cls):
482 super(MyTest, cls).resource_setup()
483 servers = cls.os_primary.compute.ServersClient()
484 # Schedule delete and wait so that we can first delete the
485 # two servers and then wait for both to delete
486 # Create server 1
487 cls.shared_server = servers.create_server()
488 # Create server 2. If something goes wrong we schedule cleanup
489 # of server 1 anyways.
490 try:
491 cls.shared_server2 = servers.create_server()
492 # Wait server 2
493 cls.addClassResourceCleanup(
494 waiters.wait_for_server_termination,
495 servers, cls.shared_server2['id'],
496 ignore_error=False)
497 finally:
498 # Wait server 1
499 cls.addClassResourceCleanup(
500 waiters.wait_for_server_termination,
501 servers, cls.shared_server['id'],
502 ignore_error=False)
503 # Delete server 1
504 cls.addClassResourceCleanup(
505 test_utils.call_and_ignore_notfound_exc,
506 servers.delete_server,
507 cls.shared_server['id'])
508 # Delete server 2 (if it was created)
509 if hasattr(cls, 'shared_server2'):
510 cls.addClassResourceCleanup(
511 test_utils.call_and_ignore_notfound_exc,
512 servers.delete_server,
513 cls.shared_server2['id'])
514 """
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100515 pass
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000516
517 @classmethod
518 def resource_cleanup(cls):
519 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000520
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100521 Resource cleanup processes the stack of cleanups produced by
Andrea Frittoli3be57482017-08-25 22:41:26 +0100522 `addClassResourceCleanup` and then cleans up validation resources
523 if any were provisioned.
524
525 All cleanups are processed whatever the outcome. Exceptions are
526 accumulated and re-raised as a `MultipleExceptions` at the end.
527
528 In most cases test cases won't need to override `resource_cleanup`,
529 but if they do they must invoke `resource_cleanup` on super.
530
531 Example::
532
533 class TestWithReallyComplexCleanup(test.BaseTestCase):
534
535 @classmethod
536 def resource_setup(cls):
537 # provision resource A
538 cls.addClassResourceCleanup(delete_resource, A)
539 # provision resource B
540 cls.addClassResourceCleanup(delete_resource, B)
541
542 @classmethod
543 def resource_cleanup(cls):
544 # It's possible to override resource_cleanup but in most
545 # cases it shouldn't be required. Nothing that may fail
546 # should be executed before the call to super since it
547 # might cause resource leak in case of error.
548 super(TestWithReallyComplexCleanup, cls).resource_cleanup()
549 # At this point test credentials are still available but
550 # anything from the cleanup stack has been already deleted.
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000551 """
Andrea Frittoli3be57482017-08-25 22:41:26 +0100552 cls.__resource_cleaup_called = True
553 cleanup_errors = []
554 while cls._class_cleanups:
555 try:
556 fn, args, kwargs = cls._class_cleanups.pop()
557 fn(*args, **kwargs)
558 except Exception:
559 cleanup_errors.append(sys.exc_info())
Andrea Frittoli3be57482017-08-25 22:41:26 +0100560 if cleanup_errors:
561 raise testtools.MultipleExceptions(*cleanup_errors)
562
563 @classmethod
564 def addClassResourceCleanup(cls, fn, *arguments, **keywordArguments):
565 """Add a cleanup function to be called during resource_cleanup.
566
567 Functions added with addClassResourceCleanup will be called in reverse
568 order of adding at the beginning of resource_cleanup, before any
569 credential, networking or validation resources cleanup is processed.
570
571 If a function added with addClassResourceCleanup raises an exception,
572 the error will be recorded as a test error, and the next cleanup will
573 then be run.
574
575 Cleanup functions are always called during the test class tearDown
576 fixture, even if an exception occured during setUp or tearDown.
577 """
578 cls._class_cleanups.append((fn, arguments, keywordArguments))
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000579
Attila Fazekasf86fa312013-07-30 19:56:39 +0200580 def setUp(self):
581 super(BaseTestCase, self).setUp()
582 if not self.setUpClassCalled:
583 raise RuntimeError("setUpClass does not calls the super's"
584 "setUpClass in the "
585 + self.__class__.__name__)
586 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400587 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
588 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500589 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400590 except ValueError:
591 test_timeout = 0
592 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200593 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400594
595 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
596 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200597 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
598 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400599 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
600 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200601 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
602 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200603 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
604 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200605 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400606 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200607 level=None))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400608
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100609 @property
610 def credentials_provider(self):
611 return self._get_credentials_provider()
612
Jamie Lennox15350172015-08-17 10:54:25 +1000613 @property
614 def identity_utils(self):
615 """A client that abstracts v2 and v3 identity operations.
616
617 This can be used for creating and tearing down projects in tests. It
618 should not be used for testing identity features.
619 """
620 if CONF.identity.auth_version == 'v2':
621 client = self.os_admin.identity_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000622 users_client = self.os_admin.users_client
Daniel Melladob04da902015-11-20 17:43:12 +0100623 project_client = self.os_admin.tenants_client
Daniel Mellado6b16b922015-12-07 12:43:08 +0000624 roles_client = self.os_admin.roles_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000625 domains_client = None
Jamie Lennox15350172015-08-17 10:54:25 +1000626 else:
627 client = self.os_admin.identity_v3_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000628 users_client = self.os_admin.users_v3_client
Arx Cruz24bcb882016-02-10 15:20:16 +0100629 project_client = self.os_admin.projects_client
630 roles_client = self.os_admin.roles_v3_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000631 domains_client = self.os_admin.domains_client
Jamie Lennox15350172015-08-17 10:54:25 +1000632
633 try:
634 domain = client.auth_provider.credentials.project_domain_name
635 except AttributeError:
636 domain = 'Default'
637
Daniel Melladob04da902015-11-20 17:43:12 +0100638 return cred_client.get_creds_client(client, project_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +0000639 users_client,
Daniel Mellado7aea5342016-02-09 09:10:12 +0000640 roles_client,
Daniel Mellado91a26b62016-02-11 11:13:04 +0000641 domains_client,
Daniel Melladob04da902015-11-20 17:43:12 +0100642 project_domain_name=domain)
Jamie Lennox15350172015-08-17 10:54:25 +1000643
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100644 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100645 def get_identity_version(cls):
646 """Returns the identity version used by the test class"""
647 identity_version = getattr(cls, 'identity_version', None)
648 return identity_version or CONF.identity.auth_version
649
650 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100651 def _get_credentials_provider(cls):
652 """Returns a credentials provider
653
654 If no credential provider exists yet creates one.
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100655 It always use the configuration value from identity.auth_version,
656 since we always want to provision accounts with the current version
657 of the identity API.
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100658 """
659 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
660 not cls._creds_provider.name == cls.__name__):
661 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
662 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100663
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700664 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100665 name=cls.__name__, network_resources=cls._network_resources,
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100666 force_tenant_isolation=force_tenant_isolation)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100667 return cls._creds_provider
668
Matthew Treinish3e046852013-07-23 16:00:24 -0400669 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100670 def get_client_manager(cls, credential_type=None, roles=None,
671 force_new=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100672 """Returns an OpenStack client manager
673
674 Returns an OpenStack client manager based on either credential_type
675 or a list of roles. If neither is specified, it defaults to
676 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100677 :param credential_type: string - primary, alt or admin
678 :param roles: list of roles
679
lei zhangdd552b22015-11-25 20:41:48 +0800680 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100681 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700682 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100683 if all([roles, credential_type]):
684 msg = "Cannot get credentials by type and roles at the same time"
685 raise ValueError(msg)
686 if not any([roles, credential_type]):
687 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100688 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100689 if roles:
690 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100691 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100692 skip_msg = (
693 "%s skipped because the configured credential provider"
694 " is not able to provide credentials with the %s role "
695 "assigned." % (cls.__name__, role))
696 raise cls.skipException(skip_msg)
697 params = dict(roles=roles)
698 if force_new is not None:
699 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100700 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000701 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100702 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100703 if hasattr(cred_provider, credentials_method):
704 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100705 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100706 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100707 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100708 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000709 # NOTE(andreaf) Ensure credentials have user and project id fields.
710 # It may not be the case when using pre-provisioned credentials.
711 manager.auth_provider.set_auth()
712 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700713
714 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700715 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000716 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200717 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700718 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700719
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100720 @staticmethod
721 def _validation_resources_params_from_conf():
722 return dict(
723 keypair=(CONF.validation.auth_method.lower() == "keypair"),
724 floating_ip=(CONF.validation.connect_method.lower() == "floating"),
725 security_group=CONF.validation.security_group,
726 security_group_rules=CONF.validation.security_group_rules,
727 use_neutron=CONF.service_available.neutron,
728 ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
729 floating_network_id=CONF.network.public_network_id,
730 floating_network_name=CONF.network.floating_network_name)
731
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700732 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100733 def get_class_validation_resources(cls, os_clients):
734 """Provision validation resources according to configuration
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000735
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100736 This is a wrapper around `create_validation_resources` from
737 `tempest.common.validation_resources` that passes parameters from
738 Tempest configuration. Only one instance of class level
739 validation resources is managed by the helper, so If resources
740 were already provisioned before, existing ones will be returned.
nithya-ganesan222efd72015-01-22 12:20:27 +0000741
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100742 Resources are returned as a dictionary. They are also scheduled for
743 automatic cleanup during class teardown using
744 `addClassResourcesCleanup`.
745
746 If `CONF.validation.run_validation` is False no resource will be
747 provisioned at all.
748
749 @param os_clients: Clients to be used to provision the resources.
nithya-ganesan222efd72015-01-22 12:20:27 +0000750 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400751 if not CONF.validation.run_validation:
752 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100753
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100754 if os_clients in cls._validation_resources:
755 return cls._validation_resources[os_clients]
Jordan Pittier79cd1822016-12-08 17:20:35 +0100756
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100757 if (CONF.validation.ip_version_for_ssh not in (4, 6) and
758 CONF.service_available.neutron):
759 msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
760 raise lib_exc.InvalidConfiguration(
761 msg % CONF.validation.ip_version_for_ssh)
Jordan Pittier79cd1822016-12-08 17:20:35 +0100762
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100763 resources = vr.create_validation_resources(
764 os_clients,
765 **cls._validation_resources_params_from_conf())
Jordan Pittier79cd1822016-12-08 17:20:35 +0100766
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100767 cls.addClassResourceCleanup(
768 vr.clear_validation_resources, os_clients,
769 use_neutron=CONF.service_available.neutron,
770 **resources)
771 cls._validation_resources[os_clients] = resources
772 return resources
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500773
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100774 def get_test_validation_resources(self, os_clients):
775 """Returns a dict of validation resources according to configuration
776
777 Initialise a validation resources fixture based on configuration.
778 Start the fixture and returns the validation resources.
779
780 If `CONF.validation.run_validation` is False no resource will be
781 provisioned at all.
782
783 @param os_clients: Clients to be used to provision the resources.
784 """
785
786 params = {}
787 # Test will try to use the fixture, so for this to be useful
788 # we must return a fixture. If validation is disabled though
789 # we don't need to provision anything, which is the default
790 # behavior for the fixture.
791 if CONF.validation.run_validation:
792 params = self._validation_resources_params_from_conf()
793
794 validation = self.useFixture(
795 vr.ValidationResourcesFixture(os_clients, **params))
796 return validation.resources
nithya-ganesan222efd72015-01-22 12:20:27 +0000797
798 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000799 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500800 dhcp=False):
801 """Specify which network resources should be created
802
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100803 The dynamic credentials provider by default provisions network
804 resources for each user/project that is provisioned. This behavior
805 can be altered using this method, which allows tests to define which
806 specific network resources to be provisioned - none if no parameter
807 is specified.
808
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100809 This method is designed so that only the network resources set on the
810 leaf class are honoured.
811
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100812 Credentials are provisioned as part of the class setup fixture,
813 during the `setup_credentials` step. For this to be effective this
814 helper must be invoked before super's `setup_credentials` is executed.
815
Matthew Treinish9f756a02014-01-15 10:26:07 -0500816 @param network
817 @param router
818 @param subnet
819 @param dhcp
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100820
821 Example::
822
823 @classmethod
824 def setup_credentials(cls):
825 # Do not setup network resources for this test
826 cls.set_network_resources()
827 super(MyTest, cls).setup_credentials()
Matthew Treinish9f756a02014-01-15 10:26:07 -0500828 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100829 # If this is invoked after the credentials are setup, it won't take
830 # any effect. To avoid this situation, fail the test in case this was
831 # invoked too late in the test lifecycle.
832 if cls.__setup_credentials_called:
833 raise RuntimeError(
834 "set_network_resources invoked after setup_credentials on the "
835 "super class has been already invoked. For "
836 "set_network_resources to have effect please invoke it before "
837 "the call to super().setup_credentials")
838
839 # Network resources should be set only once from callers
Salvatore Orlando5a337242014-01-15 22:49:22 +0000840 # in order to ensure that even if it's called multiple times in
841 # a chain of overloaded methods, the attribute is set only
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100842 # in the leaf class.
843 if not cls._network_resources:
844 cls._network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000845 'network': network,
846 'router': router,
847 'subnet': subnet,
848 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500849
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530850 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000851 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530852 """Get the network to be used in testing
853
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000854 :param credentials_type: The type of credentials for which to get the
855 tenant network
856
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530857 :return: network dict including 'id' and 'name'
858 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000859 # Get a manager for the given credentials_type, but at least
860 # always fall back on getting the manager for primary credentials
861 if isinstance(credentials_type, six.string_types):
862 manager = cls.get_client_manager(credential_type=credentials_type)
863 elif isinstance(credentials_type, list):
864 manager = cls.get_client_manager(roles=credentials_type[1:])
865 else:
866 manager = cls.get_client_manager()
867
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700868 # Make sure cred_provider exists and get a network client
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000869 networks_client = manager.compute_networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100870 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100871 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800872 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100873 # for their servers, so using an admin network client to validate
874 # the network name
875 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100876 credentials.is_admin_available(
877 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100878 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100879 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400880 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900881 return fixed_network.get_tenant_network(
882 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530883
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100884 def assertEmpty(self, items, msg=None):
885 """Asserts whether a sequence or collection is empty
Mark Maglana5885eb32014-02-28 10:57:34 -0800886
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100887 :param items: sequence or collection to be tested
888 :param msg: message to be passed to the AssertionError
889 :raises AssertionError: when items is not empty
890 """
zhufl92ade4b2017-03-03 15:20:10 +0800891 if msg is None:
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100892 msg = "sequence or collection is not empty: %s" % items
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900893 self.assertFalse(items, msg)
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100894
895 def assertNotEmpty(self, items, msg=None):
896 """Asserts whether a sequence or collection is not empty
897
898 :param items: sequence or collection to be tested
899 :param msg: message to be passed to the AssertionError
900 :raises AssertionError: when items is empty
901 """
902 if msg is None:
903 msg = "sequence or collection is empty."
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900904 self.assertTrue(items, msg)