Merge "Use base.create_image_from_server to create server snapshot"
diff --git a/README.rst b/README.rst
index 3d7c804..f44c503 100644
--- a/README.rst
+++ b/README.rst
@@ -4,7 +4,6 @@
 
 .. image:: http://governance.openstack.org/badges/tempest.svg
     :target: http://governance.openstack.org/reference/tags/index.html
-    :remote:
 
 .. Change things from this point on
 
diff --git a/releasenotes/notes/add-list-auth-project-client-5905076d914a3943.yaml b/releasenotes/notes/add-list-auth-project-client-5905076d914a3943.yaml
new file mode 100644
index 0000000..471f8f0
--- /dev/null
+++ b/releasenotes/notes/add-list-auth-project-client-5905076d914a3943.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Add the list auth projects API to the identity client library. This feature
+    enables the possibility to list projects that are available to be scoped
+    to based on the X-Auth-Token provided in the request.
diff --git a/releasenotes/notes/add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml b/releasenotes/notes/add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml
new file mode 100644
index 0000000..06f4fcd
--- /dev/null
+++ b/releasenotes/notes/add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Interface show_quota_set of compute quotas_client has been extended to include the
+    argument "detail", which allows for detailed quota set information for a project to be
+    retrieved, if set to True.
diff --git a/releasenotes/notes/deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml b/releasenotes/notes/deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml
new file mode 100644
index 0000000..788bc95
--- /dev/null
+++ b/releasenotes/notes/deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml
@@ -0,0 +1,10 @@
+---
+deprecations:
+  - |
+    Glance v1 APIs are deprecated and v2 are current.
+    Tempest should tests only v2 APIs.
+    Below API version selection config options
+    for glance have been deprecated and will be removed in future.
+
+    * CONF.image_feature_enabled.api_v2
+    * CONF.image_feature_enabled.api_v1
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 3ce42be..ceac56b 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -64,3 +64,35 @@
                                               wait_for_server=False)
         self.addCleanup(self.client.delete_image, image['id'])
         self.assertEqual(snapshot_name, image['name'])
+
+    @decorators.idempotent_id('71bcb732-0261-11e7-9086-fa163e4fa634')
+    def test_create_image_from_paused_server(self):
+        server = self.create_test_server(wait_until='ACTIVE')
+        self.servers_client.pause_server(server['id'])
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'PAUSED')
+        self.addCleanup(self.servers_client.delete_server, server['id'])
+
+        snapshot_name = data_utils.rand_name('test-snap')
+        image = self.create_image_from_server(server['id'],
+                                              name=snapshot_name,
+                                              wait_until='ACTIVE',
+                                              wait_for_server=False)
+        self.addCleanup(self.client.delete_image, image['id'])
+        self.assertEqual(snapshot_name, image['name'])
+
+    @decorators.idempotent_id('8ca07fec-0262-11e7-907e-fa163e4fa634')
+    def test_create_image_from_suspended_server(self):
+        server = self.create_test_server(wait_until='ACTIVE')
+        self.servers_client.suspend_server(server['id'])
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'SUSPENDED')
+        self.addCleanup(self.servers_client.delete_server, server['id'])
+
+        snapshot_name = data_utils.rand_name('test-snap')
+        image = self.create_image_from_server(server['id'],
+                                              name=snapshot_name,
+                                              wait_until='ACTIVE',
+                                              wait_for_server=False)
+        self.addCleanup(self.client.delete_image, image['id'])
+        self.assertEqual(snapshot_name, image['name'])
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index 0ad2df8..9d83ee1 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -62,8 +62,8 @@
             self.assertIn(quota, quota_set.keys())
 
         # get the quota set using user id
-        quota_set = self.client.show_quota_set(self.tenant_id,
-                                               self.user_id)['quota_set']
+        quota_set = self.client.show_quota_set(
+            self.tenant_id, user_id=self.user_id)['quota_set']
         self.assertEqual(quota_set['id'], self.tenant_id)
         for quota in expected_quota_set:
             self.assertIn(quota, quota_set.keys())
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index ed4d31a..fabb91c 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -16,10 +16,13 @@
 import six
 
 from tempest.api.identity import base
