Merge "Remove unnecessary assertIsNotNone check"
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 4e7a72d..0cfdf34 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -25,8 +25,6 @@
 import os
 import subprocess
 
-import openstackdocstheme
-
 # Build the plugin registry
 def build_plugin_registry(app):
     root_dir = os.path.dirname(
diff --git a/tempest/releasenotes/notes/add-return-value-to-retype-volume-a401aa619aaa2457.yaml b/releasenotes/notes/add-return-value-to-retype-volume-a401aa619aaa2457.yaml
similarity index 100%
rename from tempest/releasenotes/notes/add-return-value-to-retype-volume-a401aa619aaa2457.yaml
rename to releasenotes/notes/add-return-value-to-retype-volume-a401aa619aaa2457.yaml
diff --git a/releasenotes/notes/plugin-client-registration-enhancements-e09131742391225b.yaml b/releasenotes/notes/plugin-client-registration-enhancements-e09131742391225b.yaml
new file mode 100644
index 0000000..b6391b6
--- /dev/null
+++ b/releasenotes/notes/plugin-client-registration-enhancements-e09131742391225b.yaml
@@ -0,0 +1,12 @@
+---
+features:
+  - |
+    When registering service clients from installed plugins, all registrations
+    are now processed, even if one or more fails. All exceptions encountered
+    during the registration process are recorded.  If at least one exception
+    was encountered, the registration process fails and all interim errors are
+    reported.
+  - |
+    The __repr__ method is now implemented for the base `tempest.Exception`
+    class, its implementation is identical to __str__: it reports the error
+    message merged with input parameters.
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index cd09177..f41c3fb 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -166,8 +166,7 @@
                .format(image_ref, rebuilt_server['image']['id']))
         self.assertEqual(image_ref, rebuilt_server['image']['id'], msg)
 
-    @decorators.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
-    def test_rebuild_server(self):
+    def _test_rebuild_server(self):
         # Get the IPs the server has before rebuilding it
         original_addresses = (self.client.show_server(self.server_id)['server']
                               ['addresses'])
@@ -218,6 +217,10 @@
                 servers_client=self.client)
             linux_client.validate_authentication()
 
+    @decorators.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
+    def test_rebuild_server(self):
+        self._test_rebuild_server()
+
     @decorators.idempotent_id('30449a88-5aff-4f9b-9866-6ee9b17f906d')
     def test_rebuild_server_in_stop_state(self):
         # The server in stop state  should be rebuilt using the provided
@@ -260,7 +263,7 @@
         self.attach_volume(server, volume)
 
         # run general rebuild test
-        self.test_rebuild_server()
+        self._test_rebuild_server()
 
         # make sure the volume is attached to the instance after rebuild
         vol_after_rebuild = self.volumes_client.show_volume(volume['id'])
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 6d42b2a..ec904e6 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -33,7 +33,6 @@
             role_name = data_utils.rand_name(name='role')
             role = cls.roles_client.create_role(name=role_name)['role']
             cls.roles.append(role)
-        cls.fetched_role_ids = list()
         u_name = data_utils.rand_name('user')
         u_desc = '%s description' % u_name
         u_email = '%s@testmail.tm' % u_name
@@ -67,10 +66,6 @@
             cls.roles_client.delete_role(role['id'])
         super(RolesV3TestJSON, cls).resource_cleanup()
 
-    def _list_assertions(self, body, fetched_role_ids, role_id):
-        self.assertEqual(len(body), 1)
-        self.assertIn(role_id, fetched_role_ids)
-
     @decorators.attr(type='smoke')
     @decorators.idempotent_id('18afc6c0-46cf-4911-824e-9989cc056c3a')
     def test_role_create_update_show_list(self):
@@ -104,11 +99,8 @@
         roles = self.roles_client.list_user_roles_on_project(
             self.project['id'], self.user_body['id'])['roles']
 
-        for i in roles:
-            self.fetched_role_ids.append(i['id'])
-
-        self._list_assertions(roles, self.fetched_role_ids,
-                              self.role['id'])
+        self.assertEqual(1, len(roles))
+        self.assertEqual(self.role['id'], roles[0]['id'])
 
         self.roles_client.check_user_role_existence_on_project(
             self.project['id'], self.user_body['id'], self.role['id'])
@@ -124,11 +116,8 @@
         roles = self.roles_client.list_user_roles_on_domain(
             self.domain['id'], self.user_body['id'])['roles']
 
-        for i in roles:
-            self.fetched_role_ids.append(i['id'])
-
-        self._list_assertions(roles, self.fetched_role_ids,
-                              self.role['id'])
+        self.assertEqual(1, len(roles))
+        self.assertEqual(self.role['id'], roles[0]['id'])
 
         self.roles_client.check_user_role_existence_on_domain(
             self.domain['id'], self.user_body['id'], self.role['id'])
@@ -145,11 +134,9 @@
         roles = self.roles_client.list_group_roles_on_project(
             self.project['id'], self.group_body['id'])['roles']
 
-        for i in roles:
-            self.fetched_role_ids.append(i['id'])
+        self.assertEqual(1, len(roles))
+        self.assertEqual(self.role['id'], roles[0]['id'])
 
-        self._list_assertions(roles, self.fetched_role_ids,
-                              self.role['id'])
         # Add user to group, and insure user has role on project
         self.groups_client.add_group_user(self.group_body['id'],
                                           self.user_body['id'])
@@ -179,11 +166,8 @@
         roles = self.roles_client.list_group_roles_on_domain(
             self.domain['id'], self.group_body['id'])['roles']
 
-        for i in roles:
-            self.fetched_role_ids.append(i['id'])
-
-        self._list_assertions(roles, self.fetched_role_ids,
-                              self.role['id'])
+        self.assertEqual(1, len(roles))
+        self.assertEqual(self.role['id'], roles[0]['id'])
 
         self.roles_client.check_role_from_group_on_domain_existence(
             self.domain['id'], self.group_body['id'], self.role['id'])
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index 5dc1a3e..cecb8e3 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -265,8 +265,6 @@
     return credentials
 
 
-# Wrapper around auth.get_credentials to use the configured identity version
-# if none is specified
 def get_credentials(fill_in=True, identity_version=None, **kwargs):
     """Get credentials from dict based on config