Merge "Replaces hardcoded volume size by configured value"
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
new file mode 100644
index 0000000..08f37cc
--- /dev/null
+++ b/doc/source/configuration.rst
@@ -0,0 +1,115 @@
+Tempest Configuration Guide
+===========================
+
+Auth/Credentials
+----------------
+
+Tempest currently has 2 different ways in configuration to provide credentials
+to use when running tempest. One is a traditional set of configuration options
+in the tempest.conf file. These options are in the identity section and let you
+specify a regular user, a global admin user, and a alternate user set of
+credentials. (which consist of a username, password, and project/tenant name)
+These options should be clearly labelled in the sample config file in the
+identity section.
+
+The other method to provide credentials is using the accounts.yaml file. This
+file is used to specify an arbitrary number of users available to run tests
+with. You can specify the location of the file in the
+auth section in the tempest.conf file. To see the specific format used in
+the file please refer to the accounts.yaml.sample file included in tempest.
+Currently users that are specified in the accounts.yaml file are assumed to
+have the same set of roles which can be used for executing all the tests you
+are running. This will be addressed in the future, but is a current limitation.
+Eventually the config options for providing credentials to tempest will be
+deprecated and removed in favor of the accounts.yaml file.
+
+Credential Provider Mechanisms
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Tempest currently also has 3 different internal methods for providing
+authentication to tests. Tenant isolation, locking test accounts, and
+non-locking test accounts. Depending on which one is in use the configuration
+of tempest is slightly different.
+
+Tenant Isolation
+""""""""""""""""
+Tenant isolation was originally create to enable running tempest in parallel.
+For each test class it creates a unique set of user credentials to use for the
+tests in the class. It can create up to 3 sets of username, password, and
+tenant/project names for a primary user, an admin user, and an alternate user.
+To enable and use tenant isolation you only need to configure 2 things:
+
+ #. A set of admin credentials with permissions to create users and
+    tenants/projects. This is specified in the identity section with the
+    admin_username, admin_tenant_name, and admin_password options
+ #. To enable tenant_isolation in the auth section with the
+    allow_tenant_isolation option.
+
+
+Locking Test Accounts
+"""""""""""""""""""""
+For a long time using tenant isolation was the only method available if you
+wanted to enable parallel execution of tempest tests. However this was
+insufficient for certain use cases because of the admin credentials requirement
+to create the credential sets on demand. To get around that the accounts.yaml
+file was introduced and with that a new internal credential provider to enable
+using the list of credentials instead of creating them on demand. With locking
+test accounts each test class will reserve a set of credentials from the
+accounts.yaml before executing any of its tests so that each class is isolated
+like in tenant isolation.
+
+Currently, this mechanism has some limitations, first only non-admin users with
+the same role set can be used at one time. The second limitation is around
+networking, locking test accounts will only work with a single flat network as
+the default for each tenant/project. If another network configuration is used
+in your cloud you might face unexpected failures.
+
+To enable and use locking test accounts you need do a few things:
+
+ #. Enable the locking test account provider with the
+    locking_credentials_provider option in the auth section
+ #. Create a accounts.yaml file which contains the set of pre-existing
+    credentials to use for testing. To make sure you don't have a credentials
+    starvation issue when running in parallel make sure you have at least 2
+    times the number of parallel workers you are using to execute tempest
+    available in the file.
+ #. Provide tempest with the location of you accounts.yaml file with the
+    test_accounts_file option in the auth section
+
+
+Non-locking test accounts
+"""""""""""""""""""""""""
+When tempest was refactored to allow for locking test accounts, the original
+non-tenant isolated case was converted to support the new accounts.yaml file.
+This mechanism is the non-locking test accounts provider. It only makes sense
+to use it if parallel execution isn't needed. If the role restrictions were too
+limiting with the locking accounts provider and tenant isolation is not wanted
+then you can use the non-locking test accounts credential provider without the
+accounts.yaml file. This is also the currently the default configuration for
+tempest, since it doesn't require elevated permissions or the extra file.
+
+To use the non-locking test accounts provider you have 2 ways to configure it.
+First you can specify the sets of credentials in the configuration file like
+detailed above with following 9 options in the identity section:
+
+ #. username
+ #. password
+ #. tenant_name
+ #. admin_username
+ #. admin_password
+ #. admin_tenant_name
+ #. alt_username
+ #. alt_password
+ #. alt_tenant_name
+
+You should use this if you need to specify credentials with different roles.
+(i.e. you want to use admin credentials) However, this isn't a requirement for
+its usage.
+
+You also can use the accounts.yaml file to specify the credentials used for
+testing. This will just allocate them serially so you only need to provide
+a pair of credentials. Do note that all the restrictions associated with
+locking test accounts applies to using the accounts.yaml file this way too.
+The procedure for doing this is very similar to with the locking accounts
+provider just don't set the locking_credentials_provider to true and you
+only should need a single pair of credentials.
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 1f06bc5..cb1c504 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -29,6 +29,15 @@
    field_guide/thirdparty
    field_guide/unit_tests
 
+---------------------------
+Tempest Configuration Guide
+---------------------------
+
+.. toctree::
+   :maxdepth: 2
+
+   configuration
+
 ---------------------
 Command Documentation
 ---------------------
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index bc4198f..d81d3bb 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -125,7 +125,7 @@
 # achieved configuring a list of test accounts (boolean value)
 # Deprecated group/name - [compute]/allow_tenant_isolation
 # Deprecated group/name - [orchestration]/allow_tenant_isolation