+from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 
+CONF = config.CONF
+
 
 class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
 
@@ -150,3 +153,34 @@
                          token_auth['token']['project']['id'])
         self.assertEqual(project2['name'],
                          token_auth['token']['project']['name'])
+
+    @decorators.idempotent_id('08ed85ce-2ba8-4864-b442-bcc61f16ae89')
+    def test_get_available_project_scopes(self):
+        manager_project_id = self.manager.credentials.project_id
+        admin_user_id = self.os_adm.credentials.user_id
+        admin_role_id = self.get_role_by_name(CONF.identity.admin_role)['id']
+
+        # Grant the user the role on both projects.
+        self.roles_client.create_user_role_on_project(
+            manager_project_id, admin_user_id, admin_role_id)
+        self.addCleanup(
+            self.roles_client.delete_role_from_user_on_project,
+            manager_project_id, admin_user_id, admin_role_id)
+
+        assigned_project_ids = [self.os_adm.credentials.project_id,
+                                manager_project_id]
+
+        # Get available project scopes
+        available_projects =\
+            self.client.list_auth_projects()['projects']
+
+        # create list to save fetched project's id
+        fetched_project_ids = [i['id'] for i in available_projects]
+
+        # verifying the project ids in list
+        missing_project_ids = \
+            [p for p in assigned_project_ids
+             if p not in fetched_project_ids]
+        self.assertEmpty(missing_project_ids,
+                         "Failed to find project_id %s in fetched list" %
+                         ', '.join(missing_project_ids))
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index dc440d3..c83dd7f 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -11,7 +11,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 7b6ebef..aa8b2dc 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest import test
diff --git a/tempest/api/network/admin/test_routers_dvr.py b/tempest/api/network/admin/test_routers_dvr.py
index 78ca494..4ccad30 100644
--- a/tempest/api/network/admin/test_routers_dvr.py
+++ b/tempest/api/network/admin/test_routers_dvr.py
@@ -16,7 +16,7 @@
 import testtools
 
 from tempest.api.network import base_routers as base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 132e23e..a724dc9 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -15,9 +15,9 @@
 
 import netaddr
 
-from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions as lib_exc
 import tempest.test
diff --git a/tempest/api/network/base_security_groups.py b/tempest/api/network/base_security_groups.py
index 3ea3aea..b8d677a 100644
--- a/tempest/api/network/base_security_groups.py
+++ b/tempest/api/network/base_security_groups.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 
 
 class BaseSecGroupTest(base.BaseNetworkTest):
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 136f9e6..a7ae765 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -18,9 +18,9 @@
 import netaddr
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
 from tempest.common.utils import net_info
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 
diff --git a/tempest/api/network/test_extra_dhcp_options.py b/tempest/api/network/test_extra_dhcp_options.py
index 1156275..dc9042e 100644
--- a/tempest/api/network/test_extra_dhcp_options.py
+++ b/tempest/api/network/test_extra_dhcp_options.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/network/test_metering_extensions.py b/tempest/api/network/test_metering_extensions.py
index 42fa9e4..18dccc3 100644
--- a/tempest/api/network/test_metering_extensions.py
+++ b/tempest/api/network/test_metering_extensions.py
@@ -13,7 +13,7 @@
 # under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 69d4ebe..fc9f465 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -18,8 +18,8 @@
 
 from tempest.api.network import base
 from tempest.common import custom_matchers
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
diff --git a/tempest/api/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index 3cc6fb7..5cb12fe 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -15,7 +15,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 3908aae..376d4ae 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -21,8 +21,8 @@
 from tempest.api.network import base
 from tempest.api.network import base_security_groups as sec_base
 from tempest.common import custom_matchers
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions
 from tempest import test
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 694b86b..fbfcafc 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -17,8 +17,8 @@
 import testtools
 
 from tempest.api.network import base_routers as base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 2bda431..e945ac9 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -16,8 +16,8 @@
 import netaddr
 
 from tempest.api.network import base_routers as base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index 607baf0..d7e5149 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 from tempest.api.network import base_security_groups as base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/network/test_subnetpools_extensions.py b/tempest/api/network/test_subnetpools_extensions.py
