Split users_client from keystone V3 client

Partially implements blueprint consistent-service-method-names

Change-Id: Ib21c15d9ad3471821163cf93a6313ad384ad7123
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index 0e76d37..7c2e8e0 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -36,13 +36,13 @@
                 description=data_utils.rand_name('project-desc'))['project']
             cls.projects.append(cls.project['id'])
 
-        cls.user_body = cls.client.create_user(
+        cls.user_body = cls.users_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, project_id=cls.projects[0])['user']
 
     @classmethod
     def resource_cleanup(cls):
-        cls.client.delete_user(cls.user_body['id'])
+        cls.users_client.delete_user(cls.user_body['id'])
         for p in cls.projects:
             cls.projects_client.delete_project(p)
         super(CredentialsTestJSON, cls).resource_cleanup()
diff --git a/tempest/api/identity/admin/v3/test_default_project_id.py b/tempest/api/identity/admin/v3/test_default_project_id.py
index 661adb8..3dc3cb6 100644
--- a/tempest/api/identity/admin/v3/test_default_project_id.py
+++ b/tempest/api/identity/admin/v3/test_default_project_id.py
@@ -56,11 +56,13 @@
         # create a user in the domain, with the previous project as his
         # default project
         user_name = data_utils.rand_name('user')
-        user_body = self.client.create_user(user_name, password=user_name,
-                                            domain_id=dom_id,
-                                            default_project_id=proj_id)['user']
+        user_body = self.users_client.create_user(
+            user_name,
+            password=user_name,
+            domain_id=dom_id,
+            default_project_id=proj_id)['user']
         user_id = user_body['id']
-        self.addCleanup(self.client.delete_user, user_id)
+        self.addCleanup(self.users_client.delete_user, user_id)
         self.assertEqual(user_body['domain_id'], dom_id,
                          "user " + user_name +
                          "doesn't have domain id " + dom_id)
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 03b8b29..010e4a0 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -68,9 +68,9 @@
         for i in range(3):
             name = data_utils.rand_name('User')
             password = data_utils.rand_password()
-            user = self.client.create_user(name, password)['user']
+            user = self.users_client.create_user(name, password)['user']
             users.append(user)
-            self.addCleanup(self.client.delete_user, user['id'])
+            self.addCleanup(self.users_client.delete_user, user['id'])
             self.groups_client.add_group_user(group['id'], user['id'])
 
         # list users in group
@@ -87,9 +87,9 @@
     @test.idempotent_id('64573281-d26a-4a52-b899-503cb0f4e4ec')
     def test_list_user_groups(self):
         # create a user
