Merge "Add different_host test on multiple nodes"
diff --git a/setup.cfg b/setup.cfg
index b94a4f4..cc3a365 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -33,10 +33,12 @@
     tempest-account-generator = tempest.cmd.account_generator:main
     tempest = tempest.cmd.main:main
 tempest.cm =
+    account-generator = tempest.cmd.account_generator:TempestAccountGenerator
     init = tempest.cmd.init:TempestInit
     cleanup = tempest.cmd.cleanup:TempestCleanup
     run-stress = tempest.cmd.run_stress:TempestRunStress
     list-plugins = tempest.cmd.list_plugins:TempestListPlugins
+    verify-config = tempest.cmd.verify_tempest_config:TempestVerifyConfig
 oslo.config.opts =
     tempest.config = tempest.config:list_opts
 
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 8a27929..6d19ca7 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -329,11 +329,12 @@
             except Exception:
                 LOG.exception('Failed to delete server %s' % server_id)
 
+        cls.password = data_utils.rand_password()
         server = cls.create_test_server(
             validatable,
             wait_until='ACTIVE',
+            adminPass=cls.password,
             **kwargs)
-        cls.password = server['adminPass']
         return server['id']
 
     @classmethod
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index 49d9bc8..af840cc 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -15,7 +15,6 @@
 
 import time
 
-from oslo_log import log as logging
 import six
 import testtools
 
@@ -27,8 +26,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class ListImageFiltersTestJSON(base.BaseV2ComputeTest):
 
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index e1c22e5..f719bfc 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -50,6 +50,7 @@
         cls.accessIPv4 = '1.1.1.1'
         cls.accessIPv6 = '0000:0000:0000:0000:0000:babe:220.12.22.2'
         cls.name = data_utils.rand_name('server')
+        cls.password = data_utils.rand_password()
         disk_config = cls.disk_config
         cls.server_initial = cls.create_test_server(
             validatable=True,
@@ -58,8 +59,8 @@
             metadata=cls.meta,
             accessIPv4=cls.accessIPv4,
             accessIPv6=cls.accessIPv6,
-            disk_config=disk_config)
-        cls.password = cls.server_initial['adminPass']
+            disk_config=disk_config,
+            adminPass=cls.password)
         cls.server = (cls.client.show_server(cls.server_initial['id'])
                       ['server'])
 
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index d7f0d75..66e85a6 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -172,11 +172,16 @@
         self.assertEqual(new_name, server['name'])
 
         if CONF.validation.run_validation:
-            # TODO(jlanoux) add authentication with the provided password
+            # Authentication is attempted in the following order of priority:
+            # 1.The key passed in, if one was passed in.
+            # 2.Any key we can find through an SSH agent (if allowed).
+            # 3.Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
+            #   ~/.ssh/ (if allowed).
+            # 4.Plain username/password auth, if a password was given.
             linux_client = remote_client.RemoteClient(
                 self.get_server_ip(rebuilt_server),
                 self.ssh_user,
-                self.password,
+                password,
                 self.validation_resources['keypair']['private_key'])
             linux_client.validate_authentication()
 
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index c948f8c..dad8e90 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 import base64
+from tempest_lib.common.utils import data_utils
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.compute import base
@@ -55,14 +56,16 @@
         file_path = '/test.txt'
         personality = [{'path': file_path,
                         'contents': base64.b64encode(file_contents)}]
+        password = data_utils.rand_password()
         created_server = self.create_test_server(personality=personality,
+                                                 adminPass=password,
                                                  wait_until='ACTIVE',
                                                  validatable=True)
         server = self.client.show_server(created_server['id'])['server']
         if CONF.validation.run_validation:
             linux_client = remote_client.RemoteClient(
                 self.get_server_ip(server),
-                self.ssh_user, created_server['adminPass'],
+                self.ssh_user, password,
                 self.validation_resources['keypair']['private_key'])
             self.assertEqual(file_contents,
                              linux_client.exec_command(
@@ -117,14 +120,16 @@
                 'path': path,
                 'contents': base64.b64encode(file_contents),
             })
+        password = data_utils.rand_password()
         created_server = self.create_test_server(personality=person,
+                                                 adminPass=password,
                                                  wait_until='ACTIVE',
                                                  validatable=True)
         server = self.client.show_server(created_server['id'])['server']
         if CONF.validation.run_validation:
             linux_client = remote_client.RemoteClient(
                 self.get_server_ip(server),
-                self.ssh_user, created_server['adminPass'],
+                self.ssh_user, password,
                 self.validation_resources['keypair']['private_key'])
             for i in person:
                 self.assertEqual(base64.b64decode(i['contents']),
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 2296980..12b824f 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -52,10 +52,11 @@
             name=cls.sg_name, description=cls.sg_desc)['security_group']
         cls.sg_id = cls.sg['id']
 
+        cls.password = data_utils.rand_password()
         # Server for positive tests
-        server = cls.create_test_server(wait_until='BUILD')
+        server = cls.create_test_server(adminPass=cls.password,
+                                        wait_until='BUILD')
         cls.server_id = server['id']
-        cls.password = server['adminPass']
         waiters.wait_for_server_status(cls.servers_client, cls.server_id,
                                        'ACTIVE')
 
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index 65ad2f5..5afb4d1 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -43,14 +43,15 @@
     def resource_setup(cls):
         super(ServerRescueNegativeTestJSON, cls).resource_setup()
         cls.device = CONF.compute.volume_device_name
-
+        cls.password = data_utils.rand_password()
+        rescue_password = data_utils.rand_password()
         # Server for negative tests
-        server = cls.create_test_server(wait_until='BUILD')
-        resc_server = cls.create_test_server(wait_until='ACTIVE')
+        server = cls.create_test_server(adminPass=cls.password,
+                                        wait_until='BUILD')
+        resc_server = cls.create_test_server(adminPass=rescue_password,
+                                             wait_until='ACTIVE')
         cls.server_id = server['id']
-        cls.password = server['adminPass']
         cls.rescue_id = resc_server['id']
-        rescue_password = resc_server['adminPass']
 
         cls.servers_client.rescue_server(
             cls.rescue_id, adminPass=rescue_password)
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 8e2fbf1..2f79d47 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -13,11 +13,16 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest.common import waiters
+from tempest import config
 from tempest import test
 
+CONF = config.CONF
+
 
 class ServersTestJSON(base.BaseV2ComputeTest):
 
@@ -31,6 +36,9 @@
         super(ServersTestJSON, self).tearDown()
 
     @test.idempotent_id('b92d5ec7-b1dd-44a2-87e4-45e888c46ef0')
+    @testtools.skipUnless(CONF.compute_feature_enabled.
+                          enable_instance_password,
+                          'Instance password not available.')
     def test_create_server_with_admin_password(self):
         # If an admin password is provided on server creation, the server's
         # root password should be set to that password.
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 468c79a..01a8e58 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -63,11 +63,11 @@
 
     def _create_and_attach(self):
         # Start a server and wait for it to become ready