-#allow_tenant_isolation = false
+#allow_tenant_isolation = true
 
 # If set to True it enables the Accounts provider, which locks
 # credentials to allow for parallel execution with pre-provisioned
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 6c634b8..0441f6d 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -83,3 +83,16 @@
         self.assertEqual(new_name, fetched_domain['name'])
         self.assertEqual(new_desc, fetched_domain['description'])
         self.assertEqual('true', str(fetched_domain['enabled']).lower())
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('036df86e-bb5d-42c0-a7c2-66b9db3a6046')
+    def test_create_domain_with_disabled_status(self):
+        # Create domain with enabled status as false
+        d_name = data_utils.rand_name('domain-')
+        d_desc = data_utils.rand_name('domain-desc-')
+        domain = self.client.create_domain(
+            d_name, description=d_desc, enabled=False)
+        self.addCleanup(self.client.delete_domain, domain['id'])
+        self.assertEqual(d_name, domain['name'])
+        self.assertFalse(domain['enabled'])
+        self.assertEqual(d_desc, domain['description'])
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 4b5075c..db64a5b 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -120,7 +120,7 @@
         self.assertIsNotNone(trust['id'])
         self.assertEqual(impersonate, trust['impersonation'])
         if expires is not None:
-            # Omit microseconds of the expiry time
+            # Omit microseconds component of the expiry time
             trust_expires_at = re.sub(r'\.([0-9]){6}', '', trust['expires_at'])
             self.assertEqual(expires, trust_expires_at)
         else:
@@ -220,11 +220,14 @@
         # with an expiry specified
         expires_at = timeutils.utcnow() + datetime.timedelta(hours=1)
         # NOTE(ylobankov) In some cases the expiry time may be rounded up
-        # because of microseconds. For example, we have the following expiry
-        # time for a trust: 2015-02-17T17:34:01.907051Z. However, if we make
-        # a GET request on the trust, the response may contain the time
-        # rounded up to 2015-02-17T17:34:02.000000Z. That is why we should
-        # omit microseconds when creating a trust.
+        # because of microseconds. In fact, it depends on database and its
+        # version. At least MySQL 5.6.16 does this.
+        # For example, when creating a trust, we will set the expiry time of
+        # the trust to 2015-02-17T17:34:01.907051Z. However, if we make a GET
+        # request on the trust, the response will contain the time rounded up
+        # to 2015-02-17T17:34:02.000000Z. That is why we shouldn't set flag
+        # "subsecond" to True when we invoke timeutils.isotime(...) to avoid
+        # problems with rounding.
         expires_str = timeutils.isotime(at=expires_at)
 
         trust = self.create_trust(expires=expires_str)
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index 20b4e31..d942641 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -101,7 +101,8 @@
         self.addCleanup(self._try_delete_resource,
                         client.delete_network,
                         external_network['id'])
-        subnet = self.create_subnet(external_network, client=client)
+        subnet = self.create_subnet(external_network, client=client,
+                                    enable_dhcp=False)
         body = client.create_floatingip(
             floating_network_id=external_network['id'])
         created_floating_ip = body['floatingip']
diff --git a/tempest/api/network/test_metering_extensions.py b/tempest/api/network/test_metering_extensions.py
index f794f5a..8e4ee87 100644
--- a/tempest/api/network/test_metering_extensions.py
+++ b/tempest/api/network/test_metering_extensions.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
 #
-# Author: Emilien Macchi <emilien.macchi@enovance.com>
-#
 # 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
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 29f314d..9b379f4 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
 # 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
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 548c619..7d4008c 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
 # 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
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index a913bd7..f329675 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
 #    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
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index 644c3b1..5892340 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
 #    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
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index 102c9cd..45ecfec 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
 # 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
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
index 16ff95e..9d49a73 100644
--- a/tempest/api/object_storage/test_crossdomain.py
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
 # 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
diff --git a/tempest/api/object_storage/test_healthcheck.py b/tempest/api/object_storage/test_healthcheck.py
index a2a4497..2ca0a9f 100644
--- a/tempest/api/object_storage/test_healthcheck.py
+++ b/tempest/api/object_storage/test_healthcheck.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
 # 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
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
index 5425eaa..3e0fc7b 100644
--- a/tempest/api/object_storage/test_object_formpost.py
+++ b/tempest/api/object_storage/test_object_formpost.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Christian Schwede <christian.schwede@enovance.com>
-#
 # 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
diff --git a/tempest/api/object_storage/test_object_formpost_negative.py b/tempest/api/object_storage/test_object_formpost_negative.py
index d8fc077..d92a2e5 100644
--- a/tempest/api/object_storage/test_object_formpost_negative.py
+++ b/tempest/api/object_storage/test_object_formpost_negative.py
@@ -1,5 +1,4 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
 #
 # 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
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index 4563bfd..e6b0b05 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
 # 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
diff --git a/tempest/api/object_storage/test_object_temp_url_negative.py b/tempest/api/object_storage/test_object_temp_url_negative.py
index af927a8..343749e 100644
--- a/tempest/api/object_storage/test_object_temp_url_negative.py
+++ b/tempest/api/object_storage/test_object_temp_url_negative.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
 # 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