-        user = self.client.create_user(
+        user = self.users_client.create_user(
             data_utils.rand_name('User'), data_utils.rand_password())['user']
-        self.addCleanup(self.client.delete_user, user['id'])
+        self.addCleanup(self.users_client.delete_user, user['id'])
         # create two groups, and add user into them
         groups = []
         for i in range(2):
@@ -99,7 +99,7 @@
             self.addCleanup(self.groups_client.delete_group, group['id'])
             self.groups_client.add_group_user(group['id'], user['id'])
         # list groups which user belongs to
-        user_groups = self.client.list_user_groups(user['id'])['groups']
+        user_groups = self.users_client.list_user_groups(user['id'])['groups']
         self.assertEqual(sorted(groups), sorted(user_groups))
         self.assertEqual(2, len(user_groups))
 
diff --git a/tempest/api/identity/admin/v3/test_list_users.py b/tempest/api/identity/admin/v3/test_list_users.py
index 4921c00..5b27ab1 100644
--- a/tempest/api/identity/admin/v3/test_list_users.py
+++ b/tempest/api/identity/admin/v3/test_list_users.py
@@ -25,7 +25,7 @@
         # assert the response based on expected and not_expected
         # expected: user expected in the list response
         # not_expected: user, which should not be present in list response
-        body = self.client.list_users(params)['users']
+        body = self.users_client.list_users(params)['users']
         self.assertIn(expected[key], map(lambda x: x[key], body))
         self.assertNotIn(not_expected[key],
                          map(lambda x: x[key], body))
@@ -39,13 +39,13 @@
         cls.data.setup_test_domain()
         # Create user with Domain
         u1_name = data_utils.rand_name('test_user')
-        cls.domain_enabled_user = cls.client.create_user(
+        cls.domain_enabled_user = cls.users_client.create_user(
             u1_name, password=alt_password,
             email=cls.alt_email, domain_id=cls.data.domain['id'])['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(
+        cls.non_domain_enabled_user = cls.users_client.create_user(
             u2_name, password=alt_password,
             email=cls.alt_email, enabled=False)['user']
         cls.data.users.append(cls.non_domain_enabled_user)
@@ -77,7 +77,7 @@
     @test.idempotent_id('b30d4651-a2ea-4666-8551-0c0e49692635')
     def test_list_users(self):
         # List users
-        body = self.client.list_users()['users']
+        body = self.users_client.list_users()['users']
         fetched_ids = [u['id'] for u in body]
         missing_users = [u['id'] for u in self.data.users
                          if u['id'] not in fetched_ids]
@@ -88,7 +88,7 @@
     @test.idempotent_id('b4baa3ae-ac00-4b4e-9e27-80deaad7771f')
     def test_get_user(self):
         # Get a user detail
-        user = self.client.show_user(self.data.users[0]['id'])['user']
+        user = self.users_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'])
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index 92f5a40..607bebe 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -163,14 +163,14 @@
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_password()
-        user = self.client.create_user(
+        user = self.users_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, project_id=project['id'])['user']
         # Delete the User at the end of this method
-        self.addCleanup(self.client.delete_user, user['id'])
+        self.addCleanup(self.users_client.delete_user, user['id'])
 
         # Get User To validate the user details
-        new_user_get = self.client.show_user(user['id'])['user']
+        new_user_get = self.users_client.show_user(user['id'])['user']
         # Assert response body of GET
         self.assertEqual(u_name, new_user_get['name'])
         self.assertEqual(u_desc, new_user_get['description'])
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index f3cdd96..468f169 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -42,7 +42,7 @@
         cls.group_body = cls.groups_client.create_group(
             name=data_utils.rand_name('Group'), project_id=cls.project['id'],
             domain_id=cls.domain['id'])['group']
-        cls.user_body = cls.client.create_user(
+        cls.user_body = cls.users_client.create_user(
             u_name, description=u_desc, password=cls.u_password,
             email=u_email, project_id=cls.project['id'],
             domain_id=cls.domain['id'])['user']
@@ -53,7 +53,7 @@
     def resource_cleanup(cls):
         cls.client.delete_role(cls.role['id'])
         cls.groups_client.delete_group(cls.group_body['id'])
-        cls.client.delete_user(cls.user_body['id'])
+        cls.users_client.delete_user(cls.user_body['id'])
         cls.projects_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
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index 3452d95..3e6533a 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -30,10 +30,10 @@
         u_desc = '%s-description' % u_name
         u_email = '%s@testmail.tm' % u_name
         u_password = data_utils.rand_password()
-        user = self.client.create_user(
+        user = self.users_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email)['user']
-        self.addCleanup(self.client.delete_user, user['id'])
+        self.addCleanup(self.users_client.delete_user, user['id'])
         # Perform Authentication
         resp = self.token.auth(user_id=user['id'],
                                password=u_password).response
@@ -61,9 +61,9 @@
         # Create a user.
         user_name = data_utils.rand_name(name='user')
         user_password = data_utils.rand_password()
-        user = self.client.create_user(user_name,
-                                       password=user_password)['user']
-        self.addCleanup(self.client.delete_user, user['id'])
+        user = self.users_client.create_user(user_name,
+                                             password=user_password)['user']
+        self.addCleanup(self.users_client.delete_user, user['id'])
 
         # Create a couple projects
         project1_name = data_utils.rand_name(name='project')
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 5f44b8e..37611e0 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -56,7 +56,7 @@
         u_desc = self.trustor_username + 'description'
         u_email = self.trustor_username + '@testmail.xx'
         self.trustor_password = data_utils.rand_password()
-        user = self.client.create_user(
+        user = self.users_client.create_user(
             self.trustor_username,
             description=u_desc,
             password=self.trustor_password,
@@ -101,7 +101,7 @@
 
     def cleanup_user_and_roles(self):
         if self.trustor_user_id:
-            self.client.delete_user(self.trustor_user_id)
+            self.users_client.delete_user(self.trustor_user_id)
         if self.trustor_project_id:
             self.projects_client.delete_project(self.trustor_project_id)
         if self.delegated_role_id:
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 75c8ca5..f7f33b3 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -30,11 +30,11 @@
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_password()
-        user = self.client.create_user(
+        user = self.users_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, enabled=False)['user']
         # Delete the User at the end of this method
-        self.addCleanup(self.client.delete_user, user['id'])
+        self.addCleanup(self.users_client.delete_user, user['id'])
         # Creating second project for updation
         project = self.projects_client.create_project(
             data_utils.rand_name('project'),
@@ -45,7 +45,7 @@
         u_name2 = data_utils.rand_name('user2')
         u_email2 = u_name2 + '@testmail.tm'
         u_description2 = u_name2 + ' description'
-        update_user = self.client.update_user(
+        update_user = self.users_client.update_user(
             user['id'], name=u_name2, description=u_description2,
             project_id=project['id'],
             email=u_email2, enabled=False)['user']
@@ -56,7 +56,7 @@
         self.assertEqual(u_email2, update_user['email'])
         self.assertEqual(False, update_user['enabled'])
         # GET by id after updation
-        new_user_get = self.client.show_user(user['id'])['user']
+        new_user_get = self.users_client.show_user(user['id'])['user']
         # Assert response body of GET after updation
         self.assertEqual(u_name2, new_user_get['name'])
         self.assertEqual(u_description2, new_user_get['description'])
@@ -70,14 +70,15 @@
         # Creating User to check password updation
         u_name = data_utils.rand_name('user')
         original_password = data_utils.rand_password()
-        user = self.client.create_user(
+        user = self.users_client.create_user(
             u_name, password=original_password)['user']
         # Delete the User at the end all test methods
-        self.addCleanup(self.client.delete_user, user['id'])
+        self.addCleanup(self.users_client.delete_user, user['id'])
         # Update user with new password
         new_password = data_utils.rand_password()
-        self.client.update_user_password(user['id'], password=new_password,
-                                         original_password=original_password)
+        self.users_client.update_user_password(
+            user['id'], password=new_password,
+            original_password=original_password)
         # TODO(lbragstad): Sleeping after the response status has been checked
         # and the body loaded as JSON allows requests to fail-fast. The sleep
         # is necessary because keystone will err on the side of security and
@@ -110,18 +111,18 @@
         u_desc = u_name + 'description'
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_password()
-        user_body = self.client.create_user(
+        user_body = self.users_client.create_user(
             u_name, description=u_desc, password=u_password,
             email=u_email, enabled=False, project_id=u_project['id'])['user']
         # Delete the User at the end of this method
-        self.addCleanup(self.client.delete_user, user_body['id'])
+        self.addCleanup(self.users_client.delete_user, user_body['id'])
         # Creating Role
         role_body = self.client.create_role(
             name=data_utils.rand_name('role'))['role']
         # Delete the Role at the end of this method
         self.addCleanup(self.client.delete_role, role_body['id'])
 
-        user = self.client.show_user(user_body['id'])['user']
+        user = self.users_client.show_user(user_body['id'])['user']
         role = self.client.show_role(role_body['id'])['role']
         for i in range(2):
             # Creating project so as to assign role
@@ -138,7 +139,7 @@
                                          user['id'],
                                          role['id'])
             assigned_project_ids.append(project['id'])
-        body = self.client.list_user_projects(user['id'])['projects']
+        body = self.users_client.list_user_projects(user['id'])['projects']
         for i in body:
             fetched_project_ids.append(i['id'])
         # verifying the project ids in list
@@ -154,5 +155,5 @@
     def test_get_user(self):
         # Get a user detail
         self.data.setup_test_user()
-        user = self.client.show_user(self.data.user['id'])['user']
+        user = self.users_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 39c89a5..9dd477b 100644
--- a/tempest/api/identity/admin/v3/test_users_negative.py
+++ b/tempest/api/identity/admin/v3/test_users_negative.py
@@ -29,7 +29,7 @@
         u_name = data_utils.rand_name('user')
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_password()
-        self.assertRaises(lib_exc.NotFound, self.client.create_user,
+        self.assertRaises(lib_exc.NotFound, self.users_client.create_user,
                           u_name, u_password,
                           email=u_email,
                           domain_id=data_utils.rand_uuid_hex())
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 455a2c6..1025de7 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -129,6 +129,7 @@
     def setup_clients(cls):
         super(BaseIdentityV3Test, cls).setup_clients()
         cls.non_admin_client = cls.os.identity_v3_client
+        cls.non_admin_users_client = cls.os.users_v3_client
         cls.non_admin_token = cls.os.token_v3_client
         cls.non_admin_projects_client = cls.os.projects_client
 
@@ -145,6 +146,7 @@
     def setup_clients(cls):
         super(BaseIdentityV3AdminTest, cls).setup_clients()
         cls.client = cls.os_adm.identity_v3_client
+        cls.users_client = cls.os_adm.users_v3_client
         cls.token = cls.os_adm.token_v3_client
         cls.endpoints_client = cls.os_adm.endpoints_client
         cls.regions_client = cls.os_adm.regions_client
@@ -157,7 +159,8 @@
     @classmethod
     def resource_setup(cls):
         super(BaseIdentityV3AdminTest, cls).resource_setup()
-        cls.data = DataGeneratorV3(cls.client, cls.projects_client)
+        cls.data = DataGeneratorV3(cls.client, cls.projects_client,
+                                   cls.users_client)
 
     @classmethod
     def resource_cleanup(cls):
@@ -165,13 +168,6 @@
         super(BaseIdentityV3AdminTest, cls).resource_cleanup()
 
     @classmethod
-    def get_user_by_name(cls, name):
-        users = cls.client.list_users()['users']
-        user = [u for u in users if u['name'] == name]
-        if len(user) > 0:
-            return user[0]
-
-    @classmethod
     def get_role_by_name(cls, name):
         roles = cls.client.list_roles()['roles']
         role = [r for r in roles if r['name'] == name]
@@ -181,7 +177,7 @@
     @classmethod
     def disable_user(cls, user_name):
         user = cls.get_user_by_name(user_name)
-        cls.client.update_user(user['id'], user_name, enabled=False)
+        cls.users_client.update_user(user['id'], user_name, enabled=False)
 
     def delete_domain(self, domain_id):
         # NOTE(mpavlase) It is necessary to disable the domain before deleting
@@ -193,10 +189,10 @@
 class BaseDataGenerator(object):
 
     def __init__(self, client, projects_client,
-                 users_client=None, roles_client=None):
+                 users_client, roles_client=None):
         self.client = client
         self.projects_client = projects_client
-        self.users_client = users_client or client
+        self.users_client = users_client
         self.roles_client = roles_client or client
 
         self.user_password = None
diff --git a/tempest/api/identity/v3/test_projects.py b/tempest/api/identity/v3/test_projects.py
index a547b06..b42cf43 100644
--- a/tempest/api/identity/v3/test_projects.py
+++ b/tempest/api/identity/v3/test_projects.py
@@ -27,7 +27,7 @@
     def test_list_projects_returns_only_authorized_projects(self):
         alt_project_name =\
             self.alt_manager.credentials.credentials.project_name
-        resp = self.non_admin_client.list_user_projects(
+        resp = self.non_admin_users_client.list_user_projects(
             self.os.credentials.user_id)
 
         # check that user can see only that projects that he presents in so
diff --git a/tempest/api/identity/v3/test_users.py b/tempest/api/identity/v3/test_users.py
index 93814d3..29396a8 100644
--- a/tempest/api/identity/v3/test_users.py
+++ b/tempest/api/identity/v3/test_users.py
@@ -39,23 +39,24 @@
         self.new_creds = copy.copy(self.creds.credentials)
         self.new_creds.password = data_utils.rand_password()
         # we need new non-admin Identity V3 Client with new credentials, since
-        # current non_admin_client token will be revoked after updating
+        # current non_admin_users_client token will be revoked after updating
         # password
-        self.non_admin_client_for_cleanup = copy.copy(self.non_admin_client)
-        self.non_admin_client_for_cleanup.auth_provider = (
+        self.non_admin_users_client_for_cleanup = (
+            copy.copy(self.non_admin_users_client))
+        self.non_admin_users_client_for_cleanup.auth_provider = (
             manager.get_auth_provider(self.new_creds))
         user_id = self.creds.credentials.user_id
         old_pass = self.creds.credentials.password
         new_pass = self.new_creds.password
         # to change password back. important for allow_tenant_isolation = false
         self.addCleanup(
-            self.non_admin_client_for_cleanup.update_user_password,
+            self.non_admin_users_client_for_cleanup.update_user_password,
             user_id,
             password=old_pass,
             original_password=new_pass)
 
         # user updates own password
-        self.non_admin_client.update_user_password(
+        self.non_admin_users_client.update_user_password(
             user_id, password=new_pass, original_password=old_pass)
 
         # TODO(lbragstad): Sleeping after the response status has been checked
diff --git a/tempest/clients.py b/tempest/clients.py
index f53c2c1..0f45b79 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -124,6 +124,7 @@
     RegionsClient as RegionsV3Client
 from tempest.services.identity.v3.json.services_client import \
     ServicesClient as IdentityServicesV3Client
+from tempest.services.identity.v3.json.users_clients import UsersV3Client
 from tempest.services.image.v1.json.images_client import ImagesClient
 from tempest.services.image.v2.json.images_client import ImagesClientV2
 from tempest.services.messaging.json.messaging_client import \
@@ -535,6 +536,7 @@
         params_v3['endpoint_type'] = CONF.identity.v3_endpoint_type
         self.identity_v3_client = IdentityV3Client(self.auth_provider,
                                                    **params_v3)
+        self.users_v3_client = UsersV3Client(self.auth_provider, **params_v3)
         self.endpoints_client = EndPointV3Client(self.auth_provider,
                                                  **params_v3)
         self.identity_services_client = IdentityServicesV3Client(
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
index e2309bf..5069807 100644
--- a/tempest/common/cred_client.py
+++ b/tempest/common/cred_client.py
@@ -31,15 +31,15 @@
      admin credentials used for generating credentials.
     """
 
-    def __init__(self, identity_client, projects_client,
-                 roles_client=None, users_client=None):
+    def __init__(self, identity_client, projects_client, users_client,
+                 roles_client=None):
         # The client implies version and credentials
         self.identity_client = identity_client
+        self.users_client = users_client
         self.projects_client = projects_client
-        # this is temporary until v3 roles client and v3 users client are
-        # separated, then these clients will become mandatory
+        # this is temporary until the v3 clients are
+        # separated, then using *only* each client will become mandatory
         self.roles_client = roles_client or identity_client
-        self.users_client = users_client or identity_client
 
     def create_user(self, username, password, project, email):
         user = self.users_client.create_user(
@@ -97,12 +97,12 @@
 
 class V2CredsClient(CredsClient):
 
-    def __init__(self, identity_client, projects_client, roles_client,
-                 users_client):
+    def __init__(self, identity_client, projects_client, users_client,
+                 roles_client):
         super(V2CredsClient, self).__init__(identity_client,
                                             projects_client,
-                                            roles_client,
-                                            users_client)
+                                            users_client,
+                                            roles_client)
 
     def create_project(self, name, description):
         tenant = self.projects_client.create_tenant(
@@ -126,8 +126,10 @@
 
 class V3CredsClient(CredsClient):
 
-    def __init__(self, identity_client, projects_client, domain_name):
-        super(V3CredsClient, self).__init__(identity_client, projects_client)
+    def __init__(self, identity_client, projects_client, users_client,
+                 domain_name):
+        super(V3CredsClient, self).__init__(identity_client,
+                                            projects_client, users_client)
         try:
             # Domain names must be unique, in any case a list is returned,
             # selecting the first (and only) element
@@ -167,12 +169,12 @@
 
 def get_creds_client(identity_client,
                      projects_client,
+                     users_client,
                      roles_client=None,
-                     users_client=None,
                      project_domain_name=None):
     if isinstance(identity_client, v2_identity.IdentityClient):
-        return V2CredsClient(identity_client, projects_client, roles_client,
-                             users_client)
+        return V2CredsClient(identity_client, projects_client, users_client,
+                             roles_client)
     else:
-        return V3CredsClient(identity_client,
-                             projects_client, project_domain_name)
+        return V3CredsClient(identity_client, projects_client, users_client,
+                             project_domain_name)
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index 9e5e0dd..1810c57 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -59,8 +59,8 @@
         self.default_admin_creds = admin_creds
         (self.identity_admin_client,
          self.tenants_admin_client,
-         self.roles_admin_client,
          self.users_admin_client,
+         self.roles_admin_client,
          self.network_admin_client,
          self.networks_admin_client,
          self.subnets_admin_client,
@@ -76,8 +76,8 @@
         self.creds_client = cred_client.get_creds_client(
             self.identity_admin_client,
             self.tenants_admin_client,
-            self.roles_admin_client,
             self.users_admin_client,
+            self.roles_admin_client,
             self.creds_domain_name)
 
     def _get_admin_clients(self):
@@ -89,14 +89,15 @@
         """
         os = clients.Manager(self.default_admin_creds)
         if self.identity_version == 'v2':
-            return (os.identity_client, os.tenants_client, os.roles_client,
-                    os.users_client, os.network_client, os.networks_client,
+            return (os.identity_client, os.tenants_client, os.users_client,
+                    os.roles_client, os.network_client, os.networks_client,
                     os.subnets_client, os.ports_client,
                     os.security_groups_client)
         else:
-            return (os.identity_v3_client, os.projects_client, None, None,
-                    os.network_client, os.networks_client, os.subnets_client,
-                    os.ports_client, os.security_groups_client)
+            return (os.identity_v3_client, os.projects_client,
+                    os.users_v3_client, None, os.network_client,
+                    os.networks_client, os.subnets_client, os.ports_client,
+                    os.security_groups_client)
 
     def _create_creds(self, suffix="", admin=False, roles=None):
         """Create random credentials under the following schema.
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index 252fad7..4c19442 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -30,98 +30,6 @@
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
 
-    def create_user(self, user_name, password=None, project_id=None,
-                    email=None, domain_id='default', **kwargs):
-        """Creates a user."""
-        en = kwargs.get('enabled', True)
-        description = kwargs.get('description', None)
-        default_project_id = kwargs.get('default_project_id')
-        post_body = {
-            'project_id': project_id,
-            'default_project_id': default_project_id,
-            'description': description,
-            'domain_id': domain_id,
-            'email': email,
-            'enabled': en,
-            'name': user_name,
-            'password': password
-        }
-        post_body = json.dumps({'user': post_body})
-        resp, body = self.post('users', post_body)
-        self.expected_success(201, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def update_user(self, user_id, name, **kwargs):
-        """Updates a user."""
-        body = self.show_user(user_id)['user']
-        email = kwargs.get('email', body['email'])
-        en = kwargs.get('enabled', body['enabled'])
-        project_id = kwargs.get('project_id', body['project_id'])
-        if 'default_project_id' in body.keys():
-            default_project_id = kwargs.get('default_project_id',
-                                            body['default_project_id'])
-        else:
-            default_project_id = kwargs.get('default_project_id')
-        description = kwargs.get('description', body['description'])
-        domain_id = kwargs.get('domain_id', body['domain_id'])
-        post_body = {
-            'name': name,
-            'email': email,
-            'enabled': en,
-            'project_id': project_id,
-            'default_project_id': default_project_id,
-            'id': user_id,
-            'domain_id': domain_id,
-            'description': description
-        }
-        post_body = json.dumps({'user': post_body})
-        resp, body = self.patch('users/%s' % user_id, post_body)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def update_user_password(self, user_id, **kwargs):
-        """Update a user password
-
-        Available params: see http://developer.openstack.org/
-                              api-ref-identity-v3.html#changeUserPassword
-        """
-        update_user = json.dumps({'user': kwargs})
-        resp, _ = self.post('users/%s/password' % user_id, update_user)
-        self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp)
-
-    def list_user_projects(self, user_id):
-        """Lists the projects on which a user has roles assigned."""
-        resp, body = self.get('users/%s/projects' % user_id)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def list_users(self, params=None):
-        """Get the list of users."""
-        url = 'users'
-        if params:
-            url += '?%s' % urllib.urlencode(params)
-        resp, body = self.get(url)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def show_user(self, user_id):
-        """GET a user."""
-        resp, body = self.get("users/%s" % user_id)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def delete_user(self, user_id):
-        """Deletes a User."""
-        resp, body = self.delete("users/%s" % user_id)
-        self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
-
     def create_role(self, **kwargs):
         """Create a Role.
 
@@ -243,13 +151,6 @@
         self.expected_success(204, resp.status)
         return service_client.ResponseBody(resp, body)
 
-    def list_user_groups(self, user_id):
-        """Lists groups which a user belongs to."""
-        resp, body = self.get('users/%s/groups' % user_id)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
     def assign_user_role_on_project(self, project_id, user_id, role_id):
         """Add roles to a user on a project."""
         resp, body = self.put('projects/%s/users/%s/roles/%s' %
diff --git a/tempest/services/identity/v3/json/users_clients.py b/tempest/services/identity/v3/json/users_clients.py
new file mode 100644
index 0000000..85c2e79
--- /dev/null
+++ b/tempest/services/identity/v3/json/users_clients.py
@@ -0,0 +1,121 @@
+# 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 six.moves.urllib import parse as urllib
+
+from tempest.common import service_client
+
+
+class UsersV3Client(service_client.ServiceClient):
+    api_version = "v3"
+
+    def create_user(self, user_name, password=None, project_id=None,
+                    email=None, domain_id='default', **kwargs):
+        """Creates a user."""
+        en = kwargs.get('enabled', True)
+        description = kwargs.get('description', None)
+        default_project_id = kwargs.get('default_project_id')
+        post_body = {
+            'project_id': project_id,
+            'default_project_id': default_project_id,
+            'description': description,
+            'domain_id': domain_id,
+            'email': email,
+            'enabled': en,
+            'name': user_name,
+            'password': password
+        }
+        post_body = json.dumps({'user': post_body})
+        resp, body = self.post('users', post_body)
+        self.expected_success(201, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def update_user(self, user_id, name, **kwargs):
+        """Updates a user."""
+        body = self.show_user(user_id)['user']
+        email = kwargs.get('email', body['email'])
+        en = kwargs.get('enabled', body['enabled'])
+        project_id = kwargs.get('project_id', body['project_id'])
+        if 'default_project_id' in body.keys():
+            default_project_id = kwargs.get('default_project_id',
+                                            body['default_project_id'])
+        else:
+            default_project_id = kwargs.get('default_project_id')
+        description = kwargs.get('description', body['description'])
+        domain_id = kwargs.get('domain_id', body['domain_id'])
+        post_body = {
+            'name': name,
+            'email': email,
+            'enabled': en,
+            'project_id': project_id,
+            'default_project_id': default_project_id,
+            'id': user_id,
+            'domain_id': domain_id,
+            'description': description
+        }
+        post_body = json.dumps({'user': post_body})
+        resp, body = self.patch('users/%s' % user_id, post_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def update_user_password(self, user_id, **kwargs):
+        """Update a user password
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-identity-v3.html#changeUserPassword
+        """
+        update_user = json.dumps({'user': kwargs})
+        resp, _ = self.post('users/%s/password' % user_id, update_user)
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp)
+
+    def list_user_projects(self, user_id):
+        """Lists the projects on which a user has roles assigned."""
+        resp, body = self.get('users/%s/projects' % user_id)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def list_users(self, params=None):
+        """Get the list of users."""
+        url = 'users'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def show_user(self, user_id):
+        """GET a user."""
+        resp, body = self.get("users/%s" % user_id)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def delete_user(self, user_id):
+        """Deletes a User."""
+        resp, body = self.delete("users/%s" % user_id)
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def list_user_groups(self, user_id):
+        """Lists groups which a user belongs to."""
+        resp, body = self.get('users/%s/groups' % user_id)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 1f9df5e..3c69a8b 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -153,12 +153,12 @@
                     identity_client = admin_manager.identity_v3_client
                     projects_client = admin_manager.projects_client
                     roles_client = None
-                    users_client = None
+                    users_client = admin_manager.users_v3_client
                 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, project_domain_name=domain)
+                    identity_client, projects_client, users_client,
+                    roles_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/test.py b/tempest/test.py
index 6a0095f..a676cc2 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -437,14 +437,14 @@
         """
         if CONF.identity.auth_version == 'v2':
             client = self.os_admin.identity_client
+            users_client = self.os_admin.users_client
             project_client = self.os_admin.tenants_client
             roles_client = self.os_admin.roles_client
-            users_client = self.os_admin.users_client
         else:
             client = self.os_admin.identity_v3_client
             project_client = self.os_adm.projects_client
+            users_client = self.os_admin.users_v3_client
             roles_client = None
-            users_client = None
 
         try:
             domain = client.auth_provider.credentials.project_domain_name
@@ -452,8 +452,8 @@
             domain = 'Default'
 
         return cred_client.get_creds_client(client, project_client,
-                                            roles_client,
                                             users_client,
+                                            roles_client,
                                             project_domain_name=domain)
 
     @classmethod