Merge "Make create_server use **kwargs"
diff --git a/tempest/api/compute/admin/test_networks.py b/tempest/api/compute/admin/test_networks.py
index deb81a9..1da3f6e 100644
--- a/tempest/api/compute/admin/test_networks.py
+++ b/tempest/api/compute/admin/test_networks.py
@@ -32,7 +32,7 @@
     @classmethod
     def setup_clients(cls):
         super(NetworksTest, cls).setup_clients()
-        cls.client = cls.os_adm.networks_client
+        cls.client = cls.os_adm.compute_networks_client
 
     @test.idempotent_id('d206d211-8912-486f-86e2-a9d090d1f416')
     def test_get_network(self):
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index ef96f9b..dbca6bb 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -97,58 +97,56 @@
     # TODO(afazekas): merge these test cases
     @test.idempotent_id('ce9e0815-8091-4abd-8345-7fe5b85faa1d')
     def test_get_updated_quotas(self):
-        # Verify that GET shows the updated quota set of tenant
-        tenant_name = data_utils.rand_name('cpu_quota_tenant')
-        tenant_desc = tenant_name + '-desc'
-        identity_client = self.os_adm.identity_client
-        tenant = identity_client.create_tenant(name=tenant_name,
-                                               description=tenant_desc)
-        tenant_id = tenant['id']
-        self.addCleanup(identity_client.delete_tenant, tenant_id)
+        # Verify that GET shows the updated quota set of project
+        project_name = data_utils.rand_name('cpu_quota_project')
+        project_desc = project_name + '-desc'
+        project = self.identity_utils.create_project(name=project_name,
+                                                     description=project_desc)
+        project_id = project['id']
+        self.addCleanup(self.identity_utils.delete_project, project_id)
 
-        self.adm_client.update_quota_set(tenant_id, ram='5120')
-        quota_set = self.adm_client.show_quota_set(tenant_id)['quota_set']
+        self.adm_client.update_quota_set(project_id, ram='5120')
+        quota_set = self.adm_client.show_quota_set(project_id)['quota_set']
         self.assertEqual(5120, quota_set['ram'])
 
         # Verify that GET shows the updated quota set of user
         user_name = data_utils.rand_name('cpu_quota_user')
         password = data_utils.rand_name('password')
         email = user_name + '@testmail.tm'
-        user = identity_client.create_user(name=user_name,
-                                           password=password,
-                                           tenant_id=tenant_id,
-                                           email=email)
+        user = self.identity_utils.create_user(username=user_name,
+                                               password=password,
+                                               project=project,
+                                               email=email)
         if 'user' in user:
             user = user['user']
         user_id = user['id']
-        self.addCleanup(identity_client.delete_user, user_id)
+        self.addCleanup(self.identity_utils.delete_user, user_id)
 
-        self.adm_client.update_quota_set(tenant_id,
+        self.adm_client.update_quota_set(project_id,
                                          user_id=user_id,
                                          ram='2048')
         quota_set = self.adm_client.show_quota_set(
-            tenant_id, user_id=user_id)['quota_set']
+            project_id, user_id=user_id)['quota_set']
         self.assertEqual(2048, quota_set['ram'])
 
     @test.idempotent_id('389d04f0-3a41-405f-9317-e5f86e3c44f0')
     def test_delete_quota(self):
-        # Admin can delete the resource quota set for a tenant
-        tenant_name = data_utils.rand_name('ram_quota_tenant')
-        tenant_desc = tenant_name + '-desc'
-        identity_client = self.os_adm.identity_client
-        tenant = identity_client.create_tenant(name=tenant_name,
-                                               description=tenant_desc)
-        tenant_id = tenant['id']
-        self.addCleanup(identity_client.delete_tenant, tenant_id)
-        quota_set_default = (self.adm_client.show_quota_set(tenant_id)
+        # Admin can delete the resource quota set for a project
+        project_name = data_utils.rand_name('ram_quota_project')
+        project_desc = project_name + '-desc'
+        project = self.identity_utils.create_project(name=project_name,
+                                                     description=project_desc)
+        project_id = project['id']
+        self.addCleanup(self.identity_utils.delete_project, project_id)
+        quota_set_default = (self.adm_client.show_quota_set(project_id)
                              ['quota_set'])
         ram_default = quota_set_default['ram']
 
-        self.adm_client.update_quota_set(tenant_id, ram='5120')
+        self.adm_client.update_quota_set(project_id, ram='5120')
 
-        self.adm_client.delete_quota_set(tenant_id)
+        self.adm_client.delete_quota_set(project_id)
 
-        quota_set_new = self.adm_client.show_quota_set(tenant_id)['quota_set']
+        quota_set_new = self.adm_client.show_quota_set(project_id)['quota_set']
         self.assertEqual(ram_default, quota_set_new['ram'])
 
 
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 758cd43..bdbfde4 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -49,8 +49,8 @@
                           self.demo_tenant_id,
                           ram=0)
 
-    # TODO(afazekas): Add dedicated tenant to the skiped quota tests
-    # it can be moved into the setUpClass as well
+    # TODO(afazekas): Add dedicated tenant to the skipped quota tests.
+    # It can be moved into the setUpClass as well.
     @test.attr(type=['negative'])
     @test.idempotent_id('91058876-9947-4807-9f22-f6eb17140d9b')
     def test_create_server_when_cpu_quota_is_full(self):
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 02a183f..3952439 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -70,7 +70,7 @@
         cls.security_groups_client = cls.os.security_groups_client
         cls.quotas_client = cls.os.quotas_client
         cls.quota_classes_client = cls.os.quota_classes_client
-        cls.networks_client = cls.os.networks_client
+        cls.compute_networks_client = cls.os.compute_networks_client
         cls.limits_client = cls.os.limits_client
         cls.volumes_extensions_client = cls.os.volumes_extensions_client
         cls.snapshots_extensions_client = cls.os.snapshots_extensions_client
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 530e422..24d503f 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -186,7 +186,7 @@
         self.assertTrue(interface_count > 0)
         self._check_interface(ifs[0])
         network_id = ifs[0]['net_id']
-        self.client.add_fixed_ip(server['id'], networkId=network_id)
+        self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
         # Remove the fixed IP from server.
         server_detail = self.os.servers_client.show_server(
             server['id'])['server']
@@ -199,4 +199,4 @@
                     break
             if fixed_ip is not None:
                 break
-        self.client.remove_fixed_ip(server['id'], address=fixed_ip)
+        self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
diff --git a/tempest/api/compute/test_networks.py b/tempest/api/compute/test_networks.py
index b53db3d..d4b8003 100644
--- a/tempest/api/compute/test_networks.py
+++ b/tempest/api/compute/test_networks.py
@@ -29,7 +29,7 @@
     @classmethod
     def setup_clients(cls):
         super(ComputeNetworksTest, cls).setup_clients()
-        cls.client = cls.os.networks_client
+        cls.client = cls.os.compute_networks_client
 
     @test.idempotent_id('3fe07175-312e-49a5-a623-5f52eeada4c2')
     def test_list_networks(self):
diff --git a/tempest/api/compute/test_versions.py b/tempest/api/compute/test_versions.py
index 369cf31..f94cee6 100644
--- a/tempest/api/compute/test_versions.py
+++ b/tempest/api/compute/test_versions.py
@@ -20,5 +20,53 @@
 
     @test.idempotent_id('6c0a0990-43b6-4529-9b61-5fd8daf7c55c')
     def test_list_api_versions(self):
+        """Test that a get of the unversioned url returns the choices doc.
+
+        A key feature in OpenStack services is the idea that you can
+        GET / on the service and get a list of the versioned endpoints
+        that you can access. This comes back as a status 300
+        request. It's important that this is available to API
+        consumers to discover the API they can use.
+
+        """
         result = self.versions_client.list_versions()