index d9599c4..be6bffc 100644
--- a/tempest/api/network/test_subnetpools_extensions.py
+++ b/tempest/api/network/test_subnetpools_extensions.py
@@ -13,8 +13,8 @@
 # under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
diff --git a/tempest/config.py b/tempest/config.py
index 3ad7684..d5c8ea9 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -514,10 +514,20 @@
 ImageFeaturesGroup = [
     cfg.BoolOpt('api_v2',
                 default=True,
-                help="Is the v2 image API enabled"),
+                help="Is the v2 image API enabled",
+                deprecated_for_removal=True,
+                deprecated_reason='Glance v1 APIs are deprecated and v2 APIs '
+                                  'are current one. In future, Tempest will '
+                                  'test v2 APIs only so this config option '
+                                  'will be removed.'),
     cfg.BoolOpt('api_v1',
                 default=True,
-                help="Is the v1 image API enabled"),
+                help="Is the v1 image API enabled",
+                deprecated_for_removal=True,
+                deprecated_reason='Glance v1 APIs are deprecated and v2 APIs '
+                                  'are current one. In future, Tempest will '
+                                  'test v2 APIs only so this config option '
+                                  'will be removed.'),
     cfg.BoolOpt('deactivate_image',
                 default=False,
                 help="Is the deactivate-image feature enabled."
@@ -1087,6 +1097,12 @@
         return getattr(_CONF, attr)
 
     def _set_attrs(self):
+        # This methods ensures that config options in Tempest as well as
+        # in Tempest plugins can be accessed via:
+        #     CONF.<normalised_group_name>.<key_name>
+        # where:
+        #     normalised_group_name = group_name.replace('-', '_')
+        # Attributes are set at __init__ time *only* for known option groups
         self.auth = _CONF.auth
         self.compute = _CONF.compute
         self.compute_feature_enabled = _CONF['compute-feature-enabled']
@@ -1108,6 +1124,23 @@
         self.service_available = _CONF.service_available
         self.debug = _CONF.debug
         logging.tempest_set_log_file('tempest.log')
+        # Setting attributes for plugins
+        # NOTE(andreaf) Plugins have no access to the TempestConfigPrivate
+        # instance at discovery time, so they have no way of setting these
+        # aliases themselves.
+        ext_plugins = plugins.TempestTestPluginManager()
+        for group, _ in ext_plugins.get_plugin_options_list():
+            if isinstance(group, cfg.OptGroup):
+                # If we have an OptGroup
+                group_name = group.name
+                group_dest = group.dest
+            else:
+                # If we have a group name as a string
+                group_name = group
+                group_dest = group.replace('-', '_')
+            # NOTE(andreaf) We can set the attribute safely here since in
+            # case of name conflict we would not have reached this point.
+            setattr(self, group_dest, _CONF[group_name])
 
     def __init__(self, parse_conf=True, config_path=None):
         """Initialize a configuration from a conf directory and conf file."""
diff --git a/tempest/hacking/ignored_list_T110.txt b/tempest/hacking/ignored_list_T110.txt
index be875ee..0e7e894 100644
--- a/tempest/hacking/ignored_list_T110.txt
+++ b/tempest/hacking/ignored_list_T110.txt
@@ -1,4 +1 @@
 ./tempest/services/object_storage/object_client.py
-./tempest/services/volume/base/base_qos_client.py
-./tempest/services/volume/base/base_backups_client.py
-./tempest/services/baremetal/base.py
diff --git a/tempest/hacking/ignored_list_T111.txt b/tempest/hacking/ignored_list_T111.txt
deleted file mode 100644
index 8017e76..0000000
--- a/tempest/hacking/ignored_list_T111.txt
+++ /dev/null
@@ -1 +0,0 @@
-./tempest/services/baremetal/base.py
diff --git a/tempest/lib/api_schema/response/compute/v2_1/quotas.py b/tempest/lib/api_schema/response/compute/v2_1/quotas.py
index 7953983..44f5bdf 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/quotas.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/quotas.py
@@ -60,6 +60,124 @@
 get_quota_set['response_body']['properties']['quota_set']['required'].extend([
     'id'])
 
+get_quota_set_details = copy.deepcopy(get_quota_set)
+get_quota_set_details['response_body']['properties']['quota_set'][
+    'properties'] = {
+    'id': {'type': 'string'},
+    'instances': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'cores': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'ram': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'floating_ips': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'fixed_ips': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'metadata_items': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'key_pairs': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'security_groups': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'security_group_rules': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'server_group_members': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'server_groups': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'injected_files': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'injected_file_content_bytes': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'injected_file_path_bytes': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    }
+}
+
 delete_quota = {
     'status_code': [202]
 }