diff --git a/tempest/api/orchestration/stacks/test_resource_types.py b/tempest/api/orchestration/stacks/test_resource_types.py
index 33d2f9e..32b0b8e 100644
--- a/tempest/api/orchestration/stacks/test_resource_types.py
+++ b/tempest/api/orchestration/stacks/test_resource_types.py
@@ -43,5 +43,7 @@
         """Verify it is possible to get template about resource types."""
         type_template = self.client.get_resource_type_template(
             'OS::Nova::Server')
-        self.assert_fields_in_dict(type_template, 'Outputs',
-            'Parameters', 'Resources')
\ No newline at end of file
+        self.assert_fields_in_dict(
+            type_template,
+            'Outputs',
+            'Parameters', 'Resources')
diff --git a/tempest/api/orchestration/stacks/test_swift_resources.py b/tempest/api/orchestration/stacks/test_swift_resources.py
index efbf695..1290dfe 100644
--- a/tempest/api/orchestration/stacks/test_swift_resources.py
+++ b/tempest/api/orchestration/stacks/test_swift_resources.py
@@ -1,8 +1,6 @@
 # -*- coding: utf-8 -*-
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
-# Author: Chmouel Boudjnah <chmouel@enovance.com>
-#
 # 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
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index a2588f7..cd91552 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
 #
-# Author: Sylvain Baubeau <sylvain.baubeau@enovance.com>
-#
 #    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
diff --git a/tempest/api_schema/response/compute/flavors.py b/tempest/api_schema/response/compute/flavors.py
index 44020d2..65f2c28 100644
--- a/tempest/api_schema/response/compute/flavors.py
+++ b/tempest/api_schema/response/compute/flavors.py
@@ -30,8 +30,11 @@
                     },
                     'required': ['name', 'links', 'id']
                 }
-            }
+            },
+            'flavors_links': parameter_types.links
         },
+        # NOTE(gmann): flavors_links attribute is not necessary
+        # to be present always So it is not 'required'.
         'required': ['flavors']
     }
 }
diff --git a/tempest/api_schema/response/compute/v2/flavors.py b/tempest/api_schema/response/compute/v2/flavors.py
index 811ea84..76c4cee 100644
--- a/tempest/api_schema/response/compute/v2/flavors.py
+++ b/tempest/api_schema/response/compute/v2/flavors.py
@@ -15,6 +15,7 @@
 import copy
 
 from tempest.api_schema.response.compute import flavors
+from tempest.api_schema.response.compute import parameter_types
 
 list_flavors_details = copy.deepcopy(flavors.common_flavor_list_details)
 
@@ -23,6 +24,12 @@
 list_flavors_details['response_body']['properties']['flavors']['items'][
     'properties']['swap'] = {'type': ['string', 'integer']}
 
+# Defining 'flavors_links' attributes for V2 flavor schema
+list_flavors_details['response_body'][
+    'properties'].update({'flavors_links': parameter_types.links})
+# NOTE(gmann): flavors_links attribute is not necessary to be
+# present always So it is not 'required'.
+
 # Defining extra attributes for V2 flavor schema
 list_flavors_details['response_body']['properties']['flavors']['items'][
     'properties'].update({'OS-FLV-DISABLED:disabled': {'type': 'boolean'},
diff --git a/tempest/api_schema/response/compute/v2/floating_ips.py b/tempest/api_schema/response/compute/v2/floating_ips.py
index def0a78..7250773 100644
--- a/tempest/api_schema/response/compute/v2/floating_ips.py
+++ b/tempest/api_schema/response/compute/v2/floating_ips.py
@@ -146,8 +146,14 @@
                         'instance_uuid': {'type': ['string', 'null']},
                         'interface': {'type': ['string', 'null']},
                         'pool': {'type': ['string', 'null']},
-                        'project_id': {'type': ['string', 'null']}
+                        'project_id': {'type': ['string', 'null']},
+                        'fixed_ip': {
+                            'type': ['string', 'null'],
+                            'format': 'ip-address'
+                        }
                     },
+                    # NOTE: fixed_ip is introduced after JUNO release,
+                    # So it is not defined as 'required'.
                     'required': ['address', 'instance_uuid', 'interface',
                                  'pool', 'project_id']
                 }
diff --git a/tempest/api_schema/response/compute/v2/limits.py b/tempest/api_schema/response/compute/v2/limits.py
index b9857f1..a7decb7 100644
--- a/tempest/api_schema/response/compute/v2/limits.py
+++ b/tempest/api_schema/response/compute/v2/limits.py
@@ -38,8 +38,15 @@
                             'maxSecurityGroupRules': {'type': 'integer'},
                             'maxTotalKeypairs': {'type': 'integer'},
                             'totalRAMUsed': {'type': 'integer'},
-                            'totalInstancesUsed': {'type': 'integer'}
+                            'totalInstancesUsed': {'type': 'integer'},
+                            'maxServerGroupMembers': {'type': 'integer'},
+                            'maxServerGroups': {'type': 'integer'},
+                            'totalServerGroupsUsed': {'type': 'integer'}
                         },
