Merge "Add basic Savanna CLI tests"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 2443399..025d0f3 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -453,6 +453,12 @@
 # enabled (boolean value)
 #trust=true
 
+# Is the v2 identity API enabled (boolean value)
+#api_v2=true
+
+# Is the v3 identity API enabled (boolean value)
+#api_v3=true
+
 
 [image]
 
@@ -524,13 +530,20 @@
 # value)
 #region=
 
-# The cidr block to allocate tenant networks from (string
+# The cidr block to allocate tenant ipv4 subnets from (string
 # value)
 #tenant_network_cidr=10.100.0.0/16
 
-# The mask bits for tenant networks (integer value)
+# The mask bits for tenant ipv4 subnets (integer value)
 #tenant_network_mask_bits=28
 
+# The cidr block to allocate tenant ipv6 subnets from (string
+# value)
+#tenant_network_v6_cidr=2003::/64
+
+# The mask bits for tenant ipv6 subnets (integer value)
+#tenant_network_v6_mask_bits=96
+
 # Whether tenant network connectivity should be evaluated
 # directly (boolean value)
 #tenant_networks_reachable=false
diff --git a/setup.cfg b/setup.cfg
index 23a97ff..79f538f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -21,3 +21,6 @@
 all_files = 1
 build-dir = doc/build
 source-dir = doc/source
+
+[wheel]
+universal = 1
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 2cee78a..08df616 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -15,8 +15,7 @@
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import exceptions
-from tempest.test import attr
-from tempest.test import skip_because
+from tempest import test
 
 
 class ServersAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -25,6 +24,7 @@
     Tests Servers API using admin privileges
     """
 
+    _host_key = 'OS-EXT-SRV-ATTR:host'
     _interface = 'json'
 
     @classmethod
@@ -54,7 +54,7 @@
             flavor_id = data_utils.rand_int_id(start=1000)
         return flavor_id
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_servers_by_admin(self):
         # Listing servers by admin user returns empty list by default
         resp, body = self.client.list_servers_with_detail()
@@ -62,7 +62,7 @@
         self.assertEqual('200', resp['status'])
         self.assertEqual([], servers)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_servers_filter_by_error_status(self):
         # Filter the list of servers by server error status
         params = {'status': 'error'}
@@ -78,7 +78,7 @@
         self.assertIn(self.s1_id, map(lambda x: x['id'], servers))
         self.assertNotIn(self.s2_id, map(lambda x: x['id'], servers))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_servers_by_admin_with_all_tenants(self):
         # Listing servers by admin user with all tenants parameter
         # Here should be listed all servers
@@ -90,7 +90,34 @@
         self.assertIn(self.s1_name, servers_name)
         self.assertIn(self.s2_name, servers_name)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
+    def test_list_servers_filter_by_exist_host(self):
+        # Filter the list of servers by existent host
+        name = data_utils.rand_name('server')
+        flavor = self.flavor_ref
+        image_id = self.image_ref
+        resp, test_server = self.client.create_server(
+            name, image_id, flavor)
+        self.assertEqual('202', resp['status'])
+        self.addCleanup(self.client.delete_server, test_server['id'])
+        self.client.wait_for_server_status(test_server['id'], 'ACTIVE')
+        resp, server = self.client.get_server(test_server['id'])
+        self.assertEqual(server['status'], 'ACTIVE')
+        hostname = server[self._host_key]
+        params = {'host': hostname}
+        resp, body = self.client.list_servers(params)
+        self.assertEqual('200', resp['status'])
+        servers = body['servers']
+        nonexistent_params = {'host': 'nonexistent_host'}
+        resp, nonexistent_body = self.client.list_servers(
+            nonexistent_params)
+        self.assertEqual('200', resp['status'])
+        nonexistent_servers = nonexistent_body['servers']
+        self.assertIn(test_server['id'], map(lambda x: x['id'], servers))
+        self.assertNotIn(test_server['id'],
+                         map(lambda x: x['id'], nonexistent_servers))
+
+    @test.attr(type='gate')
     def test_admin_delete_servers_of_others(self):
         # Administrator can delete servers of others
         _, server = self.create_test_server()
@@ -98,7 +125,7 @@
         self.assertEqual('204', resp['status'])
         self.servers_client.wait_for_server_termination(server['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_server_while_in_error_state(self):
         # Delete a server while it's VM state is error
         resp, server = self.create_test_server(wait_until='ACTIVE')
@@ -110,7 +137,7 @@
         resp, _ = self.client.delete_server(server['id'])
         self.assertEqual('204', resp['status'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_reset_state_server(self):
         # Reset server's state to 'error'
         resp, server = self.client.reset_state(self.s1_id)
@@ -128,8 +155,8 @@
         resp, server = self.client.get_server(self.s1_id)
         self.assertEqual(server['status'], 'ACTIVE')
 
-    @attr(type='gate')
-    @skip_because(bug="1240043")
+    @test.attr(type='gate')
+    @test.skip_because(bug="1240043")
     def test_get_server_diagnostics_by_admin(self):
         # Retrieve server diagnostics by admin user
         resp, diagnostic = self.client.get_server_diagnostics(self.s1_id)
@@ -140,7 +167,7 @@
         for key in basic_attrs:
             self.assertIn(key, str(diagnostic.keys()))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_rebuild_server_in_error_state(self):
         # The server in error state should be rebuilt using the provided
         # image and changed to ACTIVE state
@@ -170,4 +197,6 @@
 
 
 class ServersAdminTestXML(ServersAdminTestJSON):
+    _host_key = (
+        '{http://docs.openstack.org/compute/ext/extended_status/api/v1.1}host')
     _interface = 'xml'
diff --git a/tempest/api/compute/v3/admin/test_servers.py b/tempest/api/compute/v3/admin/test_servers.py
index ef9eedc..aaa4d7f 100644
--- a/tempest/api/compute/v3/admin/test_servers.py
+++ b/tempest/api/compute/v3/admin/test_servers.py
@@ -16,8 +16,6 @@
 from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest import test
-from tempest.test import attr
-from tempest.test import skip_because
 
 
 class ServersAdminV3Test(base.BaseV3ComputeAdminTest):
@@ -26,6 +24,7 @@
     Tests Servers API using admin privileges
     """
 
+    _host_key = 'os-extended-server-attributes:host'
     _interface = 'json'
 
     @classmethod
@@ -55,7 +54,7 @@
             flavor_id = data_utils.rand_int_id(start=1000)
         return flavor_id
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_servers_by_admin(self):
         # Listing servers by admin user returns empty list by default
         resp, body = self.client.list_servers_with_detail()
@@ -64,7 +63,7 @@
         self.assertEqual([], servers)
 
     @test.skip_because(bug='1265416')
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_servers_by_admin_with_all_tenants(self):
         # Listing servers by admin user with all tenants parameter
         # Here should be listed all servers
@@ -76,7 +75,34 @@
         self.assertIn(self.s1_name, servers_name)
         self.assertIn(self.s2_name, servers_name)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
+    def test_list_servers_filter_by_existent_host(self):
+        # Filter the list of servers by existent host
+        name = data_utils.rand_name('server')
+        flavor = self.flavor_ref
+        image_id = self.image_ref
+        resp, test_server = self.client.create_server(
+            name, image_id, flavor)
+        self.assertEqual('202', resp['status'])
+        self.addCleanup(self.client.delete_server, test_server['id'])
+        self.client.wait_for_server_status(test_server['id'], 'ACTIVE')
+        resp, server = self.client.get_server(test_server['id'])
+        self.assertEqual(server['status'], 'ACTIVE')
+        hostname = server[self._host_key]
+        params = {'host': hostname}
+        resp, body = self.client.list_servers(params)
+        self.assertEqual('200', resp['status'])
+        servers = body['servers']
+        nonexistent_params = {'host': 'nonexistent_host'}
+        resp, nonexistent_body = self.client.list_servers(
+            nonexistent_params)
+        self.assertEqual('200', resp['status'])
+        nonexistent_servers = nonexistent_body['servers']
+        self.assertIn(test_server['id'], map(lambda x: x['id'], servers))
+        self.assertNotIn(test_server['id'],
+                         map(lambda x: x['id'], nonexistent_servers))
+
+    @test.attr(type='gate')
     def test_admin_delete_servers_of_others(self):
         # Administrator can delete servers of others
         _, server = self.create_test_server()