diff --git a/tempest/lib/services/compute/quotas_client.py b/tempest/lib/services/compute/quotas_client.py
index 265969a..daf4bc0 100644
--- a/tempest/lib/services/compute/quotas_client.py
+++ b/tempest/lib/services/compute/quotas_client.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
 
 from tempest.lib.api_schema.response.compute.v2_1 import quotas as schema
 from tempest.lib.common import rest_client
@@ -22,15 +23,29 @@
 
 class QuotasClient(base_compute_client.BaseComputeClient):
 
-    def show_quota_set(self, tenant_id, user_id=None):
-        """List the quota set for a tenant."""
+    def show_quota_set(self, tenant_id, user_id=None, detail=False):
+        """List the quota set for a tenant.
 
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html/#show-a-quota
+        http://developer.openstack.org/api-ref-compute-v2.1.html/#show-the-detail-of-quota
+        """
+
+        params = {}
         url = 'os-quota-sets/%s' % tenant_id
+        if detail:
+            url += '/detail'
         if user_id:
-            url += '?user_id=%s' % user_id
+            params.update({'user_id': user_id})
+        if params:
+            url += '?%s' % urllib.urlencode(params)
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.get_quota_set, resp, body)
+        if detail:
+            self.validate_response(schema.get_quota_set_details, resp, body)
+        else:
+            self.validate_response(schema.get_quota_set, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def show_default_quota_set(self, tenant_id):
diff --git a/tempest/lib/services/identity/v3/identity_client.py b/tempest/lib/services/identity/v3/identity_client.py
index 8177e35..755c14b 100644
--- a/tempest/lib/services/identity/v3/identity_client.py
+++ b/tempest/lib/services/identity/v3/identity_client.py
@@ -43,3 +43,10 @@
         resp, body = self.delete("auth/tokens", headers=headers)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
+
+    def list_auth_projects(self):
+        """Get available project scopes."""
+        resp, body = self.get("auth/projects")
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/test_discover/plugins.py b/tempest/test_discover/plugins.py
index 9ddcd9b..276cf3c 100644
--- a/tempest/test_discover/plugins.py
+++ b/tempest/test_discover/plugins.py
@@ -46,10 +46,41 @@
         """Add additional configuration options to tempest.
 
         This method will be run for the plugin during the register_opts()
-        function in tempest.config
+        function in tempest.config.
 
         :param ConfigOpts conf: The conf object that can be used to register
             additional options on.
+
+        Example:
+            >>> # Config options are defined in a config.py module
+            >>> service_option = cfg.BoolOpt(
+            >>>     "my_service",
+            >>>     default=True,
+            >>>     help="Whether or not my service is available")
+            >>>
+            >>> # Note: as long as the group is listed in get_opt_lists,
+            >>> # it will be possible to access its optins in the plugin code
+            >>> # via ("-" in the group name are replaces with "_"):
+            >>> #     CONF.my_service.<option_name>
+            >>> my_service_group = cfg.OptGroup(name="my-service",
+            >>>                                 title="My service options")
+            >>>
+            >>> MyServiceGroup = [<list of options>]
+            >>> # (...) More groups and options...
+            >>>
+            >>> # Plugin is implemented in a plugin.py module
+            >>> from my_plugin import config as my_config
+            >>>
+            >>> def register_opts(self, conf):
+            >>>    conf.register_opt(my_config.service_option,
+            >>>                      group='service_available')
+            >>>    conf.register_group(my_config.my_service_group)
+            >>>    conf.register_opts(my_config.MyService +
+            >>>                       my_config.my_service_group)
+            >>>
+            >>>    conf.register_group(my_config.my_service_feature_group)
+            >>>    conf.register_opts(my_config.MyServiceFeaturesGroup,
+            >>>                       my_config.my_service_feature_group)
         """
         return
 
diff --git a/tempest/tests/lib/services/compute/test_quotas_client.py b/tempest/tests/lib/services/compute/test_quotas_client.py
index 4c49e8d..bbb8eb7 100644
--- a/tempest/tests/lib/services/compute/test_quotas_client.py
+++ b/tempest/tests/lib/services/compute/test_quotas_client.py
@@ -49,22 +49,35 @@
         self.client = quotas_client.QuotasClient(
             fake_auth, 'compute', 'regionOne')
 
-    def _test_show_quota_set(self, bytes_body=False, user_id=None):
+    def _get_quota_set(self, detail):
+        if not detail:
+            return self.FAKE_QUOTA_SET
+        fake_quota_set = {"quota_set": {}}
+        for key, val in self.FAKE_QUOTA_SET['quota_set'].items():
+            fake_quota_set['quota_set'][key] = \
+                {'limit': val, 'reserved': 0, 'in_use': 0}
+        fake_quota_set['quota_set']['id'] = "8421f7be61064f50b680465c07f334af"
+        return fake_quota_set
+
+    def _test_show_quota_set(self, bytes_body=False, detail=False,
+                             user_id=None):
         if user_id:
             self.check_service_client_function(
                 self.client.show_quota_set,
                 'tempest.lib.common.rest_client.RestClient.get',
-                self.FAKE_QUOTA_SET,
+                self._get_quota_set(detail),
                 to_utf=bytes_body,
                 tenant_id=self.project_id,
+                detail=detail,
                 user_id=user_id)
         else:
             self.check_service_client_function(
                 self.client.show_quota_set,
                 'tempest.lib.common.rest_client.RestClient.get',
-                self.FAKE_QUOTA_SET,
+                self._get_quota_set(detail),
                 to_utf=bytes_body,
-                tenant_id=self.project_id)
+                tenant_id=self.project_id,
+                detail=detail)
 
     def test_show_quota_set_with_str_body(self):
         self._test_show_quota_set()