+                        # NOTE(gmann): maxServerGroupMembers,  maxServerGroups
+                        # and totalServerGroupsUsed are API extension,
+                        # and some environments return a response without these
+                        # attributes.So they are not 'required'.
                         'required': ['maxImageMeta',
                                      'maxPersonality',
                                      'maxPersonalitySize',
diff --git a/tempest/api_schema/response/compute/v2/servers.py b/tempest/api_schema/response/compute/v2/servers.py
index 09abaed..0132350 100644
--- a/tempest/api_schema/response/compute/v2/servers.py
+++ b/tempest/api_schema/response/compute/v2/servers.py
@@ -30,10 +30,10 @@
                     'links': parameter_types.links,
                     'OS-DCF:diskConfig': {'type': 'string'}
                 },
-                # NOTE: OS-DCF:diskConfig is API extension, and some
-                # environments return a response without the attribute.
-                # So it is not 'required'.
-                'required': ['id', 'security_groups', 'links']
+                # NOTE: OS-DCF:diskConfig & security_groups are API extension,
+                # and some environments return a response without these
+                # attributes.So they are not 'required'.
+                'required': ['id', 'links']
             }
         },
         'required': ['server']
@@ -64,6 +64,7 @@
 get_server['response_body']['properties']['server']['properties'].update({
     'key_name': {'type': ['string', 'null']},
     'hostId': {'type': 'string'},
+    'security_groups': {'type': 'array'},
 
     # NOTE: Non-admin users also can see "OS-SRV-USG" and "OS-EXT-AZ"
     # attributes.
@@ -288,10 +289,11 @@
     'properties'].update({
         'hostId': {'type': 'string'},
         'OS-DCF:diskConfig': {'type': 'string'},
+        'security_groups': {'type': 'array'},
         'accessIPv4': parameter_types.access_ip_v4,
         'accessIPv6': parameter_types.access_ip_v6
     })
-# NOTE(GMann): OS-DCF:diskConfig and accessIPv4/v6 are API
+# NOTE(GMann): OS-DCF:diskConfig, security_groups and accessIPv4/v6 are API
 # extensions, and some environments return a response
 # without these attributes. So they are not 'required'.
 list_servers_detail['response_body']['properties']['servers']['items'][
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
index 76aafd8..6733204 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -68,6 +68,14 @@
 
 
 class ClientTestBase(test.BaseTestCase):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ClientTestBase, cls).skip_checks()
+        if not CONF.identity_feature_enabled.api_v2:
+            raise cls.skipException("CLI clients rely on identity v2 API, "
+                                    "which is configured as not available")
+
     @classmethod
     def resource_setup(cls):
         if not CONF.cli.enabled:
diff --git a/tempest/clients.py b/tempest/clients.py
index 430aeb3..e5f41eb 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -195,8 +195,22 @@
                 endpoint_type=CONF.telemetry.endpoint_type,
                 **self.default_params_with_timeout_values)
         if CONF.service_available.glance:
-            self.image_client = ImageClientJSON(self.auth_provider)
-            self.image_client_v2 = ImageClientV2JSON(self.auth_provider)
+            self.image_client = ImageClientJSON(
+                self.auth_provider,
+                CONF.image.catalog_type,
+                CONF.image.region or CONF.identity.region,
+                endpoint_type=CONF.image.endpoint_type,
+                build_interval=CONF.image.build_interval,
+                build_timeout=CONF.image.build_timeout,
+                **self.default_params)
+            self.image_client_v2 = ImageClientV2JSON(
+                self.auth_provider,
+                CONF.image.catalog_type,
+                CONF.image.region or CONF.identity.region,
+                endpoint_type=CONF.image.endpoint_type,
+                build_interval=CONF.image.build_interval,
+                build_timeout=CONF.image.build_timeout,
+                **self.default_params)
         self.orchestration_client = OrchestrationClient(
             self.auth_provider,
             CONF.orchestration.catalog_type,
@@ -240,7 +254,11 @@
             SecurityGroupDefaultRulesClientJSON(self.auth_provider, **params))
         self.certificates_client = CertificatesClientJSON(self.auth_provider,
                                                           **params)
-        self.servers_client = ServersClientJSON(self.auth_provider, **params)
+        self.servers_client = ServersClientJSON(
+            self.auth_provider,
+            enable_instance_password=CONF.compute_feature_enabled
+                .enable_instance_password,
+            **params)
         self.limits_client = LimitsClientJSON(self.auth_provider, **params)
         self.images_client = ImagesClientJSON(self.auth_provider, **params)
         self.keypairs_client = KeyPairsClientJSON(self.auth_provider, **params)
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 97dbec0..4c09bd2 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -200,7 +200,14 @@
                                                   **object_storage_params)
         self.containers = container_client.ContainerClient(
             _auth, **object_storage_params)
-        self.images = image_client.ImageClientV2JSON(_auth)
+        self.images = image_client.ImageClientV2JSON(
+            _auth,
+            CONF.image.catalog_type,
+            CONF.image.region or CONF.identity.region,
+            endpoint_type=CONF.image.endpoint_type,
+            build_interval=CONF.image.build_interval,
+            build_timeout=CONF.image.build_timeout,
+            **default_params)
         self.telemetry = telemetry_client.TelemetryClientJSON(
             _auth,
             CONF.telemetry.catalog_type,
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 6e61c55..1f1414f 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -23,7 +23,7 @@
 CONF = config.CONF
 
 
-class RemoteClient():
+class RemoteClient(object):
 
     # NOTE(afazekas): It should always get an address instead of server
     def __init__(self, server, username, password=None, pkey=None):
@@ -163,4 +163,4 @@
                                                   % dhcp_client)
         if dhcp_client == 'udhcpc' and not fixed_ip:
             raise ValueError("need to set 'fixed_ip' for udhcpc client")
