Merge "Drop validation resources dependency from CONF"
diff --git a/HACKING.rst b/HACKING.rst
index e5f45ac..446d865 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -24,6 +24,7 @@
- [T114] Check that tempest.lib does not use tempest config
- [T115] Check that admin tests should exist under admin path
- [N322] Method's default argument shouldn't be mutable
+- [T116] Unsupported 'message' Exception attribute in PY3
Test Data/Configuration
-----------------------
diff --git a/doc/source/library/credential_providers.rst b/doc/source/library/credential_providers.rst
index 7e831cc..f4eb37d 100644
--- a/doc/source/library/credential_providers.rst
+++ b/doc/source/library/credential_providers.rst
@@ -6,7 +6,7 @@
These library interfaces are used to deal with allocating credentials on demand
either dynamically by calling keystone to allocate new credentials, or from
a list of preprovisioned credentials. These 2 modules are implementations of
-the same abstract credential providers class and can be used interchangably.
+the same abstract credential providers class and can be used interchangeably.
However, each implementation has some additional parameters that are used to
influence the behavior of the modules. The API reference at the bottom of this
doc shows the interface definitions for both modules, however that may be a bit
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index b3af92f..77ef9ed 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -28,6 +28,7 @@
* tempest.lib.*
* tempest.config
* tempest.test_discover.plugins
+* tempest.common.credentials_factory
If there is an interface from tempest that you need to rely on in your plugin
which is not listed above, it likely needs to be migrated to tempest.lib. In
diff --git a/releasenotes/notes/add-update-group-tempest-tests-72f8ec19b2809849.yaml b/releasenotes/notes/add-update-group-tempest-tests-72f8ec19b2809849.yaml
new file mode 100644
index 0000000..23c30af
--- /dev/null
+++ b/releasenotes/notes/add-update-group-tempest-tests-72f8ec19b2809849.yaml
@@ -0,0 +1,4 @@
+---
+features:
+ - |
+ Add update_group to groups_client in the volume service library.
diff --git a/releasenotes/notes/credentials-factory-stable-c8037bd9ae642482.yaml b/releasenotes/notes/credentials-factory-stable-c8037bd9ae642482.yaml
new file mode 100644
index 0000000..6faa536
--- /dev/null
+++ b/releasenotes/notes/credentials-factory-stable-c8037bd9ae642482.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ The credentials_factory.py module is now marked as stable for Tempest
+ plugins. It provides helpers that can be used by Tempest plugins to
+ obtain test credentials for their test cases in a format that honors the
+ Tempest configuration in use.
+ Credentials may be provisioned on the fly during the test run, or they
+ can be setup in advance and fed to test via a YAML file; they can be
+ setup for identity v2 or identity v3.
diff --git a/tempest/api/compute/admin/test_agents.py b/tempest/api/compute/admin/test_agents.py
index 69cbfb5..0901374 100644
--- a/tempest/api/compute/admin/test_agents.py
+++ b/tempest/api/compute/admin/test_agents.py
@@ -86,7 +86,7 @@
body = self.client.create_agent(**self.params_agent)['agent']
self.addCleanup(self.client.delete_agent, body['agent_id'])
agents = self.client.list_agents()['agents']
- self.assertNotEmpty(agents, 'Cannot get any agents.(%s)' % agents)
+ self.assertNotEmpty(agents, 'Cannot get any agents.')
self.assertIn(body['agent_id'], map(lambda x: x['agent_id'], agents))
@decorators.idempotent_id('eabadde4-3cd7-4ec4-a4b5-5a936d2d4408')
@@ -104,7 +104,7 @@
agent_id_xen = agent_xen['agent_id']
agents = (self.client.list_agents(hypervisor=agent_xen['hypervisor'])
['agents'])
- self.assertNotEmpty(agents, 'Cannot get any agents.(%s)' % agents)
+ self.assertNotEmpty(agents, 'Cannot get any agents.')
self.assertIn(agent_id_xen, map(lambda x: x['agent_id'], agents))
self.assertNotIn(body['agent_id'], map(lambda x: x['agent_id'],
agents))
diff --git a/tempest/api/compute/admin/test_create_server.py b/tempest/api/compute/admin/test_create_server.py
index 3449aba..66bedd9 100644
--- a/tempest/api/compute/admin/test_create_server.py
+++ b/tempest/api/compute/admin/test_create_server.py
@@ -25,8 +25,6 @@
class ServersWithSpecificFlavorTestJSON(base.BaseV2ComputeAdminTest):
- disk_config = 'AUTO'
-
@classmethod
def setup_credentials(cls):
cls.prepare_instance_network()
diff --git a/tempest/api/compute/admin/test_hypervisor.py b/tempest/api/compute/admin/test_hypervisor.py
index 0db802c..404fd94 100644
--- a/tempest/api/compute/admin/test_hypervisor.py
+++ b/tempest/api/compute/admin/test_hypervisor.py
@@ -30,26 +30,23 @@
hypers = self.client.list_hypervisors()['hypervisors']
return hypers
- def assertHypervisors(self, hypers):
- self.assertNotEmpty(hypers, "No hypervisors found: %s" % hypers)
-
@decorators.idempotent_id('7f0ceacd-c64d-4e96-b8ee-d02943142cc5')
def test_get_hypervisor_list(self):
# List of hypervisor and available hypervisors hostname
hypers = self._list_hypervisors()
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
@decorators.idempotent_id('1e7fdac2-b672-4ad1-97a4-bad0e3030118')
def test_get_hypervisor_list_details(self):
# Display the details of the all hypervisor
hypers = self.client.list_hypervisors(detail=True)['hypervisors']
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
@decorators.idempotent_id('94ff9eae-a183-428e-9cdb-79fde71211cc')
def test_get_hypervisor_show_details(self):
# Display the details of the specified hypervisor
hypers = self._list_hypervisors()
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
details = self.client.show_hypervisor(hypers[0]['id'])['hypervisor']
self.assertNotEmpty(details)
@@ -60,7 +57,7 @@
def test_get_hypervisor_show_servers(self):
# Show instances about the specific hypervisors
hypers = self._list_hypervisors()
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
hostname = hypers[0]['hypervisor_hostname']
hypervisors = (self.client.list_servers_on_hypervisor(hostname)
@@ -116,7 +113,7 @@
@decorators.idempotent_id('d7e1805b-3b14-4a3b-b6fd-50ec6d9f361f')
def test_search_hypervisor(self):
hypers = self._list_hypervisors()
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
hypers = self.client.search_hypervisor(
hypers[0]['hypervisor_hostname'])['hypervisors']
- self.assertHypervisors(hypers)
+ self.assertNotEmpty(hypers, "No hypervisors found.")
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index d9a7800..3f06c4e 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -13,9 +13,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.common import compute
from tempest.common import waiters
-from tempest.lib.common import fixed_network
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
@@ -126,26 +124,17 @@
@decorators.idempotent_id('86c7a8f7-50cf-43a9-9bac-5b985317134f')
def test_list_servers_filter_by_exist_host(self):
# Filter the list of servers by existent host
- name = data_utils.rand_name(self.__class__.__name__ + '-server')
- network = self.get_tenant_network()
- network_kwargs = fixed_network.set_networks_kwarg(network)
- # We need to create the server as an admin, so we can't use
- # self.create_test_server() here as this method creates the server
- # in the "primary" (i.e non-admin) tenant.
- test_server, _ = compute.create_test_server(
- self.os_admin, wait_until="ACTIVE", name=name, **network_kwargs)
- self.addCleanup(self.client.delete_server, test_server['id'])
- server = self.client.show_server(test_server['id'])['server']
- self.assertEqual(server['status'], 'ACTIVE')
+ server = self.client.show_server(self.s1_id)['server']
hostname = server['OS-EXT-SRV-ATTR:host']
- params = {'host': hostname}
- body = self.client.list_servers(**params)
- servers = body['servers']
- nonexistent_params = {'host': 'nonexistent_host'}
+ params = {'host': hostname, 'all_tenants': '1'}
+ servers = self.client.list_servers(**params)['servers']
+ self.assertIn(server['id'], map(lambda x: x['id'], servers))
+
+ nonexistent_params = {'host': 'nonexistent_host',
+ 'all_tenants': '1'}
nonexistent_body = self.client.list_servers(**nonexistent_params)
nonexistent_servers = nonexistent_body['servers']
- self.assertIn(test_server['id'], map(lambda x: x['id'], servers))
- self.assertNotIn(test_server['id'],
+ self.assertNotIn(server['id'],
map(lambda x: x['id'], nonexistent_servers))
@decorators.idempotent_id('ee8ae470-db70-474d-b752-690b7892cab1')
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index feabe35..746f83a 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -97,8 +97,8 @@
cls.security_group_default_rules_client = (
cls.os_primary.security_group_default_rules_client)
cls.versions_client = cls.os_primary.compute_versions_client
-
- cls.volumes_client = cls.os_primary.volumes_v2_client
+ if CONF.service_available.cinder:
+ cls.volumes_client = cls.os_primary.volumes_client_latest
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 65d5042..bfde847 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -15,6 +15,8 @@
import time
+import six
+
from tempest.api.compute import base
from tempest.common import compute
from tempest.common.utils import net_utils
@@ -195,7 +197,7 @@
except lib_exc.BadRequest as e:
msg = ('Multiple possible networks found, use a Network ID to be '
'more specific.')
- if not CONF.compute.fixed_network_name and e.message == msg:
+ if not CONF.compute.fixed_network_name and six.text_type(e) == msg:
raise
else:
ifs.append(iface)
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index a4ed8e1..14aecfd 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -262,7 +262,7 @@
# so as to ensure only one server is returned.
ip_list = {}
self.s1 = self.client.show_server(self.s1['id'])['server']
- # Get first ip address inspite of v4 or v6
+ # Get first ip address in spite of v4 or v6
ip_addr = self.s1['addresses'][self.fixed_network_name][0]['addr']
ip_list[ip_addr] = self.s1['id']
diff --git a/tempest/api/compute/servers/test_novnc.py b/tempest/api/compute/servers/test_novnc.py
index 90b0665..d9581e3 100644
--- a/tempest/api/compute/servers/test_novnc.py
+++ b/tempest/api/compute/servers/test_novnc.py
@@ -166,7 +166,7 @@
self._validate_novnc_html(body['url'])
# Do the WebSockify HTTP Request to novncproxy to do the RFB connection
self._websocket = compute.create_websocket(body['url'])
- # Validate that we succesfully connected and upgraded to Web Sockets
+ # Validate that we successfully connected and upgraded to Web Sockets
self._validate_websocket_upgrade()
# Validate the RFB Negotiation to determine if a valid VNC session
self._validate_rfb_negotiation()
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index f41c3fb..d1d29af 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -33,8 +33,6 @@
class ServerActionsTestJSON(base.BaseV2ComputeTest):
- run_ssh = CONF.validation.run_validation
-
def setUp(self):
# NOTE(afazekas): Normally we use the same server with all test cases,
# but if it has an issue, we build a new one
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
index 1a0b851..56f7d32 100644
--- a/tempest/api/identity/admin/v3/test_domains_negative.py
+++ b/tempest/api/identity/admin/v3/test_domains_negative.py
@@ -20,7 +20,6 @@
class DomainsNegativeTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
@decorators.attr(type=['negative', 'gate'])
@decorators.idempotent_id('1f3fbff5-4e44-400d-9ca1-d953f05f609b')
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 409d4f8..3813568 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -41,31 +41,26 @@
email=u_email, enabled=False)['user']
# Delete the User at the end of this method
self.addCleanup(self.users_client.delete_user, user['id'])
+
# Creating second project for updation
project = self.setup_test_project()
+
# Updating user details with new values
- u_name2 = data_utils.rand_name('user2')
- u_email2 = u_name2 + '@testmail.tm'
- u_description2 = u_name2 + ' description'
- update_user = self.users_client.update_user(
- user['id'], name=u_name2, description=u_description2,
- project_id=project['id'],
- email=u_email2, enabled=False)['user']
- self.assertEqual(u_name2, update_user['name'])
- self.assertEqual(u_description2, update_user['description'])
- self.assertEqual(project['id'],
- update_user['project_id'])
- self.assertEqual(u_email2, update_user['email'])
- self.assertEqual(False, update_user['enabled'])
- # GET by id after updation
+ update_kwargs = {'name': data_utils.rand_name('user2'),
+ 'description': data_utils.rand_name('desc2'),
+ 'project_id': project['id'],
+ 'email': 'user2@testmail.tm',
+ 'enabled': False}
+ updated_user = self.users_client.update_user(
+ user['id'], **update_kwargs)['user']
+ for field in update_kwargs:
+ self.assertEqual(update_kwargs[field], updated_user[field])
+
+ # GET by id after updating
new_user_get = self.users_client.show_user(user['id'])['user']
# Assert response body of GET after updation
- self.assertEqual(u_name2, new_user_get['name'])
- self.assertEqual(u_description2, new_user_get['description'])
- self.assertEqual(project['id'],
- new_user_get['project_id'])
- self.assertEqual(u_email2, new_user_get['email'])
- self.assertEqual(False, new_user_get['enabled'])
+ for field in update_kwargs:
+ self.assertEqual(update_kwargs[field], new_user_get[field])
@decorators.idempotent_id('2d223a0e-e457-4a70-9fb1-febe027a0ff9')
def test_update_user_password(self):
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index b29a77f..556ca2f 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -973,7 +973,7 @@
@classmethod
def setup_clients(cls):
super(PublicObjectTest, cls).setup_clients()
- cls.identity_client_alt = cls.os_alt.identity_client
+ cls.object_client_alt = cls.os_alt.object_client
def setUp(self):
super(PublicObjectTest, self).setUp()
@@ -1047,7 +1047,7 @@
self.assertEqual(resp['x-container-read'], '.r:*,.rlistings')
# get auth token of alternative user
- alt_auth_data = self.identity_client_alt.auth_provider.auth_data
+ alt_auth_data = self.object_client_alt.auth_provider.auth_data
self.object_client.auth_provider.set_alt_auth_data(
request_part='headers',
auth_data=alt_auth_data
diff --git a/tempest/api/volume/admin/test_groups.py b/tempest/api/volume/admin/test_groups.py
index 5f01166..baea37b 100644
--- a/tempest/api/volume/admin/test_groups.py
+++ b/tempest/api/volume/admin/test_groups.py
@@ -258,3 +258,65 @@
self.volumes_client, vol['id'], 'available')
waiters.wait_for_volume_resource_status(
self.groups_client, grp2['id'], 'available')
+
+ @decorators.idempotent_id('4a8a6fd2-8b3b-4641-8f54-6a6f99320006')
+ def test_group_update(self):
+ # Create volume type
+ volume_type = self.create_volume_type()
+
+ # Create group type
+ group_type = self.create_group_type()
+
+ # Create Group
+ grp = self._create_group(group_type, volume_type)
+
+ # Create volumes
+ grp_vols = []
+ for _ in range(2):
+ vol = self.create_volume(volume_type=volume_type['id'],
+ group_id=grp['id'])
+ grp_vols.append(vol)
+ vol2 = grp_vols[1]
+
+ # Remove a volume from group and update name and description
+ new_grp_name = 'new_group'
+ new_desc = 'This is a new group'
+ grp_params = {'name': new_grp_name,
+ 'description': new_desc,
+ 'remove_volumes': vol2['id']}
+ self.groups_client.update_group(grp['id'], **grp_params)
+
+ # Wait for group status to become available
+ waiters.wait_for_volume_resource_status(
+ self.groups_client, grp['id'], 'available')
+
+ # Get the updated Group
+ grp = self.groups_client.show_group(grp['id'])['group']
+ self.assertEqual(new_grp_name, grp['name'])
+ self.assertEqual(new_desc, grp['description'])
+
+ # Get volumes in the group
+ vols = self.volumes_client.list_volumes(
+ detail=True)['volumes']
+ grp_vols = []
+ for vol in vols:
+ if vol['group_id'] == grp['id']:
+ grp_vols.append(vol)
+ self.assertEqual(1, len(grp_vols))
+
+ # Add a volume to the group
+ grp_params = {'add_volumes': vol2['id']}
+ self.groups_client.update_group(grp['id'], **grp_params)
+
+ # Wait for group status to become available
+ waiters.wait_for_volume_resource_status(
+ self.groups_client, grp['id'], 'available')
+
+ # Get volumes in the group
+ vols = self.volumes_client.list_volumes(
+ detail=True)['volumes']
+ grp_vols = []
+ for vol in vols:
+ if vol['group_id'] == grp['id']:
+ grp_vols.append(vol)
+ self.assertEqual(2, len(grp_vols))
diff --git a/tempest/clients.py b/tempest/clients.py
index d7a52d1..e617c3c 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -263,6 +263,7 @@
# Set default client for users that don't need explicit version
self.volumes_client_latest = self.volumes_v2_client
+ self.snapshots_client_latest = self.snapshots_v2_client
if CONF.volume_feature_enabled.api_v3:
self.backups_v3_client = self.volume_v3.BackupsClient()
@@ -277,6 +278,7 @@
# Set default client for users that don't need explicit version
self.volumes_client_latest = self.volumes_v3_client
+ self.snapshots_client_latest = self.snapshots_v3_client
def _set_object_storage_clients(self):
# NOTE(andreaf) Load configuration from config. Once object storage
diff --git a/tempest/cmd/subunit_describe_calls.py b/tempest/cmd/subunit_describe_calls.py
index 8ee3055..f9ebe20 100644
--- a/tempest/cmd/subunit_describe_calls.py
+++ b/tempest/cmd/subunit_describe_calls.py
@@ -102,8 +102,8 @@
response_re = re.compile(r'.* Response - Headers: (?P<headers>.*)')
body_re = re.compile(r'.*Body: (?P<body>.*)')
- # Based on mitaka defaults:
- # http://docs.openstack.org/mitaka/config-reference/
+ # Based on newton defaults:
+ # http://docs.openstack.org/newton/config-reference/
# firewalls-default-ports.html
services = {
"8776": "Block Storage",
@@ -122,7 +122,8 @@
"873": "rsync",
"3260": "iSCSI",
"3306": "MySQL",
- "5672": "AMQP"}
+ "5672": "AMQP",
+ "8082": "murano"}
def __init__(self, services=None):
super(UrlParser, self).__init__()
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index cecb8e3..a340531 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -44,6 +44,9 @@
identity_uri = CONF.identity.uri_v3
elif identity_version == 'v2':
identity_uri = CONF.identity.uri
+ else:
+ raise exceptions.InvalidIdentityVersion(
+ identity_version=identity_version)
return {
'identity_version': identity_version,
'identity_uri': identity_uri,
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 99a628e..52ccfa9 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -70,7 +70,7 @@
if selected:
return "\n".join(selected)
else:
- msg = "'TYPE' column is requred but the output doesn't have it: "
+ msg = "'TYPE' column is required but the output doesn't have it: "
raise tempest.lib.exceptions.TempestException(msg + output)
def get_boot_time(self):
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index 067da09..aae685c 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -33,6 +33,7 @@
METHOD_GET_RESOURCE = re.compile(r"^\s*def (list|show)\_.+")
METHOD_DELETE_RESOURCE = re.compile(r"^\s*def delete_.+")
CLASS = re.compile(r"^class .+")
+EX_ATTRIBUTE = re.compile(r'(\s+|\()(e|ex|exc|exception).message(\s+|\))')
def import_no_clients_in_api_and_scenario_tests(physical_line, filename):
@@ -294,6 +295,17 @@
yield(0, msg)
+def unsupported_exception_attribute_PY3(logical_line):
+ """Check Unsupported 'message' exception attribute in PY3
+
+ T116
+ """
+ result = EX_ATTRIBUTE.search(logical_line)
+ msg = ("[T116] Unsupported 'message' Exception attribute in PY3")
+ if result:
+ yield(0, msg)
+
+
def factory(register):
register(import_no_clients_in_api_and_scenario_tests)
register(scenario_tests_need_service_tags)
@@ -309,3 +321,4 @@
register(dont_use_config_in_tempest_lib)
register(use_rand_uuid_instead_of_uuid4)
register(dont_put_admin_tests_on_nonadmin_path)
+ register(unsupported_exception_attribute_PY3)
diff --git a/tempest/lib/services/volume/v3/groups_client.py b/tempest/lib/services/volume/v3/groups_client.py
index e261e8e..b463fdf 100644
--- a/tempest/lib/services/volume/v3/groups_client.py
+++ b/tempest/lib/services/volume/v3/groups_client.py
@@ -97,6 +97,18 @@
self.expected_success(202, resp.status)
return rest_client.ResponseBody(resp, body)
+ def update_group(self, group_id, **kwargs):
+ """Updates the specified group.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://developer.openstack.org/api-ref/block-storage/v3/#update-group
+ """
+ put_body = json.dumps({'group': kwargs})
+ resp, body = self.put('groups/%s' % group_id, put_body)
+ self.expected_success(202, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
def is_resource_deleted(self, id):
try:
self.show_group(id)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 9b8c7a0..2843222 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -79,8 +79,10 @@
cls.security_groups_client = cls.os_primary.security_groups_client
cls.security_group_rules_client = (
cls.os_primary.security_group_rules_client)
- cls.volumes_client = cls.os_primary.volumes_v2_client
- cls.snapshots_client = cls.os_primary.snapshots_v2_client
+ # Use the latest available volume clients
+ if CONF.service_available.cinder:
+ cls.volumes_client = cls.os_primary.volumes_client_latest
+ cls.snapshots_client = cls.os_primary.snapshots_client_latest
# ## Test functions library
#
diff --git a/tempest/test.py b/tempest/test.py
index 18a51d7..47cbb5e 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -44,11 +44,6 @@
version='Mitaka', removal_version='?')
-related_bug = debtcollector.moves.moved_function(
- decorators.related_bug, 'related_bug', __name__,
- version='Pike', removal_version='?')
-
-
attr = debtcollector.moves.moved_function(
decorators.attr, 'attr', __name__,
version='Pike', removal_version='?')
diff --git a/tempest/tests/common/test_credentials_factory.py b/tempest/tests/common/test_credentials_factory.py
new file mode 100644
index 0000000..020818e
--- /dev/null
+++ b/tempest/tests/common/test_credentials_factory.py
@@ -0,0 +1,279 @@
+# Copyright 2017 IBM Corp.
+# 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.
+
+import mock
+from oslo_config import cfg
+import testtools
+
+from tempest.common import credentials_factory as cf
+from tempest import config
+from tempest.lib.common import dynamic_creds
+from tempest.lib.common import preprov_creds
+from tempest.lib import exceptions
+from tempest.tests import base
+from tempest.tests import fake_config
+from tempest.tests.lib import fake_credentials
+
+
+class TestCredentialsFactory(base.TestCase):
+
+ def setUp(self):
+ super(TestCredentialsFactory, self).setUp()
+ self.useFixture(fake_config.ConfigFixture())
+ self.patchobject(config, 'TempestConfigPrivate',
+ fake_config.FakePrivate)
+
+ def test_get_dynamic_provider_params_creds_v2(self):
+ expected_uri = 'EXPECTED_V2_URI'
+ cfg.CONF.set_default('uri', expected_uri, group='identity')
+ admin_creds = fake_credentials.FakeCredentials()
+ params = cf.get_dynamic_provider_params('v2', admin_creds=admin_creds)
+ expected_params = dict(identity_uri=expected_uri,
+ admin_creds=admin_creds)
+ for key in expected_params:
+ self.assertIn(key, params)
+ self.assertEqual(expected_params[key], params[key])
+
+ def test_get_dynamic_provider_params_creds_v3(self):
+ expected_uri = 'EXPECTED_V3_URI'
+ cfg.CONF.set_default('uri_v3', expected_uri, group='identity')
+ admin_creds = fake_credentials.FakeCredentials()
+ params = cf.get_dynamic_provider_params('v3', admin_creds=admin_creds)
+ expected_params = dict(identity_uri=expected_uri,
+ admin_creds=admin_creds)
+ for key in expected_params:
+ self.assertIn(key, params)
+ self.assertEqual(expected_params[key], params[key])
+
+ def test_get_dynamic_provider_params_creds_vx(self):
+ admin_creds = fake_credentials.FakeCredentials()
+ invalid_version = 'invalid_version_x'
+ with testtools.ExpectedException(
+ exc_type=exceptions.InvalidIdentityVersion,
+ value_re='Invalid version ' + invalid_version):
+ cf.get_dynamic_provider_params(invalid_version,
+ admin_creds=admin_creds)
+
+ def test_get_dynamic_provider_params_no_creds(self):
+ expected_identity_version = 'v3'
+ with mock.patch.object(
+ cf, 'get_configured_admin_credentials') as admin_creds_mock:
+ cf.get_dynamic_provider_params(expected_identity_version)
+ admin_creds_mock.assert_called_once_with(
+ fill_in=True, identity_version=expected_identity_version)
+
+ def test_get_preprov_provider_params_creds_v2(self):
+ expected_uri = 'EXPECTED_V2_URI'
+ cfg.CONF.set_default('uri', expected_uri, group='identity')
+ params = cf.get_preprov_provider_params('v2')
+ self.assertIn('identity_uri', params)
+ self.assertEqual(expected_uri, params['identity_uri'])
+
+ def test_get_preprov_provider_params_creds_v3(self):
+ expected_uri = 'EXPECTED_V3_URI'
+ cfg.CONF.set_default('uri_v3', expected_uri, group='identity')
+ params = cf.get_preprov_provider_params('v3')
+ self.assertIn('identity_uri', params)
+ self.assertEqual(expected_uri, params['identity_uri'])
+
+ def test_get_preprov_provider_params_creds_vx(self):
+ invalid_version = 'invalid_version_x'
+ with testtools.ExpectedException(
+ exc_type=exceptions.InvalidIdentityVersion,
+ value_re='Invalid version ' + invalid_version):
+ cf.get_dynamic_provider_params(invalid_version)
+
+ @mock.patch.object(dynamic_creds, 'DynamicCredentialProvider')
+ @mock.patch.object(cf, 'get_dynamic_provider_params')
+ def test_get_credentials_provider_dynamic(
+ self, mock_dynamic_provider_params,
+ mock_dynamic_credentials_provider_class):
+ cfg.CONF.set_default('use_dynamic_credentials', True, group='auth')
+ expected_params = {'foo': 'bar'}
+ mock_dynamic_provider_params.return_value = expected_params
+ expected_name = 'my_name'
+ expected_network_resources = {'network': 'resources'}
+ expected_identity_version = 'identity_version'
+ cf.get_credentials_provider(
+ expected_name,
+ network_resources=expected_network_resources,
+ force_tenant_isolation=False,
+ identity_version=expected_identity_version)
+ mock_dynamic_provider_params.assert_called_once_with(
+ expected_identity_version)
+ mock_dynamic_credentials_provider_class.assert_called_once_with(
+ name=expected_name, network_resources=expected_network_resources,
+ **expected_params)
+
+ @mock.patch.object(preprov_creds, 'PreProvisionedCredentialProvider')
+ @mock.patch.object(cf, 'get_preprov_provider_params')
+ def test_get_credentials_provider_preprov(
+ self, mock_preprov_provider_params,
+ mock_preprov_credentials_provider_class):
+ cfg.CONF.set_default('use_dynamic_credentials', False, group='auth')
+ cfg.CONF.set_default('test_accounts_file', '/some/file', group='auth')
+ expected_params = {'foo': 'bar'}
+ mock_preprov_provider_params.return_value = expected_params
+ expected_name = 'my_name'
+ expected_identity_version = 'identity_version'
+ cf.get_credentials_provider(
+ expected_name,
+ force_tenant_isolation=False,
+ identity_version=expected_identity_version)
+ mock_preprov_provider_params.assert_called_once_with(
+ expected_identity_version)
+ mock_preprov_credentials_provider_class.assert_called_once_with(
+ name=expected_name, **expected_params)
+
+ def test_get_credentials_provider_preprov_no_file(self):
+ cfg.CONF.set_default('use_dynamic_credentials', False, group='auth')
+ cfg.CONF.set_default('test_accounts_file', None, group='auth')
+ with testtools.ExpectedException(
+ exc_type=exceptions.InvalidConfiguration):
+ cf.get_credentials_provider(
+ 'some_name',
+ force_tenant_isolation=False,
+ identity_version='some_version')
+
+ @mock.patch.object(dynamic_creds, 'DynamicCredentialProvider')
+ @mock.patch.object(cf, 'get_dynamic_provider_params')
+ def test_get_credentials_provider_force_dynamic(
+ self, mock_dynamic_provider_params,
+ mock_dynamic_credentials_provider_class):
+ cfg.CONF.set_default('use_dynamic_credentials', False, group='auth')
+ expected_params = {'foo': 'bar'}
+ mock_dynamic_provider_params.return_value = expected_params
+ expected_name = 'my_name'
+ expected_network_resources = {'network': 'resources'}
+ expected_identity_version = 'identity_version'
+ cf.get_credentials_provider(
+ expected_name,
+ network_resources=expected_network_resources,
+ force_tenant_isolation=True,
+ identity_version=expected_identity_version)
+ mock_dynamic_provider_params.assert_called_once_with(
+ expected_identity_version)
+ mock_dynamic_credentials_provider_class.assert_called_once_with(
+ name=expected_name, network_resources=expected_network_resources,
+ **expected_params)
+
+ @mock.patch.object(cf, 'get_credentials')
+ def test_get_configured_admin_credentials(self, mock_get_credentials):
+ cfg.CONF.set_default('auth_version', 'v3', 'identity')
+ all_params = [('admin_username', 'username', 'my_name'),
+ ('admin_password', 'password', 'secret'),
+ ('admin_project_name', 'project_name', 'my_pname'),
+ ('admin_domain_name', 'domain_name', 'my_dname')]
+ expected_result = 'my_admin_credentials'
+ mock_get_credentials.return_value = expected_result
+ for config_item, _, value in all_params:
+ cfg.CONF.set_default(config_item, value, 'auth')
+ # Build the expected params
+ expected_params = dict(
+ [(field, value) for _, field, value in all_params])
+ expected_params.update(cf.DEFAULT_PARAMS)
+ admin_creds = cf.get_configured_admin_credentials()
+ mock_get_credentials.assert_called_once_with(
+ fill_in=True, identity_version='v3', **expected_params)
+ self.assertEqual(expected_result, admin_creds)
+
+ @mock.patch.object(cf, 'get_credentials')
+ def test_get_configured_admin_credentials_not_fill_valid(
+ self, mock_get_credentials):
+ cfg.CONF.set_default('auth_version', 'v2', 'identity')
+ all_params = [('admin_username', 'username', 'my_name'),
+ ('admin_password', 'password', 'secret'),
+ ('admin_project_name', 'project_name', 'my_pname'),
+ ('admin_domain_name', 'domain_name', 'my_dname')]
+ expected_result = mock.Mock()
+ expected_result.is_valid.return_value = True
+ mock_get_credentials.return_value = expected_result
+ for config_item, _, value in all_params:
+ cfg.CONF.set_default(config_item, value, 'auth')
+ # Build the expected params
+ expected_params = dict(
+ [(field, value) for _, field, value in all_params])
+ expected_params.update(cf.DEFAULT_PARAMS)
+ admin_creds = cf.get_configured_admin_credentials(
+ fill_in=False, identity_version='v3')
+ mock_get_credentials.assert_called_once_with(
+ fill_in=False, identity_version='v3', **expected_params)
+ self.assertEqual(expected_result, admin_creds)
+ expected_result.is_valid.assert_called_once()
+
+ @mock.patch.object(cf, 'get_credentials')
+ def test_get_configured_admin_credentials_not_fill_not_valid(
+ self, mock_get_credentials):
+ cfg.CONF.set_default('auth_version', 'v2', 'identity')
+ expected_result = mock.Mock()
+ expected_result.is_valid.return_value = False
+ mock_get_credentials.return_value = expected_result
+ with testtools.ExpectedException(exceptions.InvalidConfiguration,
+ value_re='.*\n.*identity version v2'):
+ cf.get_configured_admin_credentials(fill_in=False)
+
+ @mock.patch('tempest.lib.auth.get_credentials')
+ def test_get_credentials_v2(self, mock_auth_get_credentials):
+ expected_uri = 'V2_URI'
+ expected_result = 'my_creds'
+ mock_auth_get_credentials.return_value = expected_result
+ cfg.CONF.set_default('uri', expected_uri, 'identity')
+ params = {'foo': 'bar'}
+ expected_params = params.copy()
+ expected_params.update(cf.DEFAULT_PARAMS)
+ result = cf.get_credentials(identity_version='v2', **params)
+ self.assertEqual(expected_result, result)
+ mock_auth_get_credentials.assert_called_once_with(
+ expected_uri, fill_in=True, identity_version='v2',
+ **expected_params)
+
+ @mock.patch('tempest.lib.auth.get_credentials')
+ def test_get_credentials_v3_no_domain(self, mock_auth_get_credentials):
+ expected_uri = 'V3_URI'
+ expected_result = 'my_creds'
+ expected_domain = 'my_domain'
+ mock_auth_get_credentials.return_value = expected_result
+ cfg.CONF.set_default('uri_v3', expected_uri, 'identity')
+ cfg.CONF.set_default('default_credentials_domain_name',
+ expected_domain, 'auth')
+ params = {'foo': 'bar'}
+ expected_params = params.copy()
+ expected_params['domain_name'] = expected_domain
+ expected_params.update(cf.DEFAULT_PARAMS)
+ result = cf.get_credentials(fill_in=False, identity_version='v3',
+ **params)
+ self.assertEqual(expected_result, result)
+ mock_auth_get_credentials.assert_called_once_with(
+ expected_uri, fill_in=False, identity_version='v3',
+ **expected_params)
+
+ @mock.patch('tempest.lib.auth.get_credentials')
+ def test_get_credentials_v3_domain(self, mock_auth_get_credentials):
+ expected_uri = 'V3_URI'
+ expected_result = 'my_creds'
+ expected_domain = 'my_domain'
+ mock_auth_get_credentials.return_value = expected_result
+ cfg.CONF.set_default('uri_v3', expected_uri, 'identity')
+ cfg.CONF.set_default('default_credentials_domain_name',
+ expected_domain, 'auth')
+ params = {'foo': 'bar', 'user_domain_name': expected_domain}
+ expected_params = params.copy()
+ expected_params.update(cf.DEFAULT_PARAMS)
+ result = cf.get_credentials(fill_in=False, identity_version='v3',
+ **params)
+ self.assertEqual(expected_result, result)
+ mock_auth_get_credentials.assert_called_once_with(
+ expected_uri, fill_in=False, identity_version='v3',
+ **expected_params)
diff --git a/tempest/tests/lib/common/test_api_version_utils.py b/tempest/tests/lib/common/test_api_version_utils.py
index 6206379..c063556 100644
--- a/tempest/tests/lib/common/test_api_version_utils.py
+++ b/tempest/tests/lib/common/test_api_version_utils.py
@@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import six
import testtools
from tempest.lib.common import api_version_utils
@@ -30,7 +31,7 @@
cfg_max_version)
except testtools.TestCase.skipException as e:
if not expected_skip:
- raise testtools.TestCase.failureException(e.message)
+ raise testtools.TestCase.failureException(six.text_type(e))
def test_version_min_in_range(self):
self._test_version('2.2', '2.10', '2.1', '2.7')
diff --git a/tempest/tests/lib/services/volume/v3/test_groups_client.py b/tempest/tests/lib/services/volume/v3/test_groups_client.py
index 4d0d860..0884e5a 100644
--- a/tempest/tests/lib/services/volume/v3/test_groups_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_groups_client.py
@@ -44,6 +44,17 @@
}
}
+ FAKE_UPDATE_GROUP = {
+ "group": {
+ "name": "new-group",
+ "description": "New test group",
+ "add_volumes": "27d45037-ade3-4a87-b729-dba3293c06f3,"
+ "6e7cd916-d961-41cc-b3bd-0601ca0c701f",
+ "remove_volumes": "4d580519-6467-448e-95e9-5b25c94d83c7,"
+ "ea22464c-f095-4a87-a31f-c5d34e0c6fc9"
+ }
+ }
+
FAKE_INFO_GROUP = {
"group": {
"id": "0e701ab8-1bec-4b9f-b026-a7ba4af13578",
@@ -164,3 +175,12 @@
'tempest.lib.common.rest_client.RestClient.post',
self.FAKE_CREATE_GROUP_FROM_GROUP,
status=202)
+
+ def test_update_group(self):
+ self.check_service_client_function(
+ self.client.update_group,
+ 'tempest.lib.common.rest_client.RestClient.put',
+ {},
+ group_id='0e701ab8-1bec-4b9f-b026-a7ba4af13578',
+ status=202,
+ **self.FAKE_UPDATE_GROUP['group'])
diff --git a/tempest/tests/test_hacking.py b/tempest/tests/test_hacking.py
index f005c21..c04d933 100644
--- a/tempest/tests/test_hacking.py
+++ b/tempest/tests/test_hacking.py
@@ -180,3 +180,15 @@
'from oslo_config import cfg', './tempest/lib/decorators.py')))
self.assertTrue(list(checks.dont_use_config_in_tempest_lib(
'import tempest.config', './tempest/lib/common/rest_client.py')))
+
+ def test_unsupported_exception_attribute_PY3(self):
+ self.assertEqual(len(list(checks.unsupported_exception_attribute_PY3(
+ "raise TestCase.failureException(e.message)"))), 1)
+ self.assertEqual(len(list(checks.unsupported_exception_attribute_PY3(
+ "raise TestCase.failureException(ex.message)"))), 1)
+ self.assertEqual(len(list(checks.unsupported_exception_attribute_PY3(
+ "raise TestCase.failureException(exc.message)"))), 1)
+ self.assertEqual(len(list(checks.unsupported_exception_attribute_PY3(
+ "raise TestCase.failureException(exception.message)"))), 1)
+ self.assertEqual(len(list(checks.unsupported_exception_attribute_PY3(
+ "raise TestCase.failureException(ee.message)"))), 0)
diff --git a/tempest/tests/test_microversions.py b/tempest/tests/test_microversions.py
index 173accb..ee6db71 100644
--- a/tempest/tests/test_microversions.py
+++ b/tempest/tests/test_microversions.py
@@ -13,6 +13,7 @@
# under the License.
from oslo_config import cfg
+import six
import testtools
from tempest.api.compute import base as compute_base
@@ -74,7 +75,7 @@
self.assertRaises(testtools.TestCase.skipException,
test_class.skip_checks)
except testtools.TestCase.skipException as e:
- raise testtools.TestCase.failureException(e.message)
+ raise testtools.TestCase.failureException(six.text_type(e))
def test_config_version_none_none(self):
expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2]