@@ -78,6 +91,9 @@
     def test_show_quota_set_for_user_with_bytes_body(self):
         self._test_show_quota_set(bytes_body=True, user_id=self.fake_user_id)
 
+    def test_show_quota_set_with_details(self):
+        self._test_show_quota_set(detail=True)
+
     def _test_show_default_quota_set(self, bytes_body=False):
         self.check_service_client_function(
             self.client.show_default_quota_set,
diff --git a/tempest/tests/lib/services/identity/v3/test_identity_client.py b/tempest/tests/lib/services/identity/v3/test_identity_client.py
index 9eaaaaf..e435fe2 100644
--- a/tempest/tests/lib/services/identity/v3/test_identity_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_identity_client.py
@@ -32,6 +32,34 @@
         "description": "test_description"
     }
 
+    FAKE_AUTH_PROJECTS = {
+        "projects": [
+            {
+                "domain_id": "1789d1",
+                "enabled": True,
+                "id": "263fd9",
+                "links": {
+                    "self": "https://example.com/identity/v3/projects/263fd9"
+                },
+                "name": "Test Group"
+            },
+            {
+                "domain_id": "1789d1",
+                "enabled": True,
+                "id": "50ef01",
+                "links": {
+                    "self": "https://example.com/identity/v3/projects/50ef01"
+                },
+                "name": "Build Group"
+            }
+        ],
+        "links": {
+            "self": "https://example.com/identity/v3/auth/projects",
+            "previous": None,
+            "next": None
+        }
+    }
+
     def setUp(self):
         super(TestIdentityClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -54,6 +82,13 @@
             bytes_body,
             resp_token="cbc36478b0bd8e67e89")
 
+    def _test_list_auth_projects(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_auth_projects,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_AUTH_PROJECTS,
+            bytes_body)
+
     def test_show_api_description_with_str_body(self):
         self._test_show_api_description()
 
@@ -73,3 +108,9 @@
             {},
             resp_token="cbc36478b0bd8e67e89",
             status=204)
+
+    def test_list_auth_projects_with_str_body(self):
+        self._test_list_auth_projects()
+
+    def test_list_auth_projects_with_bytes_body(self):
+        self._test_list_auth_projects(bytes_body=True)