-        return getattr(self, '_renew_lease_' + dhcp_client)(fixed_ip=fixed_ip)
\ No newline at end of file
+        return getattr(self, '_renew_lease_' + dhcp_client)(fixed_ip=fixed_ip)
diff --git a/tempest/config.py b/tempest/config.py
index 4588b20..a66aa9b 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -40,7 +40,7 @@
                help="Path to the yaml file that contains the list of "
                     "credentials to use for running tests"),
     cfg.BoolOpt('allow_tenant_isolation',
-                default=False,
+                default=True,
                 help="Allows test cases to create/destroy tenants and "
                      "users. This option requires that OpenStack Identity "
                      "API admin credentials are known. If false, isolated "
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index 1069908..eed3d0b 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -62,4 +62,4 @@
         self.launch_instance()
         self.create_encrypted_volume('nova.volume.encryptors.'
                                      'cryptsetup.CryptsetupEncryptor')
-        self.attach_detach_volume()
\ No newline at end of file
+        self.attach_detach_volume()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index f29fecf..4199b2c 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -435,13 +435,15 @@
             "admin_state_up of router to True")
 
     @test.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
+    @testtools.skipIf(CONF.baremetal.driver_enabled,
+                      'network isolation not available for baremetal nodes')
     @testtools.skipUnless(CONF.scenario.dhcp_client,
                           "DHCP client is not available.")
     @test.attr(type='smoke')
     @test.services('compute', 'network')
     def test_subnet_details(self):
         """Tests that subnet's extra configuration details are affecting
-        the VMs
+        the VMs. This test relies on non-shared, isolated tenant networks.
 
          NOTE: Neutron subnets push data to servers via dhcp-agent, so any
          update in subnet requires server to actively renew its DHCP lease.
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 979953f..d5d2d77 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -12,6 +12,7 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+import functools
 import netaddr
 from tempest import config
 from tempest.openstack.common import log as logging
@@ -118,14 +119,28 @@
         ssh1, srv1 = self.prepare_server()
         ssh2, srv2 = self.prepare_server()
 
+        def guest_has_address(ssh, addr):
+            return addr in ssh.get_ip_list()
+
+        srv1_v6_addr_assigned = functools.partial(
+            guest_has_address, ssh1, srv1['accessIPv6'])
+        srv2_v6_addr_assigned = functools.partial(
+            guest_has_address, ssh2, srv2['accessIPv6'])
+
         result = ssh1.get_ip_list()
         self.assertIn(srv1['accessIPv4'], result)
         # v6 should be configured since the image supports it
-        self.assertIn(srv1['accessIPv6'], result)
+        # It can take time for ipv6 automatic address to get assigned
+        self.assertTrue(
+            test.call_until_true(srv1_v6_addr_assigned,
+                                 CONF.compute.ping_timeout, 1))
         result = ssh2.get_ip_list()
         self.assertIn(srv2['accessIPv4'], result)
         # v6 should be configured since the image supports it
-        self.assertIn(srv2['accessIPv6'], result)
+        # It can take time for ipv6 automatic address to get assigned
+        self.assertTrue(
+            test.call_until_true(srv2_v6_addr_assigned,
+                                 CONF.compute.ping_timeout, 1))
         result = ssh1.ping_host(srv2['accessIPv4'])
         self.assertIn('0% packet loss', result)
         result = ssh2.ping_host(srv1['accessIPv4'])
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index f3c1f85..4fbadb0 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -91,7 +91,7 @@
             its own router connected to the public network
     """
 
-    class TenantProperties():
+    class TenantProperties(object):
         """
         helper class to save tenant details
             id
diff --git a/tempest/scenario/test_swift_telemetry_middleware.py b/tempest/scenario/test_swift_telemetry_middleware.py
index 2427f0f..8305641 100644
--- a/tempest/scenario/test_swift_telemetry_middleware.py
+++ b/tempest/scenario/test_swift_telemetry_middleware.py
@@ -1,7 +1,5 @@
-#
 # Copyright 2014 Red Hat
 #
-# Author: Chris Dent <chdent@redhat.com>
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index b01fbf1..bd4fd0e 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -24,14 +24,17 @@
 from tempest.api_schema.response.compute.v2 import servers as schema
 from tempest.common import service_client
 from tempest.common import waiters
-from tempest import config
 from tempest import exceptions
 
-CONF = config.CONF
-
 
 class ServersClientJSON(service_client.ServiceClient):
 
+    def __init__(self, auth_provider, service, region,
+                 enable_instance_password=True, **kwargs):
+        super(ServersClientJSON, self).__init__(
+            auth_provider, service, region, **kwargs)
+        self.enable_instance_password = enable_instance_password
+
     def create_server(self, name, image_ref, flavor_ref, **kwargs):
         """
         Creates an instance of a server.
@@ -93,7 +96,7 @@
         # with return reservation id set True
         if 'reservation_id' in body:
             return service_client.ResponseBody(resp, body)
-        if CONF.compute_feature_enabled.enable_instance_password:
+        if self.enable_instance_password:
             create_schema = schema.create_server_with_admin_pass
         else:
             create_schema = schema.create_server
