Merge "Use base.get_host_for_server to get server host"
diff --git a/.gitignore b/.gitignore
index 7cb052f..06a2281 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,9 +3,8 @@
 *.pyc
 __pycache__/
 etc/accounts.yaml
-etc/tempest.conf
+etc/*.conf
 etc/tempest.conf.sample
-etc/logging.conf
 include/swift_objects/swift_small
 include/swift_objects/swift_medium
 include/swift_objects/swift_large
diff --git a/.zuul.yaml b/.zuul.yaml
index 52c11c9..ee0ae9c 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -275,6 +275,8 @@
         TEMPEST_VOLUME_TYPE: volumev2
 
 - project:
+    templates:
+      - openstack-python36-jobs
     check:
       jobs:
         - devstack-tempest:
diff --git a/README.rst b/README.rst
index c93e19f..0a130dc 100644
--- a/README.rst
+++ b/README.rst
@@ -111,15 +111,18 @@
 
     $ tempest run --workspace cloud-01
 
-   There is also the option to use testr directly, or any `testr`_ based test
-   runner, like `ostestr`_. For example, from the workspace dir run::
+   There is also the option to use `stestr`_ directly. For example, from
+   the workspace dir run::
 
-    $ ostestr --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))'
+    $ stestr run --black-regex '\[.*\bslow\b.*\]' '^tempest\.(api|scenario)'
 
-   will run the same set of tests as the default gate jobs.
+   will run the same set of tests as the default gate jobs. Or you can
+   use `unittest`_ compatible test runners such as `testr`_, `pytest`_ etc.
 
+.. _unittest: https://docs.python.org/3/library/unittest.html
 .. _testr: https://testrepository.readthedocs.org/en/latest/MANUAL.html
-.. _ostestr: https://docs.openstack.org/os-testr/latest/
+.. _stestr: https://stestr.readthedocs.org/en/latest/MANUAL.html
+.. _pytest: https://docs.pytest.org/en/latest/
 
 Library
 -------
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index 81a1cb5..983fa24 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -306,6 +306,10 @@
 
   .. _2.6: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id5
 
+  * `2.8`_
+
+  .. _2.8: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id7
+
   * `2.9`_
 
   .. _2.9: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id8
diff --git a/releasenotes/notes/removal-deprecated-volume-config-options-21c4412f3c600923.yaml b/releasenotes/notes/removal-deprecated-volume-config-options-21c4412f3c600923.yaml
new file mode 100644
index 0000000..32147c7
--- /dev/null
+++ b/releasenotes/notes/removal-deprecated-volume-config-options-21c4412f3c600923.yaml
@@ -0,0 +1,24 @@
+---
+upgrade:
+  - |
+    Below config option was deprecated for removal since juno release.
+    It's time to remove it as all supported stable branches and Tempest plugins
+    are good to handle it.
+
+    * ``[volume_feature_enabled].api_v1``
+
+    Also Tempest removes the below corresponding service clients alias from
+    client.py which were being set based on above removed config option.
+
+    * self.backups_client
+    * self.encryption_types_client
+    * self.snapshots_client
+    * self.volume_availability_zone_client
+    * self.volume_hosts_client
+    * self.volume_limits_client
+    * self.volume_qos_client
+    * self.volume_quotas_client
+    * self.volume_services_client
+    * self.volume_types_client
+    * self.volumes_client
+    * self.volumes_extension_client
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 701b371..ff2f99c 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -208,19 +208,6 @@
                 raise
 
     @classmethod
-    def clear_resources(cls, resource_name, resources, resource_del_func):
-        LOG.debug('Clearing %s: %s', resource_name,
-                  ','.join(map(str, resources)))
-        for res_id in resources:
-            try:
-                test_utils.call_and_ignore_notfound_exc(
-                    resource_del_func, res_id)
-            except Exception as exc:
-                LOG.exception('Exception raised deleting %s: %s',
-                              resource_name, res_id)
-                LOG.exception(exc)
-
-    @classmethod
     def create_test_server(cls, validatable=False, volume_backed=False,
                            validation_resources=None, **kwargs):
         """Wrapper utility that returns a test server.
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 93638b8..4b97b80 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -155,6 +155,30 @@
         self.assertEqual(volume['snapshot_id'], src_snap['id'])
         self.assertEqual(volume['size'], src_size + 1)
 
+    @decorators.idempotent_id('053d8870-8282-4fff-9dbb-99cb58bb5e0a')
+    def test_volume_from_snapshot_no_size(self):
+        # Creates a volume from a snapshot defaulting to original size
+        src_size = CONF.volume.volume_size
+
+        src_vol = self.create_volume(size=src_size)
+        src_snap = self.create_snapshot(src_vol['id'])
+        # Destination volume without specifying a size
+        dst_vol = self.create_volume(snapshot_id=src_snap['id'])
+
+        # NOTE(zhufl): dst_vol is created based on snapshot, so dst_vol
+        # should be deleted before deleting snapshot, otherwise deleting
+        # snapshot will end with status 'error-deleting'. This depends on
+        # the implementation mechanism of vendors, generally speaking,
+        # some verdors will use "virtual disk clone" which will promote
+        # disk clone speed, and in this situation the "disk clone"
+        # is just a relationship between volume and snapshot.
+        self.addCleanup(self.delete_volume, self.volumes_client, dst_vol['id'])
+
+        volume = self.volumes_client.show_volume(dst_vol['id'])['volume']
+        # Should allow
+        self.assertEqual(volume['snapshot_id'], src_snap['id'])
+        self.assertEqual(volume['size'], src_size)
+
     @decorators.idempotent_id('bbcfa285-af7f-479e-8c1a-8c34fc16543c')
     @testtools.skipUnless(CONF.volume_feature_enabled.backup,
                           "Cinder backup is disabled")
diff --git a/tempest/clients.py b/tempest/clients.py
index 4f2846e..204ce08 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -222,22 +222,6 @@
 
     def _set_volume_clients(self):
 
-        if CONF.volume_feature_enabled.api_v1:
-            self.backups_client = self.volume_v1.BackupsClient()
-            self.encryption_types_client = \
-                self.volume_v1.EncryptionTypesClient()
-            self.snapshots_client = self.volume_v1.SnapshotsClient()
-            self.volume_availability_zone_client = \
-                self.volume_v1.AvailabilityZoneClient()
-            self.volume_hosts_client = self.volume_v1.HostsClient()
-            self.volume_limits_client = self.volume_v1.LimitsClient()
-            self.volume_qos_client = self.volume_v1.QosSpecsClient()
-            self.volume_quotas_client = self.volume_v1.QuotasClient()
-            self.volume_services_client = self.volume_v1.ServicesClient()
-            self.volume_types_client = self.volume_v1.TypesClient()
-            self.volumes_client = self.volume_v1.VolumesClient()
-            self.volumes_extension_client = self.volume_v1.ExtensionsClient()
-
         # if only api_v3 is enabled, all these clients should be available
         if (CONF.volume_feature_enabled.api_v2 or
             CONF.volume_feature_enabled.api_v3):
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index aa333b3..50691ad 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -205,10 +205,6 @@
 def verify_cinder_api_versions(os, update):
     # Check cinder api versions
     versions = _get_api_versions(os, 'cinder')
-    if (CONF.volume_feature_enabled.api_v1 !=
-            contains_version('v1.', versions)):
-        print_and_or_update('api_v1', 'volume-feature-enabled',
-                            not CONF.volume_feature_enabled.api_v1, update)
     if (CONF.volume_feature_enabled.api_v2 !=
             contains_version('v2.', versions)):
         print_and_or_update('api_v2', 'volume-feature-enabled',
diff --git a/tempest/config.py b/tempest/config.py
index 0f3fa54..8314e1e 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -836,13 +836,6 @@
                 help='A list of enabled volume extensions with a special '
                      'entry all which indicates every extension is enabled. '
                      'Empty list indicates all extensions are disabled'),
-    cfg.BoolOpt('api_v1',
-                default=False,
-                help="Is the v1 volume API enabled",
-                deprecated_for_removal=True,
-                deprecated_reason="The v1 volume API has been deprecated "
-                                  "since Juno release, and the API will be "
-                                  "removed."),
     cfg.BoolOpt('api_v2',
                 default=True,
                 help="Is the v2 volume API enabled",
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index a72675e..2c40cb1 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -15,7 +15,7 @@
 import os
 import re
 
-import pep8
+import pycodestyle
 
 
 PYTHON_CLIENTS = ['cinder', 'glance', 'keystone', 'nova', 'swift', 'neutron',
@@ -69,7 +69,7 @@
 
 def no_setup_teardown_class_for_tests(physical_line, filename):
 
-    if pep8.noqa(physical_line):
+    if pycodestyle.noqa(physical_line):
         return
 
     if 'tempest/test.py' in filename or 'tempest/lib/' in filename:
@@ -164,7 +164,7 @@
     if not METHOD.match(physical_line):
         return False
 
-    if pep8.noqa(physical_line):
+    if pycodestyle.noqa(physical_line):
         return False
 
     return True
@@ -287,7 +287,7 @@
     if 'tempest/api/' not in filename:
         return
 
-    if pep8.noqa(physical_line):
+    if pycodestyle.noqa(physical_line):
         return
 
     if not re.match(r'class .*Test.*\(.*Admin.*\):', logical_line):
diff --git a/tempest/lib/api_schema/response/compute/v2_8/__init__.py b/tempest/lib/api_schema/response/compute/v2_8/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_8/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_8/servers.py b/tempest/lib/api_schema/response/compute/v2_8/servers.py
new file mode 100644
index 0000000..df7847f
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_8/servers.py
@@ -0,0 +1,37 @@
+# Copyright 2018 AT&T Corporation.  All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import copy
+
+from tempest.lib.api_schema.response.compute.v2_6 import servers
+
+# 2.8: Add 'mks' protocol and 'webmks' type for remote consoles.
+get_remote_consoles = copy.deepcopy(servers.get_remote_consoles)
+get_remote_consoles['response_body']['properties']['remote_console'][
+    'properties']['protocol']['enum'].append('mks')
+get_remote_consoles['response_body']['properties']['remote_console'][
+    'properties']['type']['enum'].append('webmks')
+
+# NOTE: Below are the unchanged schema in this microversion. We need
+# to keep this schema in this file to have the generic way to select the
+# right schema based on self.schema_versions_info mapping in service client.
+# ****** Schemas unchanged since microversion 2.6 ******
+list_servers = copy.deepcopy(servers.list_servers)
+get_server = copy.deepcopy(servers.get_server)
+list_servers_detail = copy.deepcopy(servers.list_servers_detail)
+update_server = copy.deepcopy(servers.update_server)
+rebuild_server = copy.deepcopy(servers.rebuild_server)
+rebuild_server_with_admin_pass = copy.deepcopy(
+    servers.rebuild_server_with_admin_pass)
+show_server_diagnostics = copy.deepcopy(servers.show_server_diagnostics)
diff --git a/tempest/lib/api_schema/response/compute/v2_9/servers.py b/tempest/lib/api_schema/response/compute/v2_9/servers.py
index f412839..55f8e75 100644
--- a/tempest/lib/api_schema/response/compute/v2_9/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_9/servers.py
@@ -14,16 +14,7 @@
 
 import copy
 
-from tempest.lib.api_schema.response.compute.v2_1 import servers as servers_21
-from tempest.lib.api_schema.response.compute.v2_6 import servers
-
-# NOTE: Below are the unchanged schema in this microversion. We need
-# to keep this schema in this file to have the generic way to select the
-# right schema based on self.schema_versions_info mapping in service client.
-# ****** Schemas unchanged since microversion 2.6 ******
-list_servers = copy.deepcopy(servers.list_servers)
-show_server_diagnostics = copy.deepcopy(servers.show_server_diagnostics)
-get_remote_consoles = copy.deepcopy(servers.get_remote_consoles)
+from tempest.lib.api_schema.response.compute.v2_8 import servers
 
 get_server = copy.deepcopy(servers.get_server)
 get_server['response_body']['properties']['server'][
@@ -37,21 +28,29 @@
 list_servers_detail['response_body']['properties']['servers']['items'][
     'required'].append('locked')
 
-update_server = copy.deepcopy(servers_21.update_server)
+update_server = copy.deepcopy(servers.update_server)
 update_server['response_body']['properties']['server'][
     'properties'].update({'locked': {'type': 'boolean'}})
 update_server['response_body']['properties']['server'][
     'required'].append('locked')
 
-rebuild_server = copy.deepcopy(servers_21.rebuild_server)
+rebuild_server = copy.deepcopy(servers.rebuild_server)
 rebuild_server['response_body']['properties']['server'][
     'properties'].update({'locked': {'type': 'boolean'}})
 rebuild_server['response_body']['properties']['server'][
     'required'].append('locked')
 
 rebuild_server_with_admin_pass = copy.deepcopy(
-    servers_21.rebuild_server_with_admin_pass)
+    servers.rebuild_server_with_admin_pass)
 rebuild_server_with_admin_pass['response_body']['properties']['server'][
     'properties'].update({'locked': {'type': 'boolean'}})
 rebuild_server_with_admin_pass['response_body']['properties']['server'][
     'required'].append('locked')
+
+# NOTE: Below are the unchanged schema in this microversion. We need
+# to keep this schema in this file to have the generic way to select the
+# right schema based on self.schema_versions_info mapping in service client.
+# ****** Schemas unchanged since microversion 2.8 ******
+list_servers = copy.deepcopy(servers.list_servers)
+show_server_diagnostics = copy.deepcopy(servers.show_server_diagnostics)
+get_remote_consoles = copy.deepcopy(servers.get_remote_consoles)
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index bc9cfe2..e2fd722 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -570,8 +570,10 @@
 
         :param str url: Full url to send the request
         :param str method: The HTTP verb to use for the request
-        :param str headers: Headers to use for the request if none are specifed
-                            the headers
+        :param dict headers: Headers to use for the request. If none are
+                             specified, then the headers returned from the
+                             get_headers() method are used. If the request
+                             explicitly requires no headers use an empty dict.
         :param str body: Body to send with the request
         :param bool chunked: sends the body with chunked encoding
         :rtype: tuple
@@ -605,8 +607,8 @@
                                    returned by the get_headers() method are to
                                    be used but additional headers are needed in
                                    the request pass them in as a dict.
-        :param dict headers: Headers to use for the request if none are
-                             specifed the headers returned from the
+        :param dict headers: Headers to use for the request. If none are
+                             specified, then the headers returned from the
                              get_headers() method are used. If the request
                              explicitly requires no headers use an empty dict.
         :param str body: Body to send with the request
@@ -623,10 +625,13 @@
         :raises Gone: If a 410 response code is received
         :raises Conflict: If a 409 response code is received
         :raises PreconditionFailed: If a 412 response code is received
-        :raises OverLimit: If a 413 response code is received and over_limit is
-                          not in the response body
+        :raises OverLimit: If a 413 response code is received and retry-after
+                           is not in the response body or its retry operation
+                           exceeds the limits defined by the server
         :raises RateLimitExceeded: If a 413 response code is received and
-                                   over_limit is in the response body
+                                   retry-after is in the response body and
+                                   its retry operation does not exceeds the
+                                   limits defined by the server
         :raises InvalidContentType: If a 415 response code is received
         :raises UnprocessableEntity: If a 422 response code is received
         :raises InvalidHTTPResponseBody: The response body wasn't valid JSON
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index 0314356..9eed4b3 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -33,6 +33,7 @@
 from tempest.lib.api_schema.response.compute.v2_57 import servers as schemav257
 from tempest.lib.api_schema.response.compute.v2_6 import servers as schemav26
 from tempest.lib.api_schema.response.compute.v2_63 import servers as schemav263
+from tempest.lib.api_schema.response.compute.v2_8 import servers as schemav28
 from tempest.lib.api_schema.response.compute.v2_9 import servers as schemav29
 from tempest.lib.common import rest_client
 from tempest.lib.services.compute import base_compute_client
@@ -44,7 +45,8 @@
     schema_versions_info = [
         {'min': None, 'max': '2.2', 'schema': schema},
         {'min': '2.3', 'max': '2.5', 'schema': schemav23},
-        {'min': '2.6', 'max': '2.8', 'schema': schemav26},
+        {'min': '2.6', 'max': '2.7', 'schema': schemav26},
+        {'min': '2.8', 'max': '2.8', 'schema': schemav28},
         {'min': '2.9', 'max': '2.15', 'schema': schemav29},
         {'min': '2.16', 'max': '2.18', 'schema': schemav216},
         {'min': '2.19', 'max': '2.25', 'schema': schemav219},
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 79c2d14..810480b 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -11,6 +11,7 @@
 #    under the License.
 
 from oslo_log import log as logging
+from oslo_serialization import jsonutils
 import testtools
 
 from tempest.common import utils
@@ -49,7 +50,8 @@
                                      source_type,
                                      keypair=None,
                                      security_group=None,
-                                     delete_on_termination=False):
+                                     delete_on_termination=False,
+                                     name=None):
         create_kwargs = dict()
         if keypair:
             create_kwargs['key_name'] = keypair['name']
@@ -60,6 +62,8 @@
             source_id,
             source_type,
             delete_on_termination=delete_on_termination))
+        if name:
+            create_kwargs['name'] = name
 
         return self.create_server(image_id='', **create_kwargs)
 
@@ -67,6 +71,10 @@
         self.servers_client.delete_server(server['id'])
         waiters.wait_for_server_termination(self.servers_client, server['id'])
 
+    def _delete_snapshot(self, snapshot_id):
+        self.snapshots_client.delete_snapshot(snapshot_id)
+        self.snapshots_client.wait_for_resource_deletion(snapshot_id)
+
     @decorators.idempotent_id('557cd2c2-4eb8-4dce-98be-f86765ff311b')
     # Note: This test is being skipped based on 'public_network_id'.
     # It is being used in create_floating_ip() method which gets called
@@ -202,28 +210,29 @@
     def test_image_defined_boot_from_volume(self):
         # create an instance from image-backed volume
         volume_origin = self._create_volume_from_image()
-        instance = self._boot_instance_from_resource(
+        name = data_utils.rand_name(self.__class__.__name__ +
+                                    '-volume-backed-server')
+        instance1 = self._boot_instance_from_resource(
             source_id=volume_origin['id'],
             source_type='volume',
-            delete_on_termination=True)
+            delete_on_termination=True,
+            name=name)
         # Create a snapshot image from the volume-backed server.
         # The compute service will have the block service create a snapshot of
         # the root volume and store its metadata in the image.
-        image = self.create_server_snapshot(instance)
-
-        # Delete the first server which will also delete the first image-backed
-        # volume.
-        self._delete_server(instance)
+        image = self.create_server_snapshot(instance1)
 
         # Create a server from the image snapshot which has an
         # "image-defined block device mapping (BDM)" in it, i.e. the metadata
         # about the volume snapshot. The compute service will use this to
         # create a volume from the volume snapshot and use that as the root
         # disk for the server.
-        instance = self.create_server(image_id=image['id'])
+        name = data_utils.rand_name(self.__class__.__name__ +
+                                    '-image-snapshot-server')
+        instance2 = self.create_server(image_id=image['id'], name=name)
 
         # Verify the server was created from the image-defined BDM.
-        volume_attachments = instance['os-extended-volumes:volumes_attached']
+        volume_attachments = instance2['os-extended-volumes:volumes_attached']
         self.assertEqual(1, len(volume_attachments),
                          "No volume attachment found.")
         created_volume = self.volumes_client.show_volume(
@@ -232,7 +241,7 @@
         self.assertEqual(1, len(created_volume['attachments']),
                          "No server attachment found for volume: %s" %
                          created_volume)
-        self.assertEqual(instance['id'],
+        self.assertEqual(instance2['id'],
                          created_volume['attachments'][0]['server_id'])
         self.assertEqual(volume_attachments[0]['id'],
                          created_volume['attachments'][0]['volume_id'])
@@ -242,11 +251,30 @@
 
         # Delete the second server which should also delete the second volume
         # created from the volume snapshot.
-        self._delete_server(instance)
+        self._delete_server(instance2)
 
         # Assert that the underlying volume is gone.
         self.volumes_client.wait_for_resource_deletion(created_volume['id'])
 
+        # Delete the volume snapshot. We must do this before deleting the first
+        # server created in this test because the snapshot depends on the first
+        # instance's underlying volume (volume_origin).
+        # In glance v2, the image properties are flattened and in glance v1,
+        # the image properties are under the 'properties' key.
+        bdms = image.get('block_device_mapping')
+        if not bdms:
+            bdms = image['properties']['block_device_mapping']
+        bdms = jsonutils.loads(bdms)
+        snapshot_id = bdms[0]['snapshot_id']
+        self._delete_snapshot(snapshot_id)
+
+        # Now, delete the first server which will also delete the first
+        # image-backed volume.
+        self._delete_server(instance1)
+
+        # Assert that the underlying volume is gone.
+        self.volumes_client.wait_for_resource_deletion(volume_origin['id'])
+
     @decorators.idempotent_id('cb78919a-e553-4bab-b73b-10cf4d2eb125')
     @testtools.skipUnless(CONF.compute_feature_enabled.attach_encrypted_volume,
                           'Encrypted volume attach is not supported')
diff --git a/tempest/tests/cmd/test_tempest_init.py b/tempest/tests/cmd/test_tempest_init.py
index 5f39ac9..9042b12 100644
--- a/tempest/tests/cmd/test_tempest_init.py
+++ b/tempest/tests/cmd/test_tempest_init.py
@@ -22,7 +22,7 @@
 
 class TestTempestInit(base.TestCase):
 
-    def test_generate_testr_conf(self):
+    def test_generate_stestr_conf(self):
         # Create fake conf dir
         conf_dir = self.useFixture(fixtures.TempDir())
 
diff --git a/test-requirements.txt b/test-requirements.txt
index e33f207..196387c 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.13.0,<0.14,>=0.12.0 # Apache-2.0
+hacking>=1.1.0,<1.2.0 # Apache-2.0
 mock>=2.0.0 # BSD
 coverage!=4.4,>=4.0 # Apache-2.0
 oslotest>=3.2.0 # Apache-2.0
diff --git a/tox.ini b/tox.ini
index befa991..970f415 100644
--- a/tox.ini
+++ b/tox.ini
@@ -78,6 +78,7 @@
 deps = {[tempestenv]deps}
 # The regex below is used to select which tests to run and exclude the slow tag:
 # See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
+# FIXME: We can replace it with the `--black-regex` option to exclude tests now.
 commands =
     find . -type f -name "*.pyc" -delete
     tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.api)' {posargs}
@@ -100,6 +101,7 @@
 deps = {[tempestenv]deps}
 # The regex below is used to select which tests to run and exclude the slow tag:
 # See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
+# FIXME: We can replace it with the `--black-regex` option to exclude tests now.
 commands =
     find . -type f -name "*.pyc" -delete
     tempest run --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))' {posargs}
@@ -186,7 +188,8 @@
 # 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/
 # E123 skipped because it is ignored by default in the default pep8
 # E129 skipped because it is too limiting when combined with other rules
-ignore = E125,E123,E129
+# W504 skipped because it is overeager and unnecessary
+ignore = E125,E123,E129,W504
 show-source = True
 exclude = .git,.venv,.tox,dist,doc,*egg,build
 enable-extensions = H106,H203,H904