blob: f07c071d4f91c555a02ba647f3d5cdad7f75d369 [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
Masayuki Igawa80c1b9f2013-10-07 17:19:11 +090017import functools
Ian Wienand98c35f32013-07-23 20:34:23 +100018import os
Attila Fazekas53943322014-02-10 16:07:34 +010019import sys
Jay Pipes051075a2012-04-28 17:39:37 -040020
Jordan Pittier35a63752016-08-30 13:09:12 +020021import debtcollector.moves
Matthew Treinish78561ad2013-07-26 11:41:56 -040022import fixtures
Doug Hellmann583ce2c2015-03-11 14:55:46 +000023from oslo_log import log as logging
Chris Hoge296558c2015-02-19 00:29:49 -060024import six
ivan-zhu1feeb382013-01-24 10:14:39 +080025import testtools
Jay Pipes051075a2012-04-28 17:39:37 -040026
Matthew Treinish3e046852013-07-23 16:00:24 -040027from tempest import clients
Andrea Frittoli (andreaf)290b3e12015-10-08 10:25:02 +010028from tempest.common import credentials_factory as credentials
Rohan Kanade9ce97df2013-12-10 18:59:35 +053029from tempest.common import fixed_network
nithya-ganesan222efd72015-01-22 12:20:27 +000030import tempest.common.validation_resources as vresources
Attila Fazekasdc216422013-01-29 15:12:14 +010031from tempest import config
Matthew Treinish3787e4c2016-10-07 21:25:33 -040032from tempest.lib.common import cred_client
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 Pittierc5665a62017-04-12 16:42:53 +020047related_bug = debtcollector.moves.moved_function(
48 decorators.related_bug, 'related_bug', __name__,
49 version='Pike', removal_version='?')
50
51
Jordan Pittier3b46d272017-04-12 16:17:28 +020052attr = debtcollector.moves.moved_function(
53 decorators.attr, 'attr', __name__,
54 version='Pike', removal_version='?')
Chris Yeoh55530bb2013-02-08 16:04:27 +103055
56
Andrea Frittoli07acf262017-04-09 19:36:37 +020057class InvalidServiceTag(lib_exc.TempestException):
58 message = "Invalid service tag"
59
60
Matthew Treinish3d8c7322014-08-03 23:53:28 -040061def get_service_list():
Matthew Treinish8afbffd2014-01-21 23:56:13 +000062 service_list = {
63 'compute': CONF.service_available.nova,
64 'image': CONF.service_available.glance,
65 'volume': CONF.service_available.cinder,
Matthew Treinish8afbffd2014-01-21 23:56:13 +000066 'network': True,
67 'identity': True,
68 'object_storage': CONF.service_available.swift,
Matthew Treinish8afbffd2014-01-21 23:56:13 +000069 }
Matthew Treinish3d8c7322014-08-03 23:53:28 -040070 return service_list
Matthew Treinish16c43792013-09-09 19:55:23 +000071
Matthew Treinish3d8c7322014-08-03 23:53:28 -040072
Yaroslav Lobankovda999f72015-06-30 20:32:55 +030073def services(*args):
Matthew Treinish3d8c7322014-08-03 23:53:28 -040074 """A decorator used to set an attr for each service used in a test case
75
76 This decorator applies a testtools attr for each service that gets
77 exercised by a test case.
78 """
Matthew Treinish16c43792013-09-09 19:55:23 +000079 def decorator(f):
Andrea Frittoli6f053072017-04-09 19:22:47 +020080 known_services = get_service_list()
81
Matthew Treinish16c43792013-09-09 19:55:23 +000082 for service in args:
Andrea Frittoli6f053072017-04-09 19:22:47 +020083 if service not in known_services:
Andrea Frittoli07acf262017-04-09 19:36:37 +020084 raise InvalidServiceTag('%s is not a valid service' % service)
Jordan Pittier3b46d272017-04-12 16:17:28 +020085 decorators.attr(type=list(args))(f)
Matthew Treinish8afbffd2014-01-21 23:56:13 +000086
87 @functools.wraps(f)
88 def wrapper(self, *func_args, **func_kwargs):
Matthew Treinish3d8c7322014-08-03 23:53:28 -040089 service_list = get_service_list()
90
Matthew Treinish8afbffd2014-01-21 23:56:13 +000091 for service in args:
92 if not service_list[service]:
93 msg = 'Skipped because the %s service is not available' % (
94 service)
95 raise testtools.TestCase.skipException(msg)
96 return f(self, *func_args, **func_kwargs)
97 return wrapper
Matthew Treinish16c43792013-09-09 19:55:23 +000098 return decorator
99
100
Yaroslav Lobankovda999f72015-06-30 20:32:55 +0300101def requires_ext(**kwargs):
Matthew Treinishe3d26142013-11-26 19:14:58 +0000102 """A decorator to skip tests if an extension is not enabled
103
104 @param extension
105 @param service
106 """
107 def decorator(func):
108 @functools.wraps(func)
109 def wrapper(*func_args, **func_kwargs):
110 if not is_extension_enabled(kwargs['extension'],
111 kwargs['service']):
112 msg = "Skipped because %s extension: %s is not enabled" % (
113 kwargs['service'], kwargs['extension'])
114 raise testtools.TestCase.skipException(msg)
115 return func(*func_args, **func_kwargs)
116 return wrapper
117 return decorator
118
119
120def is_extension_enabled(extension_name, service):
121 """A function that will check the list of enabled extensions from config
122
123 """
Matthew Treinishe3d26142013-11-26 19:14:58 +0000124 config_dict = {
Matthew Treinishbc0e03e2014-01-30 16:51:06 +0000125 'compute': CONF.compute_feature_enabled.api_extensions,
Matthew Treinishbc0e03e2014-01-30 16:51:06 +0000126 'volume': CONF.volume_feature_enabled.api_extensions,
127 'network': CONF.network_feature_enabled.api_extensions,
128 'object': CONF.object_storage_feature_enabled.discoverable_apis,
Jane Zadorozhna121576d2015-06-23 12:57:13 +0300129 'identity': CONF.identity_feature_enabled.api_extensions
Matthew Treinishe3d26142013-11-26 19:14:58 +0000130 }
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900131 if not config_dict[service]:
Simeon Monov5d7effe2014-07-16 07:32:38 +0300132 return False
Matthew Treinishe3d26142013-11-26 19:14:58 +0000133 if config_dict[service][0] == 'all':
134 return True
135 if extension_name in config_dict[service]:
136 return True
137 return False
138
Ian Wienand98c35f32013-07-23 20:34:23 +1000139
Yair Fried95914122016-03-03 09:14:40 +0200140def is_scheduler_filter_enabled(filter_name):
ghanshyam5817e142016-12-01 11:38:46 +0900141 """Check the list of enabled compute scheduler filters from config.
142
143 This function checks whether the given compute scheduler filter is
144 available and configured in the config file. If the
145 scheduler_available_filters option is set to 'all' (Default value. which
146 means default filters are configured in nova) in tempest.conf then, this
147 function returns True with assumption that requested filter 'filter_name'
148 is one of available filter in nova ("nova.scheduler.filters.all_filters").
149 """
Yair Friedca5cfb52016-01-04 15:41:55 +0200150
151 filters = CONF.compute_feature_enabled.scheduler_available_filters
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900152 if not filters:
Yair Friedca5cfb52016-01-04 15:41:55 +0200153 return False
154 if 'all' in filters:
155 return True
156 if filter_name in filters:
157 return True
158 return False
159
160
Attila Fazekasf86fa312013-07-30 19:56:39 +0200161at_exit_set = set()
162
163
164def validate_tearDownClass():
165 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -0400166 LOG.error(
167 "tearDownClass does not call the super's "
168 "tearDownClass in these classes: \n"
169 + str(at_exit_set))
170
Attila Fazekasf86fa312013-07-30 19:56:39 +0200171
172atexit.register(validate_tearDownClass)
173
Attila Fazekas53943322014-02-10 16:07:34 +0100174
Matthew Treinish2474f412014-11-17 18:11:56 -0500175class BaseTestCase(testtools.testcase.WithAttributes,
176 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100177 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000178
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100179 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
180 by subclasses (enforced via hacking rule T105).
181
182 Set-up is split in a series of steps (setup stages), which can be
183 overwritten by test classes. Set-up stages are:
184 - skip_checks
185 - setup_credentials
186 - setup_clients
187 - resource_setup
188
189 Tear-down is also split in a series of steps (teardown stages), which are
190 stacked for execution only if the corresponding setup stage had been
191 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700192 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100193 - resource_cleanup
194 """
Attila Fazekasc43fec82013-04-09 23:17:52 +0200195
Attila Fazekasf86fa312013-07-30 19:56:39 +0200196 setUpClassCalled = False
197
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000198 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100199 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
200 # a list of roles - the first element of the list being a label, and the
201 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000202 credentials = []
nithya-ganesan222efd72015-01-22 12:20:27 +0000203 # Resources required to validate a server using ssh
204 validation_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500205 network_resources = {}
206
Sean Dague2ef32ac2014-06-09 11:32:23 -0400207 # NOTE(sdague): log_format is defined inline here instead of using the oslo
208 # default because going through the config path recouples config to the
209 # stress tests too early, and depending on testr order will fail unit tests
210 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
211 '[%(name)s] %(message)s')
212
Ryota MIBU60687e52015-12-09 18:37:39 +0900213 # Client manager class to use in this test case.
214 client_manager = clients.Manager
215
Sean Dague02620fd2016-03-02 15:52:51 -0500216 # A way to adjust slow test classes
217 TIMEOUT_SCALING_FACTOR = 1
218
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200219 @classmethod
220 def setUpClass(cls):
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100221 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200222 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
223 super(BaseTestCase, cls).setUpClass()
Attila Fazekasf86fa312013-07-30 19:56:39 +0200224 cls.setUpClassCalled = True
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100225 # Stack of (name, callable) to be invoked in reverse order at teardown
226 cls.teardowns = []
227 # All the configuration checks that may generate a skip
228 cls.skip_checks()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100229 try:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100230 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700231 cls.teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100232 cls.setup_credentials()
233 # Shortcuts to clients
234 cls.setup_clients()
235 # Additional class-wide test resources
236 cls.teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100237 cls.resource_setup()
238 except Exception:
239 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100240 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
241 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100242 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100243 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400244 six.reraise(etype, value, trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100245 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100246 del trace # to avoid circular refs
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200247
Attila Fazekasf86fa312013-07-30 19:56:39 +0200248 @classmethod
249 def tearDownClass(cls):
Attila Fazekas5d275302013-08-29 12:35:12 +0200250 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100251 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200252 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
253 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100254 # Save any existing exception, we always want to re-raise the original
255 # exception only
256 etype, value, trace = sys.exc_info()
257 # If there was no exception during setup we shall re-raise the first
258 # exception in teardown
259 re_raise = (etype is None)
260 while cls.teardowns:
261 name, teardown = cls.teardowns.pop()
262 # Catch any exception in tearDown so we can re-raise the original
263 # exception at the end
264 try:
265 teardown()
266 except Exception as te:
267 sys_exec_info = sys.exc_info()
268 tetype = sys_exec_info[0]
269 # TODO(andreaf): Till we have the ability to cleanup only
270 # resources that were successfully setup in resource_cleanup,
271 # log AttributeError as info instead of exception.
272 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100273 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100274 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100275 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100276 if not etype:
277 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800278 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100279 # the first one
280 if re_raise and etype is not None:
281 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400282 six.reraise(etype, value, trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100283 finally:
284 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100285
286 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100287 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000288 """Class level skip checks.
289
290 Subclasses verify in here all conditions that might prevent the
291 execution of the entire test class.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100292 Checks implemented here may not make use API calls, and should rely on
293 configuration alone.
294 In general skip checks that require an API call are discouraged.
295 If one is really needed it may be implemented either in the
296 resource_setup or at test level.
297 """
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100298 identity_version = cls.get_identity_version()
299 if 'admin' in cls.credentials and not credentials.is_admin_available(
300 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000301 msg = "Missing Identity Admin API credentials in configuration."
302 raise cls.skipException(msg)
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100303 if 'alt' in cls.credentials and not credentials.is_alt_available(
304 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000305 msg = "Missing a 2nd set of API credentials in configuration."
306 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100307 if hasattr(cls, 'identity_version'):
308 if cls.identity_version == 'v2':
309 if not CONF.identity_feature_enabled.api_v2:
310 raise cls.skipException("Identity api v2 is not enabled")
311 elif cls.identity_version == 'v3':
312 if not CONF.identity_feature_enabled.api_v3:
313 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100314
315 @classmethod
316 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300317 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000318
edannon6cc6fbc2016-05-03 11:56:12 +0300319 For every element of credentials param function creates tenant/user,
320 Then it creates client manager for that credential.
321
322 Network related tests must override this function with
323 set_network_resources() method, otherwise it will create
324 network resources(network resources are created in a later step).
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000325 """
326 for credentials_type in cls.credentials:
327 # This may raise an exception in case credentials are not available
328 # In that case we want to let the exception through and the test
329 # fail accordingly
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100330 if isinstance(credentials_type, six.string_types):
331 manager = cls.get_client_manager(
332 credential_type=credentials_type)
333 setattr(cls, 'os_%s' % credentials_type, manager)
Jordan Pittier8160d312017-04-18 11:52:23 +0200334 # NOTE(jordanP): Tempest should use os_primary, os_admin
335 # and os_alt throughout its code base but we keep the aliases
336 # around for a while for Tempest plugins. Aliases should be
337 # removed eventually.
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100338 # Setup some common aliases
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100339 if credentials_type == 'primary':
Jordan Pittier8160d312017-04-18 11:52:23 +0200340 cls.os = debtcollector.moves.moved_read_only_property(
341 'os', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200342 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200343 cls.manager =\
344 debtcollector.moves.moved_read_only_property(
345 'manager', 'os_primary', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200346 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100347 if credentials_type == 'admin':
Jordan Pittier8160d312017-04-18 11:52:23 +0200348 cls.os_adm = debtcollector.moves.moved_read_only_property(
349 'os_adm', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200350 removal_version='Queens')
Jordan Pittier8160d312017-04-18 11:52:23 +0200351 cls.admin_manager =\
352 debtcollector.moves.moved_read_only_property(
353 'admin_manager', 'os_admin', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200354 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100355 if credentials_type == 'alt':
Jordan Pittier8160d312017-04-18 11:52:23 +0200356 cls.alt_manager =\
357 debtcollector.moves.moved_read_only_property(
358 'alt_manager', 'os_alt', version='Pike',
Jakub Libosvar7835ca12017-05-04 16:44:23 +0200359 removal_version='Queens')
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100360 elif isinstance(credentials_type, list):
361 manager = cls.get_client_manager(roles=credentials_type[1:],
362 force_new=True)
363 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100364
365 @classmethod
366 def setup_clients(cls):
367 """Create links to the clients into the test object."""
368 # TODO(andreaf) There is a fair amount of code that could me moved from
369 # base / test classes in here. Ideally tests should be able to only
370 # specify which client is `client` and nothing else.
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100371 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200372
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000373 @classmethod
374 def resource_setup(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000375 """Class level resource setup for test cases."""
Andrea Frittolicf999a82017-05-24 10:44:46 +0100376 if hasattr(cls, "os_primary"):
nithya-ganesan222efd72015-01-22 12:20:27 +0000377 cls.validation_resources = vresources.create_validation_resources(
Andrea Frittolicf999a82017-05-24 10:44:46 +0100378 cls.os_primary, cls.validation_resources)
nithya-ganesan222efd72015-01-22 12:20:27 +0000379 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000380 LOG.warning("Client manager not found, validation resources not"
381 " created")
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000382
383 @classmethod
384 def resource_cleanup(cls):
385 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000386
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000387 Resource cleanup must be able to handle the case of partially setup
388 resources, in case a failure during `resource_setup` should happen.
389 """
nithya-ganesan222efd72015-01-22 12:20:27 +0000390 if cls.validation_resources:
Andrea Frittolicf999a82017-05-24 10:44:46 +0100391 if hasattr(cls, "os_primary"):
392 vresources.clear_validation_resources(cls.os_primary,
nithya-ganesan222efd72015-01-22 12:20:27 +0000393 cls.validation_resources)
394 cls.validation_resources = {}
395 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000396 LOG.warning("Client manager not found, validation resources "
397 "not deleted")
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000398
Attila Fazekasf86fa312013-07-30 19:56:39 +0200399 def setUp(self):
400 super(BaseTestCase, self).setUp()
401 if not self.setUpClassCalled:
402 raise RuntimeError("setUpClass does not calls the super's"
403 "setUpClass in the "
404 + self.__class__.__name__)
405 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400406 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
407 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500408 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400409 except ValueError:
410 test_timeout = 0
411 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200412 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400413
414 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
415 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200416 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
417 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400418 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
419 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200420 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
421 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200422 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
423 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200424 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400425 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200426 level=None))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400427
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100428 @property
429 def credentials_provider(self):
430 return self._get_credentials_provider()
431
Jamie Lennox15350172015-08-17 10:54:25 +1000432 @property
433 def identity_utils(self):
434 """A client that abstracts v2 and v3 identity operations.
435
436 This can be used for creating and tearing down projects in tests. It
437 should not be used for testing identity features.
438 """
439 if CONF.identity.auth_version == 'v2':
440 client = self.os_admin.identity_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000441 users_client = self.os_admin.users_client
Daniel Melladob04da902015-11-20 17:43:12 +0100442 project_client = self.os_admin.tenants_client
Daniel Mellado6b16b922015-12-07 12:43:08 +0000443 roles_client = self.os_admin.roles_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000444 domains_client = None
Jamie Lennox15350172015-08-17 10:54:25 +1000445 else:
446 client = self.os_admin.identity_v3_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000447 users_client = self.os_admin.users_v3_client
Arx Cruz24bcb882016-02-10 15:20:16 +0100448 project_client = self.os_admin.projects_client
449 roles_client = self.os_admin.roles_v3_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000450 domains_client = self.os_admin.domains_client
Jamie Lennox15350172015-08-17 10:54:25 +1000451
452 try:
453 domain = client.auth_provider.credentials.project_domain_name
454 except AttributeError:
455 domain = 'Default'
456
Daniel Melladob04da902015-11-20 17:43:12 +0100457 return cred_client.get_creds_client(client, project_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +0000458 users_client,
Daniel Mellado7aea5342016-02-09 09:10:12 +0000459 roles_client,
Daniel Mellado91a26b62016-02-11 11:13:04 +0000460 domains_client,
Daniel Melladob04da902015-11-20 17:43:12 +0100461 project_domain_name=domain)
Jamie Lennox15350172015-08-17 10:54:25 +1000462
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100463 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100464 def get_identity_version(cls):
465 """Returns the identity version used by the test class"""
466 identity_version = getattr(cls, 'identity_version', None)
467 return identity_version or CONF.identity.auth_version
468
469 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100470 def _get_credentials_provider(cls):
471 """Returns a credentials provider
472
473 If no credential provider exists yet creates one.
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100474 It always use the configuration value from identity.auth_version,
475 since we always want to provision accounts with the current version
476 of the identity API.
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100477 """
478 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
479 not cls._creds_provider.name == cls.__name__):
480 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
481 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100482
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700483 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100484 name=cls.__name__, network_resources=cls.network_resources,
Andrea Frittoli9e01dbb2017-04-20 15:28:30 +0100485 force_tenant_isolation=force_tenant_isolation)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100486 return cls._creds_provider
487
Matthew Treinish3e046852013-07-23 16:00:24 -0400488 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100489 def get_client_manager(cls, credential_type=None, roles=None,
490 force_new=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100491 """Returns an OpenStack client manager
492
493 Returns an OpenStack client manager based on either credential_type
494 or a list of roles. If neither is specified, it defaults to
495 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100496 :param credential_type: string - primary, alt or admin
497 :param roles: list of roles
498
lei zhangdd552b22015-11-25 20:41:48 +0800499 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100500 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700501 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100502 if all([roles, credential_type]):
503 msg = "Cannot get credentials by type and roles at the same time"
504 raise ValueError(msg)
505 if not any([roles, credential_type]):
506 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100507 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100508 if roles:
509 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100510 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100511 skip_msg = (
512 "%s skipped because the configured credential provider"
513 " is not able to provide credentials with the %s role "
514 "assigned." % (cls.__name__, role))
515 raise cls.skipException(skip_msg)
516 params = dict(roles=roles)
517 if force_new is not None:
518 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100519 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000520 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100521 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100522 if hasattr(cred_provider, credentials_method):
523 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100524 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100525 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100526 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100527 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000528 # NOTE(andreaf) Ensure credentials have user and project id fields.
529 # It may not be the case when using pre-provisioned credentials.
530 manager.auth_provider.set_auth()
531 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700532
533 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700534 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000535 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200536 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700537 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700538
539 @classmethod
nithya-ganesan222efd72015-01-22 12:20:27 +0000540 def set_validation_resources(cls, keypair=None, floating_ip=None,
541 security_group=None,
542 security_group_rules=None):
543 """Specify which ssh server validation resources should be created.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000544
nithya-ganesan222efd72015-01-22 12:20:27 +0000545 Each of the argument must be set to either None, True or False, with
546 None - use default from config (security groups and security group
547 rules get created when set to None)
548 False - Do not create the validation resource
549 True - create the validation resource
550
551 @param keypair
552 @param security_group
553 @param security_group_rules
554 @param floating_ip
555 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400556 if not CONF.validation.run_validation:
557 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100558
nithya-ganesan222efd72015-01-22 12:20:27 +0000559 if keypair is None:
Jordan Pittier79cd1822016-12-08 17:20:35 +0100560 keypair = (CONF.validation.auth_method.lower() == "keypair")
561
nithya-ganesan222efd72015-01-22 12:20:27 +0000562 if floating_ip is None:
Jordan Pittier79cd1822016-12-08 17:20:35 +0100563 floating_ip = (CONF.validation.connect_method.lower() ==
564 "floating")
565
nithya-ganesan222efd72015-01-22 12:20:27 +0000566 if security_group is None:
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500567 security_group = CONF.validation.security_group
Jordan Pittier79cd1822016-12-08 17:20:35 +0100568
nithya-ganesan222efd72015-01-22 12:20:27 +0000569 if security_group_rules is None:
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500570 security_group_rules = CONF.validation.security_group_rules
571
nithya-ganesan222efd72015-01-22 12:20:27 +0000572 if not cls.validation_resources:
573 cls.validation_resources = {
574 'keypair': keypair,
575 'security_group': security_group,
576 'security_group_rules': security_group_rules,
577 'floating_ip': floating_ip}
578
579 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000580 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500581 dhcp=False):
582 """Specify which network resources should be created
583
584 @param network
585 @param router
586 @param subnet
587 @param dhcp
588 """
Salvatore Orlando5a337242014-01-15 22:49:22 +0000589 # network resources should be set only once from callers
590 # in order to ensure that even if it's called multiple times in
591 # a chain of overloaded methods, the attribute is set only
592 # in the leaf class
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000593 if not cls.network_resources:
594 cls.network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000595 'network': network,
596 'router': router,
597 'subnet': subnet,
598 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500599
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530600 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000601 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530602 """Get the network to be used in testing
603
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000604 :param credentials_type: The type of credentials for which to get the
605 tenant network
606
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530607 :return: network dict including 'id' and 'name'
608 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000609 # Get a manager for the given credentials_type, but at least
610 # always fall back on getting the manager for primary credentials
611 if isinstance(credentials_type, six.string_types):
612 manager = cls.get_client_manager(credential_type=credentials_type)
613 elif isinstance(credentials_type, list):
614 manager = cls.get_client_manager(roles=credentials_type[1:])
615 else:
616 manager = cls.get_client_manager()
617
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700618 # Make sure cred_provider exists and get a network client
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000619 networks_client = manager.compute_networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100620 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100621 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800622 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100623 # for their servers, so using an admin network client to validate
624 # the network name
625 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100626 credentials.is_admin_available(
627 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100628 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100629 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400630 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900631 return fixed_network.get_tenant_network(
632 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530633
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100634 def assertEmpty(self, items, msg=None):
635 """Asserts whether a sequence or collection is empty
Mark Maglana5885eb32014-02-28 10:57:34 -0800636
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100637 :param items: sequence or collection to be tested
638 :param msg: message to be passed to the AssertionError
639 :raises AssertionError: when items is not empty
640 """
zhufl92ade4b2017-03-03 15:20:10 +0800641 if msg is None:
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100642 msg = "sequence or collection is not empty: %s" % items
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900643 self.assertFalse(items, msg)
Andrea Frittoli71c71e92017-04-07 17:45:21 +0100644
645 def assertNotEmpty(self, items, msg=None):
646 """Asserts whether a sequence or collection is not empty
647
648 :param items: sequence or collection to be tested
649 :param msg: message to be passed to the AssertionError
650 :raises AssertionError: when items is empty
651 """
652 if msg is None:
653 msg = "sequence or collection is empty."
Masayuki Igawa0c0f0142017-04-10 17:22:02 +0900654 self.assertTrue(items, msg)