@@ -275,7 +278,7 @@
         if 'disk_config' in kwargs:
             kwargs['OS-DCF:diskConfig'] = kwargs['disk_config']
             del kwargs['disk_config']
-        if CONF.compute_feature_enabled.enable_instance_password:
+        if self.enable_instance_password:
             rebuild_schema = schema.rebuild_server_with_admin_pass
         else:
             rebuild_schema = schema.rebuild_server
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index 4ea710f..50f75b3 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -25,26 +25,32 @@
 from tempest.common import glance_http
 from tempest.common import service_client
 from tempest.common.utils import misc as misc_utils
-from tempest import config
 from tempest import exceptions
 from tempest.openstack.common import log as logging
 
-CONF = config.CONF
-
 LOG = logging.getLogger(__name__)
 
 
 class ImageClientJSON(service_client.ServiceClient):
 
-    def __init__(self, auth_provider):
+    def __init__(self, auth_provider, catalog_type, region, endpoint_type=None,
+                 build_interval=None, build_timeout=None,
+                 disable_ssl_certificate_validation=None,
+                 ca_certs=None, **kwargs):
         super(ImageClientJSON, self).__init__(
             auth_provider,
-            CONF.image.catalog_type,
-            CONF.image.region or CONF.identity.region,
-            endpoint_type=CONF.image.endpoint_type,
-            build_interval=CONF.image.build_interval,
-            build_timeout=CONF.image.build_timeout)
+            catalog_type,
+            region,
+            endpoint_type=endpoint_type,
+            build_interval=build_interval,
+            build_timeout=build_timeout,
+            disable_ssl_certificate_validation=(
+                disable_ssl_certificate_validation),
+            ca_certs=ca_certs,
+            **kwargs)
         self._http = None
+        self.dscv = disable_ssl_certificate_validation
+        self.ca_certs = ca_certs
 
     def _image_meta_from_headers(self, headers):
         meta = {'properties': {}}
@@ -112,11 +118,10 @@
             return None
 
     def _get_http(self):
-        dscv = CONF.identity.disable_ssl_certificate_validation
-        ca_certs = CONF.identity.ca_certificates_file
         return glance_http.HTTPClient(auth_provider=self.auth_provider,
                                       filters=self.filters,
-                                      insecure=dscv, ca_certs=ca_certs)
+                                      insecure=self.dscv,
+                                      ca_certs=self.ca_certs)
 
     def _create_with_data(self, headers, data):
         resp, body_iter = self.http.raw_request('POST', '/v1/images',
@@ -138,8 +143,7 @@
     @property
     def http(self):
         if self._http is None:
-            if CONF.service_available.glance:
-                self._http = self._get_http()
+            self._http = self._get_http()
         return self._http
 
     def create_image(self, name, container_format, disk_format, **kwargs):
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index 50f273c..e55a824 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -21,29 +21,34 @@
 
 from tempest.common import glance_http
 from tempest.common import service_client
-from tempest import config
-
-CONF = config.CONF
 
 
 class ImageClientV2JSON(service_client.ServiceClient):
 
-    def __init__(self, auth_provider):
+    def __init__(self, auth_provider, catalog_type, region, endpoint_type=None,
+                 build_interval=None, build_timeout=None,
+                 disable_ssl_certificate_validation=None, ca_certs=None,
+                 **kwargs):
         super(ImageClientV2JSON, self).__init__(
             auth_provider,
-            CONF.image.catalog_type,
-            CONF.image.region or CONF.identity.region,
-            endpoint_type=CONF.image.endpoint_type,
-            build_interval=CONF.image.build_interval,
-            build_timeout=CONF.image.build_timeout)
+            catalog_type,
+            region,
+            endpoint_type=endpoint_type,
+            build_interval=build_interval,
+            build_timeout=build_timeout,
+            disable_ssl_certificate_validation=(
+                disable_ssl_certificate_validation),
+            ca_certs=ca_certs,
+            **kwargs)
         self._http = None
+        self.dscv = disable_ssl_certificate_validation
+        self.ca_certs = ca_certs
 
     def _get_http(self):
-        dscv = CONF.identity.disable_ssl_certificate_validation
-        ca_certs = CONF.identity.ca_certificates_file
         return glance_http.HTTPClient(auth_provider=self.auth_provider,
                                       filters=self.filters,
-                                      insecure=dscv, ca_certs=ca_certs)
+                                      insecure=self.dscv,
+                                      ca_certs=self.ca_certs)
 
     def _validate_schema(self, body, type='image'):
         if type in ['image', 'images']:
@@ -56,8 +61,7 @@
     @property
     def http(self):
         if self._http is None:
-            if CONF.service_available.glance:
-                self._http = self._get_http()
+            self._http = self._get_http()
         return self._http
 
     def update_image(self, image_id, patch):
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index ba069e8..87f1332 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -262,9 +262,8 @@
         # expecting response in form
         # {'resources': [ res1, res2] } => when pagination disabled
         # {'resources': [..], 'resources_links': {}} => if pagination enabled
-        pagination_suffix = "_links"
         for k in res.keys():
-            if k[-len(pagination_suffix):] == pagination_suffix:
+            if k.endswith("_links"):
                 continue
             return res[k]
 
diff --git a/tempest/services/volume/json/admin/volume_quotas_client.py b/tempest/services/volume/json/admin/volume_quotas_client.py
index 19d320f..616f8e4 100644
--- a/tempest/services/volume/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/json/admin/volume_quotas_client.py
@@ -1,7 +1,5 @@
 # Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
 #