@@ -84,7 +110,7 @@
         self.assertEqual('204', resp['status'])
         self.servers_client.wait_for_server_termination(server['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_server_while_in_error_state(self):
         # Delete a server while it's VM state is error
         resp, server = self.create_test_server(wait_until='ACTIVE')
@@ -96,7 +122,7 @@
         resp, _ = self.client.delete_server(server['id'])
         self.assertEqual('204', resp['status'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_reset_state_server(self):
         # Reset server's state to 'error'
         resp, server = self.client.reset_state(self.s1_id)
@@ -114,8 +140,8 @@
         resp, server = self.client.get_server(self.s1_id)
         self.assertEqual(server['status'], 'ACTIVE')
 
-    @attr(type='gate')
-    @skip_because(bug="1240043")
+    @test.attr(type='gate')
+    @test.skip_because(bug="1240043")
     def test_get_server_diagnostics_by_admin(self):
         # Retrieve server diagnostics by admin user
         resp, diagnostic = self.client.get_server_diagnostics(self.s1_id)
@@ -126,7 +152,7 @@
         for key in basic_attrs:
             self.assertIn(key, str(diagnostic.keys()))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_servers_filter_by_error_status(self):
         # Filter the list of servers by server error status
         params = {'status': 'error'}
@@ -142,7 +168,7 @@
         self.assertIn(self.s1_id, map(lambda x: x['id'], servers))
         self.assertNotIn(self.s2_id, map(lambda x: x['id'], servers))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_rebuild_server_in_error_state(self):
         # The server in error state should be rebuilt using the provided
         # image and changed to ACTIVE state
diff --git a/tempest/api/identity/admin/test_roles.py b/tempest/api/identity/admin/test_roles.py
index f1124e4..aa64969 100644
--- a/tempest/api/identity/admin/test_roles.py
+++ b/tempest/api/identity/admin/test_roles.py
@@ -18,7 +18,7 @@
 from tempest.test import attr
 
 
-class RolesTestJSON(base.BaseIdentityAdminTest):
+class RolesTestJSON(base.BaseIdentityV2AdminTest):
     _interface = 'json'
 
     @classmethod
diff --git a/tempest/api/identity/admin/test_roles_negative.py b/tempest/api/identity/admin/test_roles_negative.py
index e5c04de..7a0bdea 100644
--- a/tempest/api/identity/admin/test_roles_negative.py
+++ b/tempest/api/identity/admin/test_roles_negative.py
@@ -21,7 +21,7 @@
 from tempest.test import attr
 
 
-class RolesNegativeTestJSON(base.BaseIdentityAdminTest):
+class RolesNegativeTestJSON(base.BaseIdentityV2AdminTest):
     _interface = 'json'
 
     def _get_role_params(self):
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/test_services.py
index 8ba333f..cbf6b58 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/test_services.py
@@ -20,7 +20,7 @@
 from tempest.test import attr
 
 
-class ServicesTestJSON(base.BaseIdentityAdminTest):
+class ServicesTestJSON(base.BaseIdentityV2AdminTest):
     _interface = 'json'
 
     def _del_service(self, service_id):
diff --git a/tempest/api/identity/admin/test_tenant_negative.py b/tempest/api/identity/admin/test_tenant_negative.py
index e9eddc8..44b54b8 100644
--- a/tempest/api/identity/admin/test_tenant_negative.py
+++ b/tempest/api/identity/admin/test_tenant_negative.py
@@ -21,7 +21,7 @@
 from tempest.test import attr
 
 
-class TenantsNegativeTestJSON(base.BaseIdentityAdminTest):
+class TenantsNegativeTestJSON(base.BaseIdentityV2AdminTest):
     _interface = 'json'
 
     @attr(type=['negative', 'gate'])
diff --git a/tempest/api/identity/admin/test_tenants.py b/tempest/api/identity/admin/test_tenants.py
index 46fa7a9..c7cacb4 100644
--- a/tempest/api/identity/admin/test_tenants.py
+++ b/tempest/api/identity/admin/test_tenants.py
@@ -18,7 +18,7 @@
 from tempest.test import attr
 
 
-class TenantsTestJSON(base.BaseIdentityAdminTest):
+class TenantsTestJSON(base.BaseIdentityV2AdminTest):
     _interface = 'json'
 
     @attr(type='gate')
diff --git a/tempest/api/identity/admin/test_tokens.py b/tempest/api/identity/admin/test_tokens.py
index 620e293..239433b 100644
--- a/tempest/api/identity/admin/test_tokens.py
+++ b/tempest/api/identity/admin/test_tokens.py
@@ -18,7 +18,7 @@
 from tempest.test import attr
 
 
-class TokensTestJSON(base.BaseIdentityAdminTest):
+class TokensTestJSON(base.BaseIdentityV2AdminTest):
     _interface = 'json'
 
     @attr(type='gate')
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index 39ef947..898cccc 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -20,7 +20,7 @@
 from tempest.test import attr
 
 
-class UsersTestJSON(base.BaseIdentityAdminTest):
+class UsersTestJSON(base.BaseIdentityV2AdminTest):
     _interface = 'json'
 
     @classmethod
diff --git a/tempest/api/identity/admin/test_users_negative.py b/tempest/api/identity/admin/test_users_negative.py
index 060f24a..1188325 100644
--- a/tempest/api/identity/admin/test_users_negative.py
+++ b/tempest/api/identity/admin/test_users_negative.py
@@ -20,7 +20,7 @@
 import uuid
 
 
-class UsersNegativeTestJSON(base.BaseIdentityAdminTest):
+class UsersNegativeTestJSON(base.BaseIdentityV2AdminTest):
     _interface = 'json'
 
     @classmethod
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index 753eaa6..5f22d43 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -18,7 +18,7 @@
 from tempest.test import attr
 
 
-class CredentialsTestJSON(base.BaseIdentityAdminTest):
+class CredentialsTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     @classmethod
@@ -32,23 +32,23 @@
         u_email = '%s@testmail.tm' % u_name
         u_password = data_utils.rand_name('pass-')
         for i in range(2):
-            resp, cls.project = cls.v3_client.create_project(
+            resp, cls.project = cls.client.create_project(
                 data_utils.rand_name('project-'),
                 description=data_utils.rand_name('project-desc-'))
             assert resp['status'] == '201', "Expected %s" % resp['status']
             cls.projects.append(cls.project['id'])
 
-        resp, cls.user_body = cls.v3_client.create_user(
+        resp, cls.user_body = cls.client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, project_id=cls.projects[0])
         assert resp['status'] == '201', "Expected: %s" % resp['status']
 
     @classmethod
     def tearDownClass(cls):
-        resp, _ = cls.v3_client.delete_user(cls.user_body['id'])
+        resp, _ = cls.client.delete_user(cls.user_body['id'])
         assert resp['status'] == '204', "Expected: %s" % resp['status']
         for p in cls.projects:
-            resp, _ = cls.v3_client.delete_project(p)
+            resp, _ = cls.client.delete_project(p)
             assert resp['status'] == '204', "Expected: %s" % resp['status']
         super(CredentialsTestJSON, cls).tearDownClass()
 
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 4017b62..086d235 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -19,14 +19,14 @@
 from tempest.test import attr
 
 
-class DomainsTestJSON(base.BaseIdentityAdminTest):
+class DomainsTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     def _delete_domain(self, domain_id):
         # It is necessary to disable the domain before deleting,
         # or else it would result in unauthorized error
-        _, body = self.v3_client.update_domain(domain_id, enabled=False)
-        resp, _ = self.v3_client.delete_domain(domain_id)
+        _, body = self.client.update_domain(domain_id, enabled=False)
+        resp, _ = self.client.delete_domain(domain_id)
         self.assertEqual(204, resp.status)
 
     @attr(type='smoke')
@@ -35,14 +35,14 @@
         domain_ids = list()
         fetched_ids = list()
         for _ in range(3):
-            _, domain = self.v3_client.create_domain(
+            _, domain = self.client.create_domain(
                 data_utils.rand_name('domain-'),
                 description=data_utils.rand_name('domain-desc-'))
             # Delete the domain at the end of this method
             self.addCleanup(self._delete_domain, domain['id'])
             domain_ids.append(domain['id'])
         # List and Verify Domains
-        resp, body = self.v3_client.list_domains()
+        resp, body = self.client.list_domains()
         self.assertEqual(resp['status'], '200')
         for d in body:
             fetched_ids.append(d['id'])
@@ -53,7 +53,7 @@
     def test_create_update_delete_domain(self):
         d_name = data_utils.rand_name('domain-')
         d_desc = data_utils.rand_name('domain-desc-')
-        resp_1, domain = self.v3_client.create_domain(
+        resp_1, domain = self.client.create_domain(
             d_name, description=d_desc)
         self.assertEqual(resp_1['status'], '201')
         self.addCleanup(self._delete_domain, domain['id'])
@@ -72,7 +72,7 @@
         new_desc = data_utils.rand_name('new-desc-')
         new_name = data_utils.rand_name('new-name-')
 
-        resp_2, updated_domain = self.v3_client.update_domain(
+        resp_2, updated_domain = self.client.update_domain(
             domain['id'], name=new_name, description=new_desc)
         self.assertEqual(resp_2['status'], '200')
         self.assertIn('id', updated_domain)
@@ -85,7 +85,7 @@
         self.assertEqual(new_desc, updated_domain['description'])
         self.assertEqual('true', str(updated_domain['enabled']).lower())
 
-        resp_3, fetched_domain = self.v3_client.get_domain(domain['id'])
+        resp_3, fetched_domain = self.client.get_domain(domain['id'])
         self.assertEqual(resp_3['status'], '200')
         self.assertEqual(new_name, fetched_domain['name'])
         self.assertEqual(new_desc, fetched_domain['description'])
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 4ae7884..78ecf93 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -18,7 +18,7 @@
 from tempest.test import attr
 
 
-class EndPointsTestJSON(base.BaseIdentityAdminTest):
+class EndPointsTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     @classmethod
@@ -31,8 +31,8 @@
         s_type = data_utils.rand_name('type--')
         s_description = data_utils.rand_name('description-')
         resp, cls.service_data =\
-            cls.identity_client.create_service(s_name, s_type,
-                                               description=s_description)
+            cls.service_client.create_service(s_name, s_type,
+                                              description=s_description)
         cls.service_id = cls.service_data['id']
         cls.service_ids.append(cls.service_id)
         # Create endpoints so as to use for LIST and GET test cases
@@ -50,7 +50,7 @@
         for e in cls.setup_endpoints:
             cls.client.delete_endpoint(e['id'])
         for s in cls.service_ids:
-            cls.identity_client.delete_service(s)
+            cls.service_client.delete_service(s)
         super(EndPointsTestJSON, cls).tearDownClass()
 
     @attr(type='gate')
@@ -107,8 +107,8 @@
         s_type = data_utils.rand_name('type--')
         s_description = data_utils.rand_name('description-')
         resp, self.service2 =\
-            self.identity_client.create_service(s_name, s_type,
-                                                description=s_description)
+            self.service_client.create_service(s_name, s_type,
+                                               description=s_description)
         self.service_ids.append(self.service2['id'])
         # Updating endpoint with new values
         region2 = data_utils.rand_name('region')
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 70afec7..6e898b2 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -18,7 +18,7 @@
 from tempest import test
 
 
-class GroupsV3TestJSON(base.BaseIdentityAdminTest):
+class GroupsV3TestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     @classmethod
@@ -29,23 +29,23 @@
     def test_group_create_update_get(self):
         name = data_utils.rand_name('Group')
         description = data_utils.rand_name('Description')
-        resp, group = self.v3_client.create_group(name,
-                                                  description=description)
-        self.addCleanup(self.v3_client.delete_group, group['id'])
+        resp, group = self.client.create_group(name,
+                                               description=description)
+        self.addCleanup(self.client.delete_group, group['id'])
         self.assertEqual(resp['status'], '201')
         self.assertEqual(group['name'], name)
         self.assertEqual(group['description'], description)
 
         new_name = data_utils.rand_name('UpdateGroup')
         new_desc = data_utils.rand_name('UpdateDescription')
-        resp, updated_group = self.v3_client.update_group(group['id'],
-                                                          name=new_name,
-                                                          description=new_desc)
+        resp, updated_group = self.client.update_group(group['id'],
+                                                       name=new_name,
+                                                       description=new_desc)
         self.assertEqual(resp['status'], '200')
         self.assertEqual(updated_group['name'], new_name)
         self.assertEqual(updated_group['description'], new_desc)
 
-        resp, new_group = self.v3_client.get_group(group['id'])
+        resp, new_group = self.client.get_group(group['id'])
         self.assertEqual(resp['status'], '200')
         self.assertEqual(group['id'], new_group['id'])
         self.assertEqual(new_name, new_group['name'])
@@ -54,27 +54,27 @@
     @test.attr(type='smoke')
     def test_group_users_add_list_delete(self):
         name = data_utils.rand_name('Group')
-        resp, group = self.v3_client.create_group(name)
-        self.addCleanup(self.v3_client.delete_group, group['id'])
+        resp, group = self.client.create_group(name)
+        self.addCleanup(self.client.delete_group, group['id'])
         # add user into group
         users = []
         for i in range(3):
             name = data_utils.rand_name('User')
-            resp, user = self.v3_client.create_user(name)
+            resp, user = self.client.create_user(name)
             users.append(user)
-            self.addCleanup(self.v3_client.delete_user, user['id'])
-            self.v3_client.add_group_user(group['id'], user['id'])
+            self.addCleanup(self.client.delete_user, user['id'])
+            self.client.add_group_user(group['id'], user['id'])
 
         # list users in group
-        resp, group_users = self.v3_client.list_group_users(group['id'])
+        resp, group_users = self.client.list_group_users(group['id'])
         self.assertEqual(resp['status'], '200')
         self.assertEqual(users.sort(), group_users.sort())
         # delete user in group
         for user in users:
-            resp, body = self.v3_client.delete_group_user(group['id'],
-                                                          user['id'])
+            resp, body = self.client.delete_group_user(group['id'],
+                                                       user['id'])
             self.assertEqual(resp['status'], '204')
-        resp, group_users = self.v3_client.list_group_users(group['id'])
+        resp, group_users = self.client.list_group_users(group['id'])
         self.assertEqual(len(group_users), 0)
 
 
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index 0e8e4c3..3e04b5f 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -18,7 +18,7 @@
 from tempest.test import attr
 
 
-class PoliciesTestJSON(base.BaseIdentityAdminTest):
+class PoliciesTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     def _delete_policy(self, policy_id):
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index 1fc5a6a..f309897 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -19,27 +19,27 @@
 from tempest.test import attr
 
 
-class ProjectsTestJSON(base.BaseIdentityAdminTest):
+class ProjectsTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     def _delete_project(self, project_id):
-        resp, _ = self.v3_client.delete_project(project_id)
+        resp, _ = self.client.delete_project(project_id)
         self.assertEqual(resp['status'], '204')
         self.assertRaises(
-            exceptions.NotFound, self.v3_client.get_project, project_id)
+            exceptions.NotFound, self.client.get_project, project_id)
 
     @attr(type='gate')
     def test_project_list_delete(self):
         # Create several projects and delete them
         for _ in xrange(3):
-            resp, project = self.v3_client.create_project(
+            resp, project = self.client.create_project(
                 data_utils.rand_name('project-new'))
             self.addCleanup(self._delete_project, project['id'])
 
-        resp, list_projects = self.v3_client.list_projects()
+        resp, list_projects = self.client.list_projects()
         self.assertEqual(resp['status'], '200')
 
-        resp, get_project = self.v3_client.get_project(project['id'])
+        resp, get_project = self.client.get_project(project['id'])
         self.assertIn(get_project, list_projects)
 
     @attr(type='gate')
@@ -47,16 +47,16 @@
         # Create project with a description
         project_name = data_utils.rand_name('project-')
         project_desc = data_utils.rand_name('desc-')
-        resp, project = self.v3_client.create_project(
+        resp, project = self.client.create_project(
             project_name, description=project_desc)
-        self.v3data.projects.append(project)
+        self.data.projects.append(project)
         st1 = resp['status']
         project_id = project['id']
         desc1 = project['description']
         self.assertEqual(st1, '201')
         self.assertEqual(desc1, project_desc, 'Description should have '
                          'been sent in response for create')
-        resp, body = self.v3_client.get_project(project_id)
+        resp, body = self.client.get_project(project_id)
         desc2 = body['description']
         self.assertEqual(desc2, project_desc, 'Description does not appear'
                          'to be set')
@@ -65,15 +65,15 @@
     def test_project_create_enabled(self):
         # Create a project that is enabled
         project_name = data_utils.rand_name('project-')
-        resp, project = self.v3_client.create_project(
+        resp, project = self.client.create_project(
             project_name, enabled=True)
-        self.v3data.projects.append(project)
+        self.data.projects.append(project)
         project_id = project['id']
         st1 = resp['status']
         en1 = project['enabled']
         self.assertEqual(st1, '201')
         self.assertTrue(en1, 'Enable should be True in response')
-        resp, body = self.v3_client.get_project(project_id)
+        resp, body = self.client.get_project(project_id)
         en2 = body['enabled']
         self.assertTrue(en2, 'Enable should be True in lookup')
 
@@ -81,15 +81,15 @@
     def test_project_create_not_enabled(self):
         # Create a project that is not enabled
         project_name = data_utils.rand_name('project-')
-        resp, project = self.v3_client.create_project(
+        resp, project = self.client.create_project(
             project_name, enabled=False)
-        self.v3data.projects.append(project)
+        self.data.projects.append(project)
         st1 = resp['status']
         en1 = project['enabled']
         self.assertEqual(st1, '201')
         self.assertEqual('false', str(en1).lower(),
                          'Enable should be False in response')
-        resp, body = self.v3_client.get_project(project['id'])
+        resp, body = self.client.get_project(project['id'])
         en2 = body['enabled']
         self.assertEqual('false', str(en2).lower(),
                          'Enable should be False in lookup')
@@ -98,19 +98,19 @@
     def test_project_update_name(self):
         # Update name attribute of a project
         p_name1 = data_utils.rand_name('project-')
-        resp, project = self.v3_client.create_project(p_name1)
-        self.v3data.projects.append(project)
+        resp, project = self.client.create_project(p_name1)
+        self.data.projects.append(project)
 
         resp1_name = project['name']
 
         p_name2 = data_utils.rand_name('project2-')
-        resp, body = self.v3_client.update_project(project['id'], name=p_name2)
+        resp, body = self.client.update_project(project['id'], name=p_name2)
         st2 = resp['status']
         resp2_name = body['name']
         self.assertEqual(st2, '200')
         self.assertNotEqual(resp1_name, resp2_name)
 
-        resp, body = self.v3_client.get_project(project['id'])
+        resp, body = self.client.get_project(project['id'])
         resp3_name = body['name']
 
         self.assertNotEqual(resp1_name, resp3_name)
@@ -122,20 +122,20 @@
         # Update description attribute of a project
         p_name = data_utils.rand_name('project-')
         p_desc = data_utils.rand_name('desc-')
-        resp, project = self.v3_client.create_project(
+        resp, project = self.client.create_project(
             p_name, description=p_desc)
-        self.v3data.projects.append(project)
+        self.data.projects.append(project)
         resp1_desc = project['description']
 
         p_desc2 = data_utils.rand_name('desc2-')
-        resp, body = self.v3_client.update_project(
+        resp, body = self.client.update_project(
             project['id'], description=p_desc2)
         st2 = resp['status']
         resp2_desc = body['description']
         self.assertEqual(st2, '200')
         self.assertNotEqual(resp1_desc, resp2_desc)
 
-        resp, body = self.v3_client.get_project(project['id'])
+        resp, body = self.client.get_project(project['id'])
         resp3_desc = body['description']
 
         self.assertNotEqual(resp1_desc, resp3_desc)
@@ -147,20 +147,20 @@
         # Update the enabled attribute of a project
         p_name = data_utils.rand_name('project-')
         p_en = False
-        resp, project = self.v3_client.create_project(p_name, enabled=p_en)
-        self.v3data.projects.append(project)
+        resp, project = self.client.create_project(p_name, enabled=p_en)
+        self.data.projects.append(project)
 
         resp1_en = project['enabled']
 
         p_en2 = True
-        resp, body = self.v3_client.update_project(
+        resp, body = self.client.update_project(
             project['id'], enabled=p_en2)
         st2 = resp['status']
         resp2_en = body['enabled']
         self.assertEqual(st2, '200')
         self.assertNotEqual(resp1_en, resp2_en)
 
-        resp, body = self.v3_client.get_project(project['id'])
+        resp, body = self.client.get_project(project['id'])
         resp3_en = body['enabled']
 
         self.assertNotEqual(resp1_en, resp3_en)
@@ -172,23 +172,23 @@
         #Associate a user to a project
         #Create a Project
         p_name = data_utils.rand_name('project-')
-        resp, project = self.v3_client.create_project(p_name)
-        self.v3data.projects.append(project)
+        resp, project = self.client.create_project(p_name)
+        self.data.projects.append(project)
 
         #Create a User
         u_name = data_utils.rand_name('user-')
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_name('pass-')
-        resp, user = self.v3_client.create_user(
+        resp, user = self.client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, project_id=project['id'])
         self.assertEqual(resp['status'], '201')
         # Delete the User at the end of this method
-        self.addCleanup(self.v3_client.delete_user, user['id'])
+        self.addCleanup(self.client.delete_user, user['id'])
 
         # Get User To validate the user details
-        resp, new_user_get = self.v3_client.get_user(user['id'])
+        resp, new_user_get = self.client.get_user(user['id'])
         #Assert response body of GET
         self.assertEqual(u_name, new_user_get['name'])
         self.assertEqual(u_desc, new_user_get['description'])
@@ -200,53 +200,53 @@
     def test_list_projects_by_unauthorized_user(self):
         # Non-admin user should not be able to list projects
         self.assertRaises(exceptions.Unauthorized,
-                          self.v3_non_admin_client.list_projects)
+                          self.non_admin_client.list_projects)
 
     @attr(type=['negative', 'gate'])
     def test_project_create_duplicate(self):
         # Project names should be unique
         project_name = data_utils.rand_name('project-dup-')
-        resp, project = self.v3_client.create_project(project_name)
-        self.v3data.projects.append(project)
+        resp, project = self.client.create_project(project_name)
+        self.data.projects.append(project)
 
         self.assertRaises(
-            exceptions.Conflict, self.v3_client.create_project, project_name)
+            exceptions.Conflict, self.client.create_project, project_name)
 
     @attr(type=['negative', 'gate'])
     def test_create_project_by_unauthorized_user(self):
         # Non-admin user should not be authorized to create a project
         project_name = data_utils.rand_name('project-')
         self.assertRaises(
-            exceptions.Unauthorized, self.v3_non_admin_client.create_project,
+            exceptions.Unauthorized, self.non_admin_client.create_project,
             project_name)
 
     @attr(type=['negative', 'gate'])
     def test_create_project_with_empty_name(self):
         # Project name should not be empty
-        self.assertRaises(exceptions.BadRequest, self.v3_client.create_project,
+        self.assertRaises(exceptions.BadRequest, self.client.create_project,
                           name='')
 
     @attr(type=['negative', 'gate'])
     def test_create_projects_name_length_over_64(self):
         # Project name length should not be greater than 64 characters
         project_name = 'a' * 65
-        self.assertRaises(exceptions.BadRequest, self.v3_client.create_project,
+        self.assertRaises(exceptions.BadRequest, self.client.create_project,
                           project_name)
 
     @attr(type=['negative', 'gate'])
     def test_project_delete_by_unauthorized_user(self):
         # Non-admin user should not be able to delete a project
         project_name = data_utils.rand_name('project-')
-        resp, project = self.v3_client.create_project(project_name)
-        self.v3data.projects.append(project)
+        resp, project = self.client.create_project(project_name)
+        self.data.projects.append(project)
         self.assertRaises(
-            exceptions.Unauthorized, self.v3_non_admin_client.delete_project,
+            exceptions.Unauthorized, self.non_admin_client.delete_project,
             project['id'])
 
     @attr(type=['negative', 'gate'])
     def test_delete_non_existent_project(self):
         # Attempt to delete a non existent project should fail
-        self.assertRaises(exceptions.NotFound, self.v3_client.delete_project,
+        self.assertRaises(exceptions.NotFound, self.client.delete_project,
                           'junk_Project_123456abc')
 
 
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index efaed39..467d28b 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -18,7 +18,7 @@
 from tempest.test import attr
 
 
-class RolesV3TestJSON(base.BaseIdentityAdminTest):
+class RolesV3TestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     @classmethod
@@ -30,20 +30,20 @@
         u_email = '%s@testmail.tm' % u_name
         u_password = data_utils.rand_name('pass-')
         resp = [None] * 5
-        resp[0], cls.project = cls.v3_client.create_project(
+        resp[0], cls.project = cls.client.create_project(
             data_utils.rand_name('project-'),
             description=data_utils.rand_name('project-desc-'))
-        resp[1], cls.domain = cls.v3_client.create_domain(
+        resp[1], cls.domain = cls.client.create_domain(
             data_utils.rand_name('domain-'),
             description=data_utils.rand_name('domain-desc-'))
-        resp[2], cls.group_body = cls.v3_client.create_group(
+        resp[2], cls.group_body = cls.client.create_group(
             data_utils.rand_name('Group-'), project_id=cls.project['id'],
             domain_id=cls.domain['id'])
-        resp[3], cls.user_body = cls.v3_client.create_user(
+        resp[3], cls.user_body = cls.client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, project_id=cls.project['id'],
             domain_id=cls.domain['id'])
-        resp[4], cls.role = cls.v3_client.create_role(
+        resp[4], cls.role = cls.client.create_role(
             data_utils.rand_name('Role-'))
         for r in resp:
             assert r['status'] == '201', "Expected: %s" % r['status']
@@ -51,14 +51,14 @@
     @classmethod
     def tearDownClass(cls):
         resp = [None] * 5
-        resp[0], _ = cls.v3_client.delete_role(cls.role['id'])
-        resp[1], _ = cls.v3_client.delete_group(cls.group_body['id'])
-        resp[2], _ = cls.v3_client.delete_user(cls.user_body['id'])
-        resp[3], _ = cls.v3_client.delete_project(cls.project['id'])
+        resp[0], _ = cls.client.delete_role(cls.role['id'])
+        resp[1], _ = cls.client.delete_group(cls.group_body['id'])
+        resp[2], _ = cls.client.delete_user(cls.user_body['id'])
+        resp[3], _ = cls.client.delete_project(cls.project['id'])
         # NOTE(harika-vakadi): It is necessary to disable the domain
         # before deleting,or else it would result in unauthorized error
-        cls.v3_client.update_domain(cls.domain['id'], enabled=False)
-        resp[4], _ = cls.v3_client.delete_domain(cls.domain['id'])
+        cls.client.update_domain(cls.domain['id'], enabled=False)
+        resp[4], _ = cls.client.delete_domain(cls.domain['id'])
         for r in resp:
             assert r['status'] == '204', "Expected: %s" % r['status']
         super(RolesV3TestJSON, cls).tearDownClass()
@@ -71,32 +71,32 @@
     @attr(type='smoke')
     def test_role_create_update_get(self):
         r_name = data_utils.rand_name('Role-')
-        resp, role = self.v3_client.create_role(r_name)
-        self.addCleanup(self.v3_client.delete_role, role['id'])
+        resp, role = self.client.create_role(r_name)
+        self.addCleanup(self.client.delete_role, role['id'])
         self.assertEqual(resp['status'], '201')
         self.assertIn('name', role)
         self.assertEqual(role['name'], r_name)
 
         new_name = data_utils.rand_name('NewRole-')
-        resp, updated_role = self.v3_client.update_role(new_name, role['id'])
+        resp, updated_role = self.client.update_role(new_name, role['id'])
         self.assertEqual(resp['status'], '200')
         self.assertIn('name', updated_role)
         self.assertIn('id', updated_role)
         self.assertIn('links', updated_role)
         self.assertNotEqual(r_name, updated_role['name'])
 
-        resp, new_role = self.v3_client.get_role(role['id'])
+        resp, new_role = self.client.get_role(role['id'])
         self.assertEqual(resp['status'], '200')
         self.assertEqual(new_name, new_role['name'])
         self.assertEqual(updated_role['id'], new_role['id'])
 
     @attr(type='smoke')
     def test_grant_list_revoke_role_to_user_on_project(self):
-        resp, _ = self.v3_client.assign_user_role_on_project(
+        resp, _ = self.client.assign_user_role_on_project(
             self.project['id'], self.user_body['id'], self.role['id'])
         self.assertEqual(resp['status'], '204')
 
-        resp, roles = self.v3_client.list_user_roles_on_project(
+        resp, roles = self.client.list_user_roles_on_project(
             self.project['id'], self.user_body['id'])
 
         for i in roles:
@@ -105,17 +105,17 @@
         self._list_assertions(resp, roles, self.fetched_role_ids,
                               self.role['id'])
 
-        resp, _ = self.v3_client.revoke_role_from_user_on_project(
+        resp, _ = self.client.revoke_role_from_user_on_project(
             self.project['id'], self.user_body['id'], self.role['id'])
         self.assertEqual(resp['status'], '204')
 
     @attr(type='smoke')
     def test_grant_list_revoke_role_to_user_on_domain(self):
-        resp, _ = self.v3_client.assign_user_role_on_domain(
+        resp, _ = self.client.assign_user_role_on_domain(
             self.domain['id'], self.user_body['id'], self.role['id'])
         self.assertEqual(resp['status'], '204')
 
-        resp, roles = self.v3_client.list_user_roles_on_domain(
+        resp, roles = self.client.list_user_roles_on_domain(
             self.domain['id'], self.user_body['id'])
 
         for i in roles:
@@ -124,17 +124,17 @@
         self._list_assertions(resp, roles, self.fetched_role_ids,
                               self.role['id'])
 
-        resp, _ = self.v3_client.revoke_role_from_user_on_domain(
+        resp, _ = self.client.revoke_role_from_user_on_domain(
             self.domain['id'], self.user_body['id'], self.role['id'])
         self.assertEqual(resp['status'], '204')
 
     @attr(type='smoke')
     def test_grant_list_revoke_role_to_group_on_project(self):
-        resp, _ = self.v3_client.assign_group_role_on_project(
+        resp, _ = self.client.assign_group_role_on_project(
             self.project['id'], self.group_body['id'], self.role['id'])
         self.assertEqual(resp['status'], '204')
 
-        resp, roles = self.v3_client.list_group_roles_on_project(
+        resp, roles = self.client.list_group_roles_on_project(
             self.project['id'], self.group_body['id'])
 
         for i in roles:
@@ -143,17 +143,17 @@
         self._list_assertions(resp, roles, self.fetched_role_ids,
                               self.role['id'])
 
-        resp, _ = self.v3_client.revoke_role_from_group_on_project(
+        resp, _ = self.client.revoke_role_from_group_on_project(
             self.project['id'], self.group_body['id'], self.role['id'])
         self.assertEqual(resp['status'], '204')
 
     @attr(type='smoke')
     def test_grant_list_revoke_role_to_group_on_domain(self):
-        resp, _ = self.v3_client.assign_group_role_on_domain(
+        resp, _ = self.client.assign_group_role_on_domain(
             self.domain['id'], self.group_body['id'], self.role['id'])
         self.assertEqual(resp['status'], '204')
 
-        resp, roles = self.v3_client.list_group_roles_on_domain(
+        resp, roles = self.client.list_group_roles_on_domain(
             self.domain['id'], self.group_body['id'])
 
         for i in roles:
@@ -162,7 +162,7 @@
         self._list_assertions(resp, roles, self.fetched_role_ids,
                               self.role['id'])
 
-        resp, _ = self.v3_client.revoke_role_from_group_on_domain(
+        resp, _ = self.client.revoke_role_from_group_on_domain(
             self.domain['id'], self.group_body['id'], self.role['id'])
         self.assertEqual(resp['status'], '204')
 
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index 4d6c22f..c5d4ddf 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -19,20 +19,20 @@
 from tempest.test import attr
 
 
-class ServicesTestJSON(base.BaseIdentityAdminTest):
+class ServicesTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     @attr(type='gate')
     def test_update_service(self):
         # Update description attribute of service
         name = data_utils.rand_name('service-')
-        type = data_utils.rand_name('type--')
-        description = data_utils.rand_name('description-')
-        resp, body = self.client.create_service(
-            name, type, description=description)
-        self.assertEqual('200', resp['status'])
+        serv_type = data_utils.rand_name('type--')
+        desc = data_utils.rand_name('description-')
+        resp, body = self.service_client.create_service(name, serv_type,
+                                                        description=desc)
+        self.assertEqual('201', resp['status'])
         # Deleting the service created in this method
-        self.addCleanup(self.client.delete_service, body['id'])
+        self.addCleanup(self.service_client.delete_service, body['id'])
 
         s_id = body['id']
         resp1_desc = body['description']
@@ -45,7 +45,7 @@
         self.assertNotEqual(resp1_desc, resp2_desc)
 
         # Get service
-        resp, body = self.client.get_service(s_id)
+        resp, body = self.service_client.get_service(s_id)
         resp3_desc = body['description']
 
         self.assertNotEqual(resp1_desc, resp3_desc)
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index d17dc4a..802113a 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -19,7 +19,7 @@
 from tempest.test import attr
 
 
-class UsersTestJSON(base.BaseIdentityAdminTest):
+class UsersTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     @attr(type='smoke')
@@ -30,24 +30,24 @@
         u_desc = '%s-description' % u_name
         u_email = '%s@testmail.tm' % u_name
         u_password = data_utils.rand_name('pass-')
-        resp, user = self.v3_client.create_user(
+        resp, user = self.client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email)
         self.assertTrue(resp['status'].startswith('2'))
-        self.addCleanup(self.v3_client.delete_user, user['id'])
+        self.addCleanup(self.client.delete_user, user['id'])
         # Perform Authentication
-        resp, body = self.v3_token.auth(user['id'], u_password)
+        resp, body = self.token.auth(user['id'], u_password)
         self.assertEqual(resp['status'], '201')
         subject_token = resp['x-subject-token']
         # Perform GET Token
-        resp, token_details = self.v3_client.get_token(subject_token)
+        resp, token_details = self.client.get_token(subject_token)
         self.assertEqual(resp['status'], '200')
         self.assertEqual(resp['x-subject-token'], subject_token)
         self.assertEqual(token_details['user']['id'], user['id'])
         self.assertEqual(token_details['user']['name'], u_name)
         # Perform Delete Token
-        resp, _ = self.v3_client.delete_token(subject_token)
-        self.assertRaises(exceptions.NotFound, self.v3_client.get_token,
+        resp, _ = self.client.delete_token(subject_token)
+        self.assertRaises(exceptions.NotFound, self.client.get_token,
                           subject_token)
 
 
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 1bebad4..c2eef36 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -23,7 +23,7 @@
 CONF = config.CONF
 
 
-class BaseTrustsV3Test(base.BaseIdentityAdminTest):
+class BaseTrustsV3Test(base.BaseIdentityV3AdminTest):
 
     def setUp(self):
         super(BaseTrustsV3Test, self).setUp()
@@ -43,7 +43,7 @@
 
     def create_trustor_and_roles(self):
         # Get trustor project ID, use the admin project
-        self.trustor_project_name = self.v3_client.tenant_name
+        self.trustor_project_name = self.client.tenant_name
         self.trustor_project_id = self.get_tenant_by_name(
             self.trustor_project_name)['id']
         self.assertIsNotNone(self.trustor_project_id)
@@ -53,7 +53,7 @@
         u_desc = self.trustor_username + 'description'
         u_email = self.trustor_username + '@testmail.xx'
         self.trustor_password = rand_name('pass-')
-        resp, user = self.v3_client.create_user(
+        resp, user = self.client.create_user(
             self.trustor_username,
             description=u_desc,
             password=self.trustor_password,
@@ -66,24 +66,24 @@
         self.delegated_role = rand_name('DelegatedRole-')
         self.not_delegated_role = rand_name('NotDelegatedRole-')
 
-        resp, role = self.v3_client.create_role(self.delegated_role)
+        resp, role = self.client.create_role(self.delegated_role)
         self.assertEqual(resp['status'], '201')
         self.delegated_role_id = role['id']
 
-        resp, role = self.v3_client.create_role(self.not_delegated_role)
+        resp, role = self.client.create_role(self.not_delegated_role)
         self.assertEqual(resp['status'], '201')
         self.not_delegated_role_id = role['id']
 
         # Assign roles to trustor
-        self.v3_client.assign_user_role(self.trustor_project_id,
-                                        self.trustor_user_id,
-                                        self.delegated_role_id)
-        self.v3_client.assign_user_role(self.trustor_project_id,
-                                        self.trustor_user_id,
-                                        self.not_delegated_role_id)
+        self.client.assign_user_role(self.trustor_project_id,
+                                     self.trustor_user_id,
+                                     self.delegated_role_id)
+        self.client.assign_user_role(self.trustor_project_id,
+                                     self.trustor_user_id,
+                                     self.not_delegated_role_id)
 
         # Get trustee user ID, use the demo user
-        trustee_username = self.v3_non_admin_client.user
+        trustee_username = self.non_admin_client.user
         self.trustee_user_id = self.get_user_by_name(trustee_username)['id']
         self.assertIsNotNone(self.trustee_user_id)
 
@@ -92,19 +92,19 @@
                              password=self.trustor_password,
                              tenant_name=self.trustor_project_name,
                              interface=self._interface)
-        self.trustor_v3_client = os.identity_v3_client
+        self.trustor_client = os.identity_v3_client
 
     def cleanup_user_and_roles(self):
         if self.trustor_user_id:
-            self.v3_client.delete_user(self.trustor_user_id)
+            self.client.delete_user(self.trustor_user_id)
         if self.delegated_role_id:
-            self.v3_client.delete_role(self.delegated_role_id)
+            self.client.delete_role(self.delegated_role_id)
         if self.not_delegated_role_id:
-            self.v3_client.delete_role(self.not_delegated_role_id)
+            self.client.delete_role(self.not_delegated_role_id)
 
     def create_trust(self, impersonate=True, expires=None):
 
-        resp, trust_create = self.trustor_v3_client.create_trust(
+        resp, trust_create = self.trustor_client.create_trust(
             trustor_user_id=self.trustor_user_id,
             trustee_user_id=self.trustee_user_id,
             project_id=self.trustor_project_id,
@@ -137,7 +137,7 @@
             self.assertEqual(1, len(trust['roles']))
 
     def get_trust(self):
-        resp, trust_get = self.trustor_v3_client.get_trust(self.trust_id)
+        resp, trust_get = self.trustor_client.get_trust(self.trust_id)
         self.assertEqual('200', resp['status'])
         return trust_get
 
@@ -153,37 +153,37 @@
 
     def check_trust_roles(self):
         # Check we find the delegated role
-        resp, roles_get = self.trustor_v3_client.get_trust_roles(
+        resp, roles_get = self.trustor_client.get_trust_roles(
             self.trust_id)
         self.assertEqual('200', resp['status'])
         self.assertEqual(1, len(roles_get))
         self.validate_role(roles_get[0])
 
-        resp, role_get = self.trustor_v3_client.get_trust_role(
+        resp, role_get = self.trustor_client.get_trust_role(
             self.trust_id, self.delegated_role_id)
         self.assertEqual('200', resp['status'])
         self.validate_role(role_get)
 
-        resp, role_get = self.trustor_v3_client.check_trust_role(
+        resp, role_get = self.trustor_client.check_trust_role(
             self.trust_id, self.delegated_role_id)
         self.assertEqual('204', resp['status'])
 
         # And that we don't find not_delegated_role
         self.assertRaises(exceptions.NotFound,
-                          self.trustor_v3_client.get_trust_role,
+                          self.trustor_client.get_trust_role,
                           self.trust_id,
                           self.not_delegated_role_id)
 
         self.assertRaises(exceptions.NotFound,
-                          self.trustor_v3_client.check_trust_role,
+                          self.trustor_client.check_trust_role,
                           self.trust_id,
                           self.not_delegated_role_id)
 
     def delete_trust(self):
-        resp, trust_delete = self.trustor_v3_client.delete_trust(self.trust_id)
+        resp, trust_delete = self.trustor_client.delete_trust(self.trust_id)
         self.assertEqual('204', resp['status'])
         self.assertRaises(exceptions.NotFound,
-                          self.trustor_v3_client.get_trust,
+                          self.trustor_client.get_trust,
                           self.trust_id)
         self.trust_id = None
 
@@ -249,7 +249,7 @@
     @attr(type='smoke')
     def test_get_trusts_query(self):
         self.create_trust()
-        resp, trusts_get = self.trustor_v3_client.get_trusts(
+        resp, trusts_get = self.trustor_client.get_trusts(
             trustor_user_id=self.trustor_user_id)
         self.assertEqual('200', resp['status'])
         self.assertEqual(1, len(trusts_get))
@@ -258,7 +258,7 @@
     @attr(type='smoke')
     def test_get_trusts_all(self):
         self.create_trust()
-        resp, trusts_get = self.v3_client.get_trusts()
+        resp, trusts_get = self.client.get_trusts()
         self.assertEqual('200', resp['status'])
         trusts = [t for t in trusts_get
                   if t['id'] == self.trust_id]
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 7cae856..a78d542 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -18,7 +18,7 @@
 from tempest.test import attr
 
 
-class UsersV3TestJSON(base.BaseIdentityAdminTest):
+class UsersV3TestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
     @attr(type='gate')
@@ -29,22 +29,22 @@
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_name('pass-')
-        resp, user = self.v3_client.create_user(
+        resp, user = self.client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, enabled=False)
         # Delete the User at the end of this method
-        self.addCleanup(self.v3_client.delete_user, user['id'])
+        self.addCleanup(self.client.delete_user, user['id'])
         # Creating second project for updation
-        resp, project = self.v3_client.create_project(
+        resp, project = self.client.create_project(
             data_utils.rand_name('project-'),
             description=data_utils.rand_name('project-desc-'))
         # Delete the Project at the end of this method
-        self.addCleanup(self.v3_client.delete_project, project['id'])
+        self.addCleanup(self.client.delete_project, project['id'])
         # Updating user details with new values
         u_name2 = data_utils.rand_name('user2-')
         u_email2 = u_name2 + '@testmail.tm'
         u_description2 = u_name2 + ' description'
-        resp, update_user = self.v3_client.update_user(
+        resp, update_user = self.client.update_user(
             user['id'], name=u_name2, description=u_description2,
             project_id=project['id'],
             email=u_email2, enabled=False)
@@ -57,7 +57,7 @@
         self.assertEqual(u_email2, update_user['email'])
         self.assertEqual('false', str(update_user['enabled']).lower())
         # GET by id after updation
-        resp, new_user_get = self.v3_client.get_user(user['id'])
+        resp, new_user_get = self.client.get_user(user['id'])
         # Assert response body of GET after updation
         self.assertEqual(u_name2, new_user_get['name'])
         self.assertEqual(u_description2, new_user_get['description'])
@@ -71,43 +71,43 @@
         # List the projects that a user has access upon
         assigned_project_ids = list()
         fetched_project_ids = list()
-        _, u_project = self.v3_client.create_project(
+        _, u_project = self.client.create_project(
             data_utils.rand_name('project-'),
             description=data_utils.rand_name('project-desc-'))
         # Delete the Project at the end of this method
-        self.addCleanup(self.v3_client.delete_project, u_project['id'])
+        self.addCleanup(self.client.delete_project, u_project['id'])
         # Create a user.
         u_name = data_utils.rand_name('user-')
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_name('pass-')
-        _, user_body = self.v3_client.create_user(
+        _, user_body = self.client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, enabled=False, project_id=u_project['id'])
         # Delete the User at the end of this method
-        self.addCleanup(self.v3_client.delete_user, user_body['id'])
+        self.addCleanup(self.client.delete_user, user_body['id'])
         # Creating Role
-        _, role_body = self.v3_client.create_role(
+        _, role_body = self.client.create_role(
             data_utils.rand_name('role-'))
         # Delete the Role at the end of this method
-        self.addCleanup(self.v3_client.delete_role, role_body['id'])
+        self.addCleanup(self.client.delete_role, role_body['id'])
 
-        _, user = self.v3_client.get_user(user_body['id'])
-        _, role = self.v3_client.get_role(role_body['id'])
+        _, user = self.client.get_user(user_body['id'])
+        _, role = self.client.get_role(role_body['id'])
         for i in range(2):
             # Creating project so as to assign role
-            _, project_body = self.v3_client.create_project(
+            _, project_body = self.client.create_project(
                 data_utils.rand_name('project-'),
                 description=data_utils.rand_name('project-desc-'))
-            _, project = self.v3_client.get_project(project_body['id'])
+            _, project = self.client.get_project(project_body['id'])
             # Delete the Project at the end of this method
-            self.addCleanup(self.v3_client.delete_project, project_body['id'])
+            self.addCleanup(self.client.delete_project, project_body['id'])
             # Assigning roles to user on project
-            self.v3_client.assign_user_role(project['id'],
-                                            user['id'],
-                                            role['id'])
+            self.client.assign_user_role(project['id'],
+                                         user['id'],
+                                         role['id'])
             assigned_project_ids.append(project['id'])
-        resp, body = self.v3_client.list_user_projects(user['id'])
+        resp, body = self.client.list_user_projects(user['id'])
         self.assertEqual(200, resp.status)
         for i in body:
             fetched_project_ids.append(i['id'])
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index a3fc65a..10f5217 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -16,67 +16,98 @@
 
 from tempest import clients
 from tempest.common.utils import data_utils
+from tempest import config
 import tempest.test
 
+CONF = config.CONF
+
 
 class BaseIdentityAdminTest(tempest.test.BaseTestCase):
 
     @classmethod
     def setUpClass(cls):
         super(BaseIdentityAdminTest, cls).setUpClass()
-        os = clients.AdminManager(interface=cls._interface)
-        cls.client = os.identity_client
-        cls.token_client = os.token_client
-        cls.endpoints_client = os.endpoints_client
-        cls.v3_client = os.identity_v3_client
-        cls.service_client = os.service_client
-        cls.policy_client = os.policy_client
-        cls.v3_token = os.token_v3_client
-        cls.creds_client = os.credentials_client
-
-        if not cls.client.has_admin_extensions():
-            raise cls.skipException("Admin extensions disabled")
-
-        cls.data = DataGenerator(cls.client)
-        cls.v3data = DataGenerator(cls.v3_client)
-
-        os = clients.Manager(interface=cls._interface)
-        cls.non_admin_client = os.identity_client
-        cls.v3_non_admin_client = os.identity_v3_client
+        cls.os_adm = clients.AdminManager(interface=cls._interface)
+        cls.os = clients.Manager(interface=cls._interface)
 
     @classmethod
-    def tearDownClass(cls):
-        cls.data.teardown_all()
-        cls.v3data.teardown_all()
-        super(BaseIdentityAdminTest, cls).tearDownClass()
+    def disable_user(cls, user_name):
+        user = cls.get_user_by_name(user_name)
+        cls.client.enable_disable_user(user['id'], False)
 
-    def disable_user(self, user_name):
-        user = self.get_user_by_name(user_name)
-        self.client.enable_disable_user(user['id'], False)
+    @classmethod
+    def disable_tenant(cls, tenant_name):
+        tenant = cls.get_tenant_by_name(tenant_name)
+        cls.client.update_tenant(tenant['id'], enabled=False)
 
-    def disable_tenant(self, tenant_name):
-        tenant = self.get_tenant_by_name(tenant_name)
-        self.client.update_tenant(tenant['id'], enabled=False)
-
-    def get_user_by_name(self, name):
-        _, users = self.client.get_users()
+    @classmethod
+    def get_user_by_name(cls, name):
+        _, users = cls.client.get_users()
         user = [u for u in users if u['name'] == name]
         if len(user) > 0:
             return user[0]
 
-    def get_tenant_by_name(self, name):
-        _, tenants = self.client.list_tenants()
+    @classmethod
+    def get_tenant_by_name(cls, name):
+        try:
+            _, tenants = cls.client.list_tenants()
+        except AttributeError:
+            _, tenants = cls.client.list_projects()
         tenant = [t for t in tenants if t['name'] == name]
         if len(tenant) > 0:
             return tenant[0]
 
-    def get_role_by_name(self, name):
-        _, roles = self.client.list_roles()
+    @classmethod
+    def get_role_by_name(cls, name):
+        _, roles = cls.client.list_roles()
         role = [r for r in roles if r['name'] == name]
         if len(role) > 0:
             return role[0]
 
 
+class BaseIdentityV2AdminTest(BaseIdentityAdminTest):
+
+    @classmethod
+    def setUpClass(cls):
+        if not CONF.identity_feature_enabled.api_v2:
+            raise cls.skipException("Identity api v2 is not enabled")
+        super(BaseIdentityV2AdminTest, cls).setUpClass()
+        cls.client = cls.os_adm.identity_client
+        cls.token_client = cls.os_adm.token_client
+        if not cls.client.has_admin_extensions():
+            raise cls.skipException("Admin extensions disabled")
+        cls.data = DataGenerator(cls.client)
+        cls.non_admin_client = cls.os.identity_client
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.data.teardown_all()
+        super(BaseIdentityV2AdminTest, cls).tearDownClass()
+
+
+class BaseIdentityV3AdminTest(BaseIdentityAdminTest):
+
+    @classmethod
+    def setUpClass(cls):
+        if not CONF.identity_feature_enabled.api_v3:
+            raise cls.skipException("Identity api v3 is not enabled")
+        super(BaseIdentityV3AdminTest, cls).setUpClass()
+        cls.client = cls.os_adm.identity_v3_client
+        cls.token = cls.os_adm.token_v3_client
+        cls.endpoints_client = cls.os_adm.endpoints_client
+        cls.data = DataGenerator(cls.client)
+        cls.non_admin_client = cls.os.identity_v3_client
+        cls.service_client = cls.os_adm.service_client
+        cls.policy_client = cls.os_adm.policy_client
+        cls.creds_client = cls.os_adm.credentials_client
+        cls.non_admin_client = cls.os.identity_v3_client
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.data.teardown_all()
+        super(BaseIdentityV3AdminTest, cls).tearDownClass()
+
+
 class DataGenerator(object):
 
         def __init__(self, client):
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 0f73aca..4cbb7be 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -51,6 +51,11 @@
 
     force_tenant_isolation = False
 
+    # Default to ipv4.
+    _ip_version = 4
+    _tenant_network_cidr = CONF.network.tenant_network_cidr
+    _tenant_network_mask_bits = CONF.network.tenant_network_mask_bits
+
     @classmethod
     def setUpClass(cls):
         # Create no network resources for these test.
@@ -139,10 +144,11 @@
         return network
 
     @classmethod
-    def create_subnet(cls, network, ip_version=4):
+    def create_subnet(cls, network):
         """Wrapper utility that returns a test subnet."""
-        cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
-        mask_bits = CONF.network.tenant_network_mask_bits
+        # The cidr and mask_bits depend on the ip version.
+        cidr = netaddr.IPNetwork(cls._tenant_network_cidr)
+        mask_bits = cls._tenant_network_mask_bits
         # Find a cidr that is not in use yet and create a subnet with it
         body = None
         failure = None
@@ -151,7 +157,7 @@
                 resp, body = cls.client.create_subnet(
                     network_id=network['id'],
                     cidr=str(subnet_cidr),
-                    ip_version=ip_version)
+                    ip_version=cls._ip_version)
                 break
             except exceptions.BadRequest as e:
                 is_overlapping_cidr = 'overlaps with another subnet' in str(e)
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index e12dedd..4cc007f 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -45,14 +45,20 @@
         network update
         subnet update
 
+        All subnet tests are run once with ipv4 and once with ipv6.
+
     v2.0 of the Neutron API is assumed. It is also assumed that the following
     options are defined in the [network] section of etc/tempest.conf:
 
         tenant_network_cidr with a block of cidr's from which smaller blocks
-        can be allocated for tenant networks
+        can be allocated for tenant ipv4 subnets
+
+        tenant_network_v6_cidr is the equivalent for ipv6 subnets
 
         tenant_network_mask_bits with the mask bits to be used to partition the
-        block defined by tenant-network_cidr
+        block defined by tenant_network_cidr
+
+        tenant_network_v6_mask_bits is the equivalent for ipv6 subnets
     """
 
     @classmethod
@@ -79,14 +85,14 @@
         updated_net = body['network']
         self.assertEqual(updated_net['name'], new_name)
         # Find a cidr that is not in use yet and create a subnet with it
-        cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
-        mask_bits = CONF.network.tenant_network_mask_bits
+        cidr = netaddr.IPNetwork(self._tenant_network_cidr)
+        mask_bits = self._tenant_network_mask_bits
         for subnet_cidr in cidr.subnet(mask_bits):
             try:
                 resp, body = self.client.create_subnet(
                     network_id=net_id,
                     cidr=str(subnet_cidr),
-                    ip_version=4)
+                    ip_version=self._ip_version)
                 break
             except exceptions.BadRequest as e:
                 is_overlapping_cidr = 'overlaps with another subnet' in str(e)
@@ -432,3 +438,13 @@
 
 class BulkNetworkOpsTestXML(BulkNetworkOpsTestJSON):
     _interface = 'xml'
+
+
+class NetworksIpV6TestJSON(NetworksTestJSON):
+    _ip_version = 6
+    _tenant_network_cidr = CONF.network.tenant_network_v6_cidr
+    _tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
+
+
+class NetworksIpV6TestXML(NetworksIpV6TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 6d89e5b..ce29b82 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -91,6 +91,12 @@
             self.assertEqual(boot_flag, False)
 
         # Update Volume
+        # Test volume update when display_name is same with original value
+        resp, update_volume = \
+            self.client.update_volume(volume['id'],
+                                      display_name=v_name)
+        self.assertEqual(200, resp.status)
+        # Test volume update when display_name is new
         new_v_name = data_utils.rand_name('new-Volume')
         new_desc = 'This is the new description of volume'
         resp, update_volume = \
@@ -111,6 +117,26 @@
                         ContainsAll(metadata.items()),
                         'The fetched Volume metadata misses data '
                         'from the created Volume')
+        # Test volume create when display_name is none and display_description
+        # contains specific characters,
+        # then test volume update if display_name is duplicated
+        new_volume = {}
+        new_v_desc = data_utils.rand_name('@#$%^* description')
+        resp, new_volume = \
+            self.client.create_volume(size=1,
+                                      display_description=new_v_desc,
+                                      availability_zone=volume[
+                                      'availability_zone'])
+        self.assertEqual(200, resp.status)
+        self.assertIn('id', new_volume)
+        self.addCleanup(self._delete_volume, new_volume['id'])
+        self.client.wait_for_volume_status(new_volume['id'], 'available')
+        resp, update_volume = \
+            self.client.update_volume(new_volume['id'],
+                                      display_name=volume['display_name'],
+                                      display_description=volume[
+                                      'display_description'])
+        self.assertEqual(200, resp.status)
 
         # NOTE(jdg): Revert back to strict true/false checking
         # after fix for bug #1227837 merges
diff --git a/tempest/common/utils/test_utils.py b/tempest/common/utils/test_utils.py
index eca716e..2e23782 100644
--- a/tempest/common/utils/test_utils.py
+++ b/tempest/common/utils/test_utils.py
@@ -112,6 +112,8 @@
         """
         :return: a scenario with name and uuid of images
         """
+        if not CONF.service_available.glance:
+            return []
         if not hasattr(self, '_scenario_images'):
             images = self.client.images.list(detailed=False)
             self._scenario_images = [
diff --git a/tempest/config.py b/tempest/config.py
index fa051d5..210c857 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -99,7 +99,13 @@
     cfg.BoolOpt('trust',
                 default=True,
                 help='Does the identity service have delegation and '
-                     'impersonation enabled')
+                     'impersonation enabled'),
+    cfg.BoolOpt('api_v2',
+                default=True,
+                help='Is the v2 identity API enabled'),
+    cfg.BoolOpt('api_v3',
+                default=True,
+                help='Is the v3 identity API enabled'),
 ]
 
 compute_group = cfg.OptGroup(name='compute',
@@ -313,10 +319,16 @@
                     "used."),
     cfg.StrOpt('tenant_network_cidr',
                default="10.100.0.0/16",
-               help="The cidr block to allocate tenant networks from"),
+               help="The cidr block to allocate tenant ipv4 subnets from"),
     cfg.IntOpt('tenant_network_mask_bits',
                default=28,
-               help="The mask bits for tenant networks"),
+               help="The mask bits for tenant ipv4 subnets"),
+    cfg.StrOpt('tenant_network_v6_cidr',
+               default="2003::/64",
+               help="The cidr block to allocate tenant ipv6 subnets from"),
+    cfg.IntOpt('tenant_network_v6_mask_bits',
+               default=96,
+               help="The mask bits for tenant ipv6 subnets"),
     cfg.BoolOpt('tenant_networks_reachable',
                 default=False,
                 help="Whether tenant network connectivity should be "
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index ec3229e..b044e4d 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 import json
-import urlparse
 
 from tempest.common.rest_client import RestClient
 from tempest import config
@@ -445,11 +444,10 @@
     def __init__(self):
         super(V3TokenClientJSON, self).__init__(None)
         auth_url = CONF.identity.uri_v3
-        # If the v3 url is not set, get it from the v2 one
-        if auth_url is None:
-            auth_url = CONF.identity.uri.replace(urlparse.urlparse(
-                CONF.identity.uri).path, "/v3")
-
+        if not auth_url and CONF.identity_feature_enabled.api_v3:
+            raise exceptions.InvalidConfiguration('you must specify a v3 uri '
+                                                  'if using the v3 identity '
+                                                  'api')
         if 'auth/tokens' not in auth_url:
             auth_url = auth_url.rstrip('/') + '/auth/tokens'
 
diff --git a/tempest/services/identity/v3/json/service_client.py b/tempest/services/identity/v3/json/service_client.py
index 094e567..10d4f97 100644
--- a/tempest/services/identity/v3/json/service_client.py
+++ b/tempest/services/identity/v3/json/service_client.py
@@ -51,3 +51,21 @@
         resp, body = self.get(url)
         body = json.loads(body)
         return resp, body['service']
+
+    def create_service(self, serv_type, name=None, description=None,
+                       enabled=True):
+        body_dict = {
+            "name": name,
+            'type': serv_type,
+            'enabled': enabled,
+            "description": description,
+        }
+        body = json.dumps({'service': body_dict})
+        resp, body = self.post("services", body, self.headers)
+        body = json.loads(body)
+        return resp, body["service"]
+
+    def delete_service(self, serv_id):
+        url = "services/" + serv_id
+        resp, body = self.delete(url, self.headers)
+        return resp, body
diff --git a/tempest/services/identity/v3/xml/identity_client.py b/tempest/services/identity/v3/xml/identity_client.py
index 6304628..5ae0461 100644
--- a/tempest/services/identity/v3/xml/identity_client.py
+++ b/tempest/services/identity/v3/xml/identity_client.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 import json
-import urlparse
 
 from lxml import etree
 
@@ -432,10 +431,10 @@
     def __init__(self):
         super(V3TokenClientXML, self).__init__(None)
         auth_url = CONF.identity.uri_v3
-        # If the v3 url is not set, get it from the v2 one
-        if auth_url is None:
-            auth_url = CONF.identity.uri.replace(urlparse.urlparse(
-                CONF.identity.uri).path, "/v3")
+        if not auth_url and CONF.identity_feature_enabled.api_v3:
+            raise exceptions.InvalidConfiguration('you must specify a v3 uri '
+                                                  'if using the v3 identity '
+                                                  'api')
         if 'auth/tokens' not in auth_url:
             auth_url = auth_url.rstrip('/') + '/auth/tokens'
 
diff --git a/tempest/services/identity/v3/xml/service_client.py b/tempest/services/identity/v3/xml/service_client.py
index f43ed2c..a2a81d2 100644
--- a/tempest/services/identity/v3/xml/service_client.py
+++ b/tempest/services/identity/v3/xml/service_client.py
@@ -67,3 +67,19 @@
         resp, body = self.get(url)
         body = self._parse_body(etree.fromstring(body))
         return resp, body
+
+    def create_service(self, serv_type, name=None, description=None):
+        post_body = Element("service",
+                            xmlns=XMLNS,
+                            name=name,
+                            description=description,
+                            type=serv_type)
+        resp, body = self.post("services", str(Document(post_body)),
+                               self.headers)
+        body = self._parse_body(etree.fromstring(body))
+        return resp, body
+
+    def delete_service(self, serv_id):
+        url = "services/" + serv_id
+        resp, body = self.delete(url, self.headers)
+        return resp, body