-        self.assertIsNotNone(result)
+        versions = result['versions']
+        # NOTE(sdague): at a later point we may want to loosen this
+        # up, but for now this should be true of all Novas deployed.
+        self.assertEqual(versions[0]['id'], 'v2.0',
+                         "The first listed version should be v2.0")
+
+    @test.idempotent_id('b953a29e-929c-4a8e-81be-ec3a7e03cb76')
+    def test_get_version_details(self):
+        """Test individual version endpoints info works.
+
+        In addition to the GET / version request, there is also a
+        version info document stored at the top of the versioned
+        endpoints. This provides access to details about that
+        endpoint, including min / max version if that implements
+        microversions.
+
+        This test starts with the version list, iterates all the
+        returned endpoints, and fetches them. This will also ensure
+        that all the version links are followable constructs which
+        will help detect configuration issues when SSL termination
+        isn't done completely for a site.
+
+        """
+        result = self.versions_client.list_versions()
+        versions = result['versions']
+
+        # iterate through all the versions that are returned and
+        # attempt to get their version documents.
+        for version in versions:
+            links = [x for x in version['links'] if x['rel'] == 'self']
+            self.assertEqual(
+                len(links), 1,
+                "There should only be 1 self link in %s" % version)
+            link = links[0]
+            # this is schema validated
+            result = self.versions_client.get_version_by_url(link['href'])
+            # ensure the new self link matches the old one
+            newlinks = [x for x in result['version']['links']
+                        if x['rel'] == 'self']
+            self.assertEqual(links, newlinks)
diff --git a/tempest/api/identity/v2/test_ec2_credentials.py b/tempest/api/identity/v2/test_ec2_credentials.py
new file mode 100644
index 0000000..dbb50be
--- /dev/null
+++ b/tempest/api/identity/v2/test_ec2_credentials.py
@@ -0,0 +1,111 @@
+# Copyright 2015 OpenStack Foundation
+# 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_lib import exceptions as lib_exc
+
+from tempest.api.identity import base
+from tempest import test
+
+
+class EC2CredentialsTest(base.BaseIdentityV2Test):
+
+    @classmethod
+    def skip_checks(cls):
+        super(EC2CredentialsTest, cls).skip_checks()
+        if not test.is_extension_enabled('OS-EC2', 'identity'):
+            msg = "OS-EC2 identity extension not enabled."
+            raise cls.skipException(msg)
+
+    @classmethod
+    def resource_setup(cls):
+        super(EC2CredentialsTest, cls).resource_setup()
+        cls.creds = cls.os.credentials
+
+    @test.idempotent_id('b580fab9-7ae9-46e8-8138-417260cb6f9f')
+    def test_create_ec2_credentials(self):
+        """Create user ec2 credentials."""
+        resp = self.non_admin_client.create_user_ec2_credentials(
+            self.creds.credentials.user_id,
+            self.creds.credentials.tenant_id)
+        access = resp['access']
+        self.addCleanup(
+            self.non_admin_client.delete_user_ec2_credentials,
+            self.creds.credentials.user_id, access)
+        self.assertNotEmpty(resp['access'])
+        self.assertNotEmpty(resp['secret'])
+        self.assertEqual(self.creds.credentials.user_id, resp['user_id'])
+        self.assertEqual(self.creds.credentials.tenant_id, resp['tenant_id'])
+
+    @test.idempotent_id('9e2ea42f-0a4f-468c-a768-51859ce492e0')
+    def test_list_ec2_credentials(self):
+        """Get the list of user ec2 credentials."""
+        created_creds = []
+        fetched_creds = []
+        # create first ec2 credentials
+        creds1 = self.non_admin_client.create_user_ec2_credentials(
+            self.creds.credentials.user_id, self.creds.credentials.tenant_id)
+        created_creds.append(creds1['access'])
+        # create second ec2 credentials
+        creds2 = self.non_admin_client.create_user_ec2_credentials(
+            self.creds.credentials.user_id, self.creds.credentials.tenant_id)
+        created_creds.append(creds2['access'])
+        # add credentials to be cleaned up
+        self.addCleanup(
+            self.non_admin_client.delete_user_ec2_credentials,
+            self.creds.credentials.user_id, creds1['access'])
+        self.addCleanup(
+            self.non_admin_client.delete_user_ec2_credentials,
+            self.creds.credentials.user_id, creds2['access'])
+        # get the list of user ec2 credentials
+        resp = self.non_admin_client.list_user_ec2_credentials(
+            self.creds.credentials.user_id)
+        fetched_creds = [cred['access'] for cred in resp]
+        # created credentials should be in a fetched list
+        missing = [cred for cred in created_creds
+                   if cred not in fetched_creds]
+        self.assertEmpty(missing,
+                         "Failed to find ec2_credentials %s in fetched list" %
+                         ', '.join(cred for cred in missing))
+
+    @test.idempotent_id('cb284075-b613-440d-83ca-fe0b33b3c2b8')
+    def test_show_ec2_credentials(self):
+        """Get the definite user ec2 credentials."""
+        resp = self.non_admin_client.create_user_ec2_credentials(
+            self.creds.credentials.user_id,
+            self.creds.credentials.tenant_id)
+        self.addCleanup(
+            self.non_admin_client.delete_user_ec2_credentials,
+            self.creds.credentials.user_id, resp['access'])
+
+        ec2_creds = self.non_admin_client.show_user_ec2_credentials(
+            self.creds.credentials.user_id, resp['access']
+        )
+        for key in ['access', 'secret', 'user_id', 'tenant_id']:
+            self.assertEqual(ec2_creds[key], resp[key])
+
+    @test.idempotent_id('6aba0d4c-b76b-4e46-aa42-add79bc1551d')
+    def test_delete_ec2_credentials(self):
+        """Delete user ec2 credentials."""
+        resp = self.non_admin_client.create_user_ec2_credentials(
+            self.creds.credentials.user_id,
+            self.creds.credentials.tenant_id)
+        access = resp['access']
+        self.non_admin_client.delete_user_ec2_credentials(
+            self.creds.credentials.user_id, access)
+        self.assertRaises(
+            lib_exc.NotFound,
+            self.non_admin_client.show_user_ec2_credentials,
+            self.creds.credentials.user_id,
+            access)
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index b446ec3..a336507 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -172,7 +172,7 @@
                 self.assertEqual(params[key], image[key], msg)
 
     @test.idempotent_id('1e341d7a-90a9-494c-b143-2cdf2aeb6aee')
-    def test_index_no_params(self):
+    def test_list_no_params(self):
         # Simple test to see all fixture images returned
         images_list = self.client.list_images()['images']
         image_list = map(lambda x: x['id'], images_list)
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 63395cc..f5c5784 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -51,18 +51,17 @@
 
     def _check_quotas(self, new_quotas):
         # Add a tenant to conduct the test
-        test_tenant = data_utils.rand_name('test_tenant_')
-        test_description = data_utils.rand_name('desc_')
-        tenant = self.identity_admin_client.create_tenant(
-            name=test_tenant,
-            description=test_description)
-        tenant_id = tenant['id']
-        self.addCleanup(self.identity_admin_client.delete_tenant, tenant_id)
+        project = data_utils.rand_name('test_project_')
+        description = data_utils.rand_name('desc_')
+        project = self.identity_utils.create_project(name=project,
+                                                     description=description)
+        project_id = project['id']
+        self.addCleanup(self.identity_utils.delete_project, project_id)
 
         # Change quotas for tenant