-# Author: Sylvain Baubeau <sylvain.baubeau@enovance.com>
-#
 #    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
diff --git a/tempest/tests/common/test_custom_matchers.py b/tempest/tests/common/test_custom_matchers.py
index 57217e3..2656a47 100644
--- a/tempest/tests/common/test_custom_matchers.py
+++ b/tempest/tests/common/test_custom_matchers.py
@@ -63,4 +63,4 @@
          "  b: expected 2, actual None\n",
          {'a': 1, 'b': None, 'foo': 1},
          matches_matcher)
-    ]
\ No newline at end of file
+    ]
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index cb3ba36..9bb58b0 100644
--- a/tempest/tests/common/test_service_clients.py
+++ b/tempest/tests/common/test_service_clients.py
@@ -55,6 +55,8 @@
 from tempest.services.identity.v3.json import policy_client
 from tempest.services.identity.v3.json import region_client
 from tempest.services.identity.v3.json import service_client
+from tempest.services.image.v1.json import image_client
+from tempest.services.image.v2.json import image_client as image_v2_client
 from tempest.services.messaging.json import messaging_client
 from tempest.services.network.json import network_client
 from tempest.services.object_storage import account_client
@@ -163,7 +165,9 @@
             identity_v3_identity_client.IdentityV3ClientJSON,
             policy_client.PolicyClientJSON,
             region_client.RegionClientJSON,
-            service_client.ServiceClientJSON
+            service_client.ServiceClientJSON,
+            image_client.ImageClientJSON,
+            image_v2_client.ImageClientV2JSON
         ]
 
         for client in test_clients:
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index edd9de1..5b2ed70 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -201,10 +201,14 @@
             raise cls.skipException("The EC2 API is not available")
 
     @classmethod
+    def setup_credentials(cls):
+        super(BotoTestCase, cls).setup_credentials()
+        cls.os = cls.get_client_manager()
+
+    @classmethod
     def resource_setup(cls):
         super(BotoTestCase, cls).resource_setup()
         cls.conclusion = decision_maker()
-        cls.os = cls.get_client_manager()
         # The trash contains cleanup functions and paramaters in tuples
         # (function, *args, **kwargs)
         cls._resource_trash_bin = {}
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 88549cb..4a2bd23 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -31,13 +31,17 @@
 class InstanceRunTest(boto_test.BotoTestCase):
 
     @classmethod
+    def setup_clients(cls):
+        super(InstanceRunTest, cls).setup_clients()
+        cls.s3_client = cls.os.s3_client
+        cls.ec2_client = cls.os.ec2api_client
+
+    @classmethod
     def resource_setup(cls):
         super(InstanceRunTest, cls).resource_setup()
         if not cls.conclusion['A_I_IMAGES_READY']:
             raise cls.skipException("".join(("EC2 ", cls.__name__,
                                     ": requires ami/aki/ari manifest")))
-        cls.s3_client = cls.os.s3_client
-        cls.ec2_client = cls.os.ec2api_client
         cls.zone = CONF.boto.aws_zone
         cls.materials_path = CONF.boto.s3_materials_path
         ami_manifest = CONF.boto.ami_manifest
diff --git a/tempest/thirdparty/boto/test_ec2_keys.py b/tempest/thirdparty/boto/test_ec2_keys.py
index 36c3386..acf797a 100644
--- a/tempest/thirdparty/boto/test_ec2_keys.py
+++ b/tempest/thirdparty/boto/test_ec2_keys.py
@@ -26,9 +26,13 @@
 class EC2KeysTest(boto_test.BotoTestCase):
 
     @classmethod
+    def setup_clients(cls):
+        super(EC2KeysTest, cls).setup_clients()
+        cls.client = cls.os.ec2api_client
+
+    @classmethod
     def resource_setup(cls):
         super(EC2KeysTest, cls).resource_setup()
-        cls.client = cls.os.ec2api_client
         cls.ec = cls.ec2_error_code
 
 # TODO(afazekas): merge create, delete, get test cases
diff --git a/tempest/thirdparty/boto/test_ec2_network.py b/tempest/thirdparty/boto/test_ec2_network.py
index c7ed00d..ce20156 100644
--- a/tempest/thirdparty/boto/test_ec2_network.py
+++ b/tempest/thirdparty/boto/test_ec2_network.py
@@ -20,8 +20,8 @@
 class EC2NetworkTest(boto_test.BotoTestCase):
 
     @classmethod
-    def resource_setup(cls):
-        super(EC2NetworkTest, cls).resource_setup()
+    def setup_clients(cls):
+        super(EC2NetworkTest, cls).setup_clients()
         cls.ec2_client = cls.os.ec2api_client
 
     # Note(afazekas): these tests for things duable without an instance
diff --git a/tempest/thirdparty/boto/test_ec2_security_groups.py b/tempest/thirdparty/boto/test_ec2_security_groups.py
index 92fe59d..7f9568b 100644
--- a/tempest/thirdparty/boto/test_ec2_security_groups.py
+++ b/tempest/thirdparty/boto/test_ec2_security_groups.py
@@ -21,8 +21,8 @@
 class EC2SecurityGroupTest(boto_test.BotoTestCase):
 
     @classmethod