-        admin_pass = self.image_ssh_password
+        self.admin_pass = self.image_ssh_password
         self.server = self.create_test_server(
             validatable=True,
             wait_until='ACTIVE',
-            adminPass=admin_pass)
+            adminPass=self.admin_pass)
 
         # Record addresses so that we can ssh later
         self.server['addresses'] = self.servers_client.list_addresses(
@@ -108,7 +108,7 @@
         linux_client = remote_client.RemoteClient(
             self.get_server_ip(self.server),
             self.image_ssh_user,
-            self.server['adminPass'],
+            self.admin_pass,
             self.validation_resources['keypair']['private_key'])
 
         partitions = linux_client.get_partitions()
@@ -127,7 +127,7 @@
         linux_client = remote_client.RemoteClient(
             self.get_server_ip(self.server),
             self.image_ssh_user,
-            self.server['adminPass'],
+            self.admin_pass,
             self.validation_resources['keypair']['private_key'])
 
         partitions = linux_client.get_partitions()
diff --git a/tempest/api/compute/volumes/test_volume_snapshots.py b/tempest/api/compute/volumes/test_volume_snapshots.py
index a00c0ba..f42d153 100644
--- a/tempest/api/compute/volumes/test_volume_snapshots.py
+++ b/tempest/api/compute/volumes/test_volume_snapshots.py
@@ -50,7 +50,7 @@
         s_name = data_utils.rand_name('Snapshot')
         # Create snapshot
         snapshot = self.snapshots_client.create_snapshot(
-            volume['id'],
+            volume_id=volume['id'],
             display_name=s_name)['snapshot']
 
         def delete_snapshot(snapshot_id):
diff --git a/tempest/api/database/base.py b/tempest/api/database/base.py
index f4c1881..01e05db 100644
--- a/tempest/api/database/base.py
+++ b/tempest/api/database/base.py
@@ -13,13 +13,10 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest import config
 import tempest.test
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class BaseDatabaseTest(tempest.test.BaseTestCase):
diff --git a/tempest/api/identity/admin/v2/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index fdb5a5a..ee04420 100644
--- a/tempest/api/identity/admin/v2/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -30,8 +30,8 @@
         tenant = self.tenants_client.create_tenant(tenant_name)['tenant']
         self.data.tenants.append(tenant)
         # second:create a user
-        user = self.client.create_user(user_name, user_password,
-                                       tenant['id'], '')['user']
+        user = self.users_client.create_user(user_name, user_password,
+                                             tenant['id'], '')['user']
         self.data.users.append(user)
         # then get a token for the user
         body = self.token_client.auth(user_name,
@@ -62,8 +62,8 @@
         user_password = data_utils.rand_password()
         tenant_id = None  # No default tenant so will get unscoped token.
         email = ''
-        user = self.client.create_user(user_name, user_password,
-                                       tenant_id, email)['user']
+        user = self.users_client.create_user(user_name, user_password,
+                                             tenant_id, email)['user']
         self.data.users.append(user)
 
         # Create a couple tenants.
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index d886524..4497575 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -34,9 +34,9 @@
     def test_create_user(self):
         # Create a user
         self.data.setup_test_tenant()
-        user = self.client.create_user(self.alt_user, self.alt_password,
-                                       self.data.tenant['id'],
-                                       self.alt_email)['user']
+        user = self.users_client.create_user(self.alt_user, self.alt_password,
+                                             self.data.tenant['id'],
+                                             self.alt_email)['user']
         self.data.users.append(user)
         self.assertEqual(self.alt_user, user['name'])
 
@@ -45,9 +45,10 @@
         # Create a user with enabled : False
         self.data.setup_test_tenant()
         name = data_utils.rand_name('test_user')
-        user = self.client.create_user(name, self.alt_password,
-                                       self.data.tenant['id'],
-                                       self.alt_email, enabled=False)['user']
+        user = self.users_client.create_user(name, self.alt_password,
+                                             self.data.tenant['id'],
+                                             self.alt_email,
+                                             enabled=False)['user']
         self.data.users.append(user)
         self.assertEqual(name, user['name'])
         self.assertEqual(False, user['enabled'])
@@ -58,22 +59,22 @@
         # Test case to check if updating of user attributes is successful.
         test_user = data_utils.rand_name('test_user')
         self.data.setup_test_tenant()
-        user = self.client.create_user(test_user, self.alt_password,
-                                       self.data.tenant['id'],
-                                       self.alt_email)['user']
+        user = self.users_client.create_user(test_user, self.alt_password,
+                                             self.data.tenant['id'],
+                                             self.alt_email)['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'])
         # Updating user details with new values
         u_name2 = data_utils.rand_name('user2')
         u_email2 = u_name2 + '@testmail.tm'
-        update_user = self.client.update_user(user['id'], name=u_name2,
-                                              email=u_email2,
-                                              enabled=False)['user']
+        update_user = self.users_client.update_user(user['id'], name=u_name2,
+                                                    email=u_email2,
+                                                    enabled=False)['user']
         self.assertEqual(u_name2, update_user['name'])
         self.assertEqual(u_email2, update_user['email'])
         self.assertEqual(False, update_user['enabled'])
         # GET by id after updating
-        updated_user = self.client.show_user(user['id'])['user']
+        updated_user = self.users_client.show_user(user['id'])['user']
         # Assert response body of GET after updating
         self.assertEqual(u_name2, updated_user['name'])
         self.assertEqual(u_email2, updated_user['email'])
@@ -84,10 +85,10 @@
         # Delete a user
         test_user = data_utils.rand_name('test_user')
         self.data.setup_test_tenant()
-        user = self.client.create_user(test_user, self.alt_password,
-                                       self.data.tenant['id'],
-                                       self.alt_email)['user']
-        self.client.delete_user(user['id'])
+        user = self.users_client.create_user(test_user, self.alt_password,
+                                             self.data.tenant['id'],
+                                             self.alt_email)['user']
+        self.users_client.delete_user(user['id'])
 
     @test.idempotent_id('aca696c3-d645-4f45-b728-63646045beb1')
     def test_user_authentication(self):
@@ -121,7 +122,7 @@
     def test_get_users(self):
         # Get a list of users and find the test user
         self.data.setup_test_user()
-        users = self.client.list_users()['users']
+        users = self.users_client.list_users()['users']
         self.assertThat([u['name'] for u in users],
                         matchers.Contains(self.data.test_user),
                         "Could not find %s" % self.data.test_user)
@@ -134,16 +135,16 @@
         fetched_user_ids = list()
         password1 = data_utils.rand_password()
         alt_tenant_user1 = data_utils.rand_name('tenant_user1')
-        user1 = self.client.create_user(alt_tenant_user1, password1,
-                                        self.data.tenant['id'],
-                                        'user1@123')['user']
+        user1 = self.users_client.create_user(alt_tenant_user1, password1,
+                                              self.data.tenant['id'],
+                                              'user1@123')['user']
         user_ids.append(user1['id'])
         self.data.users.append(user1)
         password2 = data_utils.rand_password()
         alt_tenant_user2 = data_utils.rand_name('tenant_user2')
-        user2 = self.client.create_user(alt_tenant_user2, password2,
-                                        self.data.tenant['id'],
-                                        'user2@123')['user']
+        user2 = self.users_client.create_user(alt_tenant_user2, password2,
+                                              self.data.tenant['id'],
+                                              'user2@123')['user']
         user_ids.append(user2['id'])
         self.data.users.append(user2)
         # List of users for the respective tenant ID
@@ -175,9 +176,9 @@
 
         alt_user2 = data_utils.rand_name('second_user')
         alt_password2 = data_utils.rand_password()
-        second_user = self.client.create_user(alt_user2, alt_password2,
-                                              self.data.tenant['id'],
-                                              'user2@123')['user']
+        second_user = self.users_client.create_user(alt_user2, alt_password2,
+                                                    self.data.tenant['id'],
+                                                    'user2@123')['user']
         user_ids.append(second_user['id'])
         self.data.users.append(second_user)
         role = self.roles_client.assign_user_role(tenant['id'],
@@ -201,7 +202,7 @@
         self.data.setup_test_user()
         # Updating the user with new password
         new_pass = data_utils.rand_password()
-        update_user = self.client.update_user_password(
+        update_user = self.users_client.update_user_password(
             self.data.user['id'], password=new_pass)['user']
         self.assertEqual(update_user['id'], self.data.user['id'])
 
diff --git a/tempest/api/identity/admin/v2/test_users_negative.py b/tempest/api/identity/admin/v2/test_users_negative.py
index 8fa5a36..c5248fd 100644
--- a/tempest/api/identity/admin/v2/test_users_negative.py
+++ b/tempest/api/identity/admin/v2/test_users_negative.py
@@ -37,8 +37,9 @@
         # Non-administrator should not be authorized to create a user
         self.data.setup_test_tenant()
         self.assertRaises(lib_exc.Forbidden,
-                          self.non_admin_client.create_user, self.alt_user,
-                          self.alt_password, self.data.tenant['id'],
+                          self.non_admin_users_client.create_user,
+                          self.alt_user, self.alt_password,
+                          self.data.tenant['id'],
                           self.alt_email)
 
     @test.attr(type=['negative'])
@@ -46,8 +47,8 @@
     def test_create_user_with_empty_name(self):
         # User with an empty name should not be created
         self.data.setup_test_tenant()
-        self.assertRaises(lib_exc.BadRequest, self.client.create_user, '',
-                          self.alt_password, self.data.tenant['id'],
+        self.assertRaises(lib_exc.BadRequest, self.users_client.create_user,
+                          '', self.alt_password, self.data.tenant['id'],
                           self.alt_email)
 
     @test.attr(type=['negative'])
@@ -55,7 +56,7 @@
     def test_create_user_with_name_length_over_255(self):
         # Length of user name filed should be restricted to 255 characters
         self.data.setup_test_tenant()
-        self.assertRaises(lib_exc.BadRequest, self.client.create_user,
+        self.assertRaises(lib_exc.BadRequest, self.users_client.create_user,
                           'a' * 256, self.alt_password,
                           self.data.tenant['id'], self.alt_email)
 
@@ -64,7 +65,7 @@
     def test_create_user_with_duplicate_name(self):
         # Duplicate user should not be created
         self.data.setup_test_user()
-        self.assertRaises(lib_exc.Conflict, self.client.create_user,
+        self.assertRaises(lib_exc.Conflict, self.users_client.create_user,
                           self.data.test_user, self.data.test_password,
                           self.data.tenant['id'], self.data.test_email)
 
@@ -72,7 +73,7 @@
     @test.idempotent_id('0132cc22-7c4f-42e1-9e50-ac6aad31d59a')
     def test_create_user_for_non_existent_tenant(self):
         # Attempt to create a user in a non-existent tenant should fail
-        self.assertRaises(lib_exc.NotFound, self.client.create_user,
+        self.assertRaises(lib_exc.NotFound, self.users_client.create_user,
                           self.alt_user, self.alt_password, '49ffgg99999',
                           self.alt_email)
 
@@ -85,7 +86,7 @@
         token = self.client.auth_provider.get_token()
         # Delete the token from database
         self.client.delete_token(token)
-        self.assertRaises(lib_exc.Unauthorized, self.client.create_user,
+        self.assertRaises(lib_exc.Unauthorized, self.users_client.create_user,
                           self.alt_user, self.alt_password,
                           self.data.tenant['id'], self.alt_email)
 
@@ -98,7 +99,7 @@
         # Attempt to create a user with valid enabled para should fail
         self.data.setup_test_tenant()
         name = data_utils.rand_name('test_user')
-        self.assertRaises(lib_exc.BadRequest, self.client.create_user,
+        self.assertRaises(lib_exc.BadRequest, self.users_client.create_user,
                           name, self.alt_password,
                           self.data.tenant['id'],
                           self.alt_email, enabled=3)
@@ -109,7 +110,7 @@
         # Attempt to update a user non-existent user should fail
         user_name = data_utils.rand_name('user')
         non_existent_id = str(uuid.uuid4())
-        self.assertRaises(lib_exc.NotFound, self.client.update_user,
+        self.assertRaises(lib_exc.NotFound, self.users_client.update_user,
                           non_existent_id, name=user_name)
 
     @test.attr(type=['negative'])
@@ -121,7 +122,7 @@
         token = self.client.auth_provider.get_token()
         # Delete the token from database
         self.client.delete_token(token)
-        self.assertRaises(lib_exc.Unauthorized, self.client.update_user,
+        self.assertRaises(lib_exc.Unauthorized, self.users_client.update_user,
                           self.alt_user)
 
         # Unset the token to allow further tests to generate a new token
@@ -133,7 +134,8 @@
         # Non-administrator should not be authorized to update user
         self.data.setup_test_tenant()
         self.assertRaises(lib_exc.Forbidden,
-                          self.non_admin_client.update_user, self.alt_user)
+                          self.non_admin_users_client.update_user,
+                          self.alt_user)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('d45195d5-33ed-41b9-a452-7d0d6a00f6e9')
@@ -141,14 +143,14 @@
         # Non-administrator user should not be authorized to delete a user
         self.data.setup_test_user()
         self.assertRaises(lib_exc.Forbidden,
-                          self.non_admin_client.delete_user,
+                          self.non_admin_users_client.delete_user,
                           self.data.user['id'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('7cc82f7e-9998-4f89-abae-23df36495867')
     def test_delete_non_existent_user(self):
         # Attempt to delete a non-existent user should fail
-        self.assertRaises(lib_exc.NotFound, self.client.delete_user,
+        self.assertRaises(lib_exc.NotFound, self.users_client.delete_user,
                           'junk12345123')
 
     @test.attr(type=['negative'])
@@ -160,7 +162,7 @@
         token = self.client.auth_provider.get_token()
         # Delete the token from database
         self.client.delete_token(token)
-        self.assertRaises(lib_exc.Unauthorized, self.client.delete_user,
+        self.assertRaises(lib_exc.Unauthorized, self.users_client.delete_user,
                           self.alt_user)
 
         # Unset the token to allow further tests to generate a new token
@@ -222,7 +224,7 @@
         # Non-administrator user should not be authorized to get user list
         self.data.setup_test_user()
         self.assertRaises(lib_exc.Forbidden,
-                          self.non_admin_client.list_users)
+                          self.non_admin_users_client.list_users)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('a73591ec-1903-4ffe-be42-282b39fefc9d')
@@ -230,7 +232,7 @@
         # Request to get list of users without a valid token should fail
         token = self.client.auth_provider.get_token()
         self.client.delete_token(token)
-        self.assertRaises(lib_exc.Unauthorized, self.client.list_users)
+        self.assertRaises(lib_exc.Unauthorized, self.users_client.list_users)
         self.client.auth_provider.clear_auth()
 
     @test.attr(type=['negative'])
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index d68a204..1ad8b92 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -30,7 +30,7 @@
     @classmethod
     def disable_user(cls, user_name):
         user = cls.get_user_by_name(user_name)
-        cls.client.enable_disable_user(user['id'], enabled=False)
+        cls.users_client.enable_disable_user(user['id'], enabled=False)
 
     @classmethod
     def disable_tenant(cls, tenant_name):
@@ -39,7 +39,7 @@
 
     @classmethod
     def get_user_by_name(cls, name):
-        users = cls.client.list_users()['users']
+        users = cls.users_client.list_users()['users']
         user = [u for u in users if u['name'] == name]
         if len(user) > 0:
             return user[0]
@@ -77,6 +77,7 @@
         cls.non_admin_token_client = cls.os.token_client
         cls.non_admin_tenants_client = cls.os.tenants_public_client
         cls.non_admin_roles_client = cls.os.roles_public_client
+        cls.non_admin_users_client = cls.os.users_public_client
 
     @classmethod
     def resource_setup(cls):
@@ -101,12 +102,14 @@
         cls.non_admin_tenants_client = cls.os.tenants_client
         cls.roles_client = cls.os_adm.roles_client
         cls.non_admin_roles_client = cls.os.roles_client
+        cls.users_client = cls.os_adm.users_client
+        cls.non_admin_users_client = cls.os.users_client
 
     @classmethod
     def resource_setup(cls):
         super(BaseIdentityV2AdminTest, cls).resource_setup()
         cls.data = DataGenerator(cls.client, cls.tenants_client,
-                                 cls.roles_client)
+                                 cls.roles_client, cls.users_client)
 
     @classmethod
     def resource_cleanup(cls):
@@ -191,11 +194,13 @@
 
 class DataGenerator(object):
 
-        def __init__(self, client, tenants_client=None, roles_client=None):
+        def __init__(self, client, tenants_client=None, roles_client=None,
+                     users_client=None):
             self.client = client
             # TODO(dmellado) split Datagenerator for v2 and v3
             self.tenants_client = tenants_client
             self.roles_client = roles_client
+            self.users_client = users_client
             self.users = []
             self.tenants = []
             self.roles = []
@@ -219,10 +224,10 @@
             self.test_user = data_utils.rand_name('test_user')
             self.test_password = data_utils.rand_password()
             self.test_email = self.test_user + '@testmail.tm'
-            self.user = self.client.create_user(self.test_user,
-                                                self.test_password,
-                                                self.tenant['id'],
-                                                self.test_email)['user']
+            self.user = self.users_client.create_user(self.test_user,
+                                                      self.test_password,
+                                                      self.tenant['id'],
+                                                      self.test_email)['user']
             self.users.append(self.user)
 
         def setup_test_tenant(self):
@@ -296,7 +301,7 @@
             # (e.g. delete_tenant) So we need to check resources existence
             # before using client methods.
             for user in self.users:
-                self._try_wrapper(self.client.delete_user, user)
+                self._try_wrapper(self.users_client.delete_user, user)
             for tenant in self.tenants:
                 self._try_wrapper(self.tenants_client.delete_tenant, tenant)
             for role in self.roles:
diff --git a/tempest/api/identity/v2/test_ec2_credentials.py b/tempest/api/identity/v2/test_ec2_credentials.py
index 88161a3..bd49326 100644
--- a/tempest/api/identity/v2/test_ec2_credentials.py
+++ b/tempest/api/identity/v2/test_ec2_credentials.py
@@ -36,12 +36,12 @@
     @test.idempotent_id('b580fab9-7ae9-46e8-8138-417260cb6f9f')
     def test_create_ec2_credentials(self):
         """Create user ec2 credentials."""
-        resp = self.non_admin_client.create_user_ec2_credentials(
+        resp = self.non_admin_users_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
             tenant_id=self.creds.credentials.tenant_id)["credential"]
         access = resp['access']
         self.addCleanup(
-            self.non_admin_client.delete_user_ec2_credentials,
+            self.non_admin_users_client.delete_user_ec2_credentials,
             self.creds.credentials.user_id, access)
         self.assertNotEmpty(resp['access'])
         self.assertNotEmpty(resp['secret'])
@@ -54,24 +54,24 @@
         created_creds = []
         fetched_creds = []
         # create first ec2 credentials
-        creds1 = self.non_admin_client.create_user_ec2_credentials(
+        creds1 = self.non_admin_users_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
             tenant_id=self.creds.credentials.tenant_id)["credential"]
         created_creds.append(creds1['access'])
         # create second ec2 credentials
-        creds2 = self.non_admin_client.create_user_ec2_credentials(
+        creds2 = self.non_admin_users_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
             tenant_id=self.creds.credentials.tenant_id)["credential"]
         created_creds.append(creds2['access'])
         # add credentials to be cleaned up
         self.addCleanup(
-            self.non_admin_client.delete_user_ec2_credentials,
+            self.non_admin_users_client.delete_user_ec2_credentials,
             self.creds.credentials.user_id, creds1['access'])
         self.addCleanup(
-            self.non_admin_client.delete_user_ec2_credentials,
+            self.non_admin_users_client.delete_user_ec2_credentials,
             self.creds.credentials.user_id, creds2['access'])
         # get the list of user ec2 credentials
-        resp = self.non_admin_client.list_user_ec2_credentials(
+        resp = self.non_admin_users_client.list_user_ec2_credentials(
             self.creds.credentials.user_id)["credentials"]
         fetched_creds = [cred['access'] for cred in resp]
         # created credentials should be in a fetched list
@@ -84,14 +84,14 @@
     @test.idempotent_id('cb284075-b613-440d-83ca-fe0b33b3c2b8')
     def test_show_ec2_credentials(self):
         """Get the definite user ec2 credentials."""
-        resp = self.non_admin_client.create_user_ec2_credentials(
+        resp = self.non_admin_users_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
             tenant_id=self.creds.credentials.tenant_id)["credential"]
         self.addCleanup(
-            self.non_admin_client.delete_user_ec2_credentials,
+            self.non_admin_users_client.delete_user_ec2_credentials,
             self.creds.credentials.user_id, resp['access'])
 
-        ec2_creds = self.non_admin_client.show_user_ec2_credentials(
+        ec2_creds = self.non_admin_users_client.show_user_ec2_credentials(
             self.creds.credentials.user_id, resp['access']
         )["credential"]
         for key in ['access', 'secret', 'user_id', 'tenant_id']:
@@ -100,14 +100,14 @@
     @test.idempotent_id('6aba0d4c-b76b-4e46-aa42-add79bc1551d')
     def test_delete_ec2_credentials(self):
         """Delete user ec2 credentials."""
-        resp = self.non_admin_client.create_user_ec2_credentials(
+        resp = self.non_admin_users_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
             tenant_id=self.creds.credentials.tenant_id)["credential"]
         access = resp['access']
-        self.non_admin_client.delete_user_ec2_credentials(
+        self.non_admin_users_client.delete_user_ec2_credentials(
             self.creds.credentials.user_id, access)
         self.assertRaises(
             lib_exc.NotFound,
-            self.non_admin_client.show_user_ec2_credentials,
+            self.non_admin_users_client.show_user_ec2_credentials,
             self.creds.credentials.user_id,
             access)
diff --git a/tempest/api/identity/v2/test_users.py b/tempest/api/identity/v2/test_users.py
index 98a2e68..a59a1a0 100644
--- a/tempest/api/identity/v2/test_users.py
+++ b/tempest/api/identity/v2/test_users.py
@@ -41,8 +41,9 @@
         # we need new non-admin Identity Client with new credentials, since
         # current non_admin_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
@@ -50,10 +51,10 @@
 
         # to change password back. important for allow_tenant_isolation = false
         self.addCleanup(
-            self.non_admin_client_for_cleanup.update_user_own_password,
+            self.non_admin_users_client_for_cleanup.update_user_own_password,
             user_id, original_password=new_pass, password=old_pass)
         # user updates own password
-        self.non_admin_client.update_user_own_password(
+        self.non_admin_users_client.update_user_own_password(
             user_id, password=new_pass, original_password=old_pass)
         # TODO(lbragstad): Sleeping after the response status has been checked
         # and the body loaded as JSON allows requests to fail-fast. The sleep
@@ -72,7 +73,7 @@
         # authorize with old token should lead to Unauthorized
         self.assertRaises(exceptions.Unauthorized,
                           self.non_admin_token_client.auth_token,
-                          self.non_admin_client.token)
+                          self.non_admin_users_client.token)
 
         # authorize with old password should lead to Unauthorized
         self.assertRaises(exceptions.Unauthorized,
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 18d0446..ade7b67 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -12,7 +12,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 from six import moves
 from tempest_lib import exceptions as lib_exc
 
@@ -22,8 +21,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class BaseImageTest(tempest.test.BaseTestCase):
     """Base test class for Image API tests."""
diff --git a/tempest/api/messaging/base.py b/tempest/api/messaging/base.py
index 528fbea..a324c37 100644
--- a/tempest/api/messaging/base.py
+++ b/tempest/api/messaging/base.py
@@ -13,16 +13,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from oslo_log import log as logging
-
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import test
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class BaseMessagingTest(test.BaseTestCase):
 
diff --git a/tempest/api/messaging/test_claims.py b/tempest/api/messaging/test_claims.py
index 57b8c7f..99edde1 100644
--- a/tempest/api/messaging/test_claims.py
+++ b/tempest/api/messaging/test_claims.py
@@ -13,8 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
-
 from six.moves.urllib import parse as urlparse
 from tempest_lib import decorators
 
@@ -24,7 +22,6 @@
 from tempest import test
 
 
-LOG = logging.getLogger(__name__)
 CONF = config.CONF
 
 
diff --git a/tempest/api/messaging/test_messages.py b/tempest/api/messaging/test_messages.py
index efbbf56..7f4182a 100644
--- a/tempest/api/messaging/test_messages.py
+++ b/tempest/api/messaging/test_messages.py
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
 
 from tempest.api.messaging import base
 from tempest.common.utils import data_utils
@@ -21,7 +20,6 @@
 from tempest import test
 
 
-LOG = logging.getLogger(__name__)
 CONF = config.CONF
 
 
diff --git a/tempest/api/messaging/test_queues.py b/tempest/api/messaging/test_queues.py
index df49663..dcb5450 100644
--- a/tempest/api/messaging/test_queues.py
+++ b/tempest/api/messaging/test_queues.py
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging
 
 from six import moves
 from tempest_lib import exceptions as lib_exc
@@ -24,9 +23,6 @@
 from tempest import test
 
 
-LOG = logging.getLogger(__name__)
-
-
 class TestQueues(base.BaseMessagingTest):
 
     @test.attr(type='smoke')
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 2a1776a..81337f3 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 import netaddr
-from oslo_log import log as logging
 from tempest_lib import exceptions as lib_exc
 
 from tempest.common.utils import data_utils
@@ -24,8 +23,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class BaseNetworkTest(tempest.test.BaseTestCase):
     """Base class for the Neutron tests
diff --git a/tempest/api/network/test_metering_extensions.py b/tempest/api/network/test_metering_extensions.py
index 007ba3b..299700f 100644
--- a/tempest/api/network/test_metering_extensions.py
+++ b/tempest/api/network/test_metering_extensions.py
@@ -12,16 +12,11 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-from oslo_log import log as logging
-
 from tempest.api.network import base
 from tempest.common.utils import data_utils
 from tempest import test
 
 
-LOG = logging.getLogger(__name__)
-
-
 class MeteringTestJSON(base.BaseAdminNetworkTest):
     """Tests the following operations in the Neutron API:
 
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 4968835..c93b5ed 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -12,7 +12,6 @@
 
 import os.path
 
-from oslo_log import log as logging
 from tempest_lib import exceptions as lib_exc
 import yaml
 
@@ -22,8 +21,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class BaseOrchestrationTest(tempest.test.BaseTestCase):
     """Base test case class for all Orchestration API tests."""
diff --git a/tempest/api/orchestration/stacks/test_environment.py b/tempest/api/orchestration/stacks/test_environment.py
index 0416bc7..9d2b425 100644
--- a/tempest/api/orchestration/stacks/test_environment.py
+++ b/tempest/api/orchestration/stacks/test_environment.py
@@ -10,8 +10,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
-
 from tempest.api.orchestration import base
 from tempest.common.utils import data_utils
 from tempest import config
@@ -19,7 +17,6 @@
 
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class StackEnvironmentTest(base.BaseOrchestrationTest):
diff --git a/tempest/api/orchestration/stacks/test_limits.py b/tempest/api/orchestration/stacks/test_limits.py
index bb5b89d..2acf97b 100644
--- a/tempest/api/orchestration/stacks/test_limits.py
+++ b/tempest/api/orchestration/stacks/test_limits.py
@@ -10,8 +10,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
-
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.orchestration import base
@@ -21,8 +19,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class TestServerStackLimits(base.BaseOrchestrationTest):
 
diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
index 4bc2c17..3be5bb6 100644
--- a/tempest/api/orchestration/stacks/test_non_empty_stack.py
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -10,8 +10,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
-
 from tempest.api.orchestration import base
 from tempest.common.utils import data_utils
 from tempest import config
@@ -19,8 +17,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class StacksTestJSON(base.BaseOrchestrationTest):
 
diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
index b4d7fa0..0400e76 100644
--- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -10,17 +10,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-
-import logging
-
 from tempest.api.orchestration import base
 from tempest.common.utils import data_utils
 from tempest import test
 
 
-LOG = logging.getLogger(__name__)
-
-
 class NovaKeyPairResourcesYAMLTest(base.BaseOrchestrationTest):
     _tpl_type = 'yaml'
     _resource = 'resources'
diff --git a/tempest/api/orchestration/stacks/test_soft_conf.py b/tempest/api/orchestration/stacks/test_soft_conf.py
index 34d93e4..ab45929 100644
--- a/tempest/api/orchestration/stacks/test_soft_conf.py
+++ b/tempest/api/orchestration/stacks/test_soft_conf.py
@@ -10,7 +10,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.orchestration import base
@@ -18,7 +17,6 @@
 from tempest import config
 from tempest import test
 
-LOG = logging.getLogger(__name__)
 CONF = config.CONF
 
 
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index f766b00..28463ab 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.py
@@ -10,16 +10,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest.api.orchestration import base
 from tempest.common.utils import data_utils
 from tempest import test
 
 
-LOG = logging.getLogger(__name__)
-
-
 class StacksTestJSON(base.BaseOrchestrationTest):
     empty_template = "HeatTemplateFormatVersion: '2012-12-12'\n"
 
diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index ae9a411..e51551b 100644
--- a/tempest/api/orchestration/stacks/test_volumes.py
+++ b/tempest/api/orchestration/stacks/test_volumes.py
@@ -10,8 +10,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
-
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.orchestration import base
@@ -21,7 +19,6 @@
 
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class CinderResourcesTest(base.BaseOrchestrationTest):
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index 8e43b00..60e6e6c 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -10,7 +10,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 import six
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
@@ -19,8 +18,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class VolumeMultiBackendV2Test(base.BaseVolumeAdminTest):
 
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index aa6bfdf..f2bf613 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -50,7 +50,7 @@
         snap_name = data_utils.rand_name(cls.__name__ + '-Snapshot')
         params = {cls.name_field: snap_name}
         cls.snapshot = cls.client.create_snapshot(
-            cls.volume['id'], **params)['snapshot']
+            volume_id=cls.volume['id'], **params)['snapshot']
         cls.client.wait_for_snapshot_status(cls.snapshot['id'],
                                             'available')
 
@@ -77,7 +77,7 @@
     def _create_reset_and_force_delete_temp_snapshot(self, status=None):
         # Create snapshot, reset snapshot status,
         # and force delete temp snapshot
-        temp_snapshot = self.create_snapshot(self.volume['id'])
+        temp_snapshot = self.create_snapshot(volume_id=self.volume['id'])
         if status:
             self.admin_snapshots_client.\
                 reset_snapshot_status(temp_snapshot['id'], status)
@@ -110,7 +110,7 @@
         status = 'error'
         progress_alias = self._get_progress_alias()
         self.client.update_snapshot_status(self.snapshot['id'],
-                                           status, progress)
+                                           status=status, progress=progress)
         snapshot_get = self.admin_snapshots_client.show_snapshot(
             self.snapshot['id'])['snapshot']
         self.assertEqual(status, snapshot_get['status'])
diff --git a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
index ce0b618..c66207f 100644
--- a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
@@ -52,14 +52,14 @@
         # NOTE(gfidente): no need to delete in tearDown as
         # they are created using utility wrapper methods.
         cls.volume = cls.create_volume()
-        cls.snapshot = cls.create_snapshot(cls.volume['id'])
+        cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id'])
 
     @test.attr(type='negative')
     @test.idempotent_id('02bbf63f-6c05-4357-9d98-2926a94064ff')
     def test_quota_volume_snapshots(self):
         self.assertRaises(lib_exc.OverLimit,
                           self.snapshots_client.create_snapshot,
-                          self.volume['id'])
+                          volume_id=self.volume['id'])
 
     @test.attr(type='negative')
     @test.idempotent_id('c99a1ca9-6cdf-498d-9fdf-25832babef27')
@@ -74,7 +74,7 @@
             **new_quota_set)
         self.assertRaises(lib_exc.OverLimit,
                           self.snapshots_client.create_snapshot,
-                          self.volume['id'])
+                          volume_id=self.volume['id'])
 
 
 class VolumeSnapshotNegativeV1TestJSON(VolumeSnapshotQuotasNegativeV2TestJSON):
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index ed34a9b..4b2d3f3 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 from tempest_lib import decorators
 
 from tempest.api.volume import base
@@ -22,7 +21,6 @@
 from tempest import test
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class VolumesBackupsV2Test(base.BaseVolumeAdminTest):
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index dc53450..cc906e5 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 from tempest_lib import exceptions as lib_exc
 
 from tempest.common import compute
@@ -24,8 +23,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class BaseVolumeTest(tempest.test.BaseTestCase):
     """Base test case class for all Cinder API tests."""
@@ -123,7 +120,7 @@
     def create_snapshot(cls, volume_id=1, **kwargs):
         """Wrapper utility that returns a test snapshot."""
         snapshot = cls.snapshots_client.create_snapshot(
-            volume_id, **kwargs)['snapshot']
+            volume_id=volume_id, **kwargs)['snapshot']
         cls.snapshots.append(snapshot)
         cls.snapshots_client.wait_for_snapshot_status(snapshot['id'],
                                                       'available')
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index b776494..38a5a80 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -15,15 +15,12 @@
 #    under the License.
 import operator
 
-from oslo_log import log as logging
 from testtools import matchers
 
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
 from tempest import test
 
-LOG = logging.getLogger(__name__)
-
 
 class VolumesV2ListTestJSON(base.BaseVolumeTest):
     # NOTE: This test creates a number of 1G volumes. To run successfully,
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 856adcc..c79235a 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -10,14 +10,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import test
 
-LOG = logging.getLogger(__name__)
 CONF = config.CONF
 
 
@@ -42,15 +39,15 @@
         self.volumes_client.detach_volume(volume_id)
         self.volumes_client.wait_for_volume_status(volume_id, 'available')
 
-    def _list_by_param_values_and_assert(self, params, with_detail=False):
+    def _list_by_param_values_and_assert(self, with_detail=False, **params):
         """list or list_details with given params and validates result."""
 
         if with_detail:
             fetched_snap_list = self.snapshots_client.list_snapshots(
-                detail=True, params=params)['snapshots']
+                detail=True, **params)['snapshots']
         else:
             fetched_snap_list = self.snapshots_client.list_snapshots(
-                params=params)['snapshots']
+                **params)['snapshots']
 
         # Validating params of fetched snapshots
         for snap in fetched_snap_list:
@@ -135,16 +132,16 @@
 
         # Verify list snapshots by display_name filter
         params = {self.name_field: snapshot[self.name_field]}
-        self._list_by_param_values_and_assert(params)
+        self._list_by_param_values_and_assert(**params)
 
         # Verify list snapshots by status filter
         params = {'status': 'available'}
-        self._list_by_param_values_and_assert(params)
+        self._list_by_param_values_and_assert(**params)
 
         # Verify list snapshots by status and display name filter
         params = {'status': 'available',
                   self.name_field: snapshot[self.name_field]}
-        self._list_by_param_values_and_assert(params)
+        self._list_by_param_values_and_assert(**params)
 
     @test.idempotent_id('220a1022-1fcd-4a74-a7bd-6b859156cda2')
     def test_snapshots_list_details_with_params(self):
@@ -157,14 +154,14 @@
 
         # Verify list snapshot details by display_name filter
         params = {self.name_field: snapshot[self.name_field]}
-        self._list_by_param_values_and_assert(params, with_detail=True)
+        self._list_by_param_values_and_assert(with_detail=True, **params)
         # Verify list snapshot details by status filter
         params = {'status': 'available'}
-        self._list_by_param_values_and_assert(params, with_detail=True)
+        self._list_by_param_values_and_assert(with_detail=True, **params)
         # Verify list snapshot details by status and display name filter
         params = {'status': 'available',
                   self.name_field: snapshot[self.name_field]}
-        self._list_by_param_values_and_assert(params, with_detail=True)
+        self._list_by_param_values_and_assert(with_detail=True, **params)
 
     @test.idempotent_id('677863d1-3142-456d-b6ac-9924f667a7f4')
     def test_volume_from_snapshot(self):
diff --git a/tempest/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
index b604360..d46c9b5 100644
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -37,7 +37,7 @@
         s_name = data_utils.rand_name('snap')
         self.assertRaises(lib_exc.NotFound,
                           self.snapshots_client.create_snapshot,
-                          str(uuid.uuid4()), display_name=s_name)
+                          volume_id=str(uuid.uuid4()), display_name=s_name)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('bb9da53e-d335-4309-9c15-7e76fd5e4d6d')
@@ -46,7 +46,7 @@
         s_name = data_utils.rand_name('snap')
         self.assertRaises(lib_exc.NotFound,
                           self.snapshots_client.create_snapshot,
-                          None, display_name=s_name)
+                          volume_id=None, display_name=s_name)
 
 
 class VolumesV1SnapshotNegativeTestJSON(VolumesV2SnapshotNegativeTestJSON):
diff --git a/tempest/clients.py b/tempest/clients.py
index 0507ee8..2c40d0c 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -71,6 +71,13 @@
 from tempest_lib.services.identity.v2.token_client import TokenClient
 from tempest_lib.services.identity.v3.token_client import V3TokenClient
 from tempest_lib.services.network.floating_ips_client import FloatingIPsClient
+from tempest_lib.services.network.metering_label_rules_client import \
+    MeteringLabelRulesClient
+from tempest_lib.services.network.metering_labels_client import \
+    MeteringLabelsClient
+from tempest_lib.services.network.networks_client import NetworksClient
+from tempest_lib.services.network.ports_client import PortsClient
+from tempest_lib.services.network.subnets_client import SubnetsClient
 
 from tempest.common import negative_rest_client
 from tempest import config
@@ -93,6 +100,8 @@
     RolesClient
 from tempest.services.identity.v2.json.tenants_client import \
     TenantsClient
+from tempest.services.identity.v2.json.users_client import \
+    UsersClient
 from tempest.services.identity.v3.json.credentials_client import \
     CredentialsClient as CredentialsV3Client
 from tempest.services.identity.v3.json.endpoints_client import \
@@ -112,19 +121,12 @@
     MessagingClient
 from tempest.services.network.json.agents_client import AgentsClient \
     as NetworkAgentsClient
-from tempest.services.network.json.metering_label_rules_client import \
-    MeteringLabelRulesClient
-from tempest.services.network.json.metering_labels_client import \
-    MeteringLabelsClient
 from tempest.services.network.json.network_client import NetworkClient
-from tempest.services.network.json.networks_client import NetworksClient
-from tempest.services.network.json.ports_client import PortsClient
 from tempest.services.network.json.quotas_client import QuotasClient \
     as NetworkQuotasClient
 from tempest.services.network.json.security_groups_client import \
     SecurityGroupsClient
 from tempest.services.network.json.subnetpools_client import SubnetpoolsClient
-from tempest.services.network.json.subnets_client import SubnetsClient
 from tempest.services.object_storage.account_client import AccountClient
 from tempest.services.object_storage.container_client import ContainerClient
 from tempest.services.object_storage.object_client import ObjectClient
@@ -484,6 +486,8 @@
                                             **params_v2_admin)
         self.roles_client = RolesClient(self.auth_provider,
                                         **params_v2_admin)
+        self.users_client = UsersClient(self.auth_provider,
+                                        **params_v2_admin)
         params_v2_public = params.copy()
         params_v2_public['endpoint_type'] = (
             CONF.identity.v2_public_endpoint_type)
@@ -494,6 +498,8 @@
                                                    **params_v2_public)
         self.roles_public_client = RolesClient(self.auth_provider,
                                                **params_v2_public)
+        self.users_public_client = UsersClient(self.auth_provider,
+                                               **params_v2_public)
         params_v3 = params.copy()
         params_v3['endpoint_type'] = CONF.identity.v3_endpoint_type
         # Clients below use the endpoint type of Keystone API v3
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 5a2713b..32d6ef1 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -85,8 +85,15 @@
 import argparse
 import netaddr
 import os
+import traceback
 
+from cliff import command
 from oslo_log import log as logging
+import tempest_lib.auth
+from tempest_lib.common.utils import data_utils
+import tempest_lib.exceptions
+from tempest_lib.services.network import networks_client
+from tempest_lib.services.network import subnets_client
 import yaml
 
 from tempest.common import identity
@@ -95,15 +102,16 @@
 from tempest.services.identity.v2.json import identity_client
 from tempest.services.identity.v2.json import roles_client
 from tempest.services.identity.v2.json import tenants_client
+from tempest.services.identity.v2.json import users_client
 from tempest.services.network.json import network_client
-from tempest.services.network.json import networks_client
-from tempest.services.network.json import subnets_client
-import tempest_lib.auth
-from tempest_lib.common.utils import data_utils
-import tempest_lib.exceptions
 
 LOG = None
 CONF = config.CONF
+DESCRIPTION = ('Create accounts.yaml file for concurrent test runs.%s'
+               'One primary user, one alt user, '
+               'one swift admin, one stack owner '
+               'and one admin (optionally) will be created '
+               'for each concurrent thread.' % os.linesep)
 
 
 def setup_logging():
@@ -154,6 +162,13 @@
         endpoint_type='adminURL',
         **params
     )
+    users_admin = users_client.UsersClient(
+        _auth,
+        CONF.identity.catalog_type,
+        CONF.identity.region,
+        endpoint_type='adminURL',
+        **params
+    )
     network_admin = None
     networks_admin = None
     subnets_admin = None
@@ -179,13 +194,14 @@
             CONF.network.region or CONF.identity.region,
             endpoint_type='adminURL',
             **params)
-    return (identity_admin, tenants_admin, roles_admin, neutron_iso_networks,
-            network_admin, networks_admin, subnets_admin)
+    return (identity_admin, tenants_admin, roles_admin, users_admin,
+            neutron_iso_networks, network_admin, networks_admin, subnets_admin)
 
 
 def create_resources(opts, resources):
-    (identity_admin, tenants_admin, roles_admin, neutron_iso_networks,
-     network_admin, networks_admin, subnets_admin) = get_admin_clients(opts)
+    (identity_admin, tenants_admin, roles_admin, users_admin,
+     neutron_iso_networks, network_admin, networks_admin,
+     subnets_admin) = get_admin_clients(opts)
     roles = roles_admin.list_roles()['roles']
     for u in resources['users']:
         u['role_ids'] = []
@@ -215,7 +231,7 @@
                 identity.get_user_by_username(tenants_admin,
                                               tenant['id'], u['name'])
             except tempest_lib.exceptions.NotFound:
-                identity_admin.create_user(
+                users_admin.create_user(
                     u['name'], u['pass'], tenant['id'],
                     "%s@%s" % (u['name'], tenant['id']),
                     enabled=True)
@@ -388,20 +404,7 @@
     LOG.info('%s generated successfully!' % opts.accounts)
 
 
-def get_options():
-    usage_string = ('tempest-account-generator [-h] <ARG> ...\n\n'
-                    'To see help on specific argument, do:\n'
-                    'tempest-account-generator <ARG> -h')
-    parser = argparse.ArgumentParser(
-        description='Create accounts.yaml file for concurrent test runs. '
-                    'One primary user, one alt user, '
-                    'one swift admin, one stack owner '
-                    'and one admin (optionally) will be created '
-                    'for each concurrent thread.',
-        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
-        usage=usage_string
-    )
-
+def _parser_add_args(parser):
     parser.add_argument('-c', '--config-file',
                         metavar='/etc/tempest.conf',
                         help='path to tempest config file')
@@ -438,16 +441,50 @@
                         metavar='accounts_file.yaml',
                         help='Output accounts yaml file')
 
+
+def get_options():
+    usage_string = ('tempest-account-generator [-h] <ARG> ...\n\n'
+                    'To see help on specific argument, do:\n'
+                    'tempest-account-generator <ARG> -h')
+    parser = argparse.ArgumentParser(
+        description=DESCRIPTION,
+        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+        usage=usage_string
+    )
+
+    _parser_add_args(parser)
     opts = parser.parse_args()
-    if opts.config_file:
-        config.CONF.set_config_path(opts.config_file)
     return opts
 
 
+class TempestAccountGenerator(command.Command):
+
+    def get_parser(self, prog_name):
+        parser = super(TempestAccountGenerator, self).get_parser(prog_name)
+        _parser_add_args(parser)
+        return parser
+
+    def take_action(self, parsed_args):
+        try:
+            return main(parsed_args)
+        except Exception:
+            LOG.exception("Failure generating test accounts.")
+            traceback.print_exc()
+            raise
+        return 0
+
+    def get_description(self):
+        return DESCRIPTION
+
+
 def main(opts=None):
-    if not opts:
-        opts = get_options()
     setup_logging()
+    if not opts:
+        LOG.warn("Use of: 'tempest-account-generator' is deprecated, "
+                 "please use: 'tempest account-generator'")
+        opts = get_options()
+    if opts.config_file:
+        config.CONF.set_config_path(opts.config_file)
     resources = generate_resources(opts)
     create_resources(opts, resources)
     dump_accounts(opts, resources)
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 8538509..8a47406 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -815,11 +815,14 @@
         self.client = manager.identity_client
 
 
-class UserService(IdentityService):
+class UserService(BaseService):
+
+    def __init__(self, manager, **kwargs):
+        super(UserService, self).__init__(kwargs)
+        self.client = manager.users_client
 
     def list(self):
-        client = self.client
-        users = client.list_users()['users']
+        users = self.client.list_users()['users']
 
         if not self.is_save_state:
             users = [user for user in users if user['id']
@@ -837,11 +840,10 @@
         return users
 
     def delete(self):
-        client = self.client
         users = self.list()
         for user in users:
             try:
-                client.delete_user(user['id'])
+                self.client.delete_user(user['id'])
             except Exception:
                 LOG.exception("Delete User exception.")
 
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 9d889bd..8012ad7 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -122,6 +122,7 @@
 from tempest_lib.services.compute import security_group_rules_client
 from tempest_lib.services.compute import security_groups_client
 from tempest_lib.services.compute import servers_client
+from tempest_lib.services.network import subnets_client
 import yaml
 
 from tempest.common import identity
@@ -130,9 +131,9 @@
 from tempest.services.identity.v2.json import identity_client
 from tempest.services.identity.v2.json import roles_client
 from tempest.services.identity.v2.json import tenants_client
+from tempest.services.identity.v2.json import users_client
 from tempest.services.image.v2.json import images_client
 from tempest.services.network.json import network_client
-from tempest.services.network.json import subnets_client
 from tempest.services.object_storage import container_client
 from tempest.services.object_storage import object_client
 from tempest.services.telemetry.json import alarming_client
@@ -213,6 +214,12 @@
             CONF.identity.region,
             endpoint_type='adminURL',
             **default_params_with_timeout_values)
+        self.users = users_client.UsersClient(
+            _auth,
+            CONF.identity.catalog_type,
+            CONF.identity.region,
+            endpoint_type='adminURL',
+            **default_params_with_timeout_values)
         self.servers = servers_client.ServersClient(_auth,
                                                     **compute_params)
         self.flavors = flavors_client.FlavorsClient(_auth,
@@ -375,12 +382,12 @@
             LOG.error("Tenant: %s - not found" % u['tenant'])
             continue
         try:
-            identity.get_user_by_username(admin.identity,
+            identity.get_user_by_username(admin.tenants,
                                           tenant['id'], u['name'])
             LOG.warning("User '%s' already exists in this environment"
                         % u['name'])
         except lib_exc.NotFound:
-            admin.identity.create_user(
+            admin.users.create_user(
                 u['name'], u['pass'], tenant['id'],
                 "%s@%s" % (u['name'], tenant['id']),
                 enabled=True)
@@ -391,9 +398,9 @@
     for user in users:
         tenant_id = identity.get_tenant_by_name(admin.tenants,
                                                 user['tenant'])['id']
-        user_id = identity.get_user_by_username(admin.identity,
+        user_id = identity.get_user_by_username(admin.tenants,
                                                 tenant_id, user['name'])['id']
-        admin.identity.delete_user(user_id)
+        admin.users.delete_user(user_id)
 
 
 def collect_users(users):
@@ -404,7 +411,7 @@
         tenant = identity.get_tenant_by_name(admin.tenants, u['tenant'])
         u['tenant_id'] = tenant['id']
         USERS[u['name']] = u
-        body = identity.get_user_by_username(admin.identity,
+        body = identity.get_user_by_username(admin.tenants,
                                              tenant['id'], u['name'])
         USERS[u['name']]['id'] = body['id']
 
@@ -458,7 +465,7 @@
         LOG.info("checking users")
         for name, user in six.iteritems(self.users):
             client = keystone_admin()
-            found = client.identity.show_user(user['id'])['user']
+            found = client.users.show_user(user['id'])['user']
             self.assertEqual(found['name'], user['name'])
             self.assertEqual(found['tenantId'], user['tenant_id'])
 
@@ -1133,6 +1140,8 @@
 
 
 def main():
+    print("Javelin is deprecated and will be removed from Tempest in the "
+          "future.")
     global RES
     get_options()
     setup_logging()
diff --git a/tempest/cmd/main.py b/tempest/cmd/main.py
index 577df9b..acd97a8 100644
--- a/tempest/cmd/main.py
+++ b/tempest/cmd/main.py
@@ -28,6 +28,7 @@
             description='Tempest cli application',
             version=version.VersionInfo('tempest').version_string(),
             command_manager=commandmanager.CommandManager('tempest.cm'),
+            deferred_help=True,
             )
 
     def initialize_app(self, argv):
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
old mode 100755
new mode 100644
index 9c8e2a0..5d867df
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -15,10 +15,13 @@
 #    under the License.
 
 import argparse
+import httplib2
 import os
 import sys
+import traceback
 
-import httplib2
+from cliff import command
+from oslo_log import log as logging
 from oslo_serialization import jsonutils as json
 from six import moves
 from six.moves.urllib import parse as urlparse
@@ -31,6 +34,8 @@
 CONF = config.CONF
 CONF_PARSER = None
 
+LOG = logging.getLogger(__name__)
+
 
 def _get_config_file():
     default_config_dir = os.path.join(os.path.abspath(
@@ -310,8 +315,7 @@
     return avail_services
 
 
-def parse_args():
-    parser = argparse.ArgumentParser()
+def _parser_add_args(parser):
     parser.add_argument('-u', '--update', action='store_true',
                         help='Update the config file with results from api '
                              'queries. This assumes whatever is set in the '
@@ -329,13 +333,21 @@
     parser.add_argument('-r', '--replace-ext', action='store_true',
                         help="If specified the all option will be replaced "
                              "with a full list of extensions")
-    args = parser.parse_args()
-    return args
 
 
-def main():
+def parse_args():
+    parser = argparse.ArgumentParser()
+    _parser_add_args(parser)
+    opts = parser.parse_args()
+    return opts
+
+
+def main(opts=None):
     print('Running config verification...')
-    opts = parse_args()
+    if opts is None:
+        print("Use of: 'verify-tempest-config' is deprecated, "
+              "please use: 'tempest verify-config'")
+        opts = parse_args()
     update = opts.update
     replace = opts.replace_ext
     global CONF_PARSER
@@ -373,5 +385,22 @@
         icreds.clear_creds()
 
 
+class TempestVerifyConfig(command.Command):
+    """Verify your current tempest configuration"""
+
+    def get_parser(self, prog_name):
+        parser = super(TempestVerifyConfig, self).get_parser(prog_name)
+        _parser_add_args(parser)
+        return parser
+
+    def take_action(self, parsed_args):
+        try:
+            return main(parsed_args)
+        except Exception:
+            LOG.exception("Failure verifying configuration.")
+            traceback.print_exc()
+            raise
+        return 0
+
 if __name__ == "__main__":
     main()
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 6e6ada8..d57bae3 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -55,10 +55,13 @@
     kwargs = fixed_network.set_networks_kwarg(
         tenant_network, kwargs) or {}
 
+    multiple_create_request = (max(kwargs.get('min_count', 0),
+                                   kwargs.get('max_count', 0)) > 1)
+
     if CONF.validation.run_validation and validatable:
         # As a first implementation, multiple pingable or sshable servers will
         # not be supported
-        if 'min_count' in kwargs or 'max_count' in kwargs:
+        if multiple_create_request:
             msg = ("Multiple pingable or sshable servers not supported at "
                    "this stage.")
             raise ValueError(msg)
@@ -112,7 +115,7 @@
 
     # handle the case of multiple servers
     servers = []
-    if 'min_count' in kwargs or 'max_count' in kwargs:
+    if multiple_create_request:
         # Get servers created which name match with name param.
         body_servers = clients.servers_client.list_servers()
         servers = \
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
index 5d15988..6df7eb2 100644
--- a/tempest/common/cred_client.py
+++ b/tempest/common/cred_client.py
@@ -32,16 +32,17 @@
     """
 
     def __init__(self, identity_client, projects_client=None,
-                 roles_client=None):
+                 roles_client=None, users_client=None):
         # The client implies version and credentials
         self.identity_client = identity_client
         # this is temporary until the v3 project client is
         # separated, then projects_client will become mandatory
         self.projects_client = projects_client or identity_client
         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.identity_client.create_user(
+        user = self.users_client.create_user(
             username, password, project['id'], email)
         if 'user' in user:
             user = user['user']
@@ -87,7 +88,7 @@
         pass
 
     def delete_user(self, user_id):
-        self.identity_client.delete_user(user_id)
+        self.users_client.delete_user(user_id)
 
     def _list_roles(self):
         roles = self.roles_client.list_roles()['roles']
@@ -96,10 +97,12 @@
 
 class V2CredsClient(CredsClient):
 
-    def __init__(self, identity_client, projects_client, roles_client):
+    def __init__(self, identity_client, projects_client, roles_client,
+                 users_client):
         super(V2CredsClient, self).__init__(identity_client,
                                             projects_client,
-                                            roles_client)
+                                            roles_client,
+                                            users_client)
 
     def create_project(self, name, description):
         tenant = self.projects_client.create_tenant(
@@ -165,8 +168,10 @@
 def get_creds_client(identity_client,
                      projects_client=None,
                      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)
+        return V2CredsClient(identity_client, projects_client, roles_client,
+                             users_client)
     else:
         return V3CredsClient(identity_client, project_domain_name)
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index aa237e0..9dd89ea 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -14,14 +14,11 @@
 
 import abc
 
-from oslo_log import log as logging
 import six
 from tempest_lib import auth
 
 from tempest import exceptions
 
-LOG = logging.getLogger(__name__)
-
 
 @six.add_metaclass(abc.ABCMeta)
 class CredentialProvider(object):
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index 5d290d4..24c1198 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -12,7 +12,6 @@
 #    limitations under the License.
 
 from oslo_concurrency import lockutils
-from oslo_log import log as logging
 from tempest_lib import auth
 
 from tempest import clients
@@ -23,7 +22,6 @@
 from tempest import exceptions
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 """This module provides factories of credential and credential providers
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index 0af07f0..95ad229 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -59,6 +59,7 @@
         self.default_admin_creds = admin_creds
         (self.identity_admin_client, self.tenants_admin_client,
          self.roles_admin_client,
+         self.users_admin_client,
          self.network_admin_client,
          self.networks_admin_client,
          self.subnets_admin_client,
@@ -75,6 +76,7 @@
             self.identity_admin_client,
             self.tenants_admin_client,
             self.roles_admin_client,
+            self.users_admin_client,
             self.creds_domain_name)
 
     def _get_admin_clients(self):
@@ -87,10 +89,11 @@
         os = clients.Manager(self.default_admin_creds)
         if self.identity_version == 'v2':
             return (os.identity_client, os.tenants_client, os.roles_client,
-                    os.network_client, os.networks_client, os.subnets_client,
-                    os.ports_client, os.security_groups_client)
+                    os.users_client, os.network_client, os.networks_client,
+                    os.subnets_client, os.ports_client,
+                    os.security_groups_client)
         else:
-            return (os.identity_v3_client, None, None, os.network_client,
+            return (os.identity_v3_client, None, None, None, os.network_client,
                     os.networks_client, os.subnets_client, os.ports_client,
                     os.security_groups_client)
 
diff --git a/tempest/common/generator/base_generator.py b/tempest/common/generator/base_generator.py
index a66002f..3a51f2e 100644
--- a/tempest/common/generator/base_generator.py
+++ b/tempest/common/generator/base_generator.py
@@ -17,11 +17,8 @@
 import functools
 
 import jsonschema
-from oslo_log import log as logging
 import six
 
-LOG = logging.getLogger(__name__)
-
 
 def _check_for_expected_result(name, schema):
     expected_result = None
diff --git a/tempest/common/generator/negative_generator.py b/tempest/common/generator/negative_generator.py
index 17997a5..67ace54 100644
--- a/tempest/common/generator/negative_generator.py
+++ b/tempest/common/generator/negative_generator.py
@@ -15,13 +15,9 @@
 
 import copy
 
-from oslo_log import log as logging
-
 import tempest.common.generator.base_generator as base
 import tempest.common.generator.valid_generator as valid
 
-LOG = logging.getLogger(__name__)
-
 
 class NegativeTestGenerator(base.BasicGeneratorSet):
     @base.generator_type("string")
diff --git a/tempest/common/generator/valid_generator.py b/tempest/common/generator/valid_generator.py
index 2213b4a..3070489 100644
--- a/tempest/common/generator/valid_generator.py
+++ b/tempest/common/generator/valid_generator.py
@@ -13,15 +13,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 import six
 
 import tempest.common.generator.base_generator as base
 
 
-LOG = logging.getLogger(__name__)
-
-
 class ValidTestGenerator(base.BasicGeneratorSet):
     @base.generator_type("string")
     @base.simple_generator
diff --git a/tempest/config.py b/tempest/config.py
index 92123b9..6942172 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -1046,7 +1046,8 @@
     cfg.StrOpt('img_dir',
                default='/opt/stack/new/devstack/files/images/'
                'cirros-0.3.1-x86_64-uec',
-               help='Directory containing image files'),
+               help='Directory containing image files',
+               deprecated_for_removal=True),
     cfg.StrOpt('img_file', deprecated_name='qcow2_img_file',
                default='cirros-0.3.1-x86_64-disk.img',
                help='Image file name'),
@@ -1060,13 +1061,16 @@
                 'Use for custom images which require them'),
     cfg.StrOpt('ami_img_file',
                default='cirros-0.3.1-x86_64-blank.img',
-               help='AMI image file name'),
+               help='AMI image file name',
+               deprecated_for_removal=True),
     cfg.StrOpt('ari_img_file',
                default='cirros-0.3.1-x86_64-initrd',
-               help='ARI image file name'),
+               help='ARI image file name',
+               deprecated_for_removal=True),
     cfg.StrOpt('aki_img_file',
                default='cirros-0.3.1-x86_64-vmlinuz',
-               help='AKI image file name'),
+               help='AKI image file name',
+               deprecated_for_removal=True),
     cfg.IntOpt(
         'large_ops_number',
         default=0,
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index 1dad3ba..88598de 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -185,7 +185,8 @@
             # the end of a method
             return
 
-        if 'self.get(' not in line:
+        if 'self.get(' not in line and ('self.show_resource(' not in line and
+                                        'self.list_resources(' not in line):
             continue
 
         if METHOD_GET_RESOURCE.match(logical_line):
@@ -211,7 +212,7 @@
             # the end of a method
             return
 
-        if 'self.delete(' not in line:
+        if 'self.delete(' not in line and 'self.delete_resource(' not in line:
             continue
 
         if METHOD_DELETE_RESOURCE.match(logical_line):
diff --git a/tempest/hacking/ignored_list_T110.txt b/tempest/hacking/ignored_list_T110.txt
index 8de3151..ce69931 100644
--- a/tempest/hacking/ignored_list_T110.txt
+++ b/tempest/hacking/ignored_list_T110.txt
@@ -6,3 +6,4 @@
 ./tempest/services/volume/base/base_qos_client.py
 ./tempest/services/volume/base/base_backups_client.py
 ./tempest/services/baremetal/base.py
+./tempest/services/network/json/network_client.py
diff --git a/tempest/hacking/ignored_list_T111.txt b/tempest/hacking/ignored_list_T111.txt
index 8017e76..8130c85 100644
--- a/tempest/hacking/ignored_list_T111.txt
+++ b/tempest/hacking/ignored_list_T111.txt
@@ -1 +1,3 @@
 ./tempest/services/baremetal/base.py
+./tempest/services/network/json/agents_client.py
+./tempest/services/network/json/quotas_client.py
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 62c0262..97a755d 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -13,17 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest.common import tempest_fixtures as fixtures
 from tempest.common.utils import data_utils
 from tempest.scenario import manager
 from tempest import test
 
 
-LOG = logging.getLogger(__name__)
-
-
 class TestAggregatesBasicOps(manager.ScenarioTest):
     """Creates an aggregate within an availability zone
 
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index b549ecb..402077f 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 from tempest_lib import exceptions as lib_exc
 
 from tempest.common import fixed_network
@@ -26,9 +25,6 @@
 CONF = config.CONF
 
 
-LOG = logging.getLogger(__name__)
-
-
 class TestLargeOpsScenario(manager.ScenarioTest):
 
     """Test large operations.
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 2ef3cee..d9c6924 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest.common import custom_matchers
 from tempest.common import waiters
 from tempest import config
@@ -24,8 +22,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class TestMinimumBasicScenario(manager.ScenarioTest):
 
@@ -51,13 +47,6 @@
 
     """
 
-    def _wait_for_server_status(self, server, status):
-        server_id = server['id']
-        # Raise on error defaults to True, which is consistent with the
-        # original function from scenario tests here
-        waiters.wait_for_server_status(self.servers_client,
-                                       server_id, status)
-
     def nova_list(self):
         servers = self.servers_client.list_servers()
         # The list servers in the compute client is inconsistent...
@@ -85,7 +74,8 @@
 
     def nova_reboot(self, server):
         self.servers_client.reboot_server(server['id'], type='SOFT')
-        self._wait_for_server_status(server, 'ACTIVE')
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'ACTIVE')
 
     def check_partitions(self):
         # NOTE(andreaf) The device name may be different on different guest OS
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index d6dd6f3..2cbe6dc 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 import testtools
 
 from tempest.common.utils import data_utils
@@ -23,7 +22,6 @@
 from tempest import test
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class TestNetworkAdvancedServerOps(manager.NetworkScenarioTest):
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 40c7680..cc28873 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -14,7 +14,6 @@
 #    under the License.
 import functools
 
-from oslo_log import log as logging
 import six
 
 from tempest import config
@@ -23,7 +22,6 @@
 
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class TestGettingAddress(manager.NetworkScenarioTest):
diff --git a/tempest/scenario/test_object_storage_basic_ops.py b/tempest/scenario/test_object_storage_basic_ops.py
index 98dd705..63ffa0b 100644
--- a/tempest/scenario/test_object_storage_basic_ops.py
+++ b/tempest/scenario/test_object_storage_basic_ops.py
@@ -13,16 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest import config
 from tempest.scenario import manager
 from tempest import test
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class TestObjectStorageBasicOps(manager.ObjectStorageScenarioTest):
     """Test swift basic ops.
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 783b740..8375d05 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest import clients
 from tempest.common.utils import data_utils
 from tempest import config
@@ -23,8 +21,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class TestSecurityGroupsBasicOps(manager.NetworkScenarioTest):
 
@@ -137,6 +133,9 @@
             msg = ('Either tenant_networks_reachable must be "true", or '
                    'public_network_id must be defined.')
             raise cls.skipException(msg)
+        if not test.is_extension_enabled('security-group', 'network'):
+            msg = "security-group extension not enabled."
+            raise cls.skipException(msg)
 
     @classmethod
     def setup_credentials(cls):
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index f21ff4f..0cf72c3 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -14,8 +14,6 @@
 #    under the License.
 
 
-from oslo_log import log as logging
-
 from tempest import config
 from tempest import exceptions
 from tempest.scenario import manager
@@ -23,8 +21,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class TestServerMultinode(manager.ScenarioTest):
     """This is a set of tests specific to multinode testing."""
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index faae800..8183ce3 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -67,7 +67,7 @@
     def _create_volume_snapshot(self, volume):
         snapshot_name = data_utils.rand_name('scenario-snapshot')
         snapshot = self.snapshots_client.create_snapshot(
-            volume['id'], display_name=snapshot_name)['snapshot']
+            volume_id=volume['id'], display_name=snapshot_name)['snapshot']
 
         def cleaner():
             self.snapshots_client.delete_snapshot(snapshot['id'])
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index ff6c838..0ff59d5 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -26,67 +26,6 @@
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
 
-    def create_user(self, name, password, tenant_id, email, **kwargs):
-        """Create a user."""
-        post_body = {
-            'name': name,
-            'password': password,
-            'email': email
-        }
-        if tenant_id is not None:
-            post_body['tenantId'] = tenant_id
-        if kwargs.get('enabled') is not None:
-            post_body['enabled'] = kwargs.get('enabled')
-        post_body = json.dumps({'user': post_body})
-        resp, body = self.post('users', post_body)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def update_user(self, user_id, **kwargs):
-        """Updates a user."""
-        put_body = json.dumps({'user': kwargs})
-        resp, body = self.put('users/%s' % user_id, put_body)
-        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):
-        """Delete a user."""
-        resp, body = self.delete("users/%s" % user_id)
-        self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
-
-    def list_users(self):
-        """Get the list of users."""
-        resp, body = self.get("users")
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def enable_disable_user(self, user_id, **kwargs):
-        """Enables or disables a user.
-
-        Available params: see http://developer.openstack.org/
-                              api-ref-identity-v2-ext.html#enableUser
-        """
-        # NOTE: The URL (users/<id>/enabled) is different from the api-site
-        # one (users/<id>/OS-KSADM/enabled) , but they are the same API
-        # because of the fact that in keystone/contrib/admin_crud/core.py
-        # both api use same action='set_user_enabled'
-        put_body = json.dumps({'user': kwargs})
-        resp, body = self.put('users/%s/enabled' % user_id, put_body)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
     def show_token(self, token_id):
         """Get token details."""
         resp, body = self.get("tokens/%s" % token_id)
@@ -164,66 +103,9 @@
         self.expected_success(204, resp.status)
         return service_client.ResponseBody(resp, body)
 
-    def update_user_password(self, user_id, **kwargs):
-        """Update User Password."""
-        # TODO(piyush): Current api-site doesn't contain this API description.
-        # After fixing the api-site, we need to fix here also for putting the
-        # link to api-site.
-        # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524147
-        put_body = json.dumps({'user': kwargs})
-        resp, body = self.put('users/%s/OS-KSADM/password' % user_id, put_body)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def update_user_own_password(self, user_id, **kwargs):
-        """User updates own password"""
-        # TODO(piyush): Current api-site doesn't contain this API description.
-        # After fixing the api-site, we need to fix here also for putting the
-        # link to api-site.
-        # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524153
-        # NOTE: This API is used for updating user password by itself.
-        # Ref: http://lists.openstack.org/pipermail/openstack-dev/2015-December
-        #      /081803.html
-        patch_body = json.dumps({'user': kwargs})
-        resp, body = self.patch('OS-KSCRUD/users/%s' % user_id, patch_body)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
     def list_extensions(self):
         """List all the extensions."""
         resp, body = self.get('/extensions')
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
-
-    def create_user_ec2_credentials(self, user_id, **kwargs):
-        # TODO(piyush): Current api-site doesn't contain this API description.
-        # After fixing the api-site, we need to fix here also for putting the
-        # link to api-site.
-        post_body = json.dumps(kwargs)
-        resp, body = self.post('/users/%s/credentials/OS-EC2' % user_id,
-                               post_body)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def delete_user_ec2_credentials(self, user_id, access):
-        resp, body = self.delete('/users/%s/credentials/OS-EC2/%s' %
-                                 (user_id, access))
-        self.expected_success(204, resp.status)
-        return service_client.ResponseBody(resp, body)
-
-    def list_user_ec2_credentials(self, user_id):
-        resp, body = self.get('/users/%s/credentials/OS-EC2' % user_id)
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
-
-    def show_user_ec2_credentials(self, user_id, access):
-        resp, body = self.get('/users/%s/credentials/OS-EC2/%s' %
-                              (user_id, access))
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/users_client.py b/tempest/services/identity/v2/json/users_client.py
new file mode 100644
index 0000000..5327638
--- /dev/null
+++ b/tempest/services/identity/v2/json/users_client.py
@@ -0,0 +1,137 @@
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_serialization import jsonutils as json
+
+from tempest.common import service_client
+
+
+class UsersClient(service_client.ServiceClient):
+    api_version = "v2.0"
+
+    def create_user(self, name, password, tenant_id, email, **kwargs):
+        """Create a user."""
+        post_body = {
+            'name': name,
+            'password': password,
+            'email': email
+        }
+        if tenant_id is not None:
+            post_body['tenantId'] = tenant_id
+        if kwargs.get('enabled') is not None:
+            post_body['enabled'] = kwargs.get('enabled')
+        post_body = json.dumps({'user': post_body})
+        resp, body = self.post('users', post_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def update_user(self, user_id, **kwargs):
+        """Updates a user."""
+        put_body = json.dumps({'user': kwargs})
+        resp, body = self.put('users/%s' % user_id, put_body)
+        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):
+        """Delete a user."""
+        resp, body = self.delete("users/%s" % user_id)
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def list_users(self):
+        """Get the list of users."""
+        resp, body = self.get("users")
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def enable_disable_user(self, user_id, **kwargs):
+        """Enables or disables a user.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-identity-v2-ext.html#enableUser
+        """
+        # NOTE: The URL (users/<id>/enabled) is different from the api-site
+        # one (users/<id>/OS-KSADM/enabled) , but they are the same API
+        # because of the fact that in keystone/contrib/admin_crud/core.py
+        # both api use same action='set_user_enabled'
+        put_body = json.dumps({'user': kwargs})
+        resp, body = self.put('users/%s/enabled' % user_id, put_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 User Password."""
+        # TODO(piyush): Current api-site doesn't contain this API description.
+        # After fixing the api-site, we need to fix here also for putting the
+        # link to api-site.
+        # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524147
+        put_body = json.dumps({'user': kwargs})
+        resp, body = self.put('users/%s/OS-KSADM/password' % user_id, put_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def update_user_own_password(self, user_id, **kwargs):
+        """User updates own password"""
+        # TODO(piyush): Current api-site doesn't contain this API description.
+        # After fixing the api-site, we need to fix here also for putting the
+        # link to api-site.
+        # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524153
+        # NOTE: This API is used for updating user password by itself.
+        # Ref: http://lists.openstack.org/pipermail/openstack-dev/2015-December
+        #      /081803.html
+        patch_body = json.dumps({'user': kwargs})
+        resp, body = self.patch('OS-KSCRUD/users/%s' % user_id, patch_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def create_user_ec2_credentials(self, user_id, **kwargs):
+        # TODO(piyush): Current api-site doesn't contain this API description.
+        # After fixing the api-site, we need to fix here also for putting the
+        # link to api-site.
+        post_body = json.dumps(kwargs)
+        resp, body = self.post('/users/%s/credentials/OS-EC2' % user_id,
+                               post_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def delete_user_ec2_credentials(self, user_id, access):
+        resp, body = self.delete('/users/%s/credentials/OS-EC2/%s' %
+                                 (user_id, access))
+        self.expected_success(204, resp.status)
+        return service_client.ResponseBody(resp, body)
+
+    def list_user_ec2_credentials(self, user_id):
+        resp, body = self.get('/users/%s/credentials/OS-EC2' % user_id)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
+
+    def show_user_ec2_credentials(self, user_id, access):
+        resp, body = self.get('/users/%s/credentials/OS-EC2/%s' %
+                              (user_id, access))
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/network/json/metering_label_rules_client.py b/tempest/services/network/json/metering_label_rules_client.py
deleted file mode 100644
index 374a89c..0000000
--- a/tempest/services/network/json/metering_label_rules_client.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.services.network.json import base
-
-
-class MeteringLabelRulesClient(base.BaseNetworkClient):
-
-    def create_metering_label_rule(self, **kwargs):
-        uri = '/metering/metering-label-rules'
-        post_data = {'metering_label_rule': kwargs}
-        return self.create_resource(uri, post_data)
-
-    def show_metering_label_rule(self, metering_label_rule_id, **fields):
-        uri = '/metering/metering-label-rules/%s' % metering_label_rule_id
-        return self.show_resource(uri, **fields)
-
-    def delete_metering_label_rule(self, metering_label_rule_id):
-        uri = '/metering/metering-label-rules/%s' % metering_label_rule_id
-        return self.delete_resource(uri)
-
-    def list_metering_label_rules(self, **filters):
-        uri = '/metering/metering-label-rules'
-        return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/json/metering_labels_client.py b/tempest/services/network/json/metering_labels_client.py
deleted file mode 100644
index 2e5cdae..0000000
--- a/tempest/services/network/json/metering_labels_client.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.services.network.json import base
-
-
-class MeteringLabelsClient(base.BaseNetworkClient):
-
-    def create_metering_label(self, **kwargs):
-        uri = '/metering/metering-labels'
-        post_data = {'metering_label': kwargs}
-        return self.create_resource(uri, post_data)
-
-    def show_metering_label(self, metering_label_id, **fields):
-        uri = '/metering/metering-labels/%s' % metering_label_id
-        return self.show_resource(uri, **fields)
-
-    def delete_metering_label(self, metering_label_id):
-        uri = '/metering/metering-labels/%s' % metering_label_id
-        return self.delete_resource(uri)
-
-    def list_metering_labels(self, **filters):
-        uri = '/metering/metering-labels'
-        return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/json/networks_client.py b/tempest/services/network/json/networks_client.py
deleted file mode 100644
index 2907d44..0000000
--- a/tempest/services/network/json/networks_client.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.services.network.json import base
-
-
-class NetworksClient(base.BaseNetworkClient):
-
-    def create_network(self, **kwargs):
-        uri = '/networks'
-        post_data = {'network': kwargs}
-        return self.create_resource(uri, post_data)
-
-    def update_network(self, network_id, **kwargs):
-        uri = '/networks/%s' % network_id
-        post_data = {'network': kwargs}
-        return self.update_resource(uri, post_data)
-
-    def show_network(self, network_id, **fields):
-        uri = '/networks/%s' % network_id
-        return self.show_resource(uri, **fields)
-
-    def delete_network(self, network_id):
-        uri = '/networks/%s' % network_id
-        return self.delete_resource(uri)
-
-    def list_networks(self, **filters):
-        uri = '/networks'
-        return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/json/ports_client.py b/tempest/services/network/json/ports_client.py
deleted file mode 100644
index d52d65e..0000000
--- a/tempest/services/network/json/ports_client.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.services.network.json import base
-
-
-class PortsClient(base.BaseNetworkClient):
-
-    def create_port(self, **kwargs):
-        uri = '/ports'
-        post_data = {'port': kwargs}
-        return self.create_resource(uri, post_data)
-
-    def update_port(self, port_id, **kwargs):
-        uri = '/ports/%s' % port_id
-        post_data = {'port': kwargs}
-        return self.update_resource(uri, post_data)
-
-    def show_port(self, port_id, **fields):
-        uri = '/ports/%s' % port_id
-        return self.show_resource(uri, **fields)
-
-    def delete_port(self, port_id):
-        uri = '/ports/%s' % port_id
-        return self.delete_resource(uri)
-
-    def list_ports(self, **filters):
-        uri = '/ports'
-        return self.list_resources(uri, **filters)
diff --git a/tempest/services/network/json/subnets_client.py b/tempest/services/network/json/subnets_client.py
deleted file mode 100644
index 957b606..0000000
--- a/tempest/services/network/json/subnets_client.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.services.network.json import base
-
-
-class SubnetsClient(base.BaseNetworkClient):
-
-    def create_subnet(self, **kwargs):
-        uri = '/subnets'
-        post_data = {'subnet': kwargs}
-        return self.create_resource(uri, post_data)
-
-    def update_subnet(self, subnet_id, **kwargs):
-        uri = '/subnets/%s' % subnet_id
-        post_data = {'subnet': kwargs}
-        return self.update_resource(uri, post_data)
-
-    def show_subnet(self, subnet_id, **fields):
-        uri = '/subnets/%s' % subnet_id
-        return self.show_resource(uri, **fields)
-
-    def delete_subnet(self, subnet_id):
-        uri = '/subnets/%s' % subnet_id
-        return self.delete_resource(uri)
-
-    def list_subnets(self, **filters):
-        uri = '/subnets'
-        return self.list_resources(uri, **filters)
diff --git a/tempest/services/volume/base/base_snapshots_client.py b/tempest/services/volume/base/base_snapshots_client.py
index fb705e1..1388e9c 100644
--- a/tempest/services/volume/base/base_snapshots_client.py
+++ b/tempest/services/volume/base/base_snapshots_client.py
@@ -29,7 +29,7 @@
 
     create_resp = 200
 
-    def list_snapshots(self, detail=False, params=None):
+    def list_snapshots(self, detail=False, **params):
         """List all the snapshot."""
         url = 'snapshots'
         if detail:
@@ -50,17 +50,13 @@
         self.expected_success(200, resp.status)
         return service_client.ResponseBody(resp, body)
 
-    def create_snapshot(self, volume_id, **kwargs):
+    def create_snapshot(self, **kwargs):
         """Creates a new snapshot.
 
-        volume_id(Required): id of the volume.
-        force: Create a snapshot even if the volume attached (Default=False)
-        display_name: Optional snapshot Name.
-        display_description: User friendly snapshot description.
+        Available params: see http://developer.openstack.org/
+                              api-ref-blockstorage-v2.html#createSnapshot
         """
-        post_body = {'volume_id': volume_id}
-        post_body.update(kwargs)
-        post_body = json.dumps({'snapshot': post_body})
+        post_body = json.dumps({'snapshot': kwargs})
         resp, body = self.post('snapshots', post_body)
         body = json.loads(body)
         self.expected_success(self.create_resp, resp.status)
@@ -136,13 +132,14 @@
         self.expected_success(202, resp.status)
         return service_client.ResponseBody(resp, body)
 
-    def update_snapshot_status(self, snapshot_id, status, progress):
+    def update_snapshot_status(self, snapshot_id, **kwargs):
         """Update the specified snapshot's status."""
-        post_body = {
-            'status': status,
-            'progress': progress
-        }
-        post_body = json.dumps({'os-update_snapshot_status': post_body})
+        # TODO(gmann): api-site doesn't contain doc ref
+        # for this API. After fixing the api-site, we need to
+        # add the link here.
+        # Bug https://bugs.launchpad.net/openstack-api-site/+bug/1532645
+
+        post_body = json.dumps({'os-update_snapshot_status': kwargs})
         url = 'snapshots/%s/action' % str(snapshot_id)
         resp, body = self.post(url, post_body)
         self.expected_success(202, resp.status)
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index 5c25e32..1c1fb46 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -69,11 +69,11 @@
         except Exception:
             pass
 
-    users = admin_manager.identity_client.list_users()['users']
+    users = admin_manager.users_client.list_users()['users']
     LOG.info("Cleanup::remove %s users" % len(users))
     for user in users:
         if user['name'].startswith("stress_user"):
-            admin_manager.identity_client.delete_user(user['id'])
+            admin_manager.users_client.delete_user(user['id'])
     tenants = admin_manager.tenants_client.list_tenants()['tenants']
     LOG.info("Cleanup::remove %s tenants" % len(tenants))
     for tenant in tenants:
@@ -84,7 +84,7 @@
     # volume deletion may block
 
     _, snaps = admin_manager.snapshots_client.list_snapshots(
-        params={"all_tenants": True})['snapshots']
+        all_tenants=True)['snapshots']
     LOG.info("Cleanup::remove %s snapshots" % len(snaps))
     for v in snaps:
         try:
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index a3e1ea3..6531059 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -148,12 +148,15 @@
                     identity_client = admin_manager.identity_client
                     projects_client = admin_manager.tenants_client
                     roles_client = admin_manager.roles_client
+                    users_client = admin_manager.users_client
                 else:
                     identity_client = admin_manager.identity_v3_client
                     projects_client = None
                     roles_client = None
+                    users_client = None
                 credentials_client = cred_client.get_creds_client(
-                    identity_client, projects_client, roles_client)
+                    identity_client, projects_client, roles_client,
+                    users_client)
                 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 615a6e2..dfed947 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -439,10 +439,12 @@
             client = self.os_admin.identity_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 = None
             roles_client = None
+            users_client = None
 
         try:
             domain = client.auth_provider.credentials.project_domain_name
@@ -451,6 +453,7 @@
 
         return cred_client.get_creds_client(client, project_client,
                                             roles_client,
+                                            users_client,
                                             project_domain_name=domain)
 
     @classmethod
diff --git a/tempest/tests/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
index 62409bf..ab6a7a0 100644
--- a/tempest/tests/cmd/test_javelin.py
+++ b/tempest/tests/cmd/test_javelin.py
@@ -24,7 +24,7 @@
 
     def setUp(self):
         super(JavelinUnitTest, self).setUp()
-        javelin.setup_logging()
+        javelin.LOG = mock.MagicMock()
         self.fake_client = mock.MagicMock()
         self.fake_object = mock.MagicMock()
 
@@ -119,7 +119,7 @@
 
         fake_tenant_id = self.fake_object['tenant']['id']
         fake_email = "%s@%s" % (self.fake_object['user'], fake_tenant_id)
-        mocked_function = self.fake_client.identity.create_user
+        mocked_function = self.fake_client.users.create_user
         mocked_function.assert_called_once_with(self.fake_object['name'],
                                                 self.fake_object['password'],
                                                 fake_tenant_id,
@@ -135,7 +135,7 @@
 
         javelin.create_users([self.fake_object])
 
-        mocked_function = self.fake_client.identity.create_user
+        mocked_function = self.fake_client.users.create_user
         self.assertFalse(mocked_function.called)
 
     def test_create_objects(self):
@@ -310,7 +310,7 @@
         fake_auth = self.fake_client
         fake_auth.tenants.list_tenants.return_value = \
             {'tenants': [fake_tenant]}
-        fake_auth.identity.list_users.return_value = {'users': [fake_user]}
+        fake_auth.users.list_users.return_value = {'users': [fake_user]}
 
         self.useFixture(mockpatch.Patch(
                         'tempest.common.identity.get_user_by_username',
@@ -320,7 +320,7 @@
 
         javelin.destroy_users([fake_user])
 
-        mocked_function = fake_auth.identity.delete_user
+        mocked_function = fake_auth.users.delete_user
         mocked_function.assert_called_once_with(fake_user['id'])
 
     def test_destroy_objects(self):
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index a55e556..4379756 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -28,6 +28,8 @@
     json_roles_client
 from tempest.services.identity.v2.json import tenants_client as \
     json_tenants_client
+from tempest.services.identity.v2.json import users_client as \
+    json_users_client
 from tempest.services.network.json import network_client as json_network_client
 from tempest.tests import base
 from tempest.tests import fake_config
@@ -70,7 +72,7 @@
 
     def _mock_user_create(self, id, name):
         user_fix = self.useFixture(mockpatch.PatchObject(
-            json_iden_client.IdentityClient,
+            json_users_client.UsersClient,
             'create_user',
             return_value=(service_client.ResponseBody
                           (200, {'user': {'id': id, 'name': name}}))))
@@ -125,7 +127,7 @@
 
     def _mock_list_ec2_credentials(self, user_id, tenant_id):
         ec2_creds_fix = self.useFixture(mockpatch.PatchObject(
-            json_iden_client.IdentityClient,
+            json_users_client.UsersClient,
             'list_user_ec2_credentials',
             return_value=(service_client.ResponseBody
                           (200, {'credentials': [{
@@ -241,8 +243,8 @@
         self._mock_list_roles('123456', 'admin')
         creds.get_admin_creds()
         user_mock = self.patch(
-            'tempest.services.identity.v2.json.identity_client.'
-            'IdentityClient.delete_user')
+            'tempest.services.identity.v2.json.users_client.'
+            'UsersClient.delete_user')
         tenant_mock = self.patch(
             'tempest.services.identity.v2.json.tenants_client.'
             'TenantsClient.delete_tenant')
@@ -322,7 +324,7 @@
             'tempest.services.network.json.network_client.NetworkClient.'
             'add_router_interface_with_subnet_id')
         primary_creds = creds.get_primary_creds()
-        router_interface_mock.called_once_with('1234', '1234')
+        router_interface_mock.assert_called_once_with('1234', '1234')
         network = primary_creds.network
         subnet = primary_creds.subnet
         router = primary_creds.router
@@ -354,7 +356,7 @@
             'tempest.services.network.json.network_client.NetworkClient.'
             'add_router_interface_with_subnet_id')
         creds.get_primary_creds()
-        router_interface_mock.called_once_with('1234', '1234')
+        router_interface_mock.assert_called_once_with('1234', '1234')
         router_interface_mock.reset_mock()
         # Create alternate tenant and network
         self._mock_user_create('12345', 'fake_alt_user')
@@ -363,7 +365,7 @@
         self._mock_subnet_create(creds, '12345', 'fake_alt_subnet')
         self._mock_router_create('12345', 'fake_alt_router')
         creds.get_alt_creds()
-        router_interface_mock.called_once_with('12345', '12345')
+        router_interface_mock.assert_called_once_with('12345', '12345')
         router_interface_mock.reset_mock()
         # Create admin tenant and networks
         self._mock_user_create('123456', 'fake_admin_user')
@@ -373,8 +375,8 @@
         self._mock_router_create('123456', 'fake_admin_router')
         self._mock_list_roles('123456', 'admin')
         creds.get_admin_creds()
-        self.patch('tempest.services.identity.v2.json.identity_client.'
-                   'IdentityClient.delete_user')
+        self.patch('tempest.services.identity.v2.json.users_client.'
+                   'UsersClient.delete_user')
         self.patch('tempest.services.identity.v2.json.tenants_client.'
                    'TenantsClient.delete_tenant')
         net = mock.patch.object(creds.networks_admin_client,
@@ -461,7 +463,7 @@
             'tempest.services.network.json.network_client.NetworkClient.'
             'add_router_interface_with_subnet_id')
         alt_creds = creds.get_alt_creds()
-        router_interface_mock.called_once_with('1234', '1234')
+        router_interface_mock.assert_called_once_with('1234', '1234')
         network = alt_creds.network
         subnet = alt_creds.subnet
         router = alt_creds.router
@@ -486,7 +488,7 @@
             'add_router_interface_with_subnet_id')
         self._mock_list_roles('123456', 'admin')
         admin_creds = creds.get_admin_creds()
-        router_interface_mock.called_once_with('1234', '1234')
+        router_interface_mock.assert_called_once_with('1234', '1234')
         network = admin_creds.network
         subnet = admin_creds.subnet
         router = admin_creds.router
diff --git a/tools/check_logs.py b/tools/check_logs.py
index c8d3a1a..9b707b0 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -19,7 +19,7 @@
 import gzip
 import os
 import re
-import StringIO
+import six
 import sys
 import urllib2
 
@@ -71,7 +71,7 @@
         req = urllib2.Request(url)
         req.add_header('Accept-Encoding', 'gzip')
         page = urllib2.urlopen(req)
-        buf = StringIO.StringIO(page.read())
+        buf = six.StringIO(page.read())
         f = gzip.GzipFile(fileobj=buf)
         if scan_content(name, f.read().splitlines(), regexp, whitelist):
             logs_with_errors.append(name)
diff --git a/tools/find_stack_traces.py b/tools/find_stack_traces.py
index 4862d01..49a42fe 100755
--- a/tools/find_stack_traces.py
+++ b/tools/find_stack_traces.py
@@ -18,7 +18,7 @@
 import gzip
 import pprint
 import re
-import StringIO
+import six
 import sys
 import urllib2
 
@@ -68,7 +68,7 @@
     req = urllib2.Request(url)
     req.add_header('Accept-Encoding', 'gzip')
     page = urllib2.urlopen(req)
-    buf = StringIO.StringIO(page.read())
+    buf = six.StringIO(page.read())
     f = gzip.GzipFile(fileobj=buf)
     content = f.read()
 
diff --git a/tox.ini b/tox.ini
index fedd04c..832a7b3 100644
--- a/tox.ini
+++ b/tox.ini
@@ -34,7 +34,7 @@
 sitepackages = {[tempestenv]sitepackages}
 # 'all' includes slow tests
 setenv = {[tempestenv]setenv}
-         OS_TEST_TIMEOUT=1200
+         OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:1200}
 deps = {[tempestenv]deps}
 commands =
   find . -type f -name "*.pyc" -delete
@@ -44,7 +44,7 @@
 sitepackages = True
 # 'all' includes slow tests
 setenv = {[tempestenv]setenv}
-         OS_TEST_TIMEOUT=1200
+         OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:1200}
 deps = {[tempestenv]deps}
 commands =
   find . -type f -name "*.pyc" -delete