-        quota_set = self.admin_client.update_quotas(tenant_id,
+        quota_set = self.admin_client.update_quotas(project_id,
                                                     **new_quotas)['quota']
-        self.addCleanup(self.admin_client.reset_quotas, tenant_id)
+        self.addCleanup(self.admin_client.reset_quotas, project_id)
         for key, value in six.iteritems(new_quotas):
             self.assertEqual(value, quota_set[key])
 
@@ -70,21 +69,21 @@
         non_default_quotas = self.admin_client.list_quotas()
         found = False
         for qs in non_default_quotas['quotas']:
-            if qs['tenant_id'] == tenant_id:
+            if qs['tenant_id'] == project_id:
                 found = True
         self.assertTrue(found)
 
         # Confirm from API quotas were changed as requested for tenant
-        quota_set = self.admin_client.show_quotas(tenant_id)
+        quota_set = self.admin_client.show_quotas(project_id)
         quota_set = quota_set['quota']
         for key, value in six.iteritems(new_quotas):
             self.assertEqual(value, quota_set[key])
 
         # Reset quotas to default and confirm
-        self.admin_client.reset_quotas(tenant_id)
+        self.admin_client.reset_quotas(project_id)
         non_default_quotas = self.admin_client.list_quotas()
         for q in non_default_quotas['quotas']:
-            self.assertNotEqual(tenant_id, q['tenant_id'])
+            self.assertNotEqual(project_id, q['tenant_id'])
 
     @test.idempotent_id('2390f766-836d-40ef-9aeb-e810d78207fb')
     def test_quotas(self):
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index aa3d274..ca5a868 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -85,21 +85,21 @@
         self.assertEqual(show_body['router']['name'], updated_name)
 
     @test.idempotent_id('e54dd3a3-4352-4921-b09d-44369ae17397')
-    def test_create_router_setting_tenant_id(self):
-        # Test creating router from admin user setting tenant_id.
-        test_tenant = data_utils.rand_name('test_tenant_')
-        test_description = data_utils.rand_name('desc_')
-        tenant = self.identity_admin_client.create_tenant(
-            name=test_tenant, description=test_description)
-        tenant_id = tenant['id']
-        self.addCleanup(self.identity_admin_client.delete_tenant, tenant_id)
+    def test_create_router_setting_project_id(self):
+        # Test creating router from admin user setting project_id.
+        project = data_utils.rand_name('test_tenant_')
+        description = data_utils.rand_name('desc_')
+        project = self.identity_utils.create_project(name=project,
+                                                     description=description)
+        project_id = project['id']
+        self.addCleanup(self.identity_utils.delete_project, project_id)
 
         name = data_utils.rand_name('router-')
         create_body = self.admin_client.create_router(name,
-                                                      tenant_id=tenant_id)
+                                                      tenant_id=project_id)
         self.addCleanup(self.admin_client.delete_router,
                         create_body['router']['id'])
-        self.assertEqual(tenant_id, create_body['router']['tenant_id'])
+        self.assertEqual(project_id, create_body['router']['tenant_id'])
 
     @test.idempotent_id('847257cc-6afd-4154-b8fb-af49f5670ce8')
     @test.requires_ext(extension='ext-gw-mode', service='network')
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index f9117ed..b2e52bb 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -98,21 +98,22 @@
 
     @test.idempotent_id('874b35a9-51f1-4258-bec5-cd561b6690d3')
     def test_delete_quota(self):
-        # Admin can delete the resource quota set for a tenant
-        tenant_name = data_utils.rand_name('quota_tenant')
-        identity_client = self.os_adm.identity_client
-        tenant = identity_client.create_tenant(tenant_name)
-        tenant_id = tenant['id']
-        self.addCleanup(identity_client.delete_tenant, tenant_id)
+        # Admin can delete the resource quota set for a project
+        project_name = data_utils.rand_name('quota_tenant')
+        description = data_utils.rand_name('desc_')
+        project = self.identity_utils.create_project(project_name,
+                                                     description=description)
+        project_id = project['id']
+        self.addCleanup(self.identity_utils.delete_project, project_id)
         quota_set_default = self.quotas_client.show_default_quota_set(
-            tenant_id)['quota_set']
+            project_id)['quota_set']
         volume_default = quota_set_default['volumes']
 
-        self.quotas_client.update_quota_set(tenant_id,
+        self.quotas_client.update_quota_set(project_id,
                                             volumes=(int(volume_default) + 5))
 
-        self.quotas_client.delete_quota_set(tenant_id)
-        quota_set_new = (self.quotas_client.show_quota_set(tenant_id)
+        self.quotas_client.delete_quota_set(project_id)
+        quota_set_new = (self.quotas_client.show_quota_set(project_id)
                          ['quota_set'])
         self.assertEqual(volume_default, quota_set_new['volumes'])
 
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index cc020e3..12e6761 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -61,7 +61,7 @@
     def setup_clients(cls):
         super(BaseVolumeTest, cls).setup_clients()
         cls.servers_client = cls.os.servers_client
-        cls.networks_client = cls.os.networks_client
+        cls.compute_networks_client = cls.os.compute_networks_client
         cls.images_client = cls.os.images_client
 
         if cls._api_version == 1:
diff --git a/tempest/api_schema/response/compute/v2_1/versions.py b/tempest/api_schema/response/compute/v2_1/versions.py
index f08695c..08a9fab 100644
--- a/tempest/api_schema/response/compute/v2_1/versions.py
+++ b/tempest/api_schema/response/compute/v2_1/versions.py
@@ -12,6 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import copy
+
+
 _version = {
     'type': 'object',
     'properties': {
@@ -23,6 +26,7 @@
                 'properties': {
                     'href': {'type': 'string', 'format': 'uri'},
                     'rel': {'type': 'string'},
+                    'type': {'type': 'string'},
                 },
                 'required': ['href', 'rel'],
                 'additionalProperties': False
@@ -31,10 +35,18 @@
         'status': {'type': 'string'},
         'updated': {'type': 'string', 'format': 'date-time'},
         'version': {'type': 'string'},
-        'min_version': {'type': 'string'}
+        'min_version': {'type': 'string'},
+        'media-types': {
+            'type': 'array',
+            'properties': {
+                'base': {'type': 'string'},
+                'type': {'type': 'string'},
+            }
+        },
     },
     # NOTE: version and min_version have been added since Kilo,
     # so they should not be required.
+    # NOTE(sdague): media-types only shows up in single version requests.
     'required': ['id', 'links', 'status', 'updated'],
     'additionalProperties': False
 }
@@ -53,3 +65,46 @@
         'additionalProperties': False
     }
 }
+
+
+_detail_get_version = copy.deepcopy(_version)
+_detail_get_version['properties'].pop('min_version')
+_detail_get_version['properties'].pop('version')
+_detail_get_version['properties'].pop('updated')
+_detail_get_version['properties']['media-types'] = {
+    'type': 'array',
+    'items': {
+        'type': 'object',
+        'properties': {
+            'base': {'type': 'string'},
+            'type': {'type': 'string'}
+        }
+    }
+}
+_detail_get_version['required'] = ['id', 'links', 'status', 'media-types']
+
+get_version = {
+    'status_code': [300],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'choices': {
+                'type': 'array',
+                'items': _detail_get_version
+            }
+        },
+        'required': ['choices'],
+        'additionalProperties': False
+    }
+}
+
+get_one_version = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'version': _version
+        },
+        'additionalProperties': False
+    }
+}
diff --git a/tempest/clients.py b/tempest/clients.py
index 28efd9d..2756fa8 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -59,7 +59,8 @@
 from tempest.services.compute.json.limits_client import LimitsClient
 from tempest.services.compute.json.migrations_client import \
     MigrationsClient
-from tempest.services.compute.json.networks_client import NetworksClient
+from tempest.services.compute.json.networks_client import NetworksClient \
+    as ComputeNetworksClient
 from tempest.services.compute.json.quota_classes_client import \
     QuotaClassesClient
 from tempest.services.compute.json.quotas_client import QuotasClient
@@ -262,7 +263,8 @@
         params.update(self.default_params)
 
         self.agents_client = AgentsClient(self.auth_provider, **params)
-        self.networks_client = NetworksClient(self.auth_provider, **params)
+        self.compute_networks_client = ComputeNetworksClient(
+            self.auth_provider, **params)
         self.migrations_client = MigrationsClient(self.auth_provider,
                                                   **params)
         self.security_group_default_rules_client = (
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index 27b44f6..9e6bee3 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -284,7 +284,7 @@
             identity_version=self.identity_version, **creds_dict)
         net_creds = cred_provider.TestResources(credential)
         net_clients = clients.Manager(credentials=credential)