-    def resource_setup(cls):
-        super(EC2SecurityGroupTest, cls).resource_setup()
+    def setup_clients(cls):
+        super(EC2SecurityGroupTest, cls).setup_clients()
         cls.client = cls.os.ec2api_client
 
     @test.idempotent_id('519b566e-0c38-4629-905e-7d6b6355f524')
diff --git a/tempest/thirdparty/boto/test_ec2_volumes.py b/tempest/thirdparty/boto/test_ec2_volumes.py
index 06d36cc..9a6d13f 100644
--- a/tempest/thirdparty/boto/test_ec2_volumes.py
+++ b/tempest/thirdparty/boto/test_ec2_volumes.py
@@ -30,14 +30,20 @@
 class EC2VolumesTest(boto_test.BotoTestCase):
 
     @classmethod
-    def resource_setup(cls):
-        super(EC2VolumesTest, cls).resource_setup()
-
+    def skip_checks(cls):
+        super(EC2VolumesTest, cls).skip_checks()
         if not CONF.service_available.cinder:
             skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
 
+    @classmethod
+    def setup_clients(cls):
+        super(EC2VolumesTest, cls).setup_clients()
         cls.client = cls.os.ec2api_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(EC2VolumesTest, cls).resource_setup()
         cls.zone = CONF.boto.aws_zone
 
     @test.idempotent_id('663f0077-c743-48ad-8ae0-46821cbc0918')
diff --git a/tempest/thirdparty/boto/test_s3_buckets.py b/tempest/thirdparty/boto/test_s3_buckets.py
index e3a265e..bf04803 100644
--- a/tempest/thirdparty/boto/test_s3_buckets.py
+++ b/tempest/thirdparty/boto/test_s3_buckets.py
@@ -21,8 +21,8 @@
 class S3BucketsTest(boto_test.BotoTestCase):
 
     @classmethod
-    def resource_setup(cls):
-        super(S3BucketsTest, cls).resource_setup()
+    def setup_clients(cls):
+        super(S3BucketsTest, cls).setup_clients()
         cls.client = cls.os.s3_client
 
     @test.idempotent_id('4678525d-8da0-4518-81c1-f1f67d595b00')
diff --git a/tempest/thirdparty/boto/test_s3_ec2_images.py b/tempest/thirdparty/boto/test_s3_ec2_images.py
index 773a193..21ea984 100644
--- a/tempest/thirdparty/boto/test_s3_ec2_images.py
+++ b/tempest/thirdparty/boto/test_s3_ec2_images.py
@@ -27,13 +27,17 @@
 class S3ImagesTest(boto_test.BotoTestCase):
 
     @classmethod
+    def setup_clients(cls):
+        super(S3ImagesTest, cls).setup_clients()
+        cls.s3_client = cls.os.s3_client
+        cls.images_client = cls.os.ec2api_client
+
+    @classmethod
     def resource_setup(cls):
         super(S3ImagesTest, cls).resource_setup()
         if not cls.conclusion['A_I_IMAGES_READY']:
             raise cls.skipException("".join(("EC2 ", cls.__name__,
                                     ": requires ami/aki/ari manifest")))
-        cls.s3_client = cls.os.s3_client
-        cls.images_client = cls.os.ec2api_client
         cls.materials_path = CONF.boto.s3_materials_path
         cls.ami_manifest = CONF.boto.ami_manifest
         cls.aki_manifest = CONF.boto.aki_manifest
diff --git a/tempest/thirdparty/boto/test_s3_objects.py b/tempest/thirdparty/boto/test_s3_objects.py
index bc32686..2d8152d 100644
--- a/tempest/thirdparty/boto/test_s3_objects.py
+++ b/tempest/thirdparty/boto/test_s3_objects.py
@@ -25,8 +25,8 @@
 class S3BucketsTest(boto_test.BotoTestCase):
 
     @classmethod
-    def resource_setup(cls):
-        super(S3BucketsTest, cls).resource_setup()
+    def setup_clients(cls):
+        super(S3BucketsTest, cls).setup_clients()
         cls.client = cls.os.s3_client
 
     @test.idempotent_id('4eea567a-b46a-405b-a475-6097e1faebde')
diff --git a/test-requirements.txt b/test-requirements.txt
index 6eefeee..6a9111e 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,7 +1,7 @@
 # The order of packages is significant, because pip processes them in the order
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
-hacking>=0.9.2,<0.10
+hacking<0.11,>=0.10.0
 # needed for doc build
 sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
 python-subunit>=0.0.18
diff --git a/tox.ini b/tox.ini
index f3fc8b7..ef98e90 100644
--- a/tox.ini
+++ b/tox.ini
@@ -125,11 +125,9 @@
 
 [flake8]
 # E125 is a won't fix until https://github.com/jcrocholl/pep8/issues/126 is resolved.  For further detail see https://review.openstack.org/#/c/36788/
-# H402 skipped because some docstrings aren't sentences
 # E123 skipped because it is ignored by default in the default pep8
 # E129 skipped because it is too limiting when combined with other rules
-# H305 skipped because it is inconsistent between python versions
-# Skipped because of new hacking 0.9: H405,H904
-ignore = E125,H402,E123,E129,H404,H405,H904,H305
+# Skipped because of new hacking 0.9: H405
+ignore = E125,E123,E129,H404,H405
 show-source = True
 exclude = .git,.venv,.tox,dist,doc,openstack,*egg