Merge "Remove leading underscore in _create_test_user"
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 2597f04..cbfcc09 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -1,3 +1,16 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
# Tempest documentation build configuration file, created by
# sphinx-quickstart on Tue May 21 17:43:32 2013.
#
diff --git a/releasenotes/notes/16.0.0-mitaka-eol-88ff8355fff81b55.yaml b/releasenotes/notes/16.0.0-mitaka-eol-88ff8355fff81b55.yaml
new file mode 100644
index 0000000..24ec512
--- /dev/null
+++ b/releasenotes/notes/16.0.0-mitaka-eol-88ff8355fff81b55.yaml
@@ -0,0 +1,13 @@
+---
+prelude: >
+ This release indicates end of support for Mitaka in Tempest.
+other:
+ - |
+ OpenStack Releases Supported after this release are **Newton**
+ and **Ocata**
+
+ The release under current development as of this tag is Pike,
+ meaning that every Tempest commit is also tested against master branch
+ during the Pike cycle. However, this does not necessarily mean that
+ using Tempest as of this tag will work against Pike (or future
+ releases) cloud.
diff --git a/releasenotes/notes/dreprecate_client_parameters-cb8d069e62957f7e.yaml b/releasenotes/notes/dreprecate_client_parameters-cb8d069e62957f7e.yaml
new file mode 100644
index 0000000..4081f6a
--- /dev/null
+++ b/releasenotes/notes/dreprecate_client_parameters-cb8d069e62957f7e.yaml
@@ -0,0 +1,6 @@
+---
+deprecations:
+ - |
+ Deprecate the client_parameters argument in
+ `tempest.lib.services.clients.ServiceClients`. The parameter is actually
+ not honoured already - see https://bugs.launchpad.net/tempest/+bug/1680915
diff --git a/releasenotes/notes/move-related_bug-decorator-to-lib-dbfd5c543bbb2805.yaml b/releasenotes/notes/move-related_bug-decorator-to-lib-dbfd5c543bbb2805.yaml
new file mode 100644
index 0000000..8c420c8
--- /dev/null
+++ b/releasenotes/notes/move-related_bug-decorator-to-lib-dbfd5c543bbb2805.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ A new ``related_bug`` decorator has been added to
+ ``tempest.lib.decorators``. Use it to decorate and tag a test that was
+ added in relation to a launchpad bug report.
diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py
index eec42cd..97e3a4d 100644
--- a/releasenotes/source/conf.py
+++ b/releasenotes/source/conf.py
@@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# tempest Release Notes documentation build configuration file, created by
+# Tempest Release Notes documentation build configuration file, created by
# sphinx-quickstart on Tue Nov 3 17:40:50 2015.
#
# This file is execfile()d with the current directory set to its
diff --git a/requirements.txt b/requirements.txt
index 7c934c2..14c42b3 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-pbr>=2.0.0 # Apache-2.0
+pbr!=2.1.0,>=2.0.0 # Apache-2.0
cliff>=2.3.0 # Apache-2.0
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
testtools>=1.4.0 # MIT
diff --git a/tempest/api/compute/admin/test_baremetal_nodes.py b/tempest/api/compute/admin/test_baremetal_nodes.py
deleted file mode 100644
index 7726ed4..0000000
--- a/tempest/api/compute/admin/test_baremetal_nodes.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2015 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.api.compute import base
-from tempest import config
-from tempest.lib import decorators
-from tempest import test
-
-CONF = config.CONF
-
-
-class BaremetalNodesAdminTestJSON(base.BaseV2ComputeAdminTest):
- """Tests Baremetal API"""
-
- @classmethod
- def resource_setup(cls):
- super(BaremetalNodesAdminTestJSON, cls).resource_setup()
- if not getattr(CONF.service_available, 'ironic', False):
- skip_msg = ('%s skipped as Ironic is not available' % cls.__name__)
- raise cls.skipException(skip_msg)
- cls.client = cls.os_adm.baremetal_nodes_client
- cls.ironic_client = cls.os_adm.baremetal_client
-
- @test.attr(type=['baremetal'])
- @decorators.idempotent_id('e475aa6e-416d-4fa4-b3af-28d5e84250fb')
- def test_list_get_baremetal_nodes(self):
- # Create some test nodes in Ironic directly
- test_nodes = []
- for _ in range(0, 3):
- _, node = self.ironic_client.create_node()
- test_nodes.append(node)
- self.addCleanup(self.ironic_client.delete_node, node['uuid'])
-
- # List all baremetal nodes and ensure our created test nodes are
- # listed
- bm_node_ids = set([n['id'] for n in
- self.client.list_baremetal_nodes()['nodes']])
- test_node_ids = set([n['uuid'] for n in test_nodes])
- self.assertTrue(test_node_ids.issubset(bm_node_ids))
-
- # Test getting each individually
- for node in test_nodes:
- baremetal_node = self.client.show_baremetal_node(node['uuid'])
- self.assertEqual(node['uuid'], baremetal_node['node']['id'])
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 4360586..aff61bf 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -18,7 +18,6 @@
from tempest.common import waiters
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
-from tempest import test
class ServersAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -93,7 +92,7 @@
self.assertIn(self.s1_name, servers_name)
self.assertIn(self.s2_name, servers_name)
- @test.related_bug('1659811')
+ @decorators.related_bug('1659811')
@decorators.idempotent_id('7e5d6b8f-454a-4ba1-8ae2-da857af8338b')
def test_list_servers_by_admin_with_specified_tenant(self):
# In nova v2, tenant_id is ignored unless all_tenants is specified
diff --git a/tempest/api/compute/admin/test_volumes_negative.py b/tempest/api/compute/admin/test_volumes_negative.py
index 06b0893..7ebd074 100644
--- a/tempest/api/compute/admin/test_volumes_negative.py
+++ b/tempest/api/compute/admin/test_volumes_negative.py
@@ -46,7 +46,7 @@
self.server['id'], nonexistent_volume,
volumeId=volume['id'])
- @test.related_bug('1629110', status_code=400)
+ @decorators.related_bug('1629110', status_code=400)
@test.attr(type=['negative'])
@decorators.idempotent_id('7dcac15a-b107-46d3-a5f6-cb863f4e454a')
def test_update_attached_volume_with_nonexistent_volume_in_body(self):
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index c6b3b40..40a4289 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -178,7 +178,7 @@
self.client.rebuild_server,
server['id'], self.image_ref)
- @test.related_bug('1660878', status_code=409)
+ @decorators.related_bug('1660878', status_code=409)
@test.attr(type=['negative'])
@decorators.idempotent_id('581a397d-5eab-486f-9cf9-1014bbd4c984')
def test_reboot_deleted_server(self):
@@ -219,7 +219,7 @@
name=server_name)
@test.attr(type=['negative'])
- @test.related_bug('1651064', status_code=500)
+ @decorators.related_bug('1651064', status_code=500)
@decorators.idempotent_id('12146ac1-d7df-4928-ad25-b1f99e5286cd')
def test_create_server_invalid_bdm_in_2nd_dict(self):
volume = self.create_volume()
diff --git a/tempest/api/compute/volumes/test_attach_volume_negative.py b/tempest/api/compute/volumes/test_attach_volume_negative.py
index c017690..c178a87 100644
--- a/tempest/api/compute/volumes/test_attach_volume_negative.py
+++ b/tempest/api/compute/volumes/test_attach_volume_negative.py
@@ -31,7 +31,7 @@
raise cls.skipException(skip_msg)
@test.attr(type=['negative'])
- @test.related_bug('1630783', status_code=500)
+ @decorators.related_bug('1630783', status_code=500)
@decorators.idempotent_id('a313b5cd-fbd0-49cc-94de-870e99f763c7')
def test_delete_attached_volume(self):
server = self.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/identity/admin/v2/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index af76b00..b288705 100644
--- a/tempest/api/identity/admin/v2/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -82,10 +82,7 @@
self.addCleanup(self.tenants_client.delete_tenant, tenant2['id'])
# Create a role
- role_name = data_utils.rand_name(name='role')
- role = self.roles_client.create_role(name=role_name)['role']
- # Delete the role at the end of the test
- self.addCleanup(self.roles_client.delete_role, role['id'])
+ role = self.setup_test_role()
# Grant the user the role on the tenants.
self.roles_client.create_user_role_on_project(tenant1['id'],
diff --git a/tempest/api/identity/admin/v3/test_inherits.py b/tempest/api/identity/admin/v3/test_inherits.py
index 3fe591b..4de0f5b 100644
--- a/tempest/api/identity/admin/v3/test_inherits.py
+++ b/tempest/api/identity/admin/v3/test_inherits.py
@@ -65,9 +65,7 @@
@decorators.idempotent_id('4e6f0366-97c8-423c-b2be-41eae6ac91c8')
def test_inherit_assign_list_check_revoke_roles_on_domains_user(self):
# Create role
- src_role = self.roles_client.create_role(
- name=data_utils.rand_name('Role'))['role']
- self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ src_role = self.setup_test_role()
# Assign role on domains user
self.inherited_roles_client.create_inherited_role_on_domains_user(
self.domain['id'], self.user['id'], src_role['id'])
@@ -91,9 +89,7 @@
@decorators.idempotent_id('c7a8dda2-be50-4fb4-9a9c-e830771078b1')
def test_inherit_assign_list_check_revoke_roles_on_domains_group(self):
# Create role
- src_role = self.roles_client.create_role(
- name=data_utils.rand_name('Role'))['role']
- self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ src_role = self.setup_test_role()
# Assign role on domains group
self.inherited_roles_client.create_inherited_role_on_domains_group(
self.domain['id'], self.group['id'], src_role['id'])
@@ -117,9 +113,7 @@
@decorators.idempotent_id('18b70e45-7687-4b72-8277-b8f1a47d7591')
def test_inherit_assign_check_revoke_roles_on_projects_user(self):
# Create role
- src_role = self.roles_client.create_role(
- name=data_utils.rand_name('Role'))['role']
- self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ src_role = self.setup_test_role()
# Assign role on projects user
self.inherited_roles_client.create_inherited_role_on_projects_user(
self.project['id'], self.user['id'], src_role['id'])
@@ -134,9 +128,7 @@
@decorators.idempotent_id('26021436-d5a4-4256-943c-ded01e0d4b45')
def test_inherit_assign_check_revoke_roles_on_projects_group(self):
# Create role
- src_role = self.roles_client.create_role(
- name=data_utils.rand_name('Role'))['role']
- self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ src_role = self.setup_test_role()
# Assign role on projects group
self.inherited_roles_client.create_inherited_role_on_projects_group(
self.project['id'], self.group['id'], src_role['id'])
@@ -152,9 +144,7 @@
@decorators.idempotent_id('3acf666e-5354-42ac-8e17-8b68893bcd36')
def test_inherit_assign_list_revoke_user_roles_on_domain(self):
# Create role
- src_role = self.roles_client.create_role(
- name=data_utils.rand_name('Role'))['role']
- self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ src_role = self.setup_test_role()
# Create a project hierarchy
leaf_project_name = data_utils.rand_name('project')
@@ -202,9 +192,7 @@
@decorators.idempotent_id('9f02ccd9-9b57-46b4-8f77-dd5a736f3a06')
def test_inherit_assign_list_revoke_user_roles_on_project_tree(self):
# Create role
- src_role = self.roles_client.create_role(
- name=data_utils.rand_name('Role'))['role']
- self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ src_role = self.setup_test_role()
# Create a project hierarchy
leaf_project_name = data_utils.rand_name('project')
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index c6b562b..de4f580 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -75,9 +75,7 @@
self.addCleanup(self.projects_client.delete_project, project2['id'])
# Create a role
- role_name = data_utils.rand_name(name='role')
- role = self.roles_client.create_role(name=role_name)['role']
- self.addCleanup(self.roles_client.delete_role, role['id'])
+ role = self.setup_test_role()
# Grant the user the role on both projects.
self.roles_client.create_user_role_on_project(project1['id'],
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 0d12ba9..28137ad 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -118,10 +118,7 @@
# Delete the User at the end of this method
self.addCleanup(self.users_client.delete_user, user_body['id'])
# Creating Role
- role_body = self.roles_client.create_role(
- name=data_utils.rand_name('role'))['role']
- # Delete the Role at the end of this method
- self.addCleanup(self.roles_client.delete_role, role_body['id'])
+ role_body = self.setup_test_role()
user = self.users_client.show_user(user_body['id'])['user']
role = self.roles_client.show_role(role_body['id'])['role']
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 1a32894..9d794b5 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -82,9 +82,9 @@
self.users_client.delete_user, user['id'])
return user
- def setup_test_role(self, domain_id=None):
+ def setup_test_role(self, name=None, domain_id=None):
"""Set up a test role."""
- params = {'name': data_utils.rand_name('test_role')}
+ params = {'name': name or data_utils.rand_name('test_role')}
if domain_id:
params['domain_id'] = domain_id
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index b6b5ab4..6b9f131 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -358,27 +358,24 @@
self._test_pagination('volumes', ids=self.volume_id_list, detail=False)
@decorators.idempotent_id('46eff077-100b-427f-914e-3db2abcdb7e2')
- @decorators.skip_because(bug='1572765')
def test_volume_list_with_detail_param_marker(self):
# Choosing a random volume from a list of volumes for 'marker'
# parameter
- random_volume = random.choice(self.volume_id_list)
+ marker = random.choice(self.volume_id_list)
- params = {'marker': random_volume}
+ # Though Cinder volumes are returned sorted by ID by default
+ # this is implicit. Let make this explicit in case Cinder
+ # folks change their minds.
+ params = {'marker': marker, 'sort': 'id:asc'}
# Running volume list using marker parameter
vol_with_marker = self.volumes_client.list_volumes(
detail=True, params=params)['volumes']
- # Fetching the index of the random volume from volume_id_list
- index_marker = self.volume_id_list.index(random_volume)
+ expected_volumes_id = {
+ id for id in self.volume_id_list if id > marker
+ }
- # The expected list with marker parameter
- verify_volume_list = self.volume_id_list[:index_marker]
-
- failed_msg = "Failed to list volume details by marker"
-
- # Validating the expected list is the same like the observed list
- self.assertEqual(verify_volume_list,
- map(lambda x: x['id'],
- vol_with_marker[::-1]), failed_msg)
+ self.assertEqual(
+ expected_volumes_id, {v['id'] for v in vol_with_marker}
+ )
diff --git a/tempest/clients.py b/tempest/clients.py
index 01abfd8..cceb71a 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -159,7 +159,6 @@
self.aggregates_client = self.compute.AggregatesClient()
self.services_client = self.compute.ServicesClient()
self.tenant_usages_client = self.compute.TenantUsagesClient()
- self.baremetal_nodes_client = self.compute.BaremetalNodesClient()
self.hosts_client = self.compute.HostsClient()
self.hypervisor_client = self.compute.HypervisorClient()
self.instance_usages_audit_log_client = (
@@ -168,11 +167,10 @@
# NOTE: The following client needs special timeout values because
# the API is a proxy for the other component.
- params_volume = {}
- for _key in ('build_interval', 'build_timeout'):
- _value = self.parameters['volume'].get(_key)
- if _value:
- params_volume[_key] = _value
+ params_volume = {
+ 'build_interval': CONF.volume.build_interval,
+ 'build_timeout': CONF.volume.build_timeout
+ }
self.volumes_extensions_client = self.compute.VolumesClient(
**params_volume)
self.compute_versions_client = self.compute.VersionsClient(
diff --git a/tempest/lib/decorators.py b/tempest/lib/decorators.py
index 92f9698..c2ee212 100644
--- a/tempest/lib/decorators.py
+++ b/tempest/lib/decorators.py
@@ -16,9 +16,12 @@
import uuid
import debtcollector.removals
+from oslo_log import log as logging
import six
import testtools
+LOG = logging.getLogger(__name__)
+
def skip_because(*args, **kwargs):
"""A decorator useful to skip tests hitting known bugs
@@ -45,6 +48,28 @@
return decorator
+def related_bug(bug, status_code=None):
+ """A decorator useful to know solutions from launchpad bug reports
+
+ @param bug: The launchpad bug number causing the test
+ @param status_code: The status code related to the bug report
+ """
+ def decorator(f):
+ @functools.wraps(f)
+ def wrapper(self, *func_args, **func_kwargs):
+ try:
+ return f(self, *func_args, **func_kwargs)
+ except Exception as exc:
+ exc_status_code = getattr(exc, 'status_code', None)
+ if status_code is None or status_code == exc_status_code:
+ LOG.error('Hints: This test was made for the bug %s. '
+ 'The failure could be related to '
+ 'https://launchpad.net/bugs/%s', bug, bug)
+ raise exc
+ return wrapper
+ return decorator
+
+
def idempotent_id(id):
"""Stub for metadata decorator"""
if not isinstance(id, six.string_types):
diff --git a/tempest/lib/services/clients.py b/tempest/lib/services/clients.py
index eefac66..1c8f443 100644
--- a/tempest/lib/services/clients.py
+++ b/tempest/lib/services/clients.py
@@ -17,7 +17,9 @@
import copy
import importlib
import inspect
+import warnings
+from debtcollector import removals
from oslo_log import log as logging
from tempest.lib import auth
@@ -29,7 +31,7 @@
from tempest.lib.services import network
from tempest.lib.services import volume
-
+warnings.simplefilter("once")
LOG = logging.getLogger(__name__)
@@ -244,11 +246,17 @@
Examples:
- >>> from tempest.lib.services import clients
- >>> johndoe = cred_provider.get_creds_by_role(['johndoe'])
- >>> johndoe_clients = clients.ServiceClients(johndoe,
- >>> identity_uri)
- >>> johndoe_servers = johndoe_clients.servers_client.list_servers()
+ >>> # johndoe is a tempest.lib.auth.Credentials type instance
+ >>> johndoe_clients = clients.ServiceClients(johndoe, identity_uri)
+ >>>
+ >>> # List servers in default region
+ >>> johndoe_servers_client = johndoe_clients.compute.ServersClient()
+ >>> johndoe_servers = johndoe_servers_client.list_servers()
+ >>>
+ >>> # List servers in Region B
+ >>> johndoe_servers_client_B = johndoe_clients.compute.ServersClient(
+ >>> region='B')
+ >>> johndoe_servers = johndoe_servers_client_B.list_servers()
"""
# NOTE(andreaf) This class does not depend on tempest configuration
@@ -257,6 +265,7 @@
# initialises this class using values from tempest CONF object. The wrapper
# class should only be used by tests hosted in Tempest.
+ @removals.removed_kwarg('client_parameters')
def __init__(self, credentials, identity_uri, region=None, scope='project',
disable_ssl_certificate_validation=True, ca_certs=None,
trace_requests='', client_parameters=None):
@@ -272,7 +281,12 @@
Parameters dscv, ca_certs and trace_requests all apply to the auth
provider as well as any service clients provided by this manager.
- Any other client parameter must be set via client_parameters.
+ Any other client parameter should be set via ClientsRegistry.
+
+ Client parameter used to be set via client_parameters, but this is
+ deprecated, and it is actually already not honoured
+ anymore: https://launchpad.net/bugs/1680915.
+
The list of available parameters is defined in the service clients
interfaces. For reference, most clients will accept 'region',
'service', 'endpoint_type', 'build_timeout' and 'build_interval', which
@@ -287,6 +301,10 @@
- Volume client for 'volume' accepts 'default_volume_size'
- Servers client from 'compute' accepts 'enable_instance_password'
+ If Tempest configuration is used, parameters will be loaded in the
+ Registry automatically for all service client (Tempest stable ones
+ and plugins).
+
Examples:
>>> identity_params = config.service_client_config('identity')
@@ -311,14 +329,6 @@
for the version. Values are dictionaries of parameters that are
going to be passed to all clients in the service client module.
- Examples:
-
- >>> params_service_x = {'param_name': 'param_value'}
- >>> client_parameters = { 'service_x': params_service_x }
-
- >>> params_service_y = config.service_client_config('service_y')
- >>> client_parameters['service_y'] = params_service_y
-
"""
self._registered_services = set([])
self.credentials = credentials
diff --git a/tempest/lib/services/volume/v2/transfers_client.py b/tempest/lib/services/volume/v2/transfers_client.py
index 6f21944..853948e 100644
--- a/tempest/lib/services/volume/v2/transfers_client.py
+++ b/tempest/lib/services/volume/v2/transfers_client.py
@@ -28,7 +28,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-transfer-v2
+ https://developer.openstack.org/api-ref/block-storage/v2/#create-volume-transfer
"""
post_body = json.dumps({'transfer': kwargs})
resp, body = self.post('os-volume-transfer', post_body)
@@ -49,7 +49,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-transfers-v2
+ https://developer.openstack.org/api-ref/block-storage/v2/#list-volume-transfers
"""
url = 'os-volume-transfer'
if params:
@@ -70,7 +70,7 @@
For a full list of available parameters, please refer to the official
API reference:
- http://developer.openstack.org/api-ref/block-storage/v2/#accept-volume-transfer-v2
+ https://developer.openstack.org/api-ref/block-storage/v2/#accept-volume-transfer
"""
url = 'os-volume-transfer/%s/accept' % transfer_id
post_body = json.dumps({'accept': kwargs})
diff --git a/tempest/test.py b/tempest/test.py
index 52994ac..052033d 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -45,6 +45,11 @@
version='Mitaka', removal_version='?')
+related_bug = debtcollector.moves.moved_function(
+ decorators.related_bug, 'related_bug', __name__,
+ version='Pike', removal_version='?')
+
+
def attr(**kwargs):
"""A decorator which applies the testtools attr decorator
@@ -82,10 +87,10 @@
exercised by a test case.
"""
def decorator(f):
- services = ['compute', 'image', 'baremetal', 'volume',
- 'network', 'identity', 'object_storage']
+ known_services = get_service_list()
+
for service in args:
- if service not in services:
+ if service not in known_services:
raise exceptions.InvalidServiceTag('%s is not a valid '
'service' % service)
attr(type=list(args))(f)
@@ -143,28 +148,6 @@
return False
-def related_bug(bug, status_code=None):
- """A decorator useful to know solutions from launchpad bug reports
-
- @param bug: The launchpad bug number causing the test
- @param status_code: The status code related to the bug report
- """
- def decorator(f):
- @functools.wraps(f)
- def wrapper(self, *func_args, **func_kwargs):
- try:
- return f(self, *func_args, **func_kwargs)
- except Exception as exc:
- exc_status_code = getattr(exc, 'status_code', None)
- if status_code is None or status_code == exc_status_code:
- LOG.error('Hints: This test was made for the bug %s. '
- 'The failure could be related to '
- 'https://launchpad.net/bugs/%s', bug, bug)
- raise exc
- return wrapper
- return decorator
-
-
def is_scheduler_filter_enabled(filter_name):
"""Check the list of enabled compute scheduler filters from config.
@@ -642,12 +625,24 @@
return fixed_network.get_tenant_network(
cred_provider, networks_client, CONF.compute.fixed_network_name)
- def assertEmpty(self, list, msg=None):
- if msg is None:
- msg = "list is not empty: %s" % list
- self.assertEqual(0, len(list), msg)
+ def assertEmpty(self, items, msg=None):
+ """Asserts whether a sequence or collection is empty
- def assertNotEmpty(self, list, msg=None):
+ :param items: sequence or collection to be tested
+ :param msg: message to be passed to the AssertionError
+ :raises AssertionError: when items is not empty
+ """
if msg is None:
- msg = "list is empty."
- self.assertGreater(len(list), 0, msg)
+ msg = "sequence or collection is not empty: %s" % items
+ self.assertEqual(0, len(items), msg)
+
+ def assertNotEmpty(self, items, msg=None):
+ """Asserts whether a sequence or collection is not empty
+
+ :param items: sequence or collection to be tested
+ :param msg: message to be passed to the AssertionError
+ :raises AssertionError: when items is empty
+ """
+ if msg is None:
+ msg = "sequence or collection is empty."
+ self.assertGreater(len(items), 0, msg)
diff --git a/tempest/tests/fake_config.py b/tempest/tests/fake_config.py
index 71a4c81..4e957a0 100644
--- a/tempest/tests/fake_config.py
+++ b/tempest/tests/fake_config.py
@@ -93,12 +93,6 @@
self.conf.set_default('ca_certificates_file', '/fake/certificates',
group='identity')
self.conf.set_default('region', 'fake_region', 'identity')
- # Identity endpoints
- self.conf.set_default('v3_endpoint_type', 'fake_v3_uri', 'identity')
- self.conf.set_default('v2_public_endpoint_type', 'fake_v2_public_uri',
- 'identity')
- self.conf.set_default('v2_admin_endpoint_type', 'fake_v2_admin_uri',
- 'identity')
# Compute default values
self.conf.set_default('build_interval', 88, group='compute')
self.conf.set_default('build_timeout', 8, group='compute')
diff --git a/tempest/tests/lib/test_decorators.py b/tempest/tests/lib/test_decorators.py
index f3a4e9c..ea38e08 100644
--- a/tempest/tests/lib/test_decorators.py
+++ b/tempest/tests/lib/test_decorators.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import mock
import testtools
from tempest.lib import base as test
@@ -123,3 +124,33 @@
def test_no_skip_for_attr_exist_and_true(self):
self._test_skip_unless_attr('expected_attr', expected_to_skip=False)
+
+
+class TestRelatedBugDecorator(base.TestCase):
+ def test_relatedbug_when_no_exception(self):
+ f = mock.Mock()
+ sentinel = object()
+
+ @decorators.related_bug(bug="1234", status_code=500)
+ def test_foo(self):
+ f(self)
+
+ test_foo(sentinel)
+ f.assert_called_once_with(sentinel)
+
+ def test_relatedbug_when_exception(self):
+ class MyException(Exception):
+ def __init__(self, status_code):
+ self.status_code = status_code
+
+ def f(self):
+ raise MyException(status_code=500)
+
+ @decorators.related_bug(bug="1234", status_code=500)
+ def test_foo(self):
+ f(self)
+
+ with mock.patch.object(decorators.LOG, 'error') as m_error:
+ self.assertRaises(MyException, test_foo, object())
+
+ m_error.assert_called_once_with(mock.ANY, '1234', '1234')
diff --git a/tools/generate-tempest-plugins-list.sh b/tools/generate-tempest-plugins-list.sh
index ecff508..e6aad86 100755
--- a/tools/generate-tempest-plugins-list.sh
+++ b/tools/generate-tempest-plugins-list.sh
@@ -1,4 +1,4 @@
-#!/bin/bash -ex
+#!/usr/bin/env bash
# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
#
@@ -38,6 +38,8 @@
# current working directory, it will be prepended or appended to
# the generated reStructuredText plugins table respectively.
+set -ex
+
(
declare -A plugins
diff --git a/tools/with_venv.sh b/tools/with_venv.sh
index 165c883..408b5f1 100755
--- a/tools/with_venv.sh
+++ b/tools/with_venv.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
TOOLS_PATH=${TOOLS_PATH:-$(dirname $0)/../}
VENV_PATH=${VENV_PATH:-${TOOLS_PATH}}
VENV_DIR=${VENV_DIR:-/.venv}