blob: 52994ac77a03bba914fb448e7134f06ca36dcc26 [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 Treinish16c43792013-09-09 19:55:23 +000032from tempest import exceptions
Matthew Treinish3787e4c2016-10-07 21:25:33 -040033from tempest.lib.common import cred_client
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050034from tempest.lib import decorators
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +010035from tempest.lib import exceptions as lib_exc
Jay Pipes051075a2012-04-28 17:39:37 -040036
37LOG = logging.getLogger(__name__)
38
Sean Dague86bd8422013-12-20 09:56:44 -050039CONF = config.CONF
40
Ken'ichi Ohmichi44f01272017-01-27 18:44:14 -080041# TODO(oomichi): This test.idempotent_id should be removed after all projects
42# switch to use decorators.idempotent_id.
43idempotent_id = debtcollector.moves.moved_function(
44 decorators.idempotent_id, 'idempotent_id', __name__,
45 version='Mitaka', removal_version='?')
Matthew Treinishc1802bc2015-12-03 18:48:11 -050046
Jay Pipes051075a2012-04-28 17:39:37 -040047
Yaroslav Lobankovda999f72015-06-30 20:32:55 +030048def attr(**kwargs):
liuchenhong00caec52015-07-19 22:40:28 +080049 """A decorator which applies the testtools attr decorator
Chris Yeoh55530bb2013-02-08 16:04:27 +103050
Matthew Treinisha74f5d42014-02-07 20:25:44 -050051 This decorator applies the testtools.testcase.attr if it is in the list of
52 attributes to testtools we want to apply.
Attila Fazekasb2902af2013-02-16 16:22:44 +010053 """
Chris Yeoh55530bb2013-02-08 16:04:27 +103054
55 def decorator(f):
Giulio Fidente4946a052013-05-14 12:23:51 +020056 if 'type' in kwargs and isinstance(kwargs['type'], str):
57 f = testtools.testcase.attr(kwargs['type'])(f)
58 elif 'type' in kwargs and isinstance(kwargs['type'], list):
59 for attr in kwargs['type']:
60 f = testtools.testcase.attr(attr)(f)
Matthew Treinisha74f5d42014-02-07 20:25:44 -050061 return f
Chris Yeoh55530bb2013-02-08 16:04:27 +103062
63 return decorator
64
65
Matthew Treinish3d8c7322014-08-03 23:53:28 -040066def get_service_list():
Matthew Treinish8afbffd2014-01-21 23:56:13 +000067 service_list = {
68 'compute': CONF.service_available.nova,
69 'image': CONF.service_available.glance,
70 'volume': CONF.service_available.cinder,
Matthew Treinish8afbffd2014-01-21 23:56:13 +000071 'network': True,
72 'identity': True,
73 'object_storage': CONF.service_available.swift,
Matthew Treinish8afbffd2014-01-21 23:56:13 +000074 }
Matthew Treinish3d8c7322014-08-03 23:53:28 -040075 return service_list
Matthew Treinish16c43792013-09-09 19:55:23 +000076
Matthew Treinish3d8c7322014-08-03 23:53:28 -040077
Yaroslav Lobankovda999f72015-06-30 20:32:55 +030078def services(*args):
Matthew Treinish3d8c7322014-08-03 23:53:28 -040079 """A decorator used to set an attr for each service used in a test case
80
81 This decorator applies a testtools attr for each service that gets
82 exercised by a test case.
83 """
Matthew Treinish16c43792013-09-09 19:55:23 +000084 def decorator(f):
Masayuki Igawa22b30082016-06-27 16:18:59 +090085 services = ['compute', 'image', 'baremetal', 'volume',
86 'network', 'identity', 'object_storage']
Matthew Treinish16c43792013-09-09 19:55:23 +000087 for service in args:
Matthew Treinish3d8c7322014-08-03 23:53:28 -040088 if service not in services:
89 raise exceptions.InvalidServiceTag('%s is not a valid '
90 'service' % service)
Matthew Treinish16c43792013-09-09 19:55:23 +000091 attr(type=list(args))(f)
Matthew Treinish8afbffd2014-01-21 23:56:13 +000092
93 @functools.wraps(f)
94 def wrapper(self, *func_args, **func_kwargs):
Matthew Treinish3d8c7322014-08-03 23:53:28 -040095 service_list = get_service_list()
96
Matthew Treinish8afbffd2014-01-21 23:56:13 +000097 for service in args:
98 if not service_list[service]:
99 msg = 'Skipped because the %s service is not available' % (
100 service)
101 raise testtools.TestCase.skipException(msg)
102 return f(self, *func_args, **func_kwargs)
103 return wrapper
Matthew Treinish16c43792013-09-09 19:55:23 +0000104 return decorator
105
106
Yaroslav Lobankovda999f72015-06-30 20:32:55 +0300107def requires_ext(**kwargs):
Matthew Treinishe3d26142013-11-26 19:14:58 +0000108 """A decorator to skip tests if an extension is not enabled
109
110 @param extension
111 @param service
112 """
113 def decorator(func):
114 @functools.wraps(func)
115 def wrapper(*func_args, **func_kwargs):
116 if not is_extension_enabled(kwargs['extension'],
117 kwargs['service']):
118 msg = "Skipped because %s extension: %s is not enabled" % (
119 kwargs['service'], kwargs['extension'])
120 raise testtools.TestCase.skipException(msg)
121 return func(*func_args, **func_kwargs)
122 return wrapper
123 return decorator
124
125
126def is_extension_enabled(extension_name, service):
127 """A function that will check the list of enabled extensions from config
128
129 """
Matthew Treinishe3d26142013-11-26 19:14:58 +0000130 config_dict = {
Matthew Treinishbc0e03e2014-01-30 16:51:06 +0000131 'compute': CONF.compute_feature_enabled.api_extensions,
Matthew Treinishbc0e03e2014-01-30 16:51:06 +0000132 'volume': CONF.volume_feature_enabled.api_extensions,
133 'network': CONF.network_feature_enabled.api_extensions,
134 'object': CONF.object_storage_feature_enabled.discoverable_apis,
Jane Zadorozhna121576d2015-06-23 12:57:13 +0300135 'identity': CONF.identity_feature_enabled.api_extensions
Matthew Treinishe3d26142013-11-26 19:14:58 +0000136 }
Simeon Monov5d7effe2014-07-16 07:32:38 +0300137 if len(config_dict[service]) == 0:
138 return False
Matthew Treinishe3d26142013-11-26 19:14:58 +0000139 if config_dict[service][0] == 'all':
140 return True
141 if extension_name in config_dict[service]:
142 return True
143 return False
144
Ian Wienand98c35f32013-07-23 20:34:23 +1000145
Ken'ichi Ohmichia1111c52016-12-01 19:42:03 -0800146def related_bug(bug, status_code=None):
147 """A decorator useful to know solutions from launchpad bug reports
148
149 @param bug: The launchpad bug number causing the test
150 @param status_code: The status code related to the bug report
151 """
152 def decorator(f):
153 @functools.wraps(f)
154 def wrapper(self, *func_args, **func_kwargs):
155 try:
156 return f(self, *func_args, **func_kwargs)
157 except Exception as exc:
158 exc_status_code = getattr(exc, 'status_code', None)
159 if status_code is None or status_code == exc_status_code:
160 LOG.error('Hints: This test was made for the bug %s. '
161 'The failure could be related to '
Jordan Pittier525ec712016-12-07 17:51:26 +0100162 'https://launchpad.net/bugs/%s', bug, bug)
Ken'ichi Ohmichia1111c52016-12-01 19:42:03 -0800163 raise exc
164 return wrapper
165 return decorator
166
167
Yair Fried95914122016-03-03 09:14:40 +0200168def is_scheduler_filter_enabled(filter_name):
ghanshyam5817e142016-12-01 11:38:46 +0900169 """Check the list of enabled compute scheduler filters from config.
170
171 This function checks whether the given compute scheduler filter is
172 available and configured in the config file. If the
173 scheduler_available_filters option is set to 'all' (Default value. which
174 means default filters are configured in nova) in tempest.conf then, this
175 function returns True with assumption that requested filter 'filter_name'
176 is one of available filter in nova ("nova.scheduler.filters.all_filters").
177 """
Yair Friedca5cfb52016-01-04 15:41:55 +0200178
179 filters = CONF.compute_feature_enabled.scheduler_available_filters
180 if len(filters) == 0:
181 return False
182 if 'all' in filters:
183 return True
184 if filter_name in filters:
185 return True
186 return False
187
188
Attila Fazekasf86fa312013-07-30 19:56:39 +0200189at_exit_set = set()
190
191
192def validate_tearDownClass():
193 if at_exit_set:
Sean Dagueeb1523b2014-03-10 10:17:44 -0400194 LOG.error(
195 "tearDownClass does not call the super's "
196 "tearDownClass in these classes: \n"
197 + str(at_exit_set))
198
Attila Fazekasf86fa312013-07-30 19:56:39 +0200199
200atexit.register(validate_tearDownClass)
201
Attila Fazekas53943322014-02-10 16:07:34 +0100202
Matthew Treinish2474f412014-11-17 18:11:56 -0500203class BaseTestCase(testtools.testcase.WithAttributes,
204 testtools.TestCase):
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100205 """The test base class defines Tempest framework for class level fixtures.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000206
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100207 `setUpClass` and `tearDownClass` are defined here and cannot be overwritten
208 by subclasses (enforced via hacking rule T105).
209
210 Set-up is split in a series of steps (setup stages), which can be
211 overwritten by test classes. Set-up stages are:
212 - skip_checks
213 - setup_credentials
214 - setup_clients
215 - resource_setup
216
217 Tear-down is also split in a series of steps (teardown stages), which are
218 stacked for execution only if the corresponding setup stage had been
219 reached during the setup phase. Tear-down stages are:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700220 - clear_credentials (defined in the base test class)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100221 - resource_cleanup
222 """
Attila Fazekasc43fec82013-04-09 23:17:52 +0200223
Attila Fazekasf86fa312013-07-30 19:56:39 +0200224 setUpClassCalled = False
225
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000226 # NOTE(andreaf) credentials holds a list of the credentials to be allocated
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100227 # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
228 # a list of roles - the first element of the list being a label, and the
229 # rest the actual roles
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000230 credentials = []
nithya-ganesan222efd72015-01-22 12:20:27 +0000231 # Resources required to validate a server using ssh
232 validation_resources = {}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500233 network_resources = {}
234
Sean Dague2ef32ac2014-06-09 11:32:23 -0400235 # NOTE(sdague): log_format is defined inline here instead of using the oslo
236 # default because going through the config path recouples config to the
237 # stress tests too early, and depending on testr order will fail unit tests
238 log_format = ('%(asctime)s %(process)d %(levelname)-8s '
239 '[%(name)s] %(message)s')
240
Ryota MIBU60687e52015-12-09 18:37:39 +0900241 # Client manager class to use in this test case.
242 client_manager = clients.Manager
243
Sean Dague02620fd2016-03-02 15:52:51 -0500244 # A way to adjust slow test classes
245 TIMEOUT_SCALING_FACTOR = 1
246
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200247 @classmethod
248 def setUpClass(cls):
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100249 # It should never be overridden by descendants
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200250 if hasattr(super(BaseTestCase, cls), 'setUpClass'):
251 super(BaseTestCase, cls).setUpClass()
Attila Fazekasf86fa312013-07-30 19:56:39 +0200252 cls.setUpClassCalled = True
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100253 # Stack of (name, callable) to be invoked in reverse order at teardown
254 cls.teardowns = []
255 # All the configuration checks that may generate a skip
256 cls.skip_checks()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100257 try:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100258 # Allocation of all required credentials and client managers
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700259 cls.teardowns.append(('credentials', cls.clear_credentials))
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100260 cls.setup_credentials()
261 # Shortcuts to clients
262 cls.setup_clients()
263 # Additional class-wide test resources
264 cls.teardowns.append(('resources', cls.resource_cleanup))
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100265 cls.resource_setup()
266 except Exception:
267 etype, value, trace = sys.exc_info()
Jordan Pittier525ec712016-12-07 17:51:26 +0100268 LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
269 etype, cls.__name__)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100270 cls.tearDownClass()
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100271 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400272 six.reraise(etype, value, trace)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100273 finally:
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100274 del trace # to avoid circular refs
Pavel Sedlák1053bd32013-04-16 16:47:40 +0200275
Attila Fazekasf86fa312013-07-30 19:56:39 +0200276 @classmethod
277 def tearDownClass(cls):
Attila Fazekas5d275302013-08-29 12:35:12 +0200278 at_exit_set.discard(cls)
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100279 # It should never be overridden by descendants
Attila Fazekasf86fa312013-07-30 19:56:39 +0200280 if hasattr(super(BaseTestCase, cls), 'tearDownClass'):
281 super(BaseTestCase, cls).tearDownClass()
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100282 # Save any existing exception, we always want to re-raise the original
283 # exception only
284 etype, value, trace = sys.exc_info()
285 # If there was no exception during setup we shall re-raise the first
286 # exception in teardown
287 re_raise = (etype is None)
288 while cls.teardowns:
289 name, teardown = cls.teardowns.pop()
290 # Catch any exception in tearDown so we can re-raise the original
291 # exception at the end
292 try:
293 teardown()
294 except Exception as te:
295 sys_exec_info = sys.exc_info()
296 tetype = sys_exec_info[0]
297 # TODO(andreaf): Till we have the ability to cleanup only
298 # resources that were successfully setup in resource_cleanup,
299 # log AttributeError as info instead of exception.
300 if tetype is AttributeError and name == 'resources':
Jordan Pittier525ec712016-12-07 17:51:26 +0100301 LOG.info("tearDownClass of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100302 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100303 LOG.exception("teardown of %s failed: %s", name, te)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100304 if not etype:
305 etype, value, trace = sys_exec_info
Joshua Whitebd769602016-02-02 09:30:11 -0800306 # If exceptions were raised during teardown, and not before, re-raise
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100307 # the first one
308 if re_raise and etype is not None:
309 try:
Matthew Treinish843227d2015-04-23 10:17:17 -0400310 six.reraise(etype, value, trace)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100311 finally:
312 del trace # to avoid circular refs
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100313
314 @classmethod
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100315 def skip_checks(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000316 """Class level skip checks.
317
318 Subclasses verify in here all conditions that might prevent the
319 execution of the entire test class.
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100320 Checks implemented here may not make use API calls, and should rely on
321 configuration alone.
322 In general skip checks that require an API call are discouraged.
323 If one is really needed it may be implemented either in the
324 resource_setup or at test level.
325 """
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100326 identity_version = cls.get_identity_version()
327 if 'admin' in cls.credentials and not credentials.is_admin_available(
328 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000329 msg = "Missing Identity Admin API credentials in configuration."
330 raise cls.skipException(msg)
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100331 if 'alt' in cls.credentials and not credentials.is_alt_available(
332 identity_version=identity_version):
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000333 msg = "Missing a 2nd set of API credentials in configuration."
334 raise cls.skipException(msg)
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100335 if hasattr(cls, 'identity_version'):
336 if cls.identity_version == 'v2':
337 if not CONF.identity_feature_enabled.api_v2:
338 raise cls.skipException("Identity api v2 is not enabled")
339 elif cls.identity_version == 'v3':
340 if not CONF.identity_feature_enabled.api_v3:
341 raise cls.skipException("Identity api v3 is not enabled")
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100342
343 @classmethod
344 def setup_credentials(cls):
edannon6cc6fbc2016-05-03 11:56:12 +0300345 """Allocate credentials and create the client managers from them.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000346
edannon6cc6fbc2016-05-03 11:56:12 +0300347 For every element of credentials param function creates tenant/user,
348 Then it creates client manager for that credential.
349
350 Network related tests must override this function with
351 set_network_resources() method, otherwise it will create
352 network resources(network resources are created in a later step).
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000353 """
354 for credentials_type in cls.credentials:
355 # This may raise an exception in case credentials are not available
356 # In that case we want to let the exception through and the test
357 # fail accordingly
Andrea Frittoli (andreaf)825b2d32015-04-08 20:58:01 +0100358 if isinstance(credentials_type, six.string_types):
359 manager = cls.get_client_manager(
360 credential_type=credentials_type)
361 setattr(cls, 'os_%s' % credentials_type, manager)
362 # Setup some common aliases
363 # TODO(andreaf) The aliases below are a temporary hack
364 # to avoid changing too much code in one patch. They should
365 # be removed eventually
366 if credentials_type == 'primary':
367 cls.os = cls.manager = cls.os_primary
368 if credentials_type == 'admin':
369 cls.os_adm = cls.admin_manager = cls.os_admin
370 if credentials_type == 'alt':
371 cls.alt_manager = cls.os_alt
372 elif isinstance(credentials_type, list):
373 manager = cls.get_client_manager(roles=credentials_type[1:],
374 force_new=True)
375 setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
Andrea Frittolia5ddd552014-08-19 18:30:00 +0100376
377 @classmethod
378 def setup_clients(cls):
379 """Create links to the clients into the test object."""
380 # TODO(andreaf) There is a fair amount of code that could me moved from
381 # base / test classes in here. Ideally tests should be able to only
382 # specify which client is `client` and nothing else.
Andrea Frittoli73ee2472014-09-15 12:31:53 +0100383 pass
Attila Fazekasf86fa312013-07-30 19:56:39 +0200384
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000385 @classmethod
386 def resource_setup(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000387 """Class level resource setup for test cases."""
nithya-ganesan222efd72015-01-22 12:20:27 +0000388 if hasattr(cls, "os"):
389 cls.validation_resources = vresources.create_validation_resources(
390 cls.os, cls.validation_resources)
391 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000392 LOG.warning("Client manager not found, validation resources not"
393 " created")
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000394
395 @classmethod
396 def resource_cleanup(cls):
397 """Class level resource cleanup for test cases.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000398
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000399 Resource cleanup must be able to handle the case of partially setup
400 resources, in case a failure during `resource_setup` should happen.
401 """
nithya-ganesan222efd72015-01-22 12:20:27 +0000402 if cls.validation_resources:
403 if hasattr(cls, "os"):
404 vresources.clear_validation_resources(cls.os,
405 cls.validation_resources)
406 cls.validation_resources = {}
407 else:
zhangguoqing6c096642016-01-04 06:17:21 +0000408 LOG.warning("Client manager not found, validation resources "
409 "not deleted")
Emily Hugenbruch5bd4cbf2014-12-17 21:38:38 +0000410
Attila Fazekasf86fa312013-07-30 19:56:39 +0200411 def setUp(self):
412 super(BaseTestCase, self).setUp()
413 if not self.setUpClassCalled:
414 raise RuntimeError("setUpClass does not calls the super's"
415 "setUpClass in the "
416 + self.__class__.__name__)
417 at_exit_set.add(self.__class__)
Matthew Treinish78561ad2013-07-26 11:41:56 -0400418 test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
419 try:
Sean Dague02620fd2016-03-02 15:52:51 -0500420 test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
Matthew Treinish78561ad2013-07-26 11:41:56 -0400421 except ValueError:
422 test_timeout = 0
423 if test_timeout > 0:
Attila Fazekasf86fa312013-07-30 19:56:39 +0200424 self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400425
426 if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
427 os.environ.get('OS_STDOUT_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200428 stdout = self.useFixture(fixtures.StringStream('stdout')).stream
429 self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400430 if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
431 os.environ.get('OS_STDERR_CAPTURE') == '1'):
Attila Fazekasf86fa312013-07-30 19:56:39 +0200432 stderr = self.useFixture(fixtures.StringStream('stderr')).stream
433 self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
Attila Fazekas31388072013-08-15 08:58:07 +0200434 if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
435 os.environ.get('OS_LOG_CAPTURE') != '0'):
Attila Fazekas31388072013-08-15 08:58:07 +0200436 self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
Sean Dague2ef32ac2014-06-09 11:32:23 -0400437 format=self.log_format,
Attila Fazekas90445be2013-10-24 16:46:03 +0200438 level=None))
Matthew Treinish78561ad2013-07-26 11:41:56 -0400439
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100440 @property
441 def credentials_provider(self):
442 return self._get_credentials_provider()
443
Jamie Lennox15350172015-08-17 10:54:25 +1000444 @property
445 def identity_utils(self):
446 """A client that abstracts v2 and v3 identity operations.
447
448 This can be used for creating and tearing down projects in tests. It
449 should not be used for testing identity features.
450 """
451 if CONF.identity.auth_version == 'v2':
452 client = self.os_admin.identity_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000453 users_client = self.os_admin.users_client
Daniel Melladob04da902015-11-20 17:43:12 +0100454 project_client = self.os_admin.tenants_client
Daniel Mellado6b16b922015-12-07 12:43:08 +0000455 roles_client = self.os_admin.roles_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000456 domains_client = None
Jamie Lennox15350172015-08-17 10:54:25 +1000457 else:
458 client = self.os_admin.identity_v3_client
Daniel Mellado7aea5342016-02-09 09:10:12 +0000459 users_client = self.os_admin.users_v3_client
Arx Cruz24bcb882016-02-10 15:20:16 +0100460 project_client = self.os_admin.projects_client
461 roles_client = self.os_admin.roles_v3_client
Daniel Mellado91a26b62016-02-11 11:13:04 +0000462 domains_client = self.os_admin.domains_client
Jamie Lennox15350172015-08-17 10:54:25 +1000463
464 try:
465 domain = client.auth_provider.credentials.project_domain_name
466 except AttributeError:
467 domain = 'Default'
468
Daniel Melladob04da902015-11-20 17:43:12 +0100469 return cred_client.get_creds_client(client, project_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +0000470 users_client,
Daniel Mellado7aea5342016-02-09 09:10:12 +0000471 roles_client,
Daniel Mellado91a26b62016-02-11 11:13:04 +0000472 domains_client,
Daniel Melladob04da902015-11-20 17:43:12 +0100473 project_domain_name=domain)
Jamie Lennox15350172015-08-17 10:54:25 +1000474
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100475 @classmethod
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100476 def get_identity_version(cls):
477 """Returns the identity version used by the test class"""
478 identity_version = getattr(cls, 'identity_version', None)
479 return identity_version or CONF.identity.auth_version
480
481 @classmethod
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100482 def _get_credentials_provider(cls):
483 """Returns a credentials provider
484
485 If no credential provider exists yet creates one.
486 It uses self.identity_version if defined, or the configuration value
487 """
488 if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
489 not cls._creds_provider.name == cls.__name__):
490 force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
491 False)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100492
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700493 cls._creds_provider = credentials.get_credentials_provider(
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100494 name=cls.__name__, network_resources=cls.network_resources,
495 force_tenant_isolation=force_tenant_isolation,
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100496 identity_version=cls.get_identity_version())
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100497 return cls._creds_provider
498
Matthew Treinish3e046852013-07-23 16:00:24 -0400499 @classmethod
Andrea Frittoli (andreaf)41601412015-05-12 16:39:03 +0100500 def get_client_manager(cls, credential_type=None, roles=None,
501 force_new=None):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100502 """Returns an OpenStack client manager
503
504 Returns an OpenStack client manager based on either credential_type
505 or a list of roles. If neither is specified, it defaults to
506 credential_type 'primary'
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100507 :param credential_type: string - primary, alt or admin
508 :param roles: list of roles
509
lei zhangdd552b22015-11-25 20:41:48 +0800510 :returns: the created client manager
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100511 :raises skipException: if the requested credentials are not available
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700512 """
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100513 if all([roles, credential_type]):
514 msg = "Cannot get credentials by type and roles at the same time"
515 raise ValueError(msg)
516 if not any([roles, credential_type]):
517 credential_type = 'primary'
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100518 cred_provider = cls._get_credentials_provider()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100519 if roles:
520 for role in roles:
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100521 if not cred_provider.is_role_available(role):
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100522 skip_msg = (
523 "%s skipped because the configured credential provider"
524 " is not able to provide credentials with the %s role "
525 "assigned." % (cls.__name__, role))
526 raise cls.skipException(skip_msg)
527 params = dict(roles=roles)
528 if force_new is not None:
529 params.update(force_new=force_new)
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100530 creds = cred_provider.get_creds_by_roles(**params)
Andrea Frittolib21de6c2015-02-06 20:12:38 +0000531 else:
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100532 credentials_method = 'get_%s_creds' % credential_type
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100533 if hasattr(cred_provider, credentials_method):
534 creds = getattr(cred_provider, credentials_method)()
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100535 else:
Andrea Frittoli (andreaf)af4f7cf2016-06-13 15:12:26 +0100536 raise lib_exc.InvalidCredentials(
Andrea Frittoli (andreaf)737fac92015-05-12 16:14:35 +0100537 "Invalid credentials type %s" % credential_type)
Jordan Pittiere4be9072017-01-04 19:17:35 +0100538 manager = cls.client_manager(credentials=creds.credentials)
Andrea Frittoli73224672016-12-09 21:08:19 +0000539 # NOTE(andreaf) Ensure credentials have user and project id fields.
540 # It may not be the case when using pre-provisioned credentials.
541 manager.auth_provider.set_auth()
542 return manager
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700543
544 @classmethod
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700545 def clear_credentials(cls):
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000546 """Clears creds if set"""
Attila Fazekas5b0d9262015-05-20 10:17:39 +0200547 if hasattr(cls, '_creds_provider'):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700548 cls._creds_provider.clear_creds()
Ryan Hsu6c4bb3d2013-10-21 21:22:50 -0700549
550 @classmethod
nithya-ganesan222efd72015-01-22 12:20:27 +0000551 def set_validation_resources(cls, keypair=None, floating_ip=None,
552 security_group=None,
553 security_group_rules=None):
554 """Specify which ssh server validation resources should be created.
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +0000555
nithya-ganesan222efd72015-01-22 12:20:27 +0000556 Each of the argument must be set to either None, True or False, with
557 None - use default from config (security groups and security group
558 rules get created when set to None)
559 False - Do not create the validation resource
560 True - create the validation resource
561
562 @param keypair
563 @param security_group
564 @param security_group_rules
565 @param floating_ip
566 """
Matthew Treinishe5cca002015-05-11 15:36:50 -0400567 if not CONF.validation.run_validation:
568 return
Jordan Pittier79cd1822016-12-08 17:20:35 +0100569
nithya-ganesan222efd72015-01-22 12:20:27 +0000570 if keypair is None:
Jordan Pittier79cd1822016-12-08 17:20:35 +0100571 keypair = (CONF.validation.auth_method.lower() == "keypair")
572
nithya-ganesan222efd72015-01-22 12:20:27 +0000573 if floating_ip is None:
Jordan Pittier79cd1822016-12-08 17:20:35 +0100574 floating_ip = (CONF.validation.connect_method.lower() ==
575 "floating")
576
nithya-ganesan222efd72015-01-22 12:20:27 +0000577 if security_group is None:
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500578 security_group = CONF.validation.security_group
Jordan Pittier79cd1822016-12-08 17:20:35 +0100579
nithya-ganesan222efd72015-01-22 12:20:27 +0000580 if security_group_rules is None:
Brandon Palmc6cc91d2015-08-19 13:20:21 -0500581 security_group_rules = CONF.validation.security_group_rules
582
nithya-ganesan222efd72015-01-22 12:20:27 +0000583 if not cls.validation_resources:
584 cls.validation_resources = {
585 'keypair': keypair,
586 'security_group': security_group,
587 'security_group_rules': security_group_rules,
588 'floating_ip': floating_ip}
589
590 @classmethod
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000591 def set_network_resources(cls, network=False, router=False, subnet=False,
Matthew Treinish9f756a02014-01-15 10:26:07 -0500592 dhcp=False):
593 """Specify which network resources should be created
594
595 @param network
596 @param router
597 @param subnet
598 @param dhcp
599 """
Salvatore Orlando5a337242014-01-15 22:49:22 +0000600 # network resources should be set only once from callers
601 # in order to ensure that even if it's called multiple times in
602 # a chain of overloaded methods, the attribute is set only
603 # in the leaf class
Andrea Frittoli7d5ed592015-02-10 01:10:23 +0000604 if not cls.network_resources:
605 cls.network_resources = {
Salvatore Orlando5a337242014-01-15 22:49:22 +0000606 'network': network,
607 'router': router,
608 'subnet': subnet,
609 'dhcp': dhcp}
Matthew Treinish9f756a02014-01-15 10:26:07 -0500610
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530611 @classmethod
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000612 def get_tenant_network(cls, credentials_type='primary'):
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530613 """Get the network to be used in testing
614
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000615 :param credentials_type: The type of credentials for which to get the
616 tenant network
617
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530618 :return: network dict including 'id' and 'name'
619 """
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000620 # Get a manager for the given credentials_type, but at least
621 # always fall back on getting the manager for primary credentials
622 if isinstance(credentials_type, six.string_types):
623 manager = cls.get_client_manager(credential_type=credentials_type)
624 elif isinstance(credentials_type, list):
625 manager = cls.get_client_manager(roles=credentials_type[1:])
626 else:
627 manager = cls.get_client_manager()
628
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700629 # Make sure cred_provider exists and get a network client
Ryan Rossiter9228bf72016-02-25 03:06:12 +0000630 networks_client = manager.compute_networks_client
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100631 cred_provider = cls._get_credentials_provider()
Andrea Frittoli700711e2015-04-02 11:39:38 +0100632 # In case of nova network, isolated tenants are not able to list the
Joshua Whitebd769602016-02-02 09:30:11 -0800633 # network configured in fixed_network_name, even if they can use it
Andrea Frittoli700711e2015-04-02 11:39:38 +0100634 # for their servers, so using an admin network client to validate
635 # the network name
636 if (not CONF.service_available.neutron and
Andrea Frittoli (andreaf)32d0de12015-10-09 14:43:53 +0100637 credentials.is_admin_available(
638 identity_version=cls.get_identity_version())):
Andrea Frittoli (andreaf)1f342412015-05-12 16:37:19 +0100639 admin_creds = cred_provider.get_admin_creds()
Andrea Frittoli (andreaf)848c4a12016-06-09 11:09:02 +0100640 admin_manager = clients.Manager(admin_creds.credentials)
John Warren9487a182015-09-14 18:12:56 -0400641 networks_client = admin_manager.compute_networks_client
Andrea Frittoli (andreaf)940f8c62015-10-30 16:39:24 +0900642 return fixed_network.get_tenant_network(
643 cred_provider, networks_client, CONF.compute.fixed_network_name)
Rohan Kanade9ce97df2013-12-10 18:59:35 +0530644
Mark Maglana5885eb32014-02-28 10:57:34 -0800645 def assertEmpty(self, list, msg=None):
zhufl92ade4b2017-03-03 15:20:10 +0800646 if msg is None:
647 msg = "list is not empty: %s" % list
Béla Vancsics64862f72016-11-08 09:12:31 +0100648 self.assertEqual(0, len(list), msg)
Mark Maglana5885eb32014-02-28 10:57:34 -0800649
650 def assertNotEmpty(self, list, msg=None):
zhufl92ade4b2017-03-03 15:20:10 +0800651 if msg is None:
652 msg = "list is empty."
Béla Vancsics64862f72016-11-08 09:12:31 +0100653 self.assertGreater(len(list), 0, msg)