-        compute_network_client = net_clients.networks_client
+        compute_network_client = net_clients.compute_networks_client
         net_name = self.hash_dict['networks'].get(hash, None)
         try:
             network = fixed_network.get_network_from_name(
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
new file mode 100644
index 0000000..7c3a77f
--- /dev/null
+++ b/tempest/common/cred_client.py
@@ -0,0 +1,146 @@
+# 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 abc
+
+from oslo_log import log as logging
+import six
+from tempest_lib import exceptions as lib_exc
+
+from tempest.common import cred_provider
+from tempest import config
+from tempest import exceptions
+from tempest.services.identity.v2.json import identity_client as v2_identity
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+@six.add_metaclass(abc.ABCMeta)
+class CredsClient(object):
+    """This class is a wrapper around the identity clients, to provide a
+     single interface for managing credentials in both v2 and v3 cases.
+     It's not bound to created credentials, only to a specific set of admin
+     credentials used for generating credentials.
+    """
+
+    def __init__(self, identity_client):
+        # The client implies version and credentials
+        self.identity_client = identity_client
+        self.credentials = self.identity_client.auth_provider.credentials
+
+    def create_user(self, username, password, project, email):
+        user = self.identity_client.create_user(
+            username, password, project['id'], email)
+        if 'user' in user:
+            user = user['user']
+        return user
+
+    @abc.abstractmethod
+    def create_project(self, name, description):
+        pass
+
+    def _check_role_exists(self, role_name):
+        try:
+            roles = self._list_roles()
+            role = next(r for r in roles if r['name'] == role_name)
+        except StopIteration:
+            return None
+        return role
+
+    def create_user_role(self, role_name):
+        if not self._check_role_exists(role_name):
+            self.identity_client.create_role(role_name)
+
+    def assign_user_role(self, user, project, role_name):
+        role = self._check_role_exists(role_name)
+        if not role:
+            msg = 'No "%s" role found' % role_name
+            raise lib_exc.NotFound(msg)
+        try:
+            self.identity_client.assign_user_role(project['id'], user['id'],
+                                                  role['id'])
+        except lib_exc.Conflict:
+            LOG.debug("Role %s already assigned on project %s for user %s" % (
+                role['id'], project['id'], user['id']))
+
+    @abc.abstractmethod
+    def get_credentials(self, user, project, password):
+        pass
+
+    def delete_user(self, user_id):
+        self.identity_client.delete_user(user_id)
+
+    def _list_roles(self):
+        roles = self.identity_client.list_roles()
+        return roles
+
+
+class V2CredsClient(CredsClient):
+
+    def create_project(self, name, description):
+        tenant = self.identity_client.create_tenant(
+            name=name, description=description)
+        return tenant
+
+    def get_credentials(self, user, project, password):
+        return cred_provider.get_credentials(
+            identity_version='v2',
+            username=user['name'], user_id=user['id'],
+            tenant_name=project['name'], tenant_id=project['id'],
+            password=password)
+
+    def delete_project(self, project_id):
+        self.identity_client.delete_tenant(project_id)
+
+
+class V3CredsClient(CredsClient):
+
+    def __init__(self, identity_client, domain_name):
+        super(V3CredsClient, self).__init__(identity_client)
+        try:
+            # Domain names must be unique, in any case a list is returned,
+            # selecting the first (and only) element
+            self.creds_domain = self.identity_client.list_domains(
+                params={'name': domain_name})['domains'][0]
+        except lib_exc.NotFound:
+            # TODO(andrea) we could probably create the domain on the fly
+            msg = "Configured domain %s could not be found" % domain_name
+            raise exceptions.InvalidConfiguration(msg)
+
+    def create_project(self, name, description):
+        project = self.identity_client.create_project(
+            name=name, description=description,
+            domain_id=self.creds_domain['id'])['project']
+        return project
+
+    def get_credentials(self, user, project, password):
+        return cred_provider.get_credentials(
+            identity_version='v3',
+            username=user['name'], user_id=user['id'],
+            project_name=project['name'], project_id=project['id'],
+            password=password,
+            project_domain_name=self.creds_domain['name'])
+
+    def delete_project(self, project_id):
+        self.identity_client.delete_project(project_id)
+
+    def _list_roles(self):
+        roles = self.identity_client.list_roles()['roles']
+        return roles
+
+
+def get_creds_client(identity_client, project_domain_name=None):
+    if isinstance(identity_client, v2_identity.IdentityClient):
+        return V2CredsClient(identity_client)
+    else:
+        return V3CredsClient(identity_client, project_domain_name)
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 6dca3a3..a4081c9 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -12,144 +12,22 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import abc
 import netaddr
 from oslo_log import log as logging
 import six
 from tempest_lib import exceptions as lib_exc
 
 from tempest import clients
+from tempest.common import cred_client
 from tempest.common import cred_provider
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
-from tempest.services.identity.v2.json import identity_client as v2_identity
 
 CONF = config.CONF
 LOG = logging.getLogger(__name__)
 
 
-@six.add_metaclass(abc.ABCMeta)
-class CredsClient(object):
-    """This class is a wrapper around the identity clients, to provide a
-     single interface for managing credentials in both v2 and v3 cases.
-     It's not bound to created credentials, only to a specific set of admin
-     credentials used for generating credentials.
-    """
-
-    def __init__(self, identity_client):
-        # The client implies version and credentials
-        self.identity_client = identity_client
-        self.credentials = self.identity_client.auth_provider.credentials
-
-    def create_user(self, username, password, project, email):
-        user = self.identity_client.create_user(
-            username, password, project['id'], email)
-        if 'user' in user:
-            user = user['user']
-        return user
-
-    @abc.abstractmethod
-    def create_project(self, name, description):
-        pass
-
-    def _check_role_exists(self, role_name):
-        try:
-            roles = self._list_roles()
-            role = next(r for r in roles if r['name'] == role_name)
-        except StopIteration:
-            return None
-        return role
-
-    def create_user_role(self, role_name):
-        if not self._check_role_exists(role_name):
-            self.identity_client.create_role(role_name)
-
-    def assign_user_role(self, user, project, role_name):
-        role = self._check_role_exists(role_name)
-        if not role:
-            msg = 'No "%s" role found' % role_name
-            raise lib_exc.NotFound(msg)
-        try:
-            self.identity_client.assign_user_role(project['id'], user['id'],
-                                                  role['id'])
-        except lib_exc.Conflict:
-            LOG.debug("Role %s already assigned on project %s for user %s" % (
-                role['id'], project['id'], user['id']))
-
-    @abc.abstractmethod
-    def get_credentials(self, user, project, password):
-        pass
-
-    def delete_user(self, user_id):
-        self.identity_client.delete_user(user_id)
-
-    def _list_roles(self):
-        roles = self.identity_client.list_roles()
-        return roles
-
-
-class V2CredsClient(CredsClient):
-
-    def create_project(self, name, description):
-        tenant = self.identity_client.create_tenant(
-            name=name, description=description)
-        return tenant
-
-    def get_credentials(self, user, project, password):
-        return cred_provider.get_credentials(
-            identity_version='v2',
-            username=user['name'], user_id=user['id'],
-            tenant_name=project['name'], tenant_id=project['id'],
-            password=password)
-
-    def delete_project(self, project_id):
-        self.identity_client.delete_tenant(project_id)
-
-
-class V3CredsClient(CredsClient):
-
-    def __init__(self, identity_client, domain_name):
-        super(V3CredsClient, self).__init__(identity_client)
-        try:
-            # Domain names must be unique, in any case a list is returned,
-            # selecting the first (and only) element
-            self.creds_domain = self.identity_client.list_domains(
-                params={'name': domain_name})['domains'][0]
-        except lib_exc.NotFound:
-            # TODO(andrea) we could probably create the domain on the fly
-            msg = "Configured domain %s could not be found" % domain_name
-            raise exceptions.InvalidConfiguration(msg)
-
-    def create_project(self, name, description):
-        project = self.identity_client.create_project(
-            name=name, description=description,
-            domain_id=self.creds_domain['id'])['project']
-        return project
-
-    def get_credentials(self, user, project, password):
-        return cred_provider.get_credentials(
-            identity_version='v3',
-            username=user['name'], user_id=user['id'],
-            project_name=project['name'], project_id=project['id'],
-            password=password,
-            project_domain_name=self.creds_domain['name'])
-
-    def delete_project(self, project_id):
-        self.identity_client.delete_project(project_id)
-
-    def _list_roles(self):
-        roles = self.identity_client.list_roles()['roles']
-        return roles
-
-
-def get_creds_client(identity_client, project_domain_name=None):
-    if isinstance(identity_client, v2_identity.IdentityClient):
-        return V2CredsClient(identity_client)
-    else:
-        return V3CredsClient(identity_client, project_domain_name)
-
-
 class IsolatedCreds(cred_provider.CredentialProvider):
 
     def __init__(self, identity_version=None, name=None,
@@ -171,7 +49,7 @@
             self.creds_domain_name = (
                 self.default_admin_creds.project_domain_name or
                 CONF.auth.default_credentials_domain_name)
-        self.creds_client = get_creds_client(
+        self.creds_client = cred_client.get_creds_client(
             self.identity_admin_client, self.creds_domain_name)
 
     def _get_admin_clients(self):
diff --git a/tempest/config.py b/tempest/config.py
index ccfcd9c..3d3ddff 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -188,6 +188,12 @@
     cfg.BoolOpt('api_v3',
                 default=True,
                 help='Is the v3 identity API enabled'),
+    cfg.ListOpt('api_extensions',
+                default=['all'],
+                help="A list of enabled identity extensions with a special "
+                     "entry all which indicates every extension is enabled. "
+                     "Empty list indicates all extensions are disabled. "
+                     "To get the list of extensions run: 'keystone discover'")
 ]
 
 compute_group = cfg.OptGroup(name='compute',
@@ -1042,7 +1048,7 @@
     # TODO(yfried): add support for dhcpcd
     cfg.StrOpt('dhcp_client',
                default='udhcpc',
-               choices=["udhcpc", "dhclient"],
+               choices=["udhcpc", "dhclient", ""],
                help='DHCP client used by images to renew DCHP lease. '
                     'If left empty, update operation will be skipped. '
                     'Supported clients: "udhcpc", "dhclient"')
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 022306e..5cc0509 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -64,22 +64,29 @@
         waiters.wait_for_server_status(self.servers_client, server['id'],
                                        'ACTIVE')
 
-    @test.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
-    @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
-                          'Shelve is not available.')
-    @test.services('compute', 'network', 'image')
-    def test_shelve_instance(self):
+    def _create_server_then_shelve_and_unshelve(self, boot_from_volume=False):
         self.keypair = self.create_keypair()
 
         self.security_group = self._create_security_group()
         security_groups = [{'name': self.security_group['name']}]
-
         create_kwargs = {
             'key_name': self.keypair['name'],
             'security_groups': security_groups
         }
-        server = self.create_server(image=CONF.compute.image_ref,
-                                    create_kwargs=create_kwargs)
+
+        if boot_from_volume:
+            volume = self.create_volume(size=CONF.volume.volume_size,
+                                        imageRef=CONF.compute.image_ref)
+            bd_map = [{
+                'device_name': 'vda',
+                'volume_id': volume['id'],
+                'delete_on_termination': '0'}]
+
+            create_kwargs['block_device_mapping'] = bd_map
+            server = self.create_server(create_kwargs=create_kwargs)
+        else:
+            server = self.create_server(image=CONF.compute.image_ref,
+                                        create_kwargs=create_kwargs)
 
         if CONF.compute.use_floatingip_for_ssh:
             floating_ip = (self.floating_ips_client.create_floating_ip()
@@ -101,3 +108,17 @@
             self._check_timestamp(floating_ip['ip'])
         else:
             self._check_timestamp(server)
+
+    @test.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
+    @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+                          'Shelve is not available.')
+    @test.services('compute', 'network', 'image')
+    def test_shelve_instance(self):
+        self._create_server_then_shelve_and_unshelve()
+
+    @test.idempotent_id('c1b6318c-b9da-490b-9c67-9339b627271f')
+    @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+                          'Shelve is not available.')
+    @test.services('compute', 'volume', 'network', 'image')
+    def test_shelve_volume_backed_instance(self):
+        self._create_server_then_shelve_and_unshelve(boot_from_volume=True)
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index 2e66082..fe076d8 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -16,7 +16,6 @@
 from oslo_serialization import jsonutils as json
 
 from tempest.api_schema.response.compute.v2_1 import interfaces as schema
-from tempest.api_schema.response.compute.v2_1 import servers as servers_schema
 from tempest.common import service_client
 
 
@@ -49,21 +48,3 @@
                                                                  port_id))
         self.validate_response(schema.delete_interface, resp, body)
         return service_client.ResponseBody(resp, body)
-
-    def add_fixed_ip(self, server_id, **kwargs):
-        """Add a fixed IP to input server instance."""
-        post_body = json.dumps({'addFixedIp': kwargs})
-        resp, body = self.post('servers/%s/action' % server_id,
-                               post_body)
-        self.validate_response(servers_schema.server_actions_common_schema,
-                               resp, body)
-        return service_client.ResponseBody(resp, body)
-
-    def remove_fixed_ip(self, server_id, **kwargs):
-        """Remove input fixed IP from input server instance."""
-        post_body = json.dumps({'removeFixedIp': kwargs})
-        resp, body = self.post('servers/%s/action' % server_id,
-                               post_body)
-        self.validate_response(servers_schema.server_actions_common_schema,
-                               resp, body)
-        return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index c8ddbe1..1d2c7b2 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -428,3 +428,11 @@
         return self.action(server_id, "os-getVNCConsole",
                            schema.get_vnc_console,
                            type=console_type)
+
+    def add_fixed_ip(self, server_id, **kwargs):
+        """Add a fixed IP to input server instance."""
+        return self.action(server_id, 'addFixedIp', **kwargs)
+
+    def remove_fixed_ip(self, server_id, **kwargs):
+        """Remove input fixed IP from input server instance."""
+        return self.action(server_id, 'removeFixedIp', **kwargs)
diff --git a/tempest/services/compute/json/versions_client.py b/tempest/services/compute/json/versions_client.py
index cbad02c..48c0e8d 100644
--- a/tempest/services/compute/json/versions_client.py
+++ b/tempest/services/compute/json/versions_client.py
@@ -21,7 +21,7 @@
 
 class VersionsClient(service_client.ServiceClient):
 
-    def list_versions(self):
+    def _get_base_version_url(self):
         # NOTE: The URL which is gotten from keystone's catalog contains
         # API version and project-id like "v2/{project-id}", but we need
         # to access the URL which doesn't contain them for getting API
@@ -29,9 +29,27 @@
         # get().
         endpoint = self.base_url
         url = urllib.parse.urlparse(endpoint)
-        version_url = '%s://%s/' % (url.scheme, url.netloc)
+        return '%s://%s/' % (url.scheme, url.netloc)
 
+    def list_versions(self):
+        version_url = self._get_base_version_url()
         resp, body = self.raw_request(version_url, 'GET')
         body = json.loads(body)
         self.validate_response(schema.list_versions, resp, body)
         return service_client.ResponseBody(resp, body)
+
+    def get_version_by_url(self, version_url):
+        """Get the version document by url.
+
+        This gets the version document for a url, useful in testing
+        the contents of things like /v2/ or /v2.1/ in Nova. That
+        controller needs authenticated access, so we have to get
+        ourselves a token before making the request.
+
+        """
+        # we need a token for this request
+        resp, body = self.raw_request(version_url, 'GET',
+                                      {'X-Auth-Token': self.token})
+        body = json.loads(body)
+        self.validate_response(schema.get_one_version, resp, body)
+        return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index 8eeefe7..81e967d 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -323,7 +323,19 @@
         self.expected_success(200, resp.status)
         return service_client.ResponseBody(resp, self._parse_resp(body))
 
+    def delete_user_ec2_credentials(self, user_id, access):
+        resp, body = self.delete('/users/%s/credentials/OS-EC2/%s' %
+                                 (user_id, access))
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp, body)
+
     def list_user_ec2_credentials(self, user_id):
         resp, body = self.get('/users/%s/credentials/OS-EC2' % user_id)
         self.expected_success(200, resp.status)
         return service_client.ResponseBodyList(resp, self._parse_resp(body))
+
+    def show_user_ec2_credentials(self, user_id, access):
+        resp, body = self.get('/users/%s/credentials/OS-EC2/%s' %
+                              (user_id, access))
+        self.expected_success(200, resp.status)
+        return service_client.ResponseBody(resp, self._parse_resp(body))
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index bdb39d8..7634d2c 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -25,7 +25,7 @@
 
 
 from tempest import clients
-from tempest.common import isolated_creds
+from tempest.common import cred_client
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
@@ -155,7 +155,7 @@
                     identity_client = admin_manager.identity_client
                 else:
                     identity_client = admin_manager.identity_v3_client
-                credentials_client = isolated_creds.get_creds_client(
+                credentials_client = cred_client.get_creds_client(
                     identity_client)
                 project = credentials_client.create_project(
                     name=tenant_name, description=tenant_name)
diff --git a/tempest/test.py b/tempest/test.py
index b664b47..142488c 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -31,6 +31,7 @@
 import testtools
 
 from tempest import clients
+from tempest.common import cred_client
 from tempest.common import credentials
 from tempest.common import fixed_network
 import tempest.common.generator.valid_generator as valid
@@ -182,6 +183,7 @@
         'volume': CONF.volume_feature_enabled.api_extensions,
         'network': CONF.network_feature_enabled.api_extensions,
         'object': CONF.object_storage_feature_enabled.discoverable_apis,
+        'identity': CONF.identity_feature_enabled.api_extensions
     }
     if len(config_dict[service]) == 0:
         return False
@@ -432,6 +434,25 @@
     def credentials_provider(self):
         return self._get_credentials_provider()
 
+    @property
+    def identity_utils(self):
+        """A client that abstracts v2 and v3 identity operations.
+
+        This can be used for creating and tearing down projects in tests. It
+        should not be used for testing identity features.
+        """
+        if CONF.identity.auth_version == 'v2':
+            client = self.os_admin.identity_client
+        else:
+            client = self.os_admin.identity_v3_client
+
+        try:
+            domain = client.auth_provider.credentials.project_domain_name
+        except AttributeError:
+            domain = 'Default'
+
+        return cred_client.get_creds_client(client, domain)
+
     @classmethod
     def _get_credentials_provider(cls):
         """Returns a credentials provider
@@ -569,7 +590,7 @@
         :return: network dict including 'id' and 'name'
         """
         # Make sure isolated_creds exists and get a network client
-        networks_client = cls.get_client_manager().networks_client
+        networks_client = cls.get_client_manager().compute_networks_client
         cred_provider = cls._get_credentials_provider()
         # In case of nova network, isolated tenants are not able to list the
         # network configured in fixed_network_name, even if the can use it
@@ -578,7 +599,8 @@
         if (not CONF.service_available.neutron and
                 credentials.is_admin_available()):
             admin_creds = cred_provider.get_admin_creds()
-            networks_client = clients.Manager(admin_creds).networks_client
+            admin_manager = clients.Manager(admin_creds)
+            networks_client = admin_manager.compute_networks_client
         return fixed_network.get_tenant_network(cred_provider,
                                                 networks_client)
 
diff --git a/tempest/tests/services/compute/test_agents_client.py b/tempest/tests/services/compute/test_agents_client.py
index 01035ab..31e576e 100644
--- a/tempest/tests/services/compute/test_agents_client.py
+++ b/tempest/tests/services/compute/test_agents_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import agents_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_aggregates_client.py b/tempest/tests/services/compute/test_aggregates_client.py
index 8184a46..e92b76b 100644
--- a/tempest/tests/services/compute/test_aggregates_client.py
+++ b/tempest/tests/services/compute/test_aggregates_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import aggregates_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_availability_zone_client.py b/tempest/tests/services/compute/test_availability_zone_client.py
index 715cfd7..e1d94bc 100644
--- a/tempest/tests/services/compute/test_availability_zone_client.py
+++ b/tempest/tests/services/compute/test_availability_zone_client.py
@@ -12,14 +12,17 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import copy
+
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import availability_zone_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
 class TestAvailabilityZoneClient(base.BaseComputeServiceTest):
 
