blob: 25366bc1437dca97563d880a2001affcb0aa2104 [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
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000101 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100102 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
103 # a list of roles - the first element of the list being a label, and the
104 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000105 credentials = []
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100106
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600107 # Track if setUpClass was invoked
108 __setupclass_called = False
109
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100110 # Network resources to be provisioned for the requested test credentials.
111 # Only used with the dynamic credentials provider.
112 _network_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500113
Andrea Frittoli3be57482017-08-25 22:41:26 +0100114 # Stack of resource cleanups
115 _class_cleanups = []
116
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100117 # Resources required to validate a server using ssh
118 _validation_resources = {}
119
Sean Dague2ef32ac2014-06-09 11:32:23 -0400120 # NOTE(sdague): log_format is defined inline here instead of using the oslo
121 # default because going through the config path recouples config to the
122 # stress tests too early, and depending on testr order will fail unit tests
123 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
124 '[%(name)s] %(message)s')
125
Ryota MIBU60687e52015-12-09 18:37:39 +0900126 # Client manager class to use in this test case.
127 client_manager = clients.Manager
128
Sean Dague02620fd2016-03-02 15:52:51 -0500129 # A way to adjust slow test classes
130 TIMEOUT_SCALING_FACTOR = 1
131
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200132 @classmethod
Andrea Frittoli3be57482017-08-25 22:41:26 +0100133 def _reset_class(cls):
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100134 cls.__setup_credentials_called = False
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100135 cls.__resource_cleanup_called = False
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100136 cls.__skip_checks_called = False
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600137 # Stack of callable to be invoked in reverse order
Andrea Frittoli3be57482017-08-25 22:41:26 +0100138 cls._class_cleanups = []
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600139 # Stack of (name, callable) to be invoked in reverse order at teardown
140 cls._teardowns = []
Andrea Frittoli3be57482017-08-25 22:41:26 +0100141
142 @classmethod
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200143 def setUpClass(cls):
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600144 cls.__setupclass_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100145 # Reset state
146 cls._reset_class()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100147 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200148 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
149 super(BaseTestCase, cls).setUpClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100150 # All the configuration checks that may generate a skip
151 cls.skip_checks()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100152 if not cls.__skip_checks_called:
153 raise RuntimeError("skip_checks for %s did not call the super's "
154 "skip_checks" % cls.__name__)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100155 try:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100156 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100157 cls._teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100158 cls.setup_credentials()
Andrea Frittoli421dc3c2017-08-15 12:17:42 +0100159 if not cls.__setup_credentials_called:
160 raise RuntimeError("setup_credentials for %s did not call the "
161 "super's setup_credentials" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100162 # Shortcuts to clients
163 cls.setup_clients()
164 # Additional class-wide test resources
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100165 cls._teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100166 cls.resource_setup()
167 except Exception:
168 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100169 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
170 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100171 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100172 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400173 six.reraise(etype, value, trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100174 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100175 del trace # to avoid circular refs
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200176
Attila Fazekasf86fa312013-07-30 19:56:39 +0200177 @classmethod
178 def tearDownClass(cls):
Martin Kopecae155b72017-06-26 09:41:21 +0000179 # insert pdb breakpoint when pause_teardown is enabled
180 if CONF.pause_teardown:
181 cls.insert_pdb_breakpoint()
Attila Fazekas5d275302013-08-29 12:35:12 +0200182 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100183 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200184 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
185 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100186 # Save any existing exception, we always want to re-raise the original
187 # exception only
188 etype, value, trace = sys.exc_info()
189 # If there was no exception during setup we shall re-raise the first
190 # exception in teardown
191 re_raise = (etype is None)
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100192 while cls._teardowns:
193 name, teardown = cls._teardowns.pop()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100194 # Catch any exception in tearDown so we can re-raise the original
195 # exception at the end
196 try:
197 teardown()
Andrea Frittoli3be57482017-08-25 22:41:26 +0100198 if name == 'resources':
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100199 if not cls.__resource_cleanup_called:
Andrea Frittoli3be57482017-08-25 22:41:26 +0100200 raise RuntimeError(
201 "resource_cleanup for %s did not call the "
202 "super's resource_cleanup" % cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100203 except Exception as te:
204 sys_exec_info = sys.exc_info()
205 tetype = sys_exec_info[0]
Andrea Frittoli3be57482017-08-25 22:41:26 +0100206 # TODO(andreaf): Resource cleanup is often implemented by
207 # storing an array of resources at class level, and cleaning
208 # them up during `resource_cleanup`.
209 # In case of failure during setup, some resource arrays might
210 # not be defined at all, in which case the cleanup code might
211 # trigger an AttributeError. In such cases we log
212 # AttributeError as info instead of exception. Once all
213 # cleanups are migrated to addClassResourceCleanup we can
214 # remove this.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100215 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100216 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100217 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100218 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100219 if not etype:
220 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800221 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100222 # the first one
223 if re_raise and etype is not None:
224 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400225 six.reraise(etype, value, trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100226 finally:
227 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100228
Martin Kopecae155b72017-06-26 09:41:21 +0000229 def tearDown(self):
230 super(BaseTestCase, self).tearDown()
231 # insert pdb breakpoint when pause_teardown is enabled
232 if CONF.pause_teardown:
233 BaseTestCase.insert_pdb_breakpoint()
234
235 @classmethod
236 def insert_pdb_breakpoint(cls):
237 """Add pdb breakpoint.
238
239 This can help in debugging process, cleaning of resources is
240 paused, so they can be examined.
241 """
242 import pdb
243 pdb.set_trace()
244
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100245 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100246 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000247 """Class level skip checks.
248
249 Subclasses verify in here all conditions that might prevent the
Andrea Frittolia5440c82017-08-23 18:11:21 +0100250 execution of the entire test class. Skipping here prevents any other
251 class fixture from being executed i.e. no credentials or other
252 resource allocation will happen.
253
254 Tests defined in the test class will no longer appear in test results.
255 The `setUpClass` for the entire test class will be marked as SKIPPED
256 instead.
257
258 At this stage no test credentials are available, so skip checks
259 should rely on configuration alone. This is deliberate since skips
260 based on the result of an API call are discouraged.
261
262 The following checks are implemented in `test.py` already:
263 - 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:
314 - 'primary':
315 A normal user is provisioned.
316 It can be used only once. Multiple entries will be ignored.
317 Clients are available at os_primary.
318 - 'alt':
319 A normal user other than 'primary' is provisioned.
320 It can be used only once. Multiple entries will be ignored.
321 Clients are available at os_alt.
322 - 'admin':
323 An admin user is provisioned.
324 It can be used only once. Multiple entries will be ignored.
325 Clients are available at os_admin.
326 - A list in the format ['any_label', 'role1', ... , 'roleN']:
327 A client with roles <list>[1:] is provisioned.
328 It can be used multiple times, with unique labels.
329 Clients are available at os_roles_<list>[0].
330
331 By default network resources are allocated (in case of dynamic
332 credentials). Tests that do not need network or that require a
333 custom network setup must specify which network resources shall
334 be provisioned using the `set_network_resources()` method (note
335 that it must be invoked before the `setup_credentials` is
336 invoked on super).
337
338 Example::
339
340 class TestWithCredentials(test.BaseTestCase):
341
342 credentials = ['primary', 'admin',
343 ['special', 'special_role1']]
344
345 @classmethod
346 def setup_credentials(cls):
347 # set_network_resources must be called first
348 cls.set_network_resources(network=True)
349 super(TestWithCredentials, cls).setup_credentials()
350
351 @classmethod
352 def setup_clients(cls):
353 cls.servers = cls.os_primary.compute.ServersClient()
354 cls.admin_servers = cls.os_admin.compute.ServersClient()
355 # certain API calls may require a user with a specific
356 # role assigned. In this example `special_role1` is
357 # assigned to the user in `cls.os_roles_special`.
358 cls.special_servers = (
359 cls.os_roles_special.compute.ServersClient())
360
361 def test_special_servers(self):
362 # Do something with servers
363 pass
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000364 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100365 cls.__setup_credentials_called = True
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000366 for credentials_type in cls.credentials:
367 # This may raise an exception in case credentials are not available
368 # In that case we want to let the exception through and the test
369 # fail accordingly
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100370 if isinstance(credentials_type, six.string_types):
371 manager = cls.get_client_manager(
372 credential_type=credentials_type)
373 setattr(cls, 'os_%s' % credentials_type, manager)
Jordan Pittier8160d312017-04-18 11:52:23 +0200374 # NOTE(jordanP): Tempest should use os_primary, os_admin
375 # and os_alt throughout its code base but we keep the aliases
376 # around for a while for Tempest plugins. Aliases should be
377 # removed eventually.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100378 # Setup some common aliases
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100379 if credentials_type == 'primary':
Jordan Pittier8160d312017-04-18 11:52:23 +0200380 cls.os = debtcollector.moves.moved_read_only_property(
381 'os', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200382 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200383 cls.manager =\
384 debtcollector.moves.moved_read_only_property(
385 'manager', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200386 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100387 if credentials_type == 'admin':
Jordan Pittier8160d312017-04-18 11:52:23 +0200388 cls.os_adm = debtcollector.moves.moved_read_only_property(
389 'os_adm', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200390 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200391 cls.admin_manager =\
392 debtcollector.moves.moved_read_only_property(
393 'admin_manager', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200394 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100395 if credentials_type == 'alt':
Jordan Pittier8160d312017-04-18 11:52:23 +0200396 cls.alt_manager =\
397 debtcollector.moves.moved_read_only_property(
398 'alt_manager', 'os_alt', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200399 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100400 elif isinstance(credentials_type, list):
401 manager = cls.get_client_manager(roles=credentials_type[1:],
402 force_new=True)
403 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100404
405 @classmethod
406 def setup_clients(cls):
Andrea Frittoli99583672017-08-24 15:39:20 +0100407 """Create aliases to the clients in the client managers.
408
409 `setup_clients` is invoked after the credential provisioning step.
410 Client manager objects are available to tests already. The purpose
411 of this helper is to setup shortcuts to specific clients that are
412 useful for the tests implemented in the test class.
413
414 Its purpose is mostly for code readability, however it should be used
415 carefully to avoid doing exactly the opposite, i.e. making the code
416 unreadable and hard to debug. If aliases are defined in a super class
417 it won't be obvious what they refer to, so it's good practice to define
418 all aliases used in the class. Aliases are meant to be shortcuts to
419 be used in tests, not shortcuts to avoid helper method attributes.
420 If an helper method starts relying on a client alias and a subclass
421 overrides that alias, it will become rather difficult to understand
422 what the helper method actually does.
423
424 Example::
425
426 class TestDoneItRight(test.BaseTestCase):
427
428 credentials = ['primary', 'alt']
429
430 @classmethod
431 def setup_clients(cls):
432 super(TestDoneItRight, cls).setup_clients()
433 cls.servers = cls.os_primary.ServersClient()
434 cls.servers_alt = cls.os_alt.ServersClient()
435
436 def _a_good_helper(self, clients):
437 # Some complex logic we're going to use many times
438 servers = clients.ServersClient()
439 vm = servers.create_server(...)
440
441 def delete_server():
442 test_utils.call_and_ignore_notfound_exc(
443 servers.delete_server, vm['id'])
444
445 self.addCleanup(self.delete_server)
446 return vm
447
448 def test_with_servers(self):
449 vm = self._a_good_helper(os.primary)
450 vm_alt = self._a_good_helper(os.alt)
451 cls.servers.show_server(vm['id'])
452 cls.servers_alt.show_server(vm_alt['id'])
453 """
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100454 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200455
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000456 @classmethod
457 def resource_setup(cls):
Andrea Frittoli3be57482017-08-25 22:41:26 +0100458 """Class level resource setup for test cases.
459
460 `resource_setup` is invoked once all credentials (and related network
461 resources have been provisioned and after client aliases - if any -
462 have been defined.
463
464 The use case for `resource_setup` is test optimization: provisioning
465 of project-specific "expensive" resources that are not dirtied by tests
466 and can thus safely be re-used by multiple tests.
467
468 System wide resources shared by all tests could instead be provisioned
469 only once, before the test run.
470
471 Resources provisioned here must be cleaned up during
472 `resource_cleanup`. This is best achieved by scheduling a cleanup via
473 `addClassResourceCleanup`.
474
475 Some test resources have an asynchronous delete process. It's best
476 practice for them to schedule a wait for delete via
477 `addClassResourceCleanup` to avoid having resources in process of
478 deletion when we reach the credentials cleanup step.
479
480 Example::
481
482 @classmethod
483 def resource_setup(cls):
484 super(MyTest, cls).resource_setup()
485 servers = cls.os_primary.compute.ServersClient()
486 # Schedule delete and wait so that we can first delete the
487 # two servers and then wait for both to delete
488 # Create server 1
489 cls.shared_server = servers.create_server()
490 # Create server 2. If something goes wrong we schedule cleanup
491 # of server 1 anyways.
492 try:
493 cls.shared_server2 = servers.create_server()
494 # Wait server 2
495 cls.addClassResourceCleanup(
496 waiters.wait_for_server_termination,
497 servers, cls.shared_server2['id'],
498 ignore_error=False)
499 finally:
500 # Wait server 1
501 cls.addClassResourceCleanup(
502 waiters.wait_for_server_termination,
503 servers, cls.shared_server['id'],
504 ignore_error=False)
505 # Delete server 1
506 cls.addClassResourceCleanup(
507 test_utils.call_and_ignore_notfound_exc,
508 servers.delete_server,
509 cls.shared_server['id'])
510 # Delete server 2 (if it was created)
511 if hasattr(cls, 'shared_server2'):
512 cls.addClassResourceCleanup(
513 test_utils.call_and_ignore_notfound_exc,
514 servers.delete_server,
515 cls.shared_server2['id'])
516 """
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100517 pass
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000518
519 @classmethod
520 def resource_cleanup(cls):
521 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000522
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100523 Resource cleanup processes the stack of cleanups produced by
Andrea Frittoli3be57482017-08-25 22:41:26 +0100524 `addClassResourceCleanup` and then cleans up validation resources
525 if any were provisioned.
526
527 All cleanups are processed whatever the outcome. Exceptions are
528 accumulated and re-raised as a `MultipleExceptions` at the end.
529
530 In most cases test cases won't need to override `resource_cleanup`,
531 but if they do they must invoke `resource_cleanup` on super.
532
533 Example::
534
535 class TestWithReallyComplexCleanup(test.BaseTestCase):
536
537 @classmethod
538 def resource_setup(cls):
539 # provision resource A
540 cls.addClassResourceCleanup(delete_resource, A)
541 # provision resource B
542 cls.addClassResourceCleanup(delete_resource, B)
543
544 @classmethod
545 def resource_cleanup(cls):
546 # It's possible to override resource_cleanup but in most
547 # cases it shouldn't be required. Nothing that may fail
548 # should be executed before the call to super since it
549 # might cause resource leak in case of error.
550 super(TestWithReallyComplexCleanup, cls).resource_cleanup()
551 # At this point test credentials are still available but
552 # anything from the cleanup stack has been already deleted.
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000553 """
Andrea Frittoli (andreaf)08e42d42017-09-07 17:09:13 +0100554 cls.__resource_cleanup_called = True
Andrea Frittoli3be57482017-08-25 22:41:26 +0100555 cleanup_errors = []
556 while cls._class_cleanups:
557 try:
558 fn, args, kwargs = cls._class_cleanups.pop()
559 fn(*args, **kwargs)
560 except Exception:
561 cleanup_errors.append(sys.exc_info())
Andrea Frittoli3be57482017-08-25 22:41:26 +0100562 if cleanup_errors:
563 raise testtools.MultipleExceptions(*cleanup_errors)
564
565 @classmethod
566 def addClassResourceCleanup(cls, fn, *arguments, **keywordArguments):
567 """Add a cleanup function to be called during resource_cleanup.
568
569 Functions added with addClassResourceCleanup will be called in reverse
570 order of adding at the beginning of resource_cleanup, before any
571 credential, networking or validation resources cleanup is processed.
572
573 If a function added with addClassResourceCleanup raises an exception,
574 the error will be recorded as a test error, and the next cleanup will
575 then be run.
576
577 Cleanup functions are always called during the test class tearDown
578 fixture, even if an exception occured during setUp or tearDown.
579 """
580 cls._class_cleanups.append((fn, arguments, keywordArguments))
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000581
Attila Fazekasf86fa312013-07-30 19:56:39 +0200582 def setUp(self):
583 super(BaseTestCase, self).setUp()
Andrea Frittoliba712ac2017-09-13 16:54:47 -0600584 if not self.__setupclass_called:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200585 raise RuntimeError("setUpClass does not calls the super's"
586 "setUpClass in the "
587 + self.__class__.__name__)
588 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400589 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
590 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500591 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400592 except ValueError:
593 test_timeout = 0
594 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200595 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400596
597 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
598 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200599 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
600 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400601 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
602 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200603 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
604 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200605 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
606 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200607 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400608 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200609 level=None))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400610
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100611 @property
612 def credentials_provider(self):
613 return self._get_credentials_provider()
614
Jamie Lennox15350172015-08-17 10:54:25 +1000615 @property
616 def identity_utils(self):
617 """A client that abstracts v2 and v3 identity operations.
618
619 This can be used for creating and tearing down projects in tests. It
620 should not be used for testing identity features.
621 """
622 if CONF.identity.auth_version == 'v2':
623 client = self.os_admin.identity_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000624 users_client = self.os_admin.users_client
Daniel Melladob04da902015-11-20 17:43:12 +0100625 project_client = self.os_admin.tenants_client
Daniel Mellado6b16b922015-12-07 12:43:08 +0000626 roles_client = self.os_admin.roles_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000627 domains_client = None
Jamie Lennox15350172015-08-17 10:54:25 +1000628 else:
629 client = self.os_admin.identity_v3_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000630 users_client = self.os_admin.users_v3_client
Arx Cruz24bcb882016-02-10 15:20:16 +0100631 project_client = self.os_admin.projects_client
632 roles_client = self.os_admin.roles_v3_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000633 domains_client = self.os_admin.domains_client
Jamie Lennox15350172015-08-17 10:54:25 +1000634
635 try:
636 domain = client.auth_provider.credentials.project_domain_name
637 except AttributeError:
638 domain = 'Default'
639
Daniel Melladob04da902015-11-20 17:43:12 +0100640 return cred_client.get_creds_client(client, project_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +0000641 users_client,
Daniel Mellado7aea5342016-02-09 09:10:12 +0000642 roles_client,
Daniel Mellado91a26b62016-02-11 11:13:04 +0000643 domains_client,
Daniel Melladob04da902015-11-20 17:43:12 +0100644 project_domain_name=domain)
Jamie Lennox15350172015-08-17 10:54:25 +1000645
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100646 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100647 def get_identity_version(cls):
648 """Returns the identity version used by the test class"""
649 identity_version = getattr(cls, 'identity_version', None)
650 return identity_version or CONF.identity.auth_version
651
652 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100653 def _get_credentials_provider(cls):
654 """Returns a credentials provider
655
656 If no credential provider exists yet creates one.
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100657 It always use the configuration value from identity.auth_version,
658 since we always want to provision accounts with the current version
659 of the identity API.
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100660 """
661 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
662 not cls._creds_provider.name == cls.__name__):
663 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
664 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100665
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700666 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100667 name=cls.__name__, network_resources=cls._network_resources,
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100668 force_tenant_isolation=force_tenant_isolation)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100669 return cls._creds_provider
670
Matthew Treinish3e046852013-07-23 16:00:24 -0400671 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100672 def get_client_manager(cls, credential_type=None, roles=None,
673 force_new=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100674 """Returns an OpenStack client manager
675
676 Returns an OpenStack client manager based on either credential_type
677 or a list of roles. If neither is specified, it defaults to
678 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100679 :param credential_type: string - primary, alt or admin
680 :param roles: list of roles
681
lei zhangdd552b22015-11-25 20:41:48 +0800682 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100683 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700684 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100685 if all([roles, credential_type]):
686 msg = "Cannot get credentials by type and roles at the same time"
687 raise ValueError(msg)
688 if not any([roles, credential_type]):
689 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100690 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100691 if roles:
692 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100693 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100694 skip_msg = (
695 "%s skipped because the configured credential provider"
696 " is not able to provide credentials with the %s role "
697 "assigned." % (cls.__name__, role))
698 raise cls.skipException(skip_msg)
699 params = dict(roles=roles)
700 if force_new is not None:
701 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100702 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000703 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100704 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100705 if hasattr(cred_provider, credentials_method):
706 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100707 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100708 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100709 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100710 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000711 # NOTE(andreaf) Ensure credentials have user and project id fields.
712 # It may not be the case when using pre-provisioned credentials.
713 manager.auth_provider.set_auth()
714 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700715
716 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700717 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000718 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200719 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700720 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700721
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100722 @staticmethod
723 def _validation_resources_params_from_conf():
724 return dict(
725 keypair=(CONF.validation.auth_method.lower() == "keypair"),
726 floating_ip=(CONF.validation.connect_method.lower() == "floating"),
727 security_group=CONF.validation.security_group,
728 security_group_rules=CONF.validation.security_group_rules,
729 use_neutron=CONF.service_available.neutron,
730 ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
731 floating_network_id=CONF.network.public_network_id,
732 floating_network_name=CONF.network.floating_network_name)
733
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700734 @classmethod
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100735 def get_class_validation_resources(cls, os_clients):
736 """Provision validation resources according to configuration
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000737
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100738 This is a wrapper around `create_validation_resources` from
739 `tempest.common.validation_resources` that passes parameters from
740 Tempest configuration. Only one instance of class level
741 validation resources is managed by the helper, so If resources
742 were already provisioned before, existing ones will be returned.
nithya-ganesan222efd72015-01-22 12:20:27 +0000743
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100744 Resources are returned as a dictionary. They are also scheduled for
745 automatic cleanup during class teardown using
746 `addClassResourcesCleanup`.
747
748 If `CONF.validation.run_validation` is False no resource will be
749 provisioned at all.
750
751 @param os_clients: Clients to be used to provision the resources.
nithya-ganesan222efd72015-01-22 12:20:27 +0000752 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400753 if not CONF.validation.run_validation:
754 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100755
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100756 if os_clients in cls._validation_resources:
757 return cls._validation_resources[os_clients]
Jordan Pittier79cd1822016-12-08 17:20:35 +0100758
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100759 if (CONF.validation.ip_version_for_ssh not in (4, 6) and
760 CONF.service_available.neutron):
761 msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
762 raise lib_exc.InvalidConfiguration(
763 msg % CONF.validation.ip_version_for_ssh)
Jordan Pittier79cd1822016-12-08 17:20:35 +0100764
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100765 resources = vr.create_validation_resources(
766 os_clients,
767 **cls._validation_resources_params_from_conf())
Jordan Pittier79cd1822016-12-08 17:20:35 +0100768
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100769 cls.addClassResourceCleanup(
770 vr.clear_validation_resources, os_clients,
771 use_neutron=CONF.service_available.neutron,
772 **resources)
773 cls._validation_resources[os_clients] = resources
774 return resources
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500775
Andrea Frittoli9f416dd2017-08-10 15:38:00 +0100776 def get_test_validation_resources(self, os_clients):
777 """Returns a dict of validation resources according to configuration
778
779 Initialise a validation resources fixture based on configuration.
780 Start the fixture and returns the validation resources.
781
782 If `CONF.validation.run_validation` is False no resource will be
783 provisioned at all.
784
785 @param os_clients: Clients to be used to provision the resources.
786 """
787
788 params = {}
789 # Test will try to use the fixture, so for this to be useful
790 # we must return a fixture. If validation is disabled though
791 # we don't need to provision anything, which is the default
792 # behavior for the fixture.
793 if CONF.validation.run_validation:
794 params = self._validation_resources_params_from_conf()
795
796 validation = self.useFixture(
797 vr.ValidationResourcesFixture(os_clients, **params))
798 return validation.resources
nithya-ganesan222efd72015-01-22 12:20:27 +0000799
800 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000801 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500802 dhcp=False):
803 """Specify which network resources should be created
804
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100805 The dynamic credentials provider by default provisions network
806 resources for each user/project that is provisioned. This behavior
807 can be altered using this method, which allows tests to define which
808 specific network resources to be provisioned - none if no parameter
809 is specified.
810
Andrea Frittolia6c885a2017-08-23 19:37:50 +0100811 This method is designed so that only the network resources set on the
812 leaf class are honoured.
813
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100814 Credentials are provisioned as part of the class setup fixture,
815 during the `setup_credentials` step. For this to be effective this
816 helper must be invoked before super's `setup_credentials` is executed.
817
Matthew Treinish9f756a02014-01-15 10:26:07 -0500818 @param network
819 @param router
820 @param subnet
821 @param dhcp
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100822
823 Example::
824
825 @classmethod
826 def setup_credentials(cls):
827 # Do not setup network resources for this test
828 cls.set_network_resources()
829 super(MyTest, cls).setup_credentials()
Matthew Treinish9f756a02014-01-15 10:26:07 -0500830 """
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100831 # If this is invoked after the credentials are setup, it won't take
832 # any effect. To avoid this situation, fail the test in case this was
833 # invoked too late in the test lifecycle.
834 if cls.__setup_credentials_called:
835 raise RuntimeError(
836 "set_network_resources invoked after setup_credentials on the "
837 "super class has been already invoked. For "
838 "set_network_resources to have effect please invoke it before "
839 "the call to super().setup_credentials")
840
841 # Network resources should be set only once from callers
Salvatore Orlando5a337242014-01-15 22:49:22 +0000842 # in order to ensure that even if it's called multiple times in
843 # a chain of overloaded methods, the attribute is set only
Andrea Frittolibcbf1af12017-08-14 11:53:35 +0100844 # in the leaf class.
845 if not cls._network_resources:
846 cls._network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000847 'network': network,
848 'router': router,
849 'subnet': subnet,
850 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500851
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530852 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000853 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530854 """Get the network to be used in testing
855
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000856 :param credentials_type: The type of credentials for which to get the
857 tenant network
858
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530859 :return: network dict including 'id' and 'name'
860 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000861 # Get a manager for the given credentials_type, but at least
862 # always fall back on getting the manager for primary credentials
863 if isinstance(credentials_type, six.string_types):
864 manager = cls.get_client_manager(credential_type=credentials_type)
865 elif isinstance(credentials_type, list):
866 manager = cls.get_client_manager(roles=credentials_type[1:])
867 else:
868 manager = cls.get_client_manager()
869
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700870 # Make sure cred_provider exists and get a network client
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000871 networks_client = manager.compute_networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100872 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100873 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800874 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100875 # for their servers, so using an admin network client to validate
876 # the network name
877 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100878 credentials.is_admin_available(
879 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100880 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100881 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400882 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900883 return fixed_network.get_tenant_network(
884 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530885
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100886 def assertEmpty(self, items, msg=None):
887 """Asserts whether a sequence or collection is empty
Mark Maglana5885eb32014-02-28 10:57:34 -0800888
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100889 :param items: sequence or collection to be tested
890 :param msg: message to be passed to the AssertionError
891 :raises AssertionError: when items is not empty
892 """
zhufl92ade4b2017-03-03 15:20:10 +0800893 if msg is None:
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100894 msg = "sequence or collection is not empty: %s" % items
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900895 self.assertFalse(items, msg)
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100896
897 def assertNotEmpty(self, items, msg=None):
898 """Asserts whether a sequence or collection is not empty
899
900 :param items: sequence or collection to be tested
901 :param msg: message to be passed to the AssertionError
902 :raises AssertionError: when items is empty
903 """
904 if msg is None:
905 msg = "sequence or collection is empty."
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900906 self.assertTrue(items, msg)