Merge "skip test_list_server_filters_by_regex"
diff --git a/.coveragerc b/.coveragerc
index c9b6467..51482d3 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,4 +1,4 @@
 [run]
 branch = True
 source = tempest
-omit = tempest/tests/*,tempest/openstack/*
+omit = tempest/tests/*,tempest/scenario/test_*.py,tempest/api_schema/*,tempest/api/*
diff --git a/requirements.txt b/requirements.txt
index aa304a4..43f8ff7 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,27 +1,27 @@
 # The order of packages is significant, because pip processes them in the order
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
-pbr>=1.6
+pbr>=1.6 # Apache-2.0
 cliff>=1.15.0 # Apache-2.0
-anyjson>=0.3.3
-httplib2>=0.7.5
-jsonschema!=2.5.0,<3.0.0,>=2.0.0
-testtools>=1.4.0
-paramiko>=1.13.0
-netaddr!=0.7.16,>=0.7.12
-testrepository>=0.0.18
-pyOpenSSL>=0.14
+anyjson>=0.3.3 # BSD
+httplib2>=0.7.5 # MIT
+jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
+testtools>=1.4.0 # MIT
+paramiko>=1.13.0 # LGPL
+netaddr!=0.7.16,>=0.7.12 # BSD
+testrepository>=0.0.18 # Apache-2.0/BSD
+pyOpenSSL>=0.14 # Apache-2.0
 oslo.concurrency>=2.3.0 # Apache-2.0
-oslo.config>=3.2.0 # Apache-2.0
-oslo.i18n>=1.5.0 # Apache-2.0
+oslo.config>=3.4.0 # Apache-2.0
+oslo.i18n>=2.1.0 # Apache-2.0
 oslo.log>=1.14.0 # Apache-2.0
 oslo.serialization>=1.10.0 # Apache-2.0
-oslo.utils>=3.2.0 # Apache-2.0
-six>=1.9.0
-iso8601>=0.1.9
-fixtures>=1.3.1
-testscenarios>=0.4
-tempest-lib>=0.13.0
-PyYAML>=3.1.0
+oslo.utils>=3.4.0 # Apache-2.0
+six>=1.9.0 # MIT
+iso8601>=0.1.9 # MIT
+fixtures>=1.3.1 # Apache-2.0/BSD
+testscenarios>=0.4 # Apache-2.0/BSD
+tempest-lib>=0.13.0 # Apache-2.0
+PyYAML>=3.1.0 # MIT
 stevedore>=1.5.0 # Apache-2.0
-PrettyTable<0.8,>=0.7
+PrettyTable<0.8,>=0.7 # BSD
diff --git a/tempest/api/compute/keypairs/base.py b/tempest/api/compute/keypairs/base.py
index 15f231b..ebfb724 100644
--- a/tempest/api/compute/keypairs/base.py
+++ b/tempest/api/compute/keypairs/base.py
@@ -27,10 +27,12 @@
     def _delete_keypair(self, keypair_name):
         self.client.delete_keypair(keypair_name)
 
-    def _create_keypair(self, keypair_name, pub_key=None):
+    def _create_keypair(self, keypair_name, pub_key=None, keypair_type=None):
         kwargs = {'name': keypair_name}
         if pub_key:
             kwargs.update({'public_key': pub_key})
+        if keypair_type:
+            kwargs.update({'type': keypair_type})
         body = self.client.create_keypair(**kwargs)['keypair']
         self.addCleanup(self._delete_keypair, keypair_name)
         return body
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index d10bf14..be6f615 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -19,6 +19,8 @@
 
 
 class KeyPairsV2TestJSON(base.BaseKeypairTest):
+    max_microversion = '2.1'
+
     @test.idempotent_id('1d1dbedb-d7a0-432a-9d09-83f543c3c19b')
     def test_keypairs_create_list_delete(self):
         # Keypairs created should be available in the response list
diff --git a/tempest/api/compute/keypairs/test_keypairs_v22.py b/tempest/api/compute/keypairs/test_keypairs_v22.py
new file mode 100644
index 0000000..997ef9b
--- /dev/null
+++ b/tempest/api/compute/keypairs/test_keypairs_v22.py
@@ -0,0 +1,51 @@
+# Copyright 2016 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute.keypairs import test_keypairs
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class KeyPairsV22TestJSON(test_keypairs.KeyPairsV2TestJSON):
+    min_microversion = '2.2'
+    max_microversion = 'latest'
+
+    def _check_keypair_type(self, keypair, keypair_type):
+        if keypair_type is None:
+            keypair_type = 'ssh'
+        self.assertEqual(keypair_type, keypair['type'])
+
+    def _test_keypairs_create_list_show(self, keypair_type=None):
+        k_name = data_utils.rand_name('keypair')
+        keypair = self._create_keypair(k_name, keypair_type=keypair_type)
+        # Verify whether 'type' is present in keypair create response of
+        # version 2.2 and it is with default value 'ssh'.
+        self._check_keypair_type(keypair, keypair_type)
+        keypair_detail = self.client.show_keypair(k_name)['keypair']
+        self._check_keypair_type(keypair_detail, keypair_type)
+        fetched_list = self.client.list_keypairs()['keypairs']
+        for keypair in fetched_list:
+            # Verify whether 'type' is present in keypair list response of
+            # version 2.2 and it is with default value 'ssh'.
+            if keypair['keypair']['name'] == k_name:
+                self._check_keypair_type(keypair['keypair'], keypair_type)
+
+    @test.idempotent_id('8726fa85-7f98-4b20-af9e-f710a4f3391c')
+    def test_keypairsv22_create_list_show(self):
+        self._test_keypairs_create_list_show()
+
+    @test.idempotent_id('89d59d43-f735-441a-abcf-0601727f47b6')
+    def test_keypairsv22_create_list_show_with_type(self):
+        keypair_type = 'x509'
+        self._test_keypairs_create_list_show(keypair_type=keypair_type)
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index 9aa59f7..38c294b 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -158,7 +158,9 @@
             to_port=to_port2)['security_group_rule']
         rule2_id = rule['id']
         # Delete the Security Group rule2 at the end of this method
-        self.addCleanup(self.client.delete_security_group_rule, rule2_id)
+        self.addCleanup(
+            self.security_group_rules_client.delete_security_group_rule,
+            rule2_id)
 
         # Get rules of the created Security Group
         rules = self.security_groups_client.show_security_group(
diff --git a/tempest/api/identity/admin/v2/test_endpoints.py b/tempest/api/identity/admin/v2/test_endpoints.py
index bff4f91..df75d0a 100644
--- a/tempest/api/identity/admin/v2/test_endpoints.py
+++ b/tempest/api/identity/admin/v2/test_endpoints.py
@@ -27,7 +27,7 @@
         s_name = data_utils.rand_name('service')
         s_type = data_utils.rand_name('type')
         s_description = data_utils.rand_name('description')
-        cls.service_data = cls.client.create_service(
+        cls.service_data = cls.services_client.create_service(
             s_name, s_type, description=s_description)['OS-KSADM:service']
         cls.service_id = cls.service_data['id']
         cls.service_ids.append(cls.service_id)
@@ -36,11 +36,12 @@
         for i in range(2):
             region = data_utils.rand_name('region')
             url = data_utils.rand_url()
-            endpoint = cls.client.create_endpoint(cls.service_id,
-                                                  region,
-                                                  publicurl=url,
-                                                  adminurl=url,
-                                                  internalurl=url)['endpoint']
+            endpoint = cls.endpoints_client.create_endpoint(
+                cls.service_id,
+                region,
+                publicurl=url,
+                adminurl=url,
+                internalurl=url)['endpoint']
             # list_endpoints() will return 'enabled' field
             endpoint['enabled'] = True
             cls.setup_endpoints.append(endpoint)
@@ -48,15 +49,15 @@
     @classmethod
     def resource_cleanup(cls):
         for e in cls.setup_endpoints:
-            cls.client.delete_endpoint(e['id'])
+            cls.endpoints_client.delete_endpoint(e['id'])
         for s in cls.service_ids:
-            cls.client.delete_service(s)
+            cls.services_client.delete_service(s)
         super(EndPointsTestJSON, cls).resource_cleanup()
 
     @test.idempotent_id('11f590eb-59d8-4067-8b2b-980c7f387f51')
     def test_list_endpoints(self):
         # Get a list of endpoints
-        fetched_endpoints = self.client.list_endpoints()['endpoints']
+        fetched_endpoints = self.endpoints_client.list_endpoints()['endpoints']
         # Asserting LIST endpoints
         missing_endpoints =\
             [e for e in self.setup_endpoints if e not in fetched_endpoints]
@@ -68,22 +69,23 @@
     def test_create_list_delete_endpoint(self):
         region = data_utils.rand_name('region')
         url = data_utils.rand_url()
-        endpoint = self.client.create_endpoint(self.service_id,
-                                               region,
-                                               publicurl=url,
-                                               adminurl=url,
-                                               internalurl=url)['endpoint']
+        endpoint = self.endpoints_client.create_endpoint(
+            self.service_id,
+            region,
+            publicurl=url,
+            adminurl=url,
+            internalurl=url)['endpoint']
         # Asserting Create Endpoint response body
         self.assertIn('id', endpoint)
         self.assertEqual(region, endpoint['region'])
         self.assertEqual(url, endpoint['publicurl'])
         # Checking if created endpoint is present in the list of endpoints
-        fetched_endpoints = self.client.list_endpoints()['endpoints']
+        fetched_endpoints = self.endpoints_client.list_endpoints()['endpoints']
         fetched_endpoints_id = [e['id'] for e in fetched_endpoints]
         self.assertIn(endpoint['id'], fetched_endpoints_id)
         # Deleting the endpoint created in this method
-        self.client.delete_endpoint(endpoint['id'])
+        self.endpoints_client.delete_endpoint(endpoint['id'])
         # Checking whether endpoint is deleted successfully
-        fetched_endpoints = self.client.list_endpoints()['endpoints']
+        fetched_endpoints = self.endpoints_client.list_endpoints()['endpoints']
         fetched_endpoints_id = [e['id'] for e in fetched_endpoints]
         self.assertNotIn(endpoint['id'], fetched_endpoints_id)
diff --git a/tempest/api/identity/admin/v2/test_roles.py b/tempest/api/identity/admin/v2/test_roles.py
index 3f3d16e..5847129 100644
--- a/tempest/api/identity/admin/v2/test_roles.py
+++ b/tempest/api/identity/admin/v2/test_roles.py
@@ -33,9 +33,9 @@
     def _get_role_params(self):
         self.data.setup_test_user()
         self.data.setup_test_role()
-        user = self.get_user_by_name(self.data.test_user)
-        tenant = self.get_tenant_by_name(self.data.test_tenant)
-        role = self.get_role_by_name(self.data.test_role)
+        user = self.get_user_by_name(self.data.user['name'])
+        tenant = self.get_tenant_by_name(self.data.tenant['name'])
+        role = self.get_role_by_name(self.data.role['name'])
         return (user, tenant, role)
 
     def assert_role_in_role_list(self, role, roles):
diff --git a/tempest/api/identity/admin/v2/test_roles_negative.py b/tempest/api/identity/admin/v2/test_roles_negative.py
index c9af7c6..23a1958 100644
--- a/tempest/api/identity/admin/v2/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.py
@@ -27,9 +27,9 @@
     def _get_role_params(self):
         self.data.setup_test_user()
         self.data.setup_test_role()
-        user = self.get_user_by_name(self.data.test_user)
-        tenant = self.get_tenant_by_name(self.data.test_tenant)
-        role = self.get_role_by_name(self.data.test_role)
+        user = self.get_user_by_name(self.data.user['name'])
+        tenant = self.get_tenant_by_name(self.data.tenant['name'])
+        role = self.get_role_by_name(self.data.role['name'])
         return (user, tenant, role)
 
     @test.attr(type=['negative'])
diff --git a/tempest/api/identity/admin/v2/test_services.py b/tempest/api/identity/admin/v2/test_services.py
index 04e15d2..5685922 100644
--- a/tempest/api/identity/admin/v2/test_services.py
+++ b/tempest/api/identity/admin/v2/test_services.py
@@ -25,9 +25,9 @@
 
     def _del_service(self, service_id):
         # Deleting the service created in this method
-        self.client.delete_service(service_id)
+        self.services_client.delete_service(service_id)
         # Checking whether service is deleted successfully
-        self.assertRaises(lib_exc.NotFound, self.client.show_service,
+        self.assertRaises(lib_exc.NotFound, self.services_client.show_service,
                           service_id)
 
     @test.idempotent_id('84521085-c6e6-491c-9a08-ec9f70f90110')
@@ -37,7 +37,7 @@
         name = data_utils.rand_name('service')
         type = data_utils.rand_name('type')
         description = data_utils.rand_name('description')
-        service_data = self.client.create_service(
+        service_data = self.services_client.create_service(
             name, type, description=description)['OS-KSADM:service']
         self.assertFalse(service_data['id'] is None)
         self.addCleanup(self._del_service, service_data['id'])
@@ -50,8 +50,9 @@
         self.assertIn('description', service_data)
         self.assertEqual(description, service_data['description'])
         # Get service
-        fetched_service = (self.client.show_service(service_data['id'])
-                           ['OS-KSADM:service'])
+        fetched_service = (
+            self.services_client.show_service(service_data['id'])
+            ['OS-KSADM:service'])
         # verifying the existence of service created
         self.assertIn('id', fetched_service)
         self.assertEqual(fetched_service['id'], service_data['id'])
@@ -68,7 +69,8 @@
         # Create a service only with name and type
         name = data_utils.rand_name('service')
         type = data_utils.rand_name('type')
-        service = self.client.create_service(name, type)['OS-KSADM:service']
+        service = self.services_client.create_service(name,
+                                                      type)['OS-KSADM:service']
         self.assertIn('id', service)
         self.addCleanup(self._del_service, service['id'])
         self.assertIn('name', service)
@@ -85,17 +87,17 @@
             name = data_utils.rand_name('service')
             type = data_utils.rand_name('type')
             description = data_utils.rand_name('description')
-            service = self.client.create_service(
+            service = self.services_client.create_service(
                 name, type, description=description)['OS-KSADM:service']
             services.append(service)
         service_ids = map(lambda x: x['id'], services)
 
         def delete_services():
             for service_id in service_ids:
-                self.client.delete_service(service_id)
+                self.services_client.delete_service(service_id)
 
         self.addCleanup(delete_services)
         # List and Verify Services
-        body = self.client.list_services()['OS-KSADM:services']
+        body = self.services_client.list_services()['OS-KSADM:services']
         found = [serv for serv in body if serv['id'] in service_ids]
         self.assertEqual(len(found), len(services), 'Services not found')
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index 4497575..60c4e97 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -95,27 +95,29 @@
         # Valid user's token is authenticated
         self.data.setup_test_user()
         # Get a token
-        self.token_client.auth(self.data.test_user, self.data.test_password,
-                               self.data.test_tenant)
+        self.token_client.auth(self.data.user['name'],
+                               self.data.user_password,
+                               self.data.tenant['name'])
         # Re-auth
-        self.token_client.auth(self.data.test_user,
-                               self.data.test_password,
-                               self.data.test_tenant)
+        self.token_client.auth(self.data.user['name'],
+                               self.data.user_password,
+                               self.data.tenant['name'])
 
     @test.idempotent_id('5d1fa498-4c2d-4732-a8fe-2b054598cfdd')
     def test_authentication_request_without_token(self):
         # Request for token authentication with a valid token in header
         self.data.setup_test_user()
-        self.token_client.auth(self.data.test_user, self.data.test_password,
-                               self.data.test_tenant)
+        self.token_client.auth(self.data.user['name'],
+                               self.data.user_password,
+                               self.data.tenant['name'])
         # Get the token of the current client
         token = self.client.auth_provider.get_token()
         # Delete the token from database
         self.client.delete_token(token)
         # Re-auth
-        self.token_client.auth(self.data.test_user,
-                               self.data.test_password,
-                               self.data.test_tenant)
+        self.token_client.auth(self.data.user['name'],
+                               self.data.user_password,
+                               self.data.tenant['name'])
         self.client.auth_provider.clear_auth()
 
     @test.idempotent_id('a149c02e-e5e0-4b89-809e-7e8faf33ccda')
@@ -124,8 +126,8 @@
         self.data.setup_test_user()
         users = self.users_client.list_users()['users']
         self.assertThat([u['name'] for u in users],
-                        matchers.Contains(self.data.test_user),
-                        "Could not find %s" % self.data.test_user)
+                        matchers.Contains(self.data.user['name']),
+                        "Could not find %s" % self.data.user['name'])
 
     @test.idempotent_id('6e317209-383a-4bed-9f10-075b7c82c79a')
     def test_list_users_for_tenant(self):
@@ -164,9 +166,9 @@
         # Return list of users on tenant when roles are assigned to users
         self.data.setup_test_user()
         self.data.setup_test_role()
-        user = self.get_user_by_name(self.data.test_user)
-        tenant = self.get_tenant_by_name(self.data.test_tenant)
-        role = self.get_role_by_name(self.data.test_role)
+        user = self.get_user_by_name(self.data.user['name'])
+        tenant = self.get_tenant_by_name(self.data.tenant['name'])
+        role = self.get_role_by_name(self.data.role['name'])
         # Assigning roles to two users
         user_ids = list()
         fetched_user_ids = list()
@@ -208,6 +210,6 @@
 
         # Validate the updated password
         # Get a token
-        body = self.token_client.auth(self.data.test_user, new_pass,
-                                      self.data.test_tenant)
+        body = self.token_client.auth(self.data.user['name'], new_pass,
+                                      self.data.tenant['name'])
         self.assertTrue('id' in body['token'])
diff --git a/tempest/api/identity/admin/v2/test_users_negative.py b/tempest/api/identity/admin/v2/test_users_negative.py
index c5248fd..0a5d0c9 100644
--- a/tempest/api/identity/admin/v2/test_users_negative.py
+++ b/tempest/api/identity/admin/v2/test_users_negative.py
@@ -66,8 +66,8 @@
         # Duplicate user should not be created
         self.data.setup_test_user()
         self.assertRaises(lib_exc.Conflict, self.users_client.create_user,
-                          self.data.test_user, self.data.test_password,
-                          self.data.tenant['id'], self.data.test_email)
+                          self.data.user['name'], self.data.user_password,
+                          self.data.tenant['id'], self.data.user['email'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('0132cc22-7c4f-42e1-9e50-ac6aad31d59a')
@@ -173,22 +173,22 @@
     def test_authentication_for_disabled_user(self):
         # Disabled user's token should not get authenticated
         self.data.setup_test_user()
-        self.disable_user(self.data.test_user)
+        self.disable_user(self.data.user['name'])
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          self.data.test_user,
-                          self.data.test_password,
-                          self.data.test_tenant)
+                          self.data.user['name'],
+                          self.data.user_password,
+                          self.data.tenant['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('440a7a8d-9328-4b7b-83e0-d717010495e4')
     def test_authentication_when_tenant_is_disabled(self):
         # User's token for a disabled tenant should not be authenticated
         self.data.setup_test_user()
-        self.disable_tenant(self.data.test_tenant)
+        self.disable_tenant(self.data.tenant['name'])
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          self.data.test_user,
-                          self.data.test_password,
-                          self.data.test_tenant)
+                          self.data.user['name'],
+                          self.data.user_password,
+                          self.data.tenant['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('921f1ad6-7907-40b8-853f-637e7ee52178')
@@ -196,8 +196,8 @@
         # User's token for an invalid tenant should not be authenticated
         self.data.setup_test_user()
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          self.data.test_user,
-                          self.data.test_password,
+                          self.data.user['name'],
+                          self.data.user_password,
                           'junktenant1234')
 
     @test.attr(type=['negative'])
@@ -206,8 +206,8 @@
         # Non-existent user's token should not get authenticated
         self.data.setup_test_user()
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          'junkuser123', self.data.test_password,
-                          self.data.test_tenant)
+                          'junkuser123', self.data.user_password,
+                          self.data.tenant['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('d5308b33-3574-43c3-8d87-1c090c5e1eca')
@@ -215,8 +215,8 @@
         # User's token with invalid password should not be authenticated
         self.data.setup_test_user()
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          self.data.test_user, 'junkpass1234',
-                          self.data.test_tenant)
+                          self.data.user['name'], 'junkpass1234',
+                          self.data.tenant['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('284192ce-fb7c-4909-a63b-9a502e0ddd11')
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 21fc62a..03b8b29 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -76,8 +76,10 @@
         # list users in group
         group_users = self.groups_client.list_group_users(group['id'])['users']
         self.assertEqual(sorted(users), sorted(group_users))
-        # delete user in group
+        # check and delete user in group
         for user in users:
+            self.groups_client.check_group_user_existence(
+                group['id'], user['id'])
             self.groups_client.delete_group_user(group['id'], user['id'])
         group_users = self.groups_client.list_group_users(group['id'])['users']
         self.assertEqual(len(group_users), 0)
diff --git a/tempest/api/identity/admin/v3/test_list_users.py b/tempest/api/identity/admin/v3/test_list_users.py
index ca91ce5..4921c00 100644
--- a/tempest/api/identity/admin/v3/test_list_users.py
+++ b/tempest/api/identity/admin/v3/test_list_users.py
@@ -42,13 +42,13 @@
         cls.domain_enabled_user = cls.client.create_user(
             u1_name, password=alt_password,
             email=cls.alt_email, domain_id=cls.data.domain['id'])['user']
-        cls.data.v3_users.append(cls.domain_enabled_user)
+        cls.data.users.append(cls.domain_enabled_user)
         # Create default not enabled user
         u2_name = data_utils.rand_name('test_user')
         cls.non_domain_enabled_user = cls.client.create_user(
             u2_name, password=alt_password,
             email=cls.alt_email, enabled=False)['user']
-        cls.data.v3_users.append(cls.non_domain_enabled_user)
+        cls.data.users.append(cls.non_domain_enabled_user)
 
     @test.idempotent_id('08f9aabb-dcfe-41d0-8172-82b5fa0bd73d')
     def test_list_user_domains(self):
@@ -79,7 +79,7 @@
         # List users
         body = self.client.list_users()['users']
         fetched_ids = [u['id'] for u in body]
-        missing_users = [u['id'] for u in self.data.v3_users
+        missing_users = [u['id'] for u in self.data.users
                          if u['id'] not in fetched_ids]
         self.assertEqual(0, len(missing_users),
                          "Failed to find user %s in fetched list" %
@@ -88,8 +88,8 @@
     @test.idempotent_id('b4baa3ae-ac00-4b4e-9e27-80deaad7771f')
     def test_get_user(self):
         # Get a user detail
-        user = self.client.show_user(self.data.v3_users[0]['id'])['user']
-        self.assertEqual(self.data.v3_users[0]['id'], user['id'])
-        self.assertEqual(self.data.v3_users[0]['name'], user['name'])
+        user = self.client.show_user(self.data.users[0]['id'])['user']
+        self.assertEqual(self.data.users[0]['id'], user['id'])
+        self.assertEqual(self.data.users[0]['name'], user['name'])
         self.assertEqual(self.alt_email, user['email'])
         self.assertEqual(self.data.domain['id'], user['domain_id'])
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index ae714aa..f1f06ee 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -26,7 +26,7 @@
         for _ in range(3):
             role_name = data_utils.rand_name(name='role')
             role = cls.client.create_role(name=role_name)['role']
-            cls.data.v3_roles.append(role)
+            cls.data.roles.append(role)
         cls.fetched_role_ids = list()
         u_name = data_utils.rand_name('user')
         u_desc = '%s description' % u_name
@@ -103,6 +103,9 @@
         self._list_assertions(roles, self.fetched_role_ids,
                               self.role['id'])
 
+        self.client.check_user_role_existence_on_project(
+            self.project['id'], self.user_body['id'], self.role['id'])
+
         self.client.delete_role_from_user_on_project(
             self.project['id'], self.user_body['id'], self.role['id'])
 
@@ -120,6 +123,9 @@
         self._list_assertions(roles, self.fetched_role_ids,
                               self.role['id'])
 
+        self.client.check_user_role_existence_on_domain(
+            self.domain['id'], self.user_body['id'], self.role['id'])
+
         self.client.delete_role_from_user_on_domain(
             self.domain['id'], self.user_body['id'], self.role['id'])
 
@@ -150,6 +156,10 @@
         roles = body['token']['roles']
         self.assertEqual(len(roles), 1)
         self.assertEqual(roles[0]['id'], self.role['id'])
+
+        self.client.check_role_from_group_on_project_existence(
+            self.project['id'], self.group_body['id'], self.role['id'])
+
         # Revoke role to group on project
         self.client.delete_role_from_group_on_project(
             self.project['id'], self.group_body['id'], self.role['id'])
@@ -168,6 +178,9 @@
         self._list_assertions(roles, self.fetched_role_ids,
                               self.role['id'])
 
+        self.client.check_role_from_group_on_domain_existence(
+            self.domain['id'], self.group_body['id'], self.role['id'])
+
         self.client.delete_role_from_group_on_domain(
             self.domain['id'], self.group_body['id'], self.role['id'])
 
@@ -175,5 +188,5 @@
     def test_list_roles(self):
         # Return a list of all roles
         body = self.client.list_roles()['roles']
-        found = [role for role in body if role in self.data.v3_roles]
-        self.assertEqual(len(found), len(self.data.v3_roles))
+        found = [role for role in body if role in self.data.roles]
+        self.assertEqual(len(found), len(self.data.roles))
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index a402b3f..894a7a9 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -151,6 +151,6 @@
     @test.idempotent_id('c10dcd90-461d-4b16-8e23-4eb836c00644')
     def test_get_user(self):
         # Get a user detail
-        self.data.setup_test_v3_user()
-        user = self.client.show_user(self.data.v3_user['id'])['user']
-        self.assertEqual(self.data.v3_user['id'], user['id'])
+        self.data.setup_test_user()
+        user = self.client.show_user(self.data.user['id'])['user']
+        self.assertEqual(self.data.user['id'], user['id'])
diff --git a/tempest/api/identity/admin/v3/test_users_negative.py b/tempest/api/identity/admin/v3/test_users_negative.py
index 4c80bda..39c89a5 100644
--- a/tempest/api/identity/admin/v3/test_users_negative.py
+++ b/tempest/api/identity/admin/v3/test_users_negative.py
@@ -38,9 +38,9 @@
     @test.idempotent_id('b3c9fccc-4134-46f5-b600-1da6fb0a3b1f')
     def test_authentication_for_disabled_user(self):
         # Attempt to authenticate for disabled user should fail
-        self.data.setup_test_v3_user()
-        self.disable_user(self.data.test_user)
+        self.data.setup_test_user()
+        self.disable_user(self.data.user['name'])
         self.assertRaises(lib_exc.Unauthorized, self.token.auth,
-                          username=self.data.test_user,
-                          password=self.data.test_password,
+                          username=self.data.user['name'],
+                          password=self.data.user_password,
                           user_domain_id='default')
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 1ad8b92..91d620c 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -16,7 +16,6 @@
 from oslo_log import log as logging
 from tempest_lib import exceptions as lib_exc
 
-from tempest.common import credentials_factory as common_creds
 from tempest.common.utils import data_utils
 from tempest import config
 import tempest.test
@@ -104,12 +103,14 @@
         cls.non_admin_roles_client = cls.os.roles_client
         cls.users_client = cls.os_adm.users_client
         cls.non_admin_users_client = cls.os.users_client
+        cls.services_client = cls.os_adm.services_v2_client
+        cls.endpoints_client = cls.os_adm.endpoints_v2_client
 
     @classmethod
     def resource_setup(cls):
         super(BaseIdentityV2AdminTest, cls).resource_setup()
-        cls.data = DataGenerator(cls.client, cls.tenants_client,
-                                 cls.roles_client, cls.users_client)
+        cls.data = DataGeneratorV2(cls.client, cls.tenants_client,
+                                   cls.users_client, cls.roles_client)
 
     @classmethod
     def resource_cleanup(cls):
@@ -152,7 +153,10 @@
         cls.creds_client = cls.os_adm.credentials_client
         cls.groups_client = cls.os_adm.groups_client
 
-        cls.data = DataGenerator(cls.client)
+    @classmethod
+    def resource_setup(cls):
+        super(BaseIdentityV3AdminTest, cls).resource_setup()
+        cls.data = DataGeneratorV3(cls.client)
 
     @classmethod
     def resource_cleanup(cls):
@@ -192,127 +196,98 @@
         self.client.delete_domain(domain_id)
 
 
-class DataGenerator(object):
+class BaseDataGenerator(object):
 
-        def __init__(self, client, tenants_client=None, roles_client=None,
-                     users_client=None):
-            self.client = client
-            # TODO(dmellado) split Datagenerator for v2 and v3
-            self.tenants_client = tenants_client
-            self.roles_client = roles_client
-            self.users_client = users_client
-            self.users = []
-            self.tenants = []
-            self.roles = []
-            self.role_name = None
-            self.v3_users = []
-            self.projects = []
-            self.v3_roles = []
-            self.domains = []
+    def __init__(self, client, projects_client=None,
+                 users_client=None, roles_client=None):
+        self.client = client
+        self.projects_client = projects_client or client
+        self.users_client = users_client or client
+        self.roles_client = roles_client or client
 
-        @property
-        def test_credentials(self):
-            return common_creds.get_credentials(username=self.test_user,
-                                                user_id=self.user['id'],
-                                                password=self.test_password,
-                                                tenant_name=self.test_tenant,
-                                                tenant_id=self.tenant['id'])
+        self.user_password = None
+        self.user = None
+        self.tenant = None
+        self.project = None
+        self.role = None
+        self.domain = None
 
-        def setup_test_user(self):
-            """Set up a test user."""
-            self.setup_test_tenant()
-            self.test_user = data_utils.rand_name('test_user')
-            self.test_password = data_utils.rand_password()
-            self.test_email = self.test_user + '@testmail.tm'
-            self.user = self.users_client.create_user(self.test_user,
-                                                      self.test_password,
-                                                      self.tenant['id'],
-                                                      self.test_email)['user']
-            self.users.append(self.user)
+        self.users = []
+        self.tenants = []
+        self.projects = []
+        self.roles = []
+        self.domains = []
 
-        def setup_test_tenant(self):
-            """Set up a test tenant."""
-            self.test_tenant = data_utils.rand_name('test_tenant')
-            self.test_description = data_utils.rand_name('desc')
-            self.tenant = self.tenants_client.create_tenant(
-                name=self.test_tenant,
-                description=self.test_description)['tenant']
-            self.tenants.append(self.tenant)
+    def _create_test_user(self, **kwargs):
+        username = data_utils.rand_name('test_user')
+        self.user_password = data_utils.rand_password()
+        self.user = self.users_client.create_user(
+            username, password=self.user_password,
+            email=username + '@testmail.tm', **kwargs)['user']
+        self.users.append(self.user)
 
-        def setup_test_role(self):
-            """Set up a test role."""
-            self.test_role = data_utils.rand_name('role')
-            self.role = self.roles_client.create_role(
-                name=self.test_role)['role']
-            self.roles.append(self.role)
+    def setup_test_role(self):
+        """Set up a test role."""
+        self.role = self.roles_client.create_role(
+            name=data_utils.rand_name('test_role'))['role']
+        self.roles.append(self.role)
 
-        def setup_test_v3_user(self):
-            """Set up a test v3 user."""
-            self.setup_test_project()
-            self.test_user = data_utils.rand_name('test_user')
-            self.test_password = data_utils.rand_password()
-            self.test_email = self.test_user + '@testmail.tm'
-            self.v3_user = self.client.create_user(
-                self.test_user,
-                password=self.test_password,
-                project_id=self.project['id'],
-                email=self.test_email)['user']
-            self.v3_users.append(self.v3_user)
+    @staticmethod
+    def _try_wrapper(func, item, **kwargs):
+        try:
+            func(item['id'], **kwargs)
+        except lib_exc.NotFound:
+            pass
+        except Exception:
+            LOG.exception("Unexpected exception occurred in %s deletion. "
+                          "But ignored here." % item['id'])
 
-        def setup_test_project(self):
-            """Set up a test project."""
-            self.test_project = data_utils.rand_name('test_project')
-            self.test_description = data_utils.rand_name('desc')
-            self.project = self.client.create_project(
-                name=self.test_project,
-                description=self.test_description)['project']
-            self.projects.append(self.project)
+    def teardown_all(self):
+        for user in self.users:
+            self._try_wrapper(self.users_client.delete_user, user)
+        for tenant in self.tenants:
+            self._try_wrapper(self.projects_client.delete_tenant, tenant)
+        for project in self.projects:
+            self._try_wrapper(self.projects_client.delete_project, project)
+        for role in self.roles:
+            self._try_wrapper(self.roles_client.delete_role, role)
+        for domain in self.domains:
+            self._try_wrapper(self.client.update_domain, domain, enabled=False)
+            self._try_wrapper(self.client.delete_domain, domain)
 
-        def setup_test_v3_role(self):
-            """Set up a test v3 role."""
-            self.test_role = data_utils.rand_name('role')
-            self.v3_role = self.client.create_role(name=self.test_role)['role']
-            self.v3_roles.append(self.v3_role)
 
-        def setup_test_domain(self):
-            """Set up a test domain."""
-            self.test_domain = data_utils.rand_name('test_domain')
-            self.test_description = data_utils.rand_name('desc')
-            self.domain = self.client.create_domain(
-                name=self.test_domain,
-                description=self.test_description)['domain']
-            self.domains.append(self.domain)
+class DataGeneratorV2(BaseDataGenerator):
 
-        @staticmethod
-        def _try_wrapper(func, item, **kwargs):
-            try:
-                if kwargs:
-                    func(item['id'], **kwargs)
-                else:
-                    func(item['id'])
-            except lib_exc.NotFound:
-                pass
-            except Exception:
-                LOG.exception("Unexpected exception occurred in %s deletion."
-                              " But ignored here." % item['id'])
+    def setup_test_user(self):
+        """Set up a test user."""
+        self.setup_test_tenant()
+        self._create_test_user(tenant_id=self.tenant['id'])
 
-        def teardown_all(self):
-            # NOTE(masayukig): v3 client doesn't have v2 method.
-            # (e.g. delete_tenant) So we need to check resources existence
-            # before using client methods.
-            for user in self.users:
-                self._try_wrapper(self.users_client.delete_user, user)
-            for tenant in self.tenants:
-                self._try_wrapper(self.tenants_client.delete_tenant, tenant)
-            for role in self.roles:
-                self._try_wrapper(self.roles_client.delete_role, role)
-            for v3_user in self.v3_users:
-                self._try_wrapper(self.client.delete_user, v3_user)
-            for v3_project in self.projects:
-                self._try_wrapper(self.client.delete_project, v3_project)
-            for v3_role in self.v3_roles:
-                self._try_wrapper(self.client.delete_role, v3_role)
-            for domain in self.domains:
-                self._try_wrapper(self.client.update_domain, domain,
-                                  enabled=False)
-                self._try_wrapper(self.client.delete_domain, domain)
+    def setup_test_tenant(self):
+        """Set up a test tenant."""
+        self.tenant = self.projects_client.create_tenant(
+            name=data_utils.rand_name('test_tenant'),
+            description=data_utils.rand_name('desc'))['tenant']
+        self.tenants.append(self.tenant)
+
+
+class DataGeneratorV3(BaseDataGenerator):
+
+    def setup_test_user(self):
+        """Set up a test user."""
+        self.setup_test_project()
+        self._create_test_user(project_id=self.project['id'])
+
+    def setup_test_project(self):
+        """Set up a test project."""
+        self.project = self.projects_client.create_project(
+            name=data_utils.rand_name('test_project'),
+            description=data_utils.rand_name('desc'))['project']
+        self.projects.append(self.project)
+
+    def setup_test_domain(self):
+        """Set up a test domain."""
+        self.domain = self.client.create_domain(
+            name=data_utils.rand_name('test_domain'),
+            description=data_utils.rand_name('desc'))['domain']
+        self.domains.append(self.domain)
diff --git a/tempest/api/network/admin/test_dhcp_agent_scheduler.py b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
index 5ff465b..fcb6fce 100644
--- a/tempest/api/network/admin/test_dhcp_agent_scheduler.py
+++ b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
@@ -84,7 +84,7 @@
             self._remove_network_from_dhcp_agent(network_id, agent)
 
     def _remove_network_from_dhcp_agent(self, network_id, agent):
-        self.admin_agents_client.remove_network_from_dhcp_agent(
+        self.admin_agents_client.delete_network_from_dhcp_agent(
             agent_id=agent['id'],
             network_id=network_id)
         self.assertFalse(self._check_network_in_dhcp_agent(
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index c64cf77..5d12e17 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -110,7 +110,7 @@
     @test.idempotent_id('9464e5e7-8625-49c3-8fd1-89c52be59d66')
     def test_add_list_remove_router_on_l3_agent(self):
         l3_agent_ids = list()
-        self.admin_agents_client.add_router_to_l3_agent(
+        self.admin_agents_client.create_router_on_l3_agent(
             self.agent['id'],
             router_id=self.router['id'])
         body = (
@@ -120,7 +120,7 @@
             self.assertIn('agent_type', agent)
             self.assertEqual('L3 agent', agent['agent_type'])
         self.assertIn(self.agent['id'], l3_agent_ids)
-        body = self.admin_agents_client.remove_router_from_l3_agent(
+        body = self.admin_agents_client.delete_router_from_l3_agent(
             self.agent['id'],
             self.router['id'])
         # NOTE(afazekas): The deletion not asserted, because neutron
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 81337f3..db4561f 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -69,6 +69,7 @@
         super(BaseNetworkTest, cls).setup_clients()
         cls.client = cls.os.network_client
         cls.agents_client = cls.os.network_agents_client
+        cls.network_extensions_client = cls.os.network_extensions_client
         cls.networks_client = cls.os.networks_client
         cls.subnetpools_client = cls.os.subnetpools_client
         cls.subnets_client = cls.os.subnets_client
@@ -76,6 +77,8 @@
         cls.quotas_client = cls.os.network_quotas_client
         cls.floating_ips_client = cls.os.floating_ips_client
         cls.security_groups_client = cls.os.security_groups_client
+        cls.security_group_rules_client = (
+            cls.os.security_group_rules_client)
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/network/base_security_groups.py b/tempest/api/network/base_security_groups.py
index 1525e19..3ea3aea 100644
--- a/tempest/api/network/base_security_groups.py
+++ b/tempest/api/network/base_security_groups.py
@@ -40,10 +40,11 @@
         self.assertNotIn(secgroup_id, secgroup_list)
 
     def _delete_security_group_rule(self, rule_id):
-        self.client.delete_security_group_rule(rule_id)
+        self.security_group_rules_client.delete_security_group_rule(rule_id)
         # Asserting that the security group is not found in the list
         # after deletion
-        list_body = self.client.list_security_group_rules()
+        list_body = (
+            self.security_group_rules_client.list_security_group_rules())
         rules_list = list()
         for rule in list_body['security_group_rules']:
             rules_list.append(rule['id'])
diff --git a/tempest/api/network/test_extensions.py b/tempest/api/network/test_extensions.py
index b83d2b0..d71d600 100644
--- a/tempest/api/network/test_extensions.py
+++ b/tempest/api/network/test_extensions.py
@@ -41,14 +41,15 @@
         expected_alias = [ext for ext in expected_alias if
                           test.is_extension_enabled(ext, 'network')]
         actual_alias = list()
-        extensions = self.client.list_extensions()
+        extensions = self.network_extensions_client.list_extensions()
         list_extensions = extensions['extensions']
         # Show and verify the details of the available extensions
         for ext in list_extensions:
             ext_name = ext['name']
             ext_alias = ext['alias']
             actual_alias.append(ext['alias'])
-            ext_details = self.client.show_extension(ext_alias)
+            ext_details = self.network_extensions_client.show_extension(
+                ext_alias)
             ext_details = ext_details['extension']
 
             self.assertIsNotNone(ext_details)
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index cf45328..7d0765e 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -41,7 +41,8 @@
                                            remote_ip_prefix=None):
         # Create Security Group rule with the input params and validate
         # that SG rule is created with the same parameters.
-        rule_create_body = self.client.create_security_group_rule(
+        sec_group_rules_client = self.security_group_rules_client
+        rule_create_body = sec_group_rules_client.create_security_group_rule(
             security_group_id=sg_id,
             direction=direction,
             ethertype=ethertype,
@@ -116,8 +117,9 @@
 
         # Create rules for each protocol
         protocols = ['tcp', 'udp', 'icmp']
+        client = self.security_group_rules_client
         for protocol in protocols:
-            rule_create_body = self.client.create_security_group_rule(
+            rule_create_body = client.create_security_group_rule(
                 security_group_id=group_create_body['security_group']['id'],
                 protocol=protocol,
                 direction='ingress',
@@ -125,7 +127,7 @@
             )
 
             # Show details of the created security rule
-            show_rule_body = self.client.show_security_group_rule(
+            show_rule_body = client.show_security_group_rule(
                 rule_create_body['security_group_rule']['id']
             )
             create_dict = rule_create_body['security_group_rule']
@@ -135,7 +137,8 @@
                                  "%s does not match." % key)
 
             # List rules and verify created rule is in response
-            rule_list_body = self.client.list_security_group_rules()
+            rule_list_body = (
+                self.security_group_rules_client.list_security_group_rules())
             rule_list = [rule['id']
                          for rule in rule_list_body['security_group_rules']]
             self.assertIn(rule_create_body['security_group_rule']['id'],
@@ -223,7 +226,8 @@
         direction = 'ingress'
         protocol = 17
         security_group_id = group_create_body['security_group']['id']
-        rule_create_body = self.client.create_security_group_rule(
+        client = self.security_group_rules_client
+        rule_create_body = client.create_security_group_rule(
             security_group_id=security_group_id,
             direction=direction,
             protocol=protocol
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index 58e39e9..ff38e9e 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -46,9 +46,10 @@
     @test.idempotent_id('4c094c09-000b-4e41-8100-9617600c02a6')
     def test_show_non_existent_security_group_rule(self):
         non_exist_id = str(uuid.uuid4())
-        self.assertRaises(lib_exc.NotFound,
-                          self.client.show_security_group_rule,
-                          non_exist_id)
+        self.assertRaises(
+            lib_exc.NotFound,
+            self.security_group_rules_client.show_security_group_rule,
+            non_exist_id)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('1f1bb89d-5664-4956-9fcd-83ee0fa603df')
@@ -67,7 +68,8 @@
         # Create rule with bad protocol name
         pname = 'bad_protocol_name'
         self.assertRaises(
-            lib_exc.BadRequest, self.client.create_security_group_rule,
+            lib_exc.BadRequest,
+            self.security_group_rules_client.create_security_group_rule,
             security_group_id=group_create_body['security_group']['id'],
             protocol=pname, direction='ingress', ethertype=self.ethertype)
 
@@ -80,7 +82,8 @@
         prefix = ['192.168.1./24', '192.168.1.1/33', 'bad_prefix', '256']
         for remote_ip_prefix in prefix:
             self.assertRaises(
-                lib_exc.BadRequest, self.client.create_security_group_rule,
+                lib_exc.BadRequest,
+                self.security_group_rules_client.create_security_group_rule,
                 security_group_id=group_create_body['security_group']['id'],
                 protocol='tcp', direction='ingress', ethertype=self.ethertype,
                 remote_ip_prefix=remote_ip_prefix)
@@ -95,7 +98,8 @@
         group_ids = ['bad_group_id', non_exist_id]
         for remote_group_id in group_ids:
             self.assertRaises(
-                lib_exc.NotFound, self.client.create_security_group_rule,
+                lib_exc.NotFound,
+                self.security_group_rules_client.create_security_group_rule,
                 security_group_id=group_create_body['security_group']['id'],
                 protocol='tcp', direction='ingress', ethertype=self.ethertype,
                 remote_group_id=remote_group_id)
@@ -109,7 +113,8 @@
         # Create rule specifying both remote_ip_prefix and remote_group_id
         prefix = self._tenant_network_cidr
         self.assertRaises(
-            lib_exc.BadRequest, self.client.create_security_group_rule,
+            lib_exc.BadRequest,
+            self.security_group_rules_client.create_security_group_rule,
             security_group_id=sg1_body['security_group']['id'],
             protocol='tcp', direction='ingress',
             ethertype=self.ethertype, remote_ip_prefix=prefix,
@@ -123,7 +128,8 @@
         # Create rule with bad ethertype
         ethertype = 'bad_ethertype'
         self.assertRaises(
-            lib_exc.BadRequest, self.client.create_security_group_rule,
+            lib_exc.BadRequest,
+            self.security_group_rules_client.create_security_group_rule,
             security_group_id=group_create_body['security_group']['id'],
             protocol='udp', direction='ingress', ethertype=ethertype)
 
@@ -140,7 +146,8 @@
                   (-16, 65536, 'Invalid value for port')]
         for pmin, pmax, msg in states:
             ex = self.assertRaises(
-                lib_exc.BadRequest, self.client.create_security_group_rule,
+                lib_exc.BadRequest,
+                self.security_group_rules_client.create_security_group_rule,
                 security_group_id=group_create_body['security_group']['id'],
                 protocol='tcp', port_range_min=pmin, port_range_max=pmax,
                 direction='ingress', ethertype=self.ethertype)
@@ -152,7 +159,8 @@
                   (300, 1, 'Invalid value for ICMP type')]
         for pmin, pmax, msg in states:
             ex = self.assertRaises(
-                lib_exc.BadRequest, self.client.create_security_group_rule,
+                lib_exc.BadRequest,
+                self.security_group_rules_client.create_security_group_rule,
                 security_group_id=group_create_body['security_group']['id'],
                 protocol='icmp', port_range_min=pmin, port_range_max=pmax,
                 direction='ingress', ethertype=self.ethertype)
@@ -176,7 +184,7 @@
         min_port = 66
         max_port = 67
         # Create a rule with valid params
-        self.client.create_security_group_rule(
+        self.security_group_rules_client.create_security_group_rule(
             security_group_id=body['security_group']['id'],
             direction='ingress',
             ethertype=self.ethertype,
@@ -187,7 +195,8 @@
 
         # Try creating the same security group rule, it should fail
         self.assertRaises(
-            lib_exc.Conflict, self.client.create_security_group_rule,
+            lib_exc.Conflict,
+            self.security_group_rules_client.create_security_group_rule,
             security_group_id=body['security_group']['id'],
             protocol='tcp', direction='ingress', ethertype=self.ethertype,
             port_range_min=min_port, port_range_max=max_port)
@@ -197,10 +206,11 @@
     def test_create_security_group_rule_with_non_existent_security_group(self):
         # Create security group rules with not existing security group.
         non_existent_sg = str(uuid.uuid4())
-        self.assertRaises(lib_exc.NotFound,
-                          self.client.create_security_group_rule,
-                          security_group_id=non_existent_sg,
-                          direction='ingress', ethertype=self.ethertype)
+        self.assertRaises(
+            lib_exc.NotFound,
+            self.security_group_rules_client.create_security_group_rule,
+            security_group_id=non_existent_sg,
+            direction='ingress', ethertype=self.ethertype)
 
 
 class NegativeSecGroupIPv6Test(NegativeSecGroupTest):
@@ -221,7 +231,7 @@
             self.assertRaisesRegexp(
                 lib_exc.BadRequest,
                 "Conflicting value ethertype",
-                self.client.create_security_group_rule,
+                self.security_group_rules_client.create_security_group_rule,
                 security_group_id=group_create_body['security_group']['id'],
                 protocol='tcp', direction='ingress',
                 ethertype=pair['ethertype'],
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 8466e11..09e863e 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -16,7 +16,6 @@
 import netaddr
 
 from tempest.api.orchestration import base
-from tempest.common import credentials_factory as credentials
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
@@ -37,8 +36,8 @@
 
     @classmethod
     def setup_credentials(cls):
+        cls.set_network_resources()
         super(NeutronResourcesTestJSON, cls).setup_credentials()
-        cls.os = credentials.ConfiguredUserManager()
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
index bbf6db2..ff06810 100644
--- a/tempest/api/telemetry/base.py
+++ b/tempest/api/telemetry/base.py
@@ -17,6 +17,7 @@
 
 from tempest.common import compute
 from tempest.common.utils import data_utils
+from tempest.common import waiters
 from tempest import config
 from tempest import exceptions
 import tempest.test
@@ -97,8 +98,14 @@
                 pass
 
     @classmethod
+    def wait_for_server_termination(cls, server_id):
+        waiters.wait_for_server_termination(cls.servers_client,
+                                            server_id)
+
+    @classmethod
     def resource_cleanup(cls):
         cls.cleanup_resources(cls.servers_client.delete_server, cls.server_ids)
+        cls.cleanup_resources(cls.wait_for_server_termination, cls.server_ids)
         cls.cleanup_resources(cls.image_client.delete_image, cls.image_ids)
         super(BaseTelemetryTest, cls).resource_cleanup()
 
diff --git a/tempest/api_schema/response/compute/v2_2/__init__.py b/tempest/api_schema/response/compute/v2_2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/response/compute/v2_2/__init__.py
diff --git a/tempest/api_schema/response/compute/v2_2/keypairs.py b/tempest/api_schema/response/compute/v2_2/keypairs.py
new file mode 100644
index 0000000..5d8d24d
--- /dev/null
+++ b/tempest/api_schema/response/compute/v2_2/keypairs.py
@@ -0,0 +1,41 @@
+# Copyright 2016 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.
+
+import copy
+
+from tempest.api_schema.response.compute.v2_1 import keypairs
+
+get_keypair = copy.deepcopy(keypairs.get_keypair)
+get_keypair['response_body']['properties']['keypair'][
+    'properties'].update({'type': {'type': 'string'}})
+get_keypair['response_body']['properties']['keypair'][
+    'required'].append('type')
+
+create_keypair = copy.deepcopy(keypairs.create_keypair)
+create_keypair['status_code'] = [201]
+create_keypair['response_body']['properties']['keypair'][
+    'properties'].update({'type': {'type': 'string'}})
+create_keypair['response_body']['properties']['keypair'][
+    'required'].append('type')
+
+delete_keypair = {
+    'status_code': [204],
+}
+
+list_keypairs = copy.deepcopy(keypairs.list_keypairs)
+list_keypairs['response_body']['properties']['keypairs'][
+    'items']['properties']['keypair'][
+    'properties'].update({'type': {'type': 'string'}})
+list_keypairs['response_body']['properties']['keypairs'][
+    'items']['properties']['keypair']['required'].append('type')
diff --git a/tempest/clients.py b/tempest/clients.py
index 2c40d0c..50aa6f4 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -94,10 +94,14 @@
     DatabaseLimitsClient
 from tempest.services.database.json.versions_client import \
     DatabaseVersionsClient
+from tempest.services.identity.v2.json.endpoints_client import \
+    EndpointsClient as EndpointsV2Client
 from tempest.services.identity.v2.json.identity_client import \
     IdentityClient
 from tempest.services.identity.v2.json.roles_client import \
     RolesClient
+from tempest.services.identity.v2.json.services_client import \
+    ServicesClient as ServicesV2Client
 from tempest.services.identity.v2.json.tenants_client import \
     TenantsClient
 from tempest.services.identity.v2.json.users_client import \
@@ -121,9 +125,13 @@
     MessagingClient
 from tempest.services.network.json.agents_client import AgentsClient \
     as NetworkAgentsClient
+from tempest.services.network.json.extensions_client import \
+    ExtensionsClient as NetworkExtensionsClient
 from tempest.services.network.json.network_client import NetworkClient
 from tempest.services.network.json.quotas_client import QuotasClient \
     as NetworkQuotasClient
+from tempest.services.network.json.security_group_rules_client import \
+    SecurityGroupRulesClient
 from tempest.services.network.json.security_groups_client import \
     SecurityGroupsClient
 from tempest.services.network.json.subnetpools_client import SubnetpoolsClient
@@ -238,6 +246,14 @@
             build_interval=CONF.network.build_interval,
             build_timeout=CONF.network.build_timeout,
             **self.default_params)
+        self.network_extensions_client = NetworkExtensionsClient(
+            self.auth_provider,
+            CONF.network.catalog_type,
+            CONF.network.region or CONF.identity.region,
+            endpoint_type=CONF.network.endpoint_type,
+            build_interval=CONF.network.build_interval,
+            build_timeout=CONF.network.build_timeout,
+            **self.default_params)
         self.network_client = NetworkClient(
             self.auth_provider,
             CONF.network.catalog_type,
@@ -310,6 +326,14 @@
             build_interval=CONF.network.build_interval,
             build_timeout=CONF.network.build_timeout,
             **self.default_params)
+        self.security_group_rules_client = SecurityGroupRulesClient(
+            self.auth_provider,
+            CONF.network.catalog_type,
+            CONF.network.region or CONF.identity.region,
+            endpoint_type=CONF.network.endpoint_type,
+            build_interval=CONF.network.build_interval,
+            build_timeout=CONF.network.build_timeout,
+            **self.default_params)
         self.security_groups_client = SecurityGroupsClient(
             self.auth_provider,
             CONF.network.catalog_type,
@@ -480,6 +504,8 @@
         params_v2_admin = params.copy()
         params_v2_admin['endpoint_type'] = CONF.identity.v2_admin_endpoint_type
         # Client uses admin endpoint type of Keystone API v2
+        self.endpoints_v2_client = EndpointsV2Client(self.auth_provider,
+                                                     **params_v2_admin)
         self.identity_client = IdentityClient(self.auth_provider,
                                               **params_v2_admin)
         self.tenants_client = TenantsClient(self.auth_provider,
@@ -488,6 +514,8 @@
                                         **params_v2_admin)
         self.users_client = UsersClient(self.auth_provider,
                                         **params_v2_admin)
+        self.services_v2_client = ServicesV2Client(self.auth_provider,
+                                                   **params_v2_admin)
         params_v2_public = params.copy()
         params_v2_public['endpoint_type'] = (
             CONF.identity.v2_public_endpoint_type)
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 32d6ef1..ddfc75d 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -390,7 +390,7 @@
             'password': user['pass'],
             'roles': user['roles']
         }
-        if 'network' or 'router' in user:
+        if 'network' in user or 'router' in user:
             account['resources'] = {}
         if 'network' in user:
             account['resources']['network'] = user['network']
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 5d867df..92aa19e 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -146,7 +146,7 @@
     extensions_client = {
         'nova': os.extensions_client,
         'cinder': os.volumes_extension_client,
-        'neutron': os.network_client,
+        'neutron': os.network_extensions_client,
         'swift': os.account_client,
     }
     # NOTE (e0ne): Use Cinder API v2 by default because v1 is deprecated
@@ -157,7 +157,7 @@
 
     if service not in extensions_client:
         print('No tempest extensions client for %s' % service)
-        exit(1)
+        sys.exit(1)
     return extensions_client[service]
 
 
@@ -170,7 +170,7 @@
     }
     if service not in extensions_options:
         print('No supported extensions list option for %s' % service)
-        exit(1)
+        sys.exit(1)
     return extensions_options[service]
 
 
diff --git a/tempest/common/api_version_utils.py b/tempest/common/api_version_utils.py
index ac3322e..98601a7 100644
--- a/tempest/common/api_version_utils.py
+++ b/tempest/common/api_version_utils.py
@@ -69,3 +69,27 @@
     cfg_version = api_version_request.APIVersionRequest(cfg_min_version)
     max_version = cfg_version if cfg_version >= test_version else test_version
     return max_version.get_string()
+
+
+def assert_version_header_matches_request(api_microversion_header_name,
+                                          api_microversion,
+                                          response_header):
+    """Checks API microversion in resposne header
+
+    Verify whether microversion is present in response header
+    and with specified 'api_microversion' value.
+
+    @param: api_microversion_header_name: Microversion header name
+            Example- "X-OpenStack-Nova-API-Version"
+    @param: api_microversion: Microversion number like "2.10"
+    @param: response_header: Response header where microversion is
+            expected to be present.
+    """
+    api_microversion_header_name = api_microversion_header_name.lower()
+    if (api_microversion_header_name not in response_header or
+        api_microversion != response_header[api_microversion_header_name]):
+        msg = ("Microversion header '%s' with value '%s' does not match in "
+               "response - %s. " % (api_microversion_header_name,
+                                    api_microversion,
+                                    response_header))
+        raise exceptions.InvalidHTTPResponseHeader(msg)
diff --git a/tempest/hacking/ignored_list_T111.txt b/tempest/hacking/ignored_list_T111.txt
index 8130c85..20d58d2 100644
--- a/tempest/hacking/ignored_list_T111.txt
+++ b/tempest/hacking/ignored_list_T111.txt
@@ -1,3 +1,2 @@
 ./tempest/services/baremetal/base.py
-./tempest/services/network/json/agents_client.py
 ./tempest/services/network/json/quotas_client.py
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 37d0d10..6776220 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -69,6 +69,8 @@
         cls.subnets_client = cls.manager.subnets_client
         cls.floating_ips_client = cls.manager.floating_ips_client
         cls.security_groups_client = cls.manager.security_groups_client
+        cls.security_group_rules_client = (
+            cls.manager.security_group_rules_client)
         # Heat client
         cls.orchestration_client = cls.manager.orchestration_client
 
@@ -940,11 +942,12 @@
                                             CONF.validation.ping_timeout,
                                             1)
 
-    def _create_security_group(self, client=None, tenant_id=None,
+    def _create_security_group(self, security_group_rules_client=None,
+                               tenant_id=None,
                                namestart='secgroup-smoke',
                                security_groups_client=None):
-        if client is None:
-            client = self.network_client
+        if security_group_rules_client is None:
+            security_group_rules_client = self.security_group_rules_client
         if security_groups_client is None:
             security_groups_client = self.security_groups_client
         if tenant_id is None:
@@ -955,7 +958,8 @@
 
         # Add rules to the security group
         rules = self._create_loginable_secgroup_rule(
-            client=client, secgroup=secgroup,
+            security_group_rules_client=security_group_rules_client,
+            secgroup=secgroup,
             security_groups_client=security_groups_client)
         for rule in rules:
             self.assertEqual(tenant_id, rule.tenant_id)
@@ -1011,7 +1015,8 @@
         return net_resources.DeletableSecurityGroup(client=client,
                                                     **sgs[0])
 
-    def _create_security_group_rule(self, secgroup=None, client=None,
+    def _create_security_group_rule(self, secgroup=None,
+                                    sec_group_rules_client=None,
                                     tenant_id=None,
                                     security_groups_client=None, **kwargs):
         """Create a rule from a dictionary of rule parameters.
@@ -1031,8 +1036,8 @@
                     port_range_max: 22
                     }
         """
-        if client is None:
-            client = self.network_client
+        if sec_group_rules_client is None:
+            sec_group_rules_client = self.security_group_rules_client
         if security_groups_client is None:
             security_groups_client = self.security_groups_client
         if not tenant_id:
@@ -1045,9 +1050,9 @@
                        tenant_id=secgroup.tenant_id)
         ruleset.update(kwargs)
 
-        sg_rule = client.create_security_group_rule(**ruleset)
+        sg_rule = sec_group_rules_client.create_security_group_rule(**ruleset)
         sg_rule = net_resources.DeletableSecurityGroupRule(
-            client=client,
+            client=sec_group_rules_client,
             **sg_rule['security_group_rule']
         )
         self.addCleanup(self.delete_wrapper, sg_rule.delete)
@@ -1056,7 +1061,8 @@
 
         return sg_rule
 
-    def _create_loginable_secgroup_rule(self, client=None, secgroup=None,
+    def _create_loginable_secgroup_rule(self, security_group_rules_client=None,
+                                        secgroup=None,
                                         security_groups_client=None):
         """Create loginable security group rule
 
@@ -1066,8 +1072,8 @@
         belonging to the same security group.
         """
 
-        if client is None:
-            client = self.network_client
+        if security_group_rules_client is None:
+            security_group_rules_client = self.security_group_rules_client
         if security_groups_client is None:
             security_groups_client = self.security_groups_client
         rules = []
@@ -1088,12 +1094,14 @@
                 ethertype='IPv6',
             )
         ]
+        sec_group_rules_client = security_group_rules_client
         for ruleset in rulesets:
             for r_direction in ['ingress', 'egress']:
                 ruleset['direction'] = r_direction
                 try:
                     sg_rule = self._create_security_group_rule(
-                        client=client, secgroup=secgroup,
+                        sec_group_rules_client=sec_group_rules_client,
+                        secgroup=secgroup,
                         security_groups_client=security_groups_client,
                         **ruleset)
                 except lib_exc.Conflict as ex:
@@ -1107,12 +1115,6 @@
 
         return rules
 
-    def _ssh_to_server(self, server, private_key):
-        ssh_login = CONF.validation.image_ssh_user
-        return self.get_remote_client(server,
-                                      username=ssh_login,
-                                      private_key=private_key)
-
     def _get_router(self, client=None, tenant_id=None):
         """Retrieve a router for the given tenant id.
 
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 97a755d..cace90b 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -43,16 +43,14 @@
     def _create_aggregate(self, **kwargs):
         aggregate = (self.aggregates_client.create_aggregate(**kwargs)
                      ['aggregate'])
-        self.addCleanup(self._delete_aggregate, aggregate)
+        self.addCleanup(self.aggregates_client.delete_aggregate,
+                        aggregate['id'])
         aggregate_name = kwargs['name']
         availability_zone = kwargs['availability_zone']
         self.assertEqual(aggregate['name'], aggregate_name)
         self.assertEqual(aggregate['availability_zone'], availability_zone)
         return aggregate
 
-    def _delete_aggregate(self, aggregate):
-        self.aggregates_client.delete_aggregate(aggregate['id'])
-
     def _get_host_name(self):
         hosts = self.hosts_client.list_hosts()['hosts']
         self.assertTrue(len(hosts) >= 1)
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index cb6b968..5d4f7b3 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -97,9 +97,13 @@
         req = request.Request(login_url)
         req.add_header('Content-type', 'application/x-www-form-urlencoded')
         req.add_header('Referer', CONF.dashboard.dashboard_url)
+
+        # Pass the default domain name regardless of the auth version in order
+        # to test the scenario of when horizon is running with keystone v3
         params = {'username': username,
                   'password': password,
                   'region': parser.region,
+                  'domain': CONF.auth.default_credentials_domain_name,
                   'csrfmiddlewaretoken': parser.csrf_token}
         self.opener.open(req, parse.urlencode(params))
 
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index d9c6924..f7c7434 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -62,12 +62,6 @@
             server, custom_matchers.MatchesDictExceptForKeys(
                 got_server, excluded_keys=excluded_keys))
 
-    def cinder_create(self):
-        return self.create_volume()
-
-    def cinder_list(self):
-        return self.volumes_client.list_volumes()['volumes']
-
     def cinder_show(self, volume):
         got_volume = self.volumes_client.show_volume(volume['id'])['volume']
         self.assertEqual(volume, got_volume)
@@ -115,8 +109,8 @@
 
         self.nova_show(server)
 
-        volume = self.cinder_create()
-        volumes = self.cinder_list()
+        volume = self.create_volume()
+        volumes = self.volumes_client.list_volumes()['volumes']
         self.assertIn(volume['id'], [x['id'] for x in volumes])
 
         self.cinder_show(volume)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index b8bec16..79a5099 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -240,8 +240,8 @@
         old_floating_ip, server = self.floating_ip_tuple
         ip_address = old_floating_ip.floating_ip_address
         private_key = self._get_server_key(server)
-        ssh_client = self.get_remote_client(ip_address,
-                                            private_key=private_key)
+        ssh_client = self.get_remote_client(
+            ip_address, private_key=private_key)
         old_nic_list = self._get_server_nics(ssh_client)
         # get a port from a list of one item
         port_list = self._list_ports(device_id=server['id'])
@@ -336,7 +336,8 @@
                                    should_connect=True):
         ip_address = floating_ip.floating_ip_address
         private_key = self._get_server_key(self.floating_ip_tuple.server)
-        ssh_source = self._ssh_to_server(ip_address, private_key)
+        ssh_source = self.get_remote_client(
+            ip_address, private_key=private_key)
 
         for remote_ip in address_list:
             if should_connect:
@@ -553,7 +554,8 @@
         floating_ip, server = self.floating_ip_tuple
         ip_address = floating_ip.floating_ip_address
         private_key = self._get_server_key(server)
-        ssh_client = self._ssh_to_server(ip_address, private_key)
+        ssh_client = self.get_remote_client(
+            ip_address, private_key=private_key)
 
         dns_servers = [initial_dns_server]
         servers = ssh_client.get_dns_servers()
@@ -684,9 +686,9 @@
         list_hosts = (self.admin_manager.network_client.
                       list_l3_agents_hosting_router)
         schedule_router = (self.admin_manager.network_agents_client.
-                           add_router_to_l3_agent)
+                           create_router_on_l3_agent)
         unschedule_router = (self.admin_manager.network_agents_client.
-                             remove_router_from_l3_agent)
+                             delete_router_from_l3_agent)
 
         agent_list = set(a["id"] for a in
                          self._list_agents(agent_type="L3 agent"))
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 8375d05..18bd764 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -191,9 +191,11 @@
             port_range_max=22,
             direction='ingress',
         )
-        self._create_security_group_rule(secgroup=access_sg,
-                                         client=tenant.manager.network_client,
-                                         **ssh_rule)
+        sec_group_rules_client = tenant.manager.security_group_rules_client
+        self._create_security_group_rule(
+            secgroup=access_sg,
+            sec_group_rules_client=sec_group_rules_client,
+            **ssh_rule)
 
     def _verify_network_details(self, tenant):
         # Checks that we see the newly created network/subnet/router via
@@ -319,8 +321,8 @@
         access_point_ssh = \
             self.floating_ips[tenant.access_point['id']].floating_ip_address
         private_key = tenant.keypair['private_key']
-        access_point_ssh = self._ssh_to_server(access_point_ssh,
-                                               private_key=private_key)
+        access_point_ssh = self.get_remote_client(
+            access_point_ssh, private_key=private_key)
         return access_point_ssh
 
     def _check_connectivity(self, access_point, ip, should_succeed=True):
@@ -371,9 +373,11 @@
             protocol='icmp',
             direction='ingress'
         )
+        sec_group_rules_client = (
+            dest_tenant.manager.security_group_rules_client)
         self._create_security_group_rule(
             secgroup=dest_tenant.security_groups['default'],
-            client=dest_tenant.manager.network_client,
+            sec_group_rules_client=sec_group_rules_client,
             **ruleset
         )
         access_point_ssh = self._connect_to_access_point(source_tenant)
@@ -385,9 +389,11 @@
         self._test_cross_tenant_block(dest_tenant, source_tenant)
 
         # allow reverse traffic and check
+        sec_group_rules_client = (
+            source_tenant.manager.security_group_rules_client)
         self._create_security_group_rule(
             secgroup=source_tenant.security_groups['default'],
-            client=source_tenant.manager.network_client,
+            sec_group_rules_client=sec_group_rules_client,
             **ruleset
         )
 
@@ -468,9 +474,10 @@
             protocol='icmp',
             direction='ingress',
         )
+        sec_group_rules_client = new_tenant.manager.security_group_rules_client
         self._create_security_group_rule(
             secgroup=new_sg,
-            client=new_tenant.manager.network_client,
+            sec_group_rules_client=sec_group_rules_client,
             **icmp_rule)
         new_tenant.security_groups.update(new_sg=new_sg)
 
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 239e120..6c24d04 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -69,10 +69,7 @@
                       image=self.image_ref, flavor=self.flavor_ref,
                       ssh=self.run_ssh, ssh_user=self.ssh_user))
 
-    def add_keypair(self):
-        self.keypair = self.create_keypair()
-
-    def verify_ssh(self):
+    def verify_ssh(self, keypair):
         if self.run_ssh:
             # Obtain a floating IP
             self.fip = self.create_floating_ip(self.instance)['ip']
@@ -80,7 +77,7 @@
             self.ssh_client = self.get_remote_client(
                 server_or_ip=self.fip,
                 username=self.image_utils.ssh_user(self.image_ref),
-                private_key=self.keypair['private_key'])
+                private_key=keypair['private_key'])
 
     def verify_metadata(self):
         if self.run_ssh and CONF.compute_feature_enabled.metadata_service:
@@ -123,19 +120,19 @@
     @test.attr(type='smoke')
     @test.services('compute', 'network')
     def test_server_basicops(self):
-        self.add_keypair()
+        keypair = self.create_keypair()
         self.security_group = self._create_security_group()
         security_groups = [{'name': self.security_group['name']}]
         self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
         self.instance = self.create_server(
             image_id=self.image_ref,
             flavor=self.flavor_ref,
-            key_name=self.keypair['name'],
+            key_name=keypair['name'],
             security_groups=security_groups,
             config_drive=CONF.compute_feature_enabled.config_drive,
             metadata=self.md,
             wait_until='ACTIVE')
-        self.verify_ssh()
+        self.verify_ssh(keypair)
         self.verify_metadata()
         self.verify_metadata_on_config_drive()
         self.servers_client.delete_server(self.instance['id'])
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 8183ce3..f88fb14 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -60,10 +60,6 @@
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
 
-    def _wait_for_volume_snapshot_status(self, volume_snapshot, status):
-        self.snapshots_client.wait_for_snapshot_status(volume_snapshot['id'],
-                                                       status)
-
     def _create_volume_snapshot(self, volume):
         snapshot_name = data_utils.rand_name('scenario-snapshot')
         snapshot = self.snapshots_client.create_snapshot(
@@ -78,29 +74,12 @@
             except lib_exc.NotFound:
                 pass
         self.addCleanup(cleaner)
-        self._wait_for_volume_status(volume, 'available')
+        self.volumes_client.wait_for_volume_status(volume['id'], 'available')
         self.snapshots_client.wait_for_snapshot_status(snapshot['id'],
                                                        'available')
         self.assertEqual(snapshot_name, snapshot['display_name'])
         return snapshot
 
-    def _wait_for_volume_status(self, volume, status):
-        self.volumes_client.wait_for_volume_status(volume['id'], status)
-
-    def _create_volume(self, snapshot_id=None):
-        return self.create_volume(snapshot_id=snapshot_id)
-
-    def _attach_volume(self, server, volume):
-        attached_volume = self.servers_client.attach_volume(
-            server['id'], volumeId=volume['id'], device='/dev/%s'
-            % CONF.compute.volume_device_name)['volumeAttachment']
-        self.assertEqual(volume['id'], attached_volume['id'])
-        self._wait_for_volume_status(attached_volume, 'in-use')
-
-    def _detach_volume(self, server, volume):
-        self.servers_client.detach_volume(server['id'], volume['id'])
-        self._wait_for_volume_status(volume, 'available')
-
     def _wait_for_volume_available_on_the_system(self, server_or_ip,
                                                  private_key):
         ssh = self.get_remote_client(server_or_ip, private_key=private_key)
@@ -126,7 +105,7 @@
         security_group = self._create_security_group()
 
         # boot an instance and create a timestamp file in it
-        volume = self._create_volume()
+        volume = self.create_volume()
         server = self.create_server(
             image_id=CONF.compute.image_ref,
             key_name=keypair['name'],
@@ -136,13 +115,13 @@
         # create and add floating IP to server1
         ip_for_server = self.get_server_or_ip(server)
 
-        self._attach_volume(server, volume)
+        self.nova_volume_attach(server, volume)
         self._wait_for_volume_available_on_the_system(ip_for_server,
                                                       keypair['private_key'])
         timestamp = self.create_timestamp(ip_for_server,
                                           CONF.compute.volume_device_name,
                                           private_key=keypair['private_key'])
-        self._detach_volume(server, volume)
+        self.nova_volume_detach(server, volume)
 
         # snapshot the volume
         volume_snapshot = self._create_volume_snapshot(volume)
@@ -151,7 +130,7 @@
         snapshot_image = self.create_server_snapshot(server=server)
 
         # create second volume from the snapshot(volume2)
-        volume_from_snapshot = self._create_volume(
+        volume_from_snapshot = self.create_volume(
             snapshot_id=volume_snapshot['id'])
 
         # boot second instance from the snapshot(instance2)
@@ -164,7 +143,7 @@
         ip_for_snapshot = self.get_server_or_ip(server_from_snapshot)
 
         # attach volume2 to instance2
-        self._attach_volume(server_from_snapshot, volume_from_snapshot)
+        self.nova_volume_attach(server_from_snapshot, volume_from_snapshot)
         self._wait_for_volume_available_on_the_system(ip_for_snapshot,
                                                       keypair['private_key'])
 
diff --git a/tempest/services/base_microversion_client.py b/tempest/services/base_microversion_client.py
new file mode 100644
index 0000000..4c750f5
--- /dev/null
+++ b/tempest/services/base_microversion_client.py
@@ -0,0 +1,54 @@
+# Copyright 2016 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_lib.common import rest_client
+
+
+class BaseMicroversionClient(rest_client.RestClient):
+    """Base class to support microversion in service clients
+
+    This class is used to support microversion in service clients.
+    This provides feature to make API request with microversion.
+    Service clients derived from this class will be able to send API
+    request to server with or without microversion.
+    If api_microversion is not set on service client then API request will be
+    normal request without microversion.
+
+    """
+    def __init__(self, auth_provider, service, region,
+                 api_microversion_header_name, **kwargs):
+        """Base Microversion Client __init__
+
+        :param auth_provider: an auth provider object used to wrap requests in
+                              auth
+        :param str service: The service name to use for the catalog lookup
+        :param str region: The region to use for the catalog lookup
+        :param str api_microversion_header_name: The microversion header name
+                                                 to use for sending API
+                                                 request with microversion
+        :param kwargs: kwargs required by rest_client.RestClient
+        """
+        super(BaseMicroversionClient, self).__init__(
+            auth_provider, service, region, **kwargs)
+        self.api_microversion_header_name = api_microversion_header_name
+        self.api_microversion = None
+
+    def get_headers(self):
+        headers = super(BaseMicroversionClient, self).get_headers()
+        if self.api_microversion:
+            headers[self.api_microversion_header_name] = self.api_microversion
+        return headers
+
+    def set_api_microversion(self, microversion):
+        self.api_microversion = microversion
diff --git a/tempest/services/compute/json/base.py b/tempest/services/compute/json/base_compute_client.py
similarity index 69%
rename from tempest/services/compute/json/base.py
rename to tempest/services/compute/json/base_compute_client.py
index 40d3056..5349af6 100644
--- a/tempest/services/compute/json/base.py
+++ b/tempest/services/compute/json/base_compute_client.py
@@ -12,23 +12,31 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest_lib.common import rest_client
-
 from tempest.common import api_version_request
+from tempest.common import api_version_utils
 from tempest import exceptions
+from tempest.services import base_microversion_client
 
 
-class BaseComputeClient(rest_client.RestClient):
-    api_microversion = None
+class BaseComputeClient(base_microversion_client.BaseMicroversionClient):
 
-    def get_headers(self):
-        headers = super(BaseComputeClient, self).get_headers()
-        if self.api_microversion:
-            headers['X-OpenStack-Nova-API-Version'] = self.api_microversion
-        return headers
+    def __init__(self, auth_provider, service, region,
+                 api_microversion_header_name='X-OpenStack-Nova-API-Version',
+                 **kwargs):
+        super(BaseComputeClient, self).__init__(
+            auth_provider, service, region,
+            api_microversion_header_name, **kwargs)
 
-    def set_api_microversion(self, microversion):
-        self.api_microversion = microversion
+    def request(self, method, url, extra_headers=False, headers=None,
+                body=None):
+        resp, resp_body = super(BaseComputeClient, self).request(
+            method, url, extra_headers, headers, body)
+        if self.api_microversion and self.api_microversion != 'latest':
+            api_version_utils.assert_version_header_matches_request(
+                self.api_microversion_header_name,
+                self.api_microversion,
+                resp)
+        return resp, resp_body
 
     def get_schema(self, schema_versions_info):
         """Get JSON schema
diff --git a/tempest/services/compute/json/keypairs_client.py b/tempest/services/compute/json/keypairs_client.py
index 2e22bc6..ec9b1e0 100644
--- a/tempest/services/compute/json/keypairs_client.py
+++ b/tempest/services/compute/json/keypairs_client.py
@@ -15,21 +15,28 @@
 
 from oslo_serialization import jsonutils as json
 
-from tempest.api_schema.response.compute.v2_1 import keypairs as schema
+from tempest.api_schema.response.compute.v2_1 import keypairs as schemav21
+from tempest.api_schema.response.compute.v2_2 import keypairs as schemav22
 from tempest.common import service_client
+from tempest.services.compute.json import base_compute_client
 
 
-class KeyPairsClient(service_client.ServiceClient):
+class KeyPairsClient(base_compute_client.BaseComputeClient):
+
+    schema_versions_info = [{'min': None, 'max': '2.1', 'schema': schemav21},
+                            {'min': '2.2', 'max': None, 'schema': schemav22}]
 
     def list_keypairs(self):
         resp, body = self.get("os-keypairs")
         body = json.loads(body)
+        schema = self.get_schema(self.schema_versions_info)
         self.validate_response(schema.list_keypairs, resp, body)
         return service_client.ResponseBody(resp, body)
 
     def show_keypair(self, keypair_name):
         resp, body = self.get("os-keypairs/%s" % keypair_name)
         body = json.loads(body)
+        schema = self.get_schema(self.schema_versions_info)
         self.validate_response(schema.get_keypair, resp, body)
         return service_client.ResponseBody(resp, body)
 
@@ -37,10 +44,12 @@
         post_body = json.dumps({'keypair': kwargs})
         resp, body = self.post("os-keypairs", body=post_body)
         body = json.loads(body)
+        schema = self.get_schema(self.schema_versions_info)
         self.validate_response(schema.create_keypair, resp, body)
         return service_client.ResponseBody(resp, body)
 
     def delete_keypair(self, keypair_name):
         resp, body = self.delete("os-keypairs/%s" % keypair_name)
+        schema = self.get_schema(self.schema_versions_info)
         self.validate_response(schema.delete_keypair, resp, body)
         return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/endpoints_client.py b/tempest/services/identity/v2/json/endpoints_client.py
new file mode 100644
index 0000000..ff9907d
--- /dev/null
+++ b/tempest/services/identity/v2/json/endpoints_client.py
@@ -0,0 +1,50 @@
+# Copyright 2016 Red Hat, Inc.
+#
+# 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 oslo_serialization import jsonutils as json
+
+from tempest.common import service_client
+
+
+class EndpointsClient(service_client.ServiceClient):
+    api_version = "v2.0"
+
+    def create_endpoint(self, service_id, region_id, **kwargs):
+        """Create an endpoint for service."""
+        post_body = {
+            'service_id': service_id,
+            'region': region_id,
+            'publicurl': kwargs.get('publicurl'),
+            'adminurl': kwargs.get('adminurl'),
+            'internalurl': kwargs.get('internalurl')
+        }
+        post_body = json.dumps({'endpoint': post_body})
+        resp, body = self.post('/endpoints', post_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def list_endpoints(self):
+        """List Endpoints - Returns Endpoints."""
+        resp, body = self.get('/endpoints')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def delete_endpoint(self, endpoint_id):
+        """Delete an endpoint."""
+        url = '/endpoints/%s' % endpoint_id
+        resp, body = self.delete(url)
+        self.expected_success(204, resp.status)
+        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 0ff59d5..f045bb7 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -39,70 +39,6 @@
         self.expected_success(204, resp.status)
         return service_client.ResponseBody(resp, body)
 
-    def create_service(self, name, type, **kwargs):
-        """Create a service."""
-        post_body = {
-            'name': name,
-            'type': type,
-            'description': kwargs.get('description')
-        }
-        post_body = json.dumps({'OS-KSADM:service': post_body})
-        resp, body = self.post('/OS-KSADM/services', post_body)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def show_service(self, service_id):
-        """Get Service."""
-        url = '/OS-KSADM/services/%s' % service_id
-        resp, body = self.get(url)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def list_services(self):
-        """List Service - Returns Services."""
-        resp, body = self.get('/OS-KSADM/services')
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def delete_service(self, service_id):
-        """Delete Service."""
-        url = '/OS-KSADM/services/%s' % service_id
-        resp, body = self.delete(url)
-        self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
-
-    def create_endpoint(self, service_id, region_id, **kwargs):
-        """Create an endpoint for service."""
-        post_body = {
-            'service_id': service_id,
-            'region': region_id,
-            'publicurl': kwargs.get('publicurl'),
-            'adminurl': kwargs.get('adminurl'),
-            'internalurl': kwargs.get('internalurl')
-        }
-        post_body = json.dumps({'endpoint': post_body})
-        resp, body = self.post('/endpoints', post_body)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def list_endpoints(self):
-        """List Endpoints - Returns Endpoints."""
-        resp, body = self.get('/endpoints')
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def delete_endpoint(self, endpoint_id):
-        """Delete an endpoint."""
-        url = '/endpoints/%s' % endpoint_id
-        resp, body = self.delete(url)
-        self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
-
     def list_extensions(self):
         """List all the extensions."""
         resp, body = self.get('/extensions')
diff --git a/tempest/services/identity/v2/json/services_client.py b/tempest/services/identity/v2/json/services_client.py
new file mode 100644
index 0000000..436d00d
--- /dev/null
+++ b/tempest/services/identity/v2/json/services_client.py
@@ -0,0 +1,56 @@
+# Copyright 2015 Red Hat, Inc.
+#
+# 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 oslo_serialization import jsonutils as json
+
+from tempest.common import service_client
+
+
+class ServicesClient(service_client.ServiceClient):
+    api_version = "v2.0"
+
+    def create_service(self, name, type, **kwargs):
+        """Create a service."""
+        post_body = {
+            'name': name,
+            'type': type,
+            'description': kwargs.get('description')
+        }
+        post_body = json.dumps({'OS-KSADM:service': post_body})
+        resp, body = self.post('/OS-KSADM/services', post_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def show_service(self, service_id):
+        """Get Service."""
+        url = '/OS-KSADM/services/%s' % service_id
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def list_services(self):
+        """List Service - Returns Services."""
+        resp, body = self.get('/OS-KSADM/services')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def delete_service(self, service_id):
+        """Delete Service."""
+        url = '/OS-KSADM/services/%s' % service_id
+        resp, body = self.delete(url)
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/groups_client.py b/tempest/services/identity/v3/json/groups_client.py
index 70edd23..6ed85cf 100644
--- a/tempest/services/identity/v3/json/groups_client.py
+++ b/tempest/services/identity/v3/json/groups_client.py
@@ -88,3 +88,9 @@
         resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id))
         self.expected_success(204, resp.status)
         return service_client.ResponseBody(resp, body)
+
+    def check_group_user_existence(self, group_id, user_id):
+        """Check user in group."""
+        resp, body = self.head('groups/%s/users/%s' % (group_id, user_id))
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp)
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index ab8ba2a..fba26d4 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -352,6 +352,22 @@
         self.expected_success(204, resp.status)
         return service_client.ResponseBody(resp, body)
 
+    def check_user_role_existence_on_project(self, project_id,
+                                             user_id, role_id):
+        """Check role of a user on a project."""
+        resp, body = self.head('projects/%s/users/%s/roles/%s' %
+                               (project_id, user_id, role_id))
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp)
+
+    def check_user_role_existence_on_domain(self, domain_id,
+                                            user_id, role_id):
+        """Check role of a user on a domain."""
+        resp, body = self.head('domains/%s/users/%s/roles/%s' %
+                               (domain_id, user_id, role_id))
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp)
+
     def assign_group_role_on_project(self, project_id, group_id, role_id):
         """Add roles to a user on a project."""
         resp, body = self.put('projects/%s/groups/%s/roles/%s' %
@@ -396,6 +412,22 @@
         self.expected_success(204, resp.status)
         return service_client.ResponseBody(resp, body)
 
+    def check_role_from_group_on_project_existence(self, project_id,
+                                                   group_id, role_id):
+        """Check role of a user on a project."""
+        resp, body = self.head('projects/%s/groups/%s/roles/%s' %
+                               (project_id, group_id, role_id))
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp)
+
+    def check_role_from_group_on_domain_existence(self, domain_id,
+                                                  group_id, role_id):
+        """Check role of a user on a domain."""
+        resp, body = self.head('domains/%s/groups/%s/roles/%s' %
+                               (domain_id, group_id, role_id))
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp)
+
     def create_trust(self, **kwargs):
         """Creates a trust.
 
diff --git a/tempest/services/image/v1/json/images_client.py b/tempest/services/image/v1/json/images_client.py
index 5b6a394..af2e68c 100644
--- a/tempest/services/image/v1/json/images_client.py
+++ b/tempest/services/image/v1/json/images_client.py
@@ -180,21 +180,27 @@
         self.expected_success(200, resp.status)
         return service_client.ResponseBody(resp, body)
 
-    def list_images(self, detail=False, properties=dict(),
-                    changes_since=None, **kwargs):
+    def list_images(self, detail=False, **kwargs):
+        """Return a list of all images filtered by input parameters.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-image-v1.html#listImage-v1
+
+        Most parameters except the following are passed to the API without
+        any changes.
+        :param changes_since: The name is changed to changes-since
+        """
         url = 'v1/images'
 
         if detail:
             url += '/detail'
 
-        params = {}
-        for key, value in properties.items():
-            params['property-%s' % key] = value
+        properties = kwargs.pop('properties', {})
+        for key, value in six.iteritems(properties):
+            kwargs['property-%s' % key] = value
 
-        kwargs.update(params)
-
-        if changes_since is not None:
-            kwargs['changes-since'] = changes_since
+        if kwargs.get('changes_since'):
+            kwargs['changes-since'] = kwargs.pop('changes_since')
 
         if len(kwargs) > 0:
             url += '?%s' % urllib.urlencode(kwargs)
diff --git a/tempest/services/network/json/agents_client.py b/tempest/services/network/json/agents_client.py
index 07f93b2..8bec847 100644
--- a/tempest/services/network/json/agents_client.py
+++ b/tempest/services/network/json/agents_client.py
@@ -38,7 +38,7 @@
         uri = '/agents/%s/l3-routers' % agent_id
         return self.list_resources(uri)
 
-    def add_router_to_l3_agent(self, agent_id, **kwargs):
+    def create_router_on_l3_agent(self, agent_id, **kwargs):
         # TODO(piyush): Current api-site doesn't contain this API description.
         # After fixing the api-site, we need to fix here also for putting the
         # link to api-site.
@@ -46,7 +46,7 @@
         uri = '/agents/%s/l3-routers' % agent_id
         return self.create_resource(uri, kwargs)
 
-    def remove_router_from_l3_agent(self, agent_id, router_id):
+    def delete_router_from_l3_agent(self, agent_id, router_id):
         uri = '/agents/%s/l3-routers/%s' % (agent_id, router_id)
         return self.delete_resource(uri)
 
@@ -54,7 +54,7 @@
         uri = '/agents/%s/dhcp-networks' % agent_id
         return self.list_resources(uri)
 
-    def remove_network_from_dhcp_agent(self, agent_id, network_id):
+    def delete_network_from_dhcp_agent(self, agent_id, network_id):
         uri = '/agents/%s/dhcp-networks/%s' % (agent_id,
                                                network_id)
         return self.delete_resource(uri)
diff --git a/tempest/services/network/json/extensions_client.py b/tempest/services/network/json/extensions_client.py
new file mode 100644
index 0000000..64d3a4f
--- /dev/null
+++ b/tempest/services/network/json/extensions_client.py
@@ -0,0 +1,24 @@
+#    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.network.json import base
+
+
+class ExtensionsClient(base.BaseNetworkClient):
+
+    def show_extension(self, ext_alias, **fields):
+        uri = '/extensions/%s' % ext_alias
+        return self.show_resource(uri, **fields)
+
+    def list_extensions(self, **filters):
+        uri = '/extensions'
+        return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index e8e21d2..6b0b1f9 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -35,31 +35,6 @@
     quotas
     """
 
-    def create_security_group_rule(self, **kwargs):
-        uri = '/security-group-rules'
-        post_data = {'security_group_rule': kwargs}
-        return self.create_resource(uri, post_data)
-
-    def show_security_group_rule(self, security_group_rule_id, **fields):
-        uri = '/security-group-rules/%s' % security_group_rule_id
-        return self.show_resource(uri, **fields)
-
-    def delete_security_group_rule(self, security_group_rule_id):
-        uri = '/security-group-rules/%s' % security_group_rule_id
-        return self.delete_resource(uri)
-
-    def list_security_group_rules(self, **filters):
-        uri = '/security-group-rules'
-        return self.list_resources(uri, **filters)
-
-    def show_extension(self, ext_alias, **fields):
-        uri = '/extensions/%s' % ext_alias
-        return self.show_resource(uri, **fields)
-
-    def list_extensions(self, **filters):
-        uri = '/extensions'
-        return self.list_resources(uri, **filters)
-
     def create_bulk_network(self, **kwargs):
         """create bulk network
 
diff --git a/tempest/services/network/json/security_group_rules_client.py b/tempest/services/network/json/security_group_rules_client.py
new file mode 100644
index 0000000..b2ba5b2
--- /dev/null
+++ b/tempest/services/network/json/security_group_rules_client.py
@@ -0,0 +1,33 @@
+#    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.network.json import base
+
+
+class SecurityGroupRulesClient(base.BaseNetworkClient):
+
+    def create_security_group_rule(self, **kwargs):
+        uri = '/security-group-rules'
+        post_data = {'security_group_rule': kwargs}
+        return self.create_resource(uri, post_data)
+
+    def show_security_group_rule(self, security_group_rule_id, **fields):
+        uri = '/security-group-rules/%s' % security_group_rule_id
+        return self.show_resource(uri, **fields)
+
+    def delete_security_group_rule(self, security_group_rule_id):
+        uri = '/security-group-rules/%s' % security_group_rule_id
+        return self.delete_resource(uri)
+
+    def list_security_group_rules(self, **filters):
+        uri = '/security-group-rules'
+        return self.list_resources(uri, **filters)
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 6531059..02cb901 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -154,9 +154,11 @@
                     projects_client = None
                     roles_client = None
                     users_client = None
+                domain = (identity_client.auth_provider.credentials.
+                          get('project_domain_name', 'Default'))
                 credentials_client = cred_client.get_creds_client(
                     identity_client, projects_client, roles_client,
-                    users_client)
+                    users_client, project_domain_name=domain)
                 project = credentials_client.create_project(
                     name=tenant_name, description=tenant_name)
                 user = credentials_client.create_user(username, password,
diff --git a/tempest/stress/etc/sample-unit-test.json b/tempest/stress/etc/sample-unit-test.json
index b388bfe..54433d5 100644
--- a/tempest/stress/etc/sample-unit-test.json
+++ b/tempest/stress/etc/sample-unit-test.json
@@ -1,7 +1,7 @@
 [{"action": "tempest.stress.actions.unit_test.UnitTest",
   "threads": 8,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "kwargs": {"test_method": "tempest.cli.simple_read_only.test_glance.SimpleReadOnlyGlanceClientTest.test_glance_fake_action",
              "class_setup_per": "process"}
   }
diff --git a/tempest/stress/etc/server-create-destroy-test.json b/tempest/stress/etc/server-create-destroy-test.json
index 17d5e1a..bbb5352 100644
--- a/tempest/stress/etc/server-create-destroy-test.json
+++ b/tempest/stress/etc/server-create-destroy-test.json
@@ -1,7 +1,7 @@
 [{"action": "tempest.stress.actions.server_create_destroy.ServerCreateDestroyTest",
   "threads": 8,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "kwargs": {}
   }
 ]
diff --git a/tempest/stress/etc/ssh_floating.json b/tempest/stress/etc/ssh_floating.json
index e03fd4f..c502e96 100644
--- a/tempest/stress/etc/ssh_floating.json
+++ b/tempest/stress/etc/ssh_floating.json
@@ -1,7 +1,7 @@
 [{"action": "tempest.stress.actions.ssh_floating.FloatingStress",
   "threads": 8,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "kwargs": {"vm_extra_args": {},
              "new_vm": true,
              "new_sec_group": true,
diff --git a/tempest/stress/etc/stress-tox-job.json b/tempest/stress/etc/stress-tox-job.json
index 9cee316..bfa448d 100644
--- a/tempest/stress/etc/stress-tox-job.json
+++ b/tempest/stress/etc/stress-tox-job.json
@@ -1,25 +1,25 @@
 [{"action": "tempest.stress.actions.server_create_destroy.ServerCreateDestroyTest",
   "threads": 8,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "kwargs": {}
   },
   {"action": "tempest.stress.actions.volume_create_delete.VolumeCreateDeleteTest",
   "threads": 4,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "kwargs": {}
   },
   {"action": "tempest.stress.actions.volume_attach_delete.VolumeAttachDeleteTest",
   "threads": 2,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "kwargs": {}
   },
   {"action": "tempest.stress.actions.unit_test.UnitTest",
   "threads": 4,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "required_services": ["neutron"],
   "kwargs": {"test_method": "tempest.scenario.test_network_advanced_server_ops.TestNetworkAdvancedServerOps.test_server_connectivity_stop_start",
              "class_setup_per": "process"}
diff --git a/tempest/stress/etc/volume-attach-delete-test.json b/tempest/stress/etc/volume-attach-delete-test.json
index 4553ff8..d468967 100644
--- a/tempest/stress/etc/volume-attach-delete-test.json
+++ b/tempest/stress/etc/volume-attach-delete-test.json
@@ -1,7 +1,7 @@
 [{"action": "tempest.stress.actions.volume_attach_delete.VolumeAttachDeleteTest",
   "threads": 4,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "kwargs": {}
   }
 ]
diff --git a/tempest/stress/etc/volume-attach-verify.json b/tempest/stress/etc/volume-attach-verify.json
index 731f5ed..d8c96fd 100644
--- a/tempest/stress/etc/volume-attach-verify.json
+++ b/tempest/stress/etc/volume-attach-verify.json
@@ -1,7 +1,7 @@
 [{"action": "tempest.stress.actions.volume_attach_verify.VolumeVerifyStress",
   "threads": 1,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "kwargs": {"vm_extra_args": {},
              "new_volume": true,
              "new_server": false,
diff --git a/tempest/stress/etc/volume-create-delete-test.json b/tempest/stress/etc/volume-create-delete-test.json
index e8a58f7..a60cde6 100644
--- a/tempest/stress/etc/volume-create-delete-test.json
+++ b/tempest/stress/etc/volume-create-delete-test.json
@@ -1,7 +1,7 @@
 [{"action": "tempest.stress.actions.volume_create_delete.VolumeCreateDeleteTest",
   "threads": 4,
-  "use_admin": false,
-  "use_isolated_tenants": false,
+  "use_admin": true,
+  "use_isolated_tenants": true,
   "kwargs": {}
   }
 ]
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index a5dea54..193abc7 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -201,7 +201,8 @@
                                    {'alias': 'fake2'},
                                    {'alias': 'not_fake'}]}
         fake_os = mock.MagicMock()
-        fake_os.network_client.list_extensions = fake_list_extensions
+        fake_os.network_extensions_client.list_extensions = (
+            fake_list_extensions)
         self.useFixture(mockpatch.PatchObject(
             verify_tempest_config, 'get_enabled_extensions',
             return_value=(['fake1', 'fake2', 'fake3'])))
@@ -223,7 +224,8 @@
                                    {'alias': 'fake2'},
                                    {'alias': 'not_fake'}]}
         fake_os = mock.MagicMock()
-        fake_os.network_client.list_extensions = fake_list_extensions
+        fake_os.network_extensions_client.list_extensions = (
+            fake_list_extensions)
         self.useFixture(mockpatch.PatchObject(
             verify_tempest_config, 'get_enabled_extensions',
             return_value=(['all'])))
diff --git a/tempest/tests/common/test_api_version_utils.py b/tempest/tests/common/test_api_version_utils.py
index 9f399a2..a24bc65 100644
--- a/tempest/tests/common/test_api_version_utils.py
+++ b/tempest/tests/common/test_api_version_utils.py
@@ -12,146 +12,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_config import cfg
 import testtools
 
-from tempest.api.compute import base as compute_base
 from tempest.common import api_version_utils
-from tempest import config
 from tempest import exceptions
 from tempest.tests import base
-from tempest.tests import fake_config
-
-
-class VersionTestNoneTolatest(compute_base.BaseV2ComputeTest):
-    min_microversion = None
-    max_microversion = 'latest'
-
-
-class VersionTestNoneTo2_2(compute_base.BaseV2ComputeTest):
-    min_microversion = None
-    max_microversion = '2.2'
-
-
-class VersionTest2_3ToLatest(compute_base.BaseV2ComputeTest):
-    min_microversion = '2.3'
-    max_microversion = 'latest'
-
-
-class VersionTest2_5To2_10(compute_base.BaseV2ComputeTest):
-    min_microversion = '2.5'
-    max_microversion = '2.10'
-
-
-class VersionTest2_10To2_10(compute_base.BaseV2ComputeTest):
-    min_microversion = '2.10'
-    max_microversion = '2.10'
-
-
-class InvalidVersionTest(compute_base.BaseV2ComputeTest):
-    min_microversion = '2.11'
-    max_microversion = '2.1'
-
-
-class TestMicroversionsTestsClass(base.TestCase):
-
-    def setUp(self):
-        super(TestMicroversionsTestsClass, self).setUp()
-        self.useFixture(fake_config.ConfigFixture())
-        self.stubs.Set(config, 'TempestConfigPrivate',
-                       fake_config.FakePrivate)
-
-    def _test_version(self, cfg_min, cfg_max,
-                      expected_pass_tests,
-                      expected_skip_tests):
-        cfg.CONF.set_default('min_microversion',
-                             cfg_min, group='compute-feature-enabled')
-        cfg.CONF.set_default('max_microversion',
-                             cfg_max, group='compute-feature-enabled')
-        try:
-            for test_class in expected_pass_tests:
-                test_class.skip_checks()
-            for test_class in expected_skip_tests:
-                self.assertRaises(testtools.TestCase.skipException,
-                                  test_class.skip_checks)
-        except testtools.TestCase.skipException as e:
-            raise testtools.TestCase.failureException(e.message)
-
-    def test_config_version_none_none(self):
-        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2]
-        expected_skip_tests = [VersionTest2_3ToLatest, VersionTest2_5To2_10,
-                               VersionTest2_10To2_10]
-        self._test_version(None, None,
-                           expected_pass_tests,
-                           expected_skip_tests)
-
-    def test_config_version_none_23(self):
-        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
-                               VersionTest2_3ToLatest]
-        expected_skip_tests = [VersionTest2_5To2_10, VersionTest2_10To2_10]
-        self._test_version(None, '2.3',
-                           expected_pass_tests,
-                           expected_skip_tests)
-
-    def test_config_version_22_latest(self):
-        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
-                               VersionTest2_3ToLatest, VersionTest2_5To2_10,
-                               VersionTest2_10To2_10]
-        expected_skip_tests = []
-        self._test_version('2.2', 'latest',
-                           expected_pass_tests,
-                           expected_skip_tests)
-
-    def test_config_version_22_23(self):
-        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
-                               VersionTest2_3ToLatest]
-        expected_skip_tests = [VersionTest2_5To2_10, VersionTest2_10To2_10]
-        self._test_version('2.2', '2.3',
-                           expected_pass_tests,
-                           expected_skip_tests)
-
-    def test_config_version_210_210(self):
-        expected_pass_tests = [VersionTestNoneTolatest,
-                               VersionTest2_3ToLatest,
-                               VersionTest2_5To2_10,
-                               VersionTest2_10To2_10]
-        expected_skip_tests = [VersionTestNoneTo2_2]
-        self._test_version('2.10', '2.10',
-                           expected_pass_tests,
-                           expected_skip_tests)
-
-    def test_config_version_none_latest(self):
-        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
-                               VersionTest2_3ToLatest, VersionTest2_5To2_10,
-                               VersionTest2_10To2_10]
-        expected_skip_tests = []
-        self._test_version(None, 'latest',
-                           expected_pass_tests,
-                           expected_skip_tests)
-
-    def test_config_version_latest_latest(self):
-        expected_pass_tests = [VersionTestNoneTolatest, VersionTest2_3ToLatest]
-        expected_skip_tests = [VersionTestNoneTo2_2, VersionTest2_5To2_10,
-                               VersionTest2_10To2_10]
-        self._test_version('latest', 'latest',
-                           expected_pass_tests,
-                           expected_skip_tests)
-
-    def test_config_invalid_version(self):
-        cfg.CONF.set_default('min_microversion',
-                             '2.5', group='compute-feature-enabled')
-        cfg.CONF.set_default('max_microversion',
-                             '2.1', group='compute-feature-enabled')
-        self.assertRaises(exceptions.InvalidConfiguration,
-                          VersionTestNoneTolatest.skip_checks)
-
-    def test_config_version_invalid_test_version(self):
-        cfg.CONF.set_default('min_microversion',
-                             None, group='compute-feature-enabled')
-        cfg.CONF.set_default('max_microversion',
-                             '2.13', group='compute-feature-enabled')
-        self.assertRaises(exceptions.InvalidConfiguration,
-                          InvalidVersionTest.skip_checks)
 
 
 class TestVersionSkipLogic(base.TestCase):
@@ -219,3 +84,31 @@
 
     def test_both_min_version_equal(self):
         self._test_request_version('2.3', '2.3', expected_version='2.3')
+
+
+class TestMicroversionHeaderMatches(base.TestCase):
+
+    def test_header_matches(self):
+        microversion_header_name = 'x-openstack-xyz-api-version'
+        request_microversion = '2.1'
+        test_respose = {microversion_header_name: request_microversion}
+        api_version_utils.assert_version_header_matches_request(
+            microversion_header_name, request_microversion, test_respose)
+
+    def test_header_does_not_match(self):
+        microversion_header_name = 'x-openstack-xyz-api-version'
+        request_microversion = '2.1'
+        test_respose = {microversion_header_name: '2.2'}
+        self.assertRaises(
+            exceptions.InvalidHTTPResponseHeader,
+            api_version_utils.assert_version_header_matches_request,
+            microversion_header_name, request_microversion, test_respose)
+
+    def test_header_not_present(self):
+        microversion_header_name = 'x-openstack-xyz-api-version'
+        request_microversion = '2.1'
+        test_respose = {}
+        self.assertRaises(
+            exceptions.InvalidHTTPResponseHeader,
+            api_version_utils.assert_version_header_matches_request,
+            microversion_header_name, request_microversion, test_respose)
diff --git a/tempest/tests/services/compute/test_base_compute_client.py b/tempest/tests/services/compute/test_base_compute_client.py
index 134fe39..7a55cdb 100644
--- a/tempest/tests/services/compute/test_base_compute_client.py
+++ b/tempest/tests/services/compute/test_base_compute_client.py
@@ -13,64 +13,48 @@
 #    under the License.
 
 import httplib2
-import mock
+from oslotest import mockpatch
 from tempest_lib.common import rest_client
 
 from tempest import exceptions
-from tempest.services.compute.json import base as base_compute_client
+from tempest.services.compute.json import base_compute_client
 from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
 
 
-class TestClientWithoutMicroversionHeader(base.BaseComputeServiceTest):
+class TestMicroversionHeaderCheck(base.BaseComputeServiceTest):
 
     def setUp(self):
-        super(TestClientWithoutMicroversionHeader, self).setUp()
+        super(TestMicroversionHeaderCheck, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
         self.client = base_compute_client.BaseComputeClient(
             fake_auth, 'compute', 'regionOne')
+        self.client.set_api_microversion('2.2')
 
-    def test_no_microverion_header(self):
-        header = self.client.get_headers()
-        self.assertNotIn('X-OpenStack-Nova-API-Version', header)
+    def _check_microverion_header_in_response(self, fake_response):
+        def request(*args, **kwargs):
+            return (httplib2.Response(fake_response), {})
 
-    def test_no_microverion_header_in_raw_request(self):
-        def raw_request(*args, **kwargs):
-            self.assertNotIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
-            return (httplib2.Response({'status': 200}), {})
+        self.useFixture(mockpatch.PatchObject(
+            rest_client.RestClient,
+            'request',
+            side_effect=request))
 
-        with mock.patch.object(rest_client.RestClient,
-                               'raw_request') as mock_get:
-            mock_get.side_effect = raw_request
-            self.client.get('fake_url')
+    def test_correct_microverion_in_response(self):
+        fake_response = {self.client.api_microversion_header_name: '2.2'}
+        self._check_microverion_header_in_response(fake_response)
+        self.client.get('fake_url')
 
+    def test_incorrect_microverion_in_response(self):
+        fake_response = {self.client.api_microversion_header_name: '2.3'}
+        self._check_microverion_header_in_response(fake_response)
+        self.assertRaises(exceptions.InvalidHTTPResponseHeader,
+                          self.client.get, 'fake_url')
 
-class TestClientWithMicroversionHeader(base.BaseComputeServiceTest):
-
-    def setUp(self):
-        super(TestClientWithMicroversionHeader, self).setUp()
-        fake_auth = fake_auth_provider.FakeAuthProvider()
-        self.client = base_compute_client.BaseComputeClient(
-            fake_auth, 'compute', 'regionOne')
-        self.client.api_microversion = '2.2'
-
-    def test_microverion_header(self):
-        header = self.client.get_headers()
-        self.assertIn('X-OpenStack-Nova-API-Version', header)
-        self.assertEqual(self.client.api_microversion,
-                         header['X-OpenStack-Nova-API-Version'])
-
-    def test_microverion_header_in_raw_request(self):
-        def raw_request(*args, **kwargs):
-            self.assertIn('X-OpenStack-Nova-API-Version', kwargs['headers'])
-            self.assertEqual(self.client.api_microversion,
-                             kwargs['headers']['X-OpenStack-Nova-API-Version'])
-            return (httplib2.Response({'status': 200}), {})
-
-        with mock.patch.object(rest_client.RestClient,
-                               'raw_request') as mock_get:
-            mock_get.side_effect = raw_request
-            self.client.get('fake_url')
+    def test_no_microverion_header_in_response(self):
+        self._check_microverion_header_in_response({})
+        self.assertRaises(exceptions.InvalidHTTPResponseHeader,
+                          self.client.get, 'fake_url')
 
 
 class DummyServiceClient1(base_compute_client.BaseComputeClient):
diff --git a/tempest/tests/services/test_base_microversion_client.py b/tempest/tests/services/test_base_microversion_client.py
new file mode 100644
index 0000000..11b8170
--- /dev/null
+++ b/tempest/tests/services/test_base_microversion_client.py
@@ -0,0 +1,75 @@
+# Copyright 2016 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.
+
+import httplib2
+import mock
+from tempest_lib.common import rest_client
+
+from tempest.services import base_microversion_client
+from tempest.tests import fake_auth_provider
+from tempest.tests.services.compute import base
+
+
+class TestClientWithoutMicroversionHeader(base.BaseComputeServiceTest):
+
+    def setUp(self):
+        super(TestClientWithoutMicroversionHeader, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = base_microversion_client.BaseMicroversionClient(
+            fake_auth, 'compute', 'regionOne', 'X-OpenStack-Nova-API-Version')
+
+    def test_no_microverion_header(self):
+        header = self.client.get_headers()
+        self.assertNotIn(self.client.api_microversion_header_name, header)
+
+    def test_no_microverion_header_in_raw_request(self):
+        def raw_request(*args, **kwargs):
+            self.assertNotIn(self.client.api_microversion_header_name,
+                             kwargs['headers'])
+            return (httplib2.Response({'status': 200}), {})
+
+        with mock.patch.object(rest_client.RestClient,
+                               'raw_request') as mock_get:
+            mock_get.side_effect = raw_request
+            self.client.get('fake_url')
+
+
+class TestClientWithMicroversionHeader(base.BaseComputeServiceTest):
+
+    def setUp(self):
+        super(TestClientWithMicroversionHeader, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = base_microversion_client.BaseMicroversionClient(
+            fake_auth, 'compute', 'regionOne', 'X-OpenStack-Nova-API-Version')
+        self.client.set_api_microversion('2.2')
+
+    def test_microverion_header(self):
+        header = self.client.get_headers()
+        self.assertIn(self.client.api_microversion_header_name, header)
+        self.assertEqual(self.client.api_microversion,
+                         header[self.client.api_microversion_header_name])
+
+    def test_microverion_header_in_raw_request(self):
+        def raw_request(*args, **kwargs):
+            self.assertIn(self.client.api_microversion_header_name,
+                          kwargs['headers'])
+            self.assertEqual(
+                self.client.api_microversion,
+                kwargs['headers'][self.client.api_microversion_header_name])
+            return (httplib2.Response({'status': 200}), {})
+
+        with mock.patch.object(rest_client.RestClient,
+                               'raw_request') as mock_get:
+            mock_get.side_effect = raw_request
+            self.client.get('fake_url')
diff --git a/tempest/tests/test_microversions.py b/tempest/tests/test_microversions.py
new file mode 100644
index 0000000..fc37af4
--- /dev/null
+++ b/tempest/tests/test_microversions.py
@@ -0,0 +1,153 @@
+# 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 oslo_config import cfg
+import testtools
+
+from tempest.api.compute import base as compute_base
+from tempest import config
+from tempest import exceptions
+from tempest.tests import base
+from tempest.tests import fake_config
+
+
+class VersionTestNoneTolatest(compute_base.BaseV2ComputeTest):
+    min_microversion = None
+    max_microversion = 'latest'
+
+
+class VersionTestNoneTo2_2(compute_base.BaseV2ComputeTest):
+    min_microversion = None
+    max_microversion = '2.2'
+
+
+class VersionTest2_3ToLatest(compute_base.BaseV2ComputeTest):
+    min_microversion = '2.3'
+    max_microversion = 'latest'
+
+
+class VersionTest2_5To2_10(compute_base.BaseV2ComputeTest):
+    min_microversion = '2.5'
+    max_microversion = '2.10'
+
+
+class VersionTest2_10To2_10(compute_base.BaseV2ComputeTest):
+    min_microversion = '2.10'
+    max_microversion = '2.10'
+
+
+class InvalidVersionTest(compute_base.BaseV2ComputeTest):
+    min_microversion = '2.11'
+    max_microversion = '2.1'
+
+
+class TestMicroversionsTestsClass(base.TestCase):
+
+    def setUp(self):
+        super(TestMicroversionsTestsClass, self).setUp()
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate',
+                       fake_config.FakePrivate)
+
+    def _test_version(self, cfg_min, cfg_max,
+                      expected_pass_tests,
+                      expected_skip_tests):
+        cfg.CONF.set_default('min_microversion',
+                             cfg_min, group='compute-feature-enabled')
+        cfg.CONF.set_default('max_microversion',
+                             cfg_max, group='compute-feature-enabled')
+        try:
+            for test_class in expected_pass_tests:
+                test_class.skip_checks()
+            for test_class in expected_skip_tests:
+                self.assertRaises(testtools.TestCase.skipException,
+                                  test_class.skip_checks)
+        except testtools.TestCase.skipException as e:
+            raise testtools.TestCase.failureException(e.message)
+
+    def test_config_version_none_none(self):
+        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2]
+        expected_skip_tests = [VersionTest2_3ToLatest, VersionTest2_5To2_10,
+                               VersionTest2_10To2_10]
+        self._test_version(None, None,
+                           expected_pass_tests,
+                           expected_skip_tests)
+
+    def test_config_version_none_23(self):
+        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+                               VersionTest2_3ToLatest]
+        expected_skip_tests = [VersionTest2_5To2_10, VersionTest2_10To2_10]
+        self._test_version(None, '2.3',
+                           expected_pass_tests,
+                           expected_skip_tests)
+
+    def test_config_version_22_latest(self):
+        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+                               VersionTest2_3ToLatest, VersionTest2_5To2_10,
+                               VersionTest2_10To2_10]
+        expected_skip_tests = []
+        self._test_version('2.2', 'latest',
+                           expected_pass_tests,
+                           expected_skip_tests)
+
+    def test_config_version_22_23(self):
+        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+                               VersionTest2_3ToLatest]
+        expected_skip_tests = [VersionTest2_5To2_10, VersionTest2_10To2_10]
+        self._test_version('2.2', '2.3',
+                           expected_pass_tests,
+                           expected_skip_tests)
+
+    def test_config_version_210_210(self):
+        expected_pass_tests = [VersionTestNoneTolatest,
+                               VersionTest2_3ToLatest,
+                               VersionTest2_5To2_10,
+                               VersionTest2_10To2_10]
+        expected_skip_tests = [VersionTestNoneTo2_2]
+        self._test_version('2.10', '2.10',
+                           expected_pass_tests,
+                           expected_skip_tests)
+
+    def test_config_version_none_latest(self):
+        expected_pass_tests = [VersionTestNoneTolatest, VersionTestNoneTo2_2,
+                               VersionTest2_3ToLatest, VersionTest2_5To2_10,
+                               VersionTest2_10To2_10]
+        expected_skip_tests = []
+        self._test_version(None, 'latest',
+                           expected_pass_tests,
+                           expected_skip_tests)
+
+    def test_config_version_latest_latest(self):
+        expected_pass_tests = [VersionTestNoneTolatest, VersionTest2_3ToLatest]
+        expected_skip_tests = [VersionTestNoneTo2_2, VersionTest2_5To2_10,
+                               VersionTest2_10To2_10]
+        self._test_version('latest', 'latest',
+                           expected_pass_tests,
+                           expected_skip_tests)
+
+    def test_config_invalid_version(self):
+        cfg.CONF.set_default('min_microversion',
+                             '2.5', group='compute-feature-enabled')
+        cfg.CONF.set_default('max_microversion',
+                             '2.1', group='compute-feature-enabled')
+        self.assertRaises(exceptions.InvalidConfiguration,
+                          VersionTestNoneTolatest.skip_checks)
+
+    def test_config_version_invalid_test_version(self):
+        cfg.CONF.set_default('min_microversion',
+                             None, group='compute-feature-enabled')
+        cfg.CONF.set_default('max_microversion',
+                             '2.13', group='compute-feature-enabled')
+        self.assertRaises(exceptions.InvalidConfiguration,
+                          InvalidVersionTest.skip_checks)
diff --git a/test-requirements.txt b/test-requirements.txt
index 5b01ea9..eb43f31 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -3,10 +3,10 @@
 # process, which may cause wedges in the gate later.
 hacking<0.11,>=0.10.0
 # needed for doc build
-sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
-python-subunit>=0.0.18
+sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD
+python-subunit>=0.0.18 # Apache-2.0/BSD
 oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
-mox>=0.5.3
-mock>=1.2
-coverage>=3.6
+mox>=0.5.3 # Apache-2.0
+mock>=1.2 # BSD
+coverage>=3.6 # Apache-2.0
 oslotest>=1.10.0 # Apache-2.0
diff --git a/tools/check_logs.py b/tools/check_logs.py
index 9b707b0..fa7129d 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -105,7 +105,7 @@
 def main(opts):
     if opts.directory and opts.url or not (opts.directory or opts.url):
         print("Must provide exactly one of -d or -u")
-        exit(1)
+        return 1
     print("Checking logs...")
     WHITELIST_FILE = os.path.join(
         os.path.abspath(os.path.dirname(os.path.dirname(__file__))),
diff --git a/tools/install_venv_common.py b/tools/install_venv_common.py
index e279159..d1643f8 100644
--- a/tools/install_venv_common.py
+++ b/tools/install_venv_common.py
@@ -113,7 +113,7 @@
 
         # First things first, make sure our venv has the latest pip and
         # setuptools and pbr
-        self.pip_install('pip>=1.4')
+        self.pip_install('pip<8,>=1.4')
         self.pip_install('setuptools')
         self.pip_install('pbr')
 
diff --git a/tox.ini b/tox.ini
index 832a7b3..95f2cf1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
 [tox]
 envlist = pep8,py34,py27
-minversion = 1.6
+minversion = 2.3.1
 skipsdist = True
 
 [tempestenv]