-    FAKE_AVAILABIRITY_ZONE_INFO = {
+    FAKE_AZ_INFO = {
         "availabilityZoneInfo":
         [
             {
@@ -32,20 +35,48 @@
         ]
     }
 
+    FAKE_AZ_DETAILS = {
+        "testhost": {
+            "nova-compute": {
+                "available": True,
+                "active": True,
+                "updated_at": "2015-09-10T07:16:46.000000"
+            }
+        }
+    }
+
     def setUp(self):
         super(TestAvailabilityZoneClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
         self.client = availability_zone_client.AvailabilityZoneClient(
             fake_auth, 'compute', 'regionOne')
 
-    def test_list_availability_zones_with_str_body(self):
+    def _test_availability_zones(self, to_utf=False):
         self.check_service_client_function(
             self.client.list_availability_zones,
             'tempest.common.service_client.ServiceClient.get',
-            self.FAKE_AVAILABIRITY_ZONE_INFO)
+            self.FAKE_AZ_INFO,
+            to_utf)
+
+    def _test_availability_zones_with_details(self, to_utf=False):
+        fake_az_details = copy.deepcopy(self.FAKE_AZ_INFO)
+        fake_az_details['availabilityZoneInfo'][0]['hosts'] = \
+            self.FAKE_AZ_DETAILS
+        self.check_service_client_function(
+            self.client.list_availability_zones,
+            'tempest.common.service_client.ServiceClient.get',
+            fake_az_details,
+            to_utf,
+            detail=True)
+
+    def test_list_availability_zones_with_str_body(self):
+        self._test_availability_zones()
 
     def test_list_availability_zones_with_bytes_body(self):
-        self.check_service_client_function(
-            self.client.list_availability_zones,
-            'tempest.common.service_client.ServiceClient.get',
-            self.FAKE_AVAILABIRITY_ZONE_INFO, to_utf=True)
+        self._test_availability_zones(True)
+
+    def test_list_availability_zones_with_str_body_and_details(self):
+        self._test_availability_zones_with_details()
+
+    def test_list_availability_zones_with_bytes_body_and_details(self):
+        self._test_availability_zones_with_details(True)
diff --git a/tempest/tests/services/compute/test_baremetal_nodes_client.py b/tempest/tests/services/compute/test_baremetal_nodes_client.py
index edf9014..86c035c 100644
--- a/tempest/tests/services/compute/test_baremetal_nodes_client.py
+++ b/tempest/tests/services/compute/test_baremetal_nodes_client.py
@@ -14,8 +14,9 @@
 
 import copy
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import baremetal_nodes_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_certificates_client.py b/tempest/tests/services/compute/test_certificates_client.py
index c926fce..2ba90d0 100644
--- a/tempest/tests/services/compute/test_certificates_client.py
+++ b/tempest/tests/services/compute/test_certificates_client.py
@@ -14,8 +14,9 @@
 
 import copy
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import certificates_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_extensions_client.py b/tempest/tests/services/compute/test_extensions_client.py
index 86f81f3..21efc52 100644
--- a/tempest/tests/services/compute/test_extensions_client.py
+++ b/tempest/tests/services/compute/test_extensions_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import extensions_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_fixedIPs_client.py b/tempest/tests/services/compute/test_fixedIPs_client.py
index d7a9694..5acb422 100644
--- a/tempest/tests/services/compute/test_fixedIPs_client.py
+++ b/tempest/tests/services/compute/test_fixedIPs_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import fixed_ips_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_floating_ip_pools_client.py b/tempest/tests/services/compute/test_floating_ip_pools_client.py
index 0d19b7b..1cb4bf3 100644
--- a/tempest/tests/services/compute/test_floating_ip_pools_client.py
+++ b/tempest/tests/services/compute/test_floating_ip_pools_client.py
@@ -12,9 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
 
 from tempest.services.compute.json import floating_ip_pools_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_floating_ips_bulk_client.py b/tempest/tests/services/compute/test_floating_ips_bulk_client.py
index 6cf1b17..600985b 100644
--- a/tempest/tests/services/compute/test_floating_ips_bulk_client.py
+++ b/tempest/tests/services/compute/test_floating_ips_bulk_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import floating_ips_bulk_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_floating_ips_client.py b/tempest/tests/services/compute/test_floating_ips_client.py
new file mode 100644
index 0000000..ee22004
--- /dev/null
+++ b/tempest/tests/services/compute/test_floating_ips_client.py
@@ -0,0 +1,113 @@
+# Copyright 2015 IBM Corp.
+#
+#    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 oslotest import mockpatch
+from tempest_lib import exceptions as lib_exc
+
+from tempest.services.compute.json import floating_ips_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestFloatingIpsClient(base.BaseComputeServiceTest):
+
+    floating_ip = {"fixed_ip": None,
+                   "id": "46d61064-13ba-4bf0-9557-69de824c3d6f",
+                   "instance_id": "a1daa443-a6bb-463e-aea2-104b7d912eb8",
+                   "ip": "10.10.10.1",
+                   "pool": "nova"}
+
+    def setUp(self):
+        super(TestFloatingIpsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = floating_ips_client.FloatingIPsClient(
+            fake_auth, 'compute', 'regionOne')
+
+    def _test_list_floating_ips(self, bytes_body=False):
+        expected = {'floating_ips': [TestFloatingIpsClient.floating_ip]}
+        self.check_service_client_function(
+            self.client.list_floating_ips,
+            'tempest.common.service_client.ServiceClient.get',
+            expected,
+            bytes_body)
+
+    def test_list_floating_ips_str_body(self):
+        self._test_list_floating_ips(bytes_body=False)
+
+    def test_list_floating_ips_byte_body(self):
+        self._test_list_floating_ips(bytes_body=True)
+
+    def _test_show_floating_ip(self, bytes_body=False):
+        expected = {"floating_ip": TestFloatingIpsClient.floating_ip}
+        self.check_service_client_function(
+            self.client.show_floating_ip,
+            'tempest.common.service_client.ServiceClient.get',
+            expected,
+            bytes_body,
+            floating_ip_id='a1daa443-a6bb-463e-aea2-104b7d912eb8')
+
+    def test_show_floating_ip_str_body(self):
+        self._test_show_floating_ip(bytes_body=False)
+
+    def test_show_floating_ip_byte_body(self):
+        self._test_show_floating_ip(bytes_body=True)
+
+    def _test_create_floating_ip(self, bytes_body=False):
+        expected = {"floating_ip": TestFloatingIpsClient.floating_ip}
+        self.check_service_client_function(
+            self.client.create_floating_ip,
+            'tempest.common.service_client.ServiceClient.post',
+            expected,
+            bytes_body,
+            pool_name='nova')
+
+    def test_create_floating_ip_str_body(self):
+        self._test_create_floating_ip(bytes_body=False)
+
+    def test_create_floating_ip_byte_body(self):
+        self._test_create_floating_ip(bytes_body=True)
+
+    def test_delete_floating_ip(self):
+        self.check_service_client_function(
+            self.client.delete_floating_ip,
+            'tempest.common.service_client.ServiceClient.delete',
+            {}, status=202, floating_ip_id='fake-id')
+
+    def test_associate_floating_ip_to_server(self):
+        self.check_service_client_function(
+            self.client.associate_floating_ip_to_server,
+            'tempest.common.service_client.ServiceClient.post',
+            {}, status=202, floating_ip='10.10.10.1',
+            server_id='c782b7a9-33cd-45f0-b795-7f87f456408b')
+
+    def test_disassociate_floating_ip_from_server(self):
+        self.check_service_client_function(
+            self.client.disassociate_floating_ip_from_server,
+            'tempest.common.service_client.ServiceClient.post',
+            {}, status=202, floating_ip='10.10.10.1',
+            server_id='c782b7a9-33cd-45f0-b795-7f87f456408b')
+
+    def test_is_resource_deleted_true(self):
+        self.useFixture(mockpatch.Patch(
+            'tempest.services.compute.json.floating_ips_client.'
+            'FloatingIPsClient.show_floating_ip',
+            side_effect=lib_exc.NotFound()))
+        self.assertTrue(self.client.is_resource_deleted('fake-id'))
+
+    def test_is_resource_deleted_false(self):
+        self.useFixture(mockpatch.Patch(
+            'tempest.services.compute.json.floating_ips_client.'
+            'FloatingIPsClient.show_floating_ip',
+            return_value={"floating_ip": TestFloatingIpsClient.floating_ip}))
+        self.assertFalse(self.client.is_resource_deleted('fake-id'))
diff --git a/tempest/tests/services/compute/test_hypervisor_client.py b/tempest/tests/services/compute/test_hypervisor_client.py
new file mode 100644
index 0000000..441e7e6
--- /dev/null
+++ b/tempest/tests/services/compute/test_hypervisor_client.py
@@ -0,0 +1,167 @@
+# Copyright 2015 IBM Corp.
+#
+#    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.services.compute.json import hypervisor_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestHypervisorClient(base.BaseComputeServiceTest):
+
+    hypervisor_id = "1"
+    hypervisor_name = "hyper.hostname.com"
+
+    def setUp(self):
+        super(TestHypervisorClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = hypervisor_client.HypervisorClient(
+            fake_auth, 'compute', 'regionOne')
+
+    def test_list_hypervisor_str_body(self):
+        self._test_list_hypervisor(bytes_body=False)
+
+    def test_list_hypervisor_byte_body(self):
+        self._test_list_hypervisor(bytes_body=True)
+
+    def _test_list_hypervisor(self, bytes_body=False):
+        expected = {"hypervisors": [{
+            "id": 1,
+            "hypervisor_hostname": "hypervisor1.hostname.com"},
+            {
+            "id": 2,
+            "hypervisor_hostname": "hypervisor2.hostname.com"}]}
+        self.check_service_client_function(
+            self.client.list_hypervisors,
+            'tempest.common.service_client.ServiceClient.get',
+            expected, bytes_body)
+
+    def test_show_hypervisor_str_body(self):
+        self._test_show_hypervisor(bytes_body=False)
+
+    def test_show_hypervisor_byte_body(self):
+        self._test_show_hypervisor(bytes_body=True)
+
+    def _test_show_hypervisor(self, bytes_body=False):
+        expected = {"hypervisor": {
+            "cpu_info": "?",
+            "current_workload": 0,
+            "disk_available_least": 1,
+            "host_ip": "10.10.10.10",
+            "free_disk_gb": 1028,
+            "free_ram_mb": 7680,
+            "hypervisor_hostname": "fake-mini",
+            "hypervisor_type": "fake",
+            "hypervisor_version": 1,
+            "id": 1,
+            "local_gb": 1028,
+            "local_gb_used": 0,
+            "memory_mb": 8192,
+            "memory_mb_used": 512,
+            "running_vms": 0,
+            "service": {
+                "host": "fake_host",
+                "id": 2},
+            "vcpus": 1,
+            "vcpus_used": 0}}
+        self.check_service_client_function(
+            self.client.show_hypervisor,
+            'tempest.common.service_client.ServiceClient.get',
+            expected, bytes_body,
+            hypervisor_id=self.hypervisor_id)
+
+    def test_list_servers_on_hypervisor_str_body(self):
+        self._test_list_servers_on_hypervisor(bytes_body=False)
+
+    def test_list_servers_on_hypervisor_byte_body(self):
+        self._test_list_servers_on_hypervisor(bytes_body=True)
+
+    def _test_list_servers_on_hypervisor(self, bytes_body=False):
+        expected = {"hypervisors": [{
+            "id": 1,
+            "hypervisor_hostname": "hyper.hostname.com",
+            "servers": [{
+                "uuid": "e1ae8fc4-b72d-4c2f-a427-30dd420b6277",
+                "name": "instance-00000001"},
+                {
+                "uuid": "e1ae8fc4-b72d-4c2f-a427-30dd42066666",
+                "name": "instance-00000002"}
+                ]}
+            ]}
+        self.check_service_client_function(
+            self.client.list_servers_on_hypervisor,
+            'tempest.common.service_client.ServiceClient.get',
+            expected, bytes_body,
+            hypervisor_name=self.hypervisor_name)
+
+    def test_show_hypervisor_statistics_str_body(self):
+        self._test_show_hypervisor_statistics(bytes_body=False)
+
+    def test_show_hypervisor_statistics_byte_body(self):
+        self._test_show_hypervisor_statistics(bytes_body=True)
+
+    def _test_show_hypervisor_statistics(self, bytes_body=False):
+        expected = {
+            "hypervisor_statistics": {
+                "count": 1,
+                "current_workload": 0,
+                "disk_available_least": 0,
+                "free_disk_gb": 1028,
+                "free_ram_mb": 7680,
+                "local_gb": 1028,
+                "local_gb_used": 0,
+                "memory_mb": 8192,
+                "memory_mb_used": 512,
+                "running_vms": 0,
+                "vcpus": 1,
+                "vcpus_used": 0}}
+        self.check_service_client_function(
+            self.client.show_hypervisor_statistics,
+            'tempest.common.service_client.ServiceClient.get',
+            expected, bytes_body)
+
+    def test_show_hypervisor_uptime_str_body(self):
+        self._test_show_hypervisor_uptime(bytes_body=False)
+
+    def test_show_hypervisor_uptime_byte_body(self):
+        self._test_show_hypervisor_uptime(bytes_body=True)
+
+    def _test_show_hypervisor_uptime(self, bytes_body=False):
+        expected = {
+            "hypervisor": {
+                "hypervisor_hostname": "fake-mini",
+                "id": 1,
+                "uptime": (" 08:32:11 up 93 days, 18:25, 12 users, "
+                           " load average: 0.20, 0.12, 0.14")
+            }}
+        self.check_service_client_function(
+            self.client.show_hypervisor_uptime,
+            'tempest.common.service_client.ServiceClient.get',
+            expected, bytes_body,
+            hypervisor_id=self.hypervisor_id)
+
+    def test_search_hypervisor_str_body(self):
+        self._test_search_hypervisor(bytes_body=False)
+
+    def test_search_hypervisor_byte_body(self):
+        self._test_search_hypervisor(bytes_body=True)
+
+    def _test_search_hypervisor(self, bytes_body=False):
+        expected = {"hypervisors": [{
+            "id": 2,
+            "hypervisor_hostname": "hyper.hostname.com"}]}
+        self.check_service_client_function(
+            self.client.search_hypervisor,
+            'tempest.common.service_client.ServiceClient.get',
+            expected, bytes_body,
+            hypervisor_name=self.hypervisor_name)
diff --git a/tempest/tests/services/compute/test_instance_usage_audit_log_client.py b/tempest/tests/services/compute/test_instance_usage_audit_log_client.py
index d4bc889..b4af9d5 100644
--- a/tempest/tests/services/compute/test_instance_usage_audit_log_client.py
+++ b/tempest/tests/services/compute/test_instance_usage_audit_log_client.py
@@ -14,8 +14,9 @@
 
 import datetime
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import instance_usage_audit_log_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_keypairs_client.py b/tempest/tests/services/compute/test_keypairs_client.py
index 6ad187b..8b1a9a8 100644
--- a/tempest/tests/services/compute/test_keypairs_client.py
+++ b/tempest/tests/services/compute/test_keypairs_client.py
@@ -14,8 +14,9 @@
 
 import copy
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import keypairs_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_limits_client.py b/tempest/tests/services/compute/test_limits_client.py
index 0036a3d..733d3d1 100644
--- a/tempest/tests/services/compute/test_limits_client.py
+++ b/tempest/tests/services/compute/test_limits_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import limits_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_migrations_client.py b/tempest/tests/services/compute/test_migrations_client.py
index 83fe461..55f2ef2 100644
--- a/tempest/tests/services/compute/test_migrations_client.py
+++ b/tempest/tests/services/compute/test_migrations_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import migrations_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_networks_client.py b/tempest/tests/services/compute/test_networks_client.py
index b47430b..cec8262 100644
--- a/tempest/tests/services/compute/test_networks_client.py
+++ b/tempest/tests/services/compute/test_networks_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import networks_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_quota_classes_client.py b/tempest/tests/services/compute/test_quota_classes_client.py
index f4fc51a..29800a2 100644
--- a/tempest/tests/services/compute/test_quota_classes_client.py
+++ b/tempest/tests/services/compute/test_quota_classes_client.py
@@ -14,8 +14,9 @@
 
 import copy
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import quota_classes_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_quotas_client.py b/tempest/tests/services/compute/test_quotas_client.py
index 68f74aa..9a9d8fe 100644
--- a/tempest/tests/services/compute/test_quotas_client.py
+++ b/tempest/tests/services/compute/test_quotas_client.py
@@ -14,8 +14,9 @@
 
 import copy
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import quotas_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_security_group_default_rules_client.py b/tempest/tests/services/compute/test_security_group_default_rules_client.py
index 75fa1cb..99ab305 100644
--- a/tempest/tests/services/compute/test_security_group_default_rules_client.py
+++ b/tempest/tests/services/compute/test_security_group_default_rules_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import security_group_default_rules_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_security_group_rules_client.py b/tempest/tests/services/compute/test_security_group_rules_client.py
new file mode 100644
index 0000000..c182742
--- /dev/null
+++ b/tempest/tests/services/compute/test_security_group_rules_client.py
@@ -0,0 +1,66 @@
+# 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.services.compute.json import security_group_rules_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestSecurityGroupRulesClient(base.BaseComputeServiceTest):
+
+    FAKE_SECURITY_GROUP_RULE = {
+        "security_group_rule": {
+            "id": "2d021cf1-ce4b-4292-994f-7a785d62a144",
+            "ip_range": {
+                "cidr": "0.0.0.0/0"
+            },
+            "parent_group_id": "48700ff3-30b8-4e63-845f-a79c9633e9fb",
+            "to_port": 443,
+            "ip_protocol": "tcp",
+            "group": {},
+            "from_port": 443
+        }
+    }
+
+    def setUp(self):
+        super(TestSecurityGroupRulesClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = security_group_rules_client.SecurityGroupRulesClient(
+            fake_auth, 'compute', 'regionOne')
+
+    def _test_create_security_group_rule(self, bytes_body=False):
+        req_body = {
+            "from_port": "443",
+            "ip_protocol": "tcp",
+            "to_port": "443",
+            "cidr": "0.0.0.0/0",
+            "parent_group_id": "48700ff3-30b8-4e63-845f-a79c9633e9fb"
+        }
+        self.check_service_client_function(
+            self.client.create_security_group_rule,
+            'tempest.common.service_client.ServiceClient.post',
+            self.FAKE_SECURITY_GROUP_RULE,
+            to_utf=bytes_body, **req_body)
+
+    def test_create_security_group_rule_with_str_body(self):
+        self._test_create_security_group_rule()
+
+    def test_create_security_group_rule_with_bytes_body(self):
+        self._test_create_security_group_rule(bytes_body=True)
+
+    def test_delete_security_group_rule(self):
+        self.check_service_client_function(
+            self.client.delete_security_group_rule,
+            'tempest.common.service_client.ServiceClient.delete',
+            {}, status=202, group_rule_id='group-id')
diff --git a/tempest/tests/services/compute/test_security_groups_client.py b/tempest/tests/services/compute/test_security_groups_client.py
index 7a39048..9e40b96 100644
--- a/tempest/tests/services/compute/test_security_groups_client.py
+++ b/tempest/tests/services/compute/test_security_groups_client.py
@@ -14,9 +14,9 @@
 
 from oslotest import mockpatch
 from tempest_lib import exceptions as lib_exc
+from tempest_lib.tests import fake_auth_provider
 
 from tempest.services.compute.json import security_groups_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_server_groups_client.py b/tempest/tests/services/compute/test_server_groups_client.py
index 253dac1..5e058d6 100644
--- a/tempest/tests/services/compute/test_server_groups_client.py
+++ b/tempest/tests/services/compute/test_server_groups_client.py
@@ -15,9 +15,9 @@
 import httplib2
 
 from oslotest import mockpatch
+from tempest_lib.tests import fake_auth_provider
 
 from tempest.services.compute.json import server_groups_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_services_client.py b/tempest/tests/services/compute/test_services_client.py
index e5a25ab..fce28e8 100644
--- a/tempest/tests/services/compute/test_services_client.py
+++ b/tempest/tests/services/compute/test_services_client.py
@@ -14,8 +14,9 @@
 
 import copy
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import services_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_tenant_networks_client.py b/tempest/tests/services/compute/test_tenant_networks_client.py
index dc2de00..691792a 100644
--- a/tempest/tests/services/compute/test_tenant_networks_client.py
+++ b/tempest/tests/services/compute/test_tenant_networks_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import tenant_networks_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
diff --git a/tempest/tests/services/compute/test_tenant_usages_client.py b/tempest/tests/services/compute/test_tenant_usages_client.py
index 8a2c1a4..58e0b7a 100644
--- a/tempest/tests/services/compute/test_tenant_usages_client.py
+++ b/tempest/tests/services/compute/test_tenant_usages_client.py
@@ -12,8 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib.tests import fake_auth_provider
+
 from tempest.services.compute.json import tenant_usages_client
-from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base