Merge "Refactor methods to be used by other tests"
diff --git a/.zuul.yaml b/.zuul.yaml
index 403c93d..f749b74 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -458,18 +458,6 @@
     override-checkout: stable/rocky
 
 - job:
-    name: tempest-full-queens
-    parent: tempest-full
-    nodeset: openstack-single-node-xenial
-    override-checkout: stable/queens
-
-- job:
-    name: tempest-full-queens-py3
-    parent: tempest-full-py3
-    nodeset: openstack-single-node-xenial
-    override-checkout: stable/queens
-
-- job:
     name: tempest-tox-plugin-sanity-check
     parent: tox
     description: |
@@ -615,8 +603,6 @@
       - integrated-gate
       - integrated-gate-py3
       - openstack-cover-jobs
-      - openstack-python-jobs
-      - openstack-python35-jobs
       - openstack-python3-train-jobs
       - publish-openstack-docs-pti
       - release-notes-jobs-python3
@@ -663,12 +649,10 @@
             irrelevant-files: *tempest-irrelevant-files
         - tempest-full-rocky:
             irrelevant-files: *tempest-irrelevant-files
+            voting: false
         - tempest-full-rocky-py3:
             irrelevant-files: *tempest-irrelevant-files
-        - tempest-full-queens:
-            irrelevant-files: *tempest-irrelevant-files
-        - tempest-full-queens-py3:
-            irrelevant-files: *tempest-irrelevant-files
+            voting: false
         - tempest-multinode-full:
             irrelevant-files: *tempest-irrelevant-files
         - tempest-multinode-full-py3:
@@ -769,8 +753,6 @@
         - tempest-full-stein-py3
         - tempest-full-rocky
         - tempest-full-rocky-py3
-        - tempest-full-queens
-        - tempest-full-queens-py3
     periodic:
       jobs:
         - tempest-all
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 7acfd62..ab994d1 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -48,6 +48,14 @@
    workspace
    run
 
+Supported OpenStack Releases and Python Versions
+------------------------------------------------
+
+.. toctree::
+   :maxdepth: 1
+
+   supported_version
+
 Developers Guide
 ================
 
diff --git a/doc/source/supported_version.rst b/doc/source/supported_version.rst
new file mode 100644
index 0000000..a97ec5b
--- /dev/null
+++ b/doc/source/supported_version.rst
@@ -0,0 +1,36 @@
+Supported OpenStack Releases and Python Versions
+================================================
+
+This Document list the officially supported OpenStack releases
+and python versions by Tempest.
+
+Compatible OpenStack Releases
+-----------------------------
+
+Tempest master supports the below OpenStack Releases:
+
+* Train
+* Stein
+* Rocky
+
+For older OpenStack Release:
+
+For any older OpenStack Release than the listed above, Tempest master might work. But if
+Tempest master starts failing then, you can use the respective Tempest tag listed in OpenStack
+release page.
+
+For example: OpenStack Stein: Tempest 20.0.0
+
+* https://releases.openstack.org/stein/index.html#stein-tempest
+
+How to use Tempest tag on Extended Maintenance stable branch:
+* https://review.opendev.org/#/c/681950/
+
+Supported Python Versions
+-------------------------
+
+Tempest master supports the below python versions:
+
+* Python 2.7
+* Python 3.6
+* Python 3.7
diff --git a/releasenotes/notes/add-consistency-group-exceptions-01cbb792cd710231.yaml b/releasenotes/notes/add-consistency-group-exceptions-01cbb792cd710231.yaml
new file mode 100644
index 0000000..e879c2c
--- /dev/null
+++ b/releasenotes/notes/add-consistency-group-exceptions-01cbb792cd710231.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+  - |
+    Fixed bug #1858417. Adding consistency group exceptions
+    ``ConsistencyGroupException`` and ``ConsistencyGroupSnapshotException``
+    that didn't exist before and caused failure in cinder-tempest-plugin.
diff --git a/releasenotes/notes/change-default-region-for-placement-to-empty-string-394f1132c28345bb.yaml b/releasenotes/notes/change-default-region-for-placement-to-empty-string-394f1132c28345bb.yaml
new file mode 100644
index 0000000..a28e4e2
--- /dev/null
+++ b/releasenotes/notes/change-default-region-for-placement-to-empty-string-394f1132c28345bb.yaml
@@ -0,0 +1,13 @@
+---
+upgrade:
+  - |
+     Default value of config option ``CONF.placement.region`` is updated
+     from ``RegionOne`` to empty string.
+
+     As per tempest design, if tempest conf is not having any region for
+     a service then identity region should be used. In case of placement
+     the default value is "RegionOne" which is considered as placement
+     region if region missing in tempest conf. In order to have identity
+     region to be used as default we need to change to empty string for
+     placement service. Empty string can be seen being used in other
+     services like volume, image etc.
diff --git a/releasenotes/notes/drop-py-3-5-support-76ca78f1a650fcad.yaml b/releasenotes/notes/drop-py-3-5-support-76ca78f1a650fcad.yaml
new file mode 100644
index 0000000..99ef31e
--- /dev/null
+++ b/releasenotes/notes/drop-py-3-5-support-76ca78f1a650fcad.yaml
@@ -0,0 +1,8 @@
+---
+prelude: >
+    Remove the support of python3.5.
+    Tempest, its plugins dependencies in ussuri cycle
+    are python-requires>=py3.6 which makes distro not
+    having python 3.6 to do hack to install py3.6 etc.
+    It time to drop the py3.5 from Tempest. Last supported
+    version of Tempest for py3.5 is 23.0.0.
diff --git a/releasenotes/notes/intermediate-ussuri-release-8aebeca312a6718c.yaml b/releasenotes/notes/intermediate-ussuri-release-8aebeca312a6718c.yaml
new file mode 100644
index 0000000..6caeacd
--- /dev/null
+++ b/releasenotes/notes/intermediate-ussuri-release-8aebeca312a6718c.yaml
@@ -0,0 +1,14 @@
+---
+prelude: >
+    This is an intermediate release during the Ussuri development cycle to
+    mark the end of support for EM Queens in Tempest.
+    After this release, Tempest will support below OpenStack Releases:
+
+      * Train
+      * Stein
+      * Rocky
+
+    Current development of Tempest is for OpenStack Ussuri development
+    cycle.
+
+    This is the last release of Tempest to officially support python2.7.
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 43c102c..bfd8b2d 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,8 @@
    :maxdepth: 1
 
    unreleased
+   v23.0.0
+   v22.1.0
    v22.0.0
    v21.0.0
    v20.0.0
diff --git a/releasenotes/source/v22.1.0.rst b/releasenotes/source/v22.1.0.rst
new file mode 100644
index 0000000..6a4fd1f
--- /dev/null
+++ b/releasenotes/source/v22.1.0.rst
@@ -0,0 +1,6 @@
+=====================
+v22.1.0 Release Notes
+=====================
+
+.. release-notes:: 22.1.0 Release Notes
+   :version: 22.1.0
diff --git a/releasenotes/source/v23.0.0.rst b/releasenotes/source/v23.0.0.rst
new file mode 100644
index 0000000..7c5edf8
--- /dev/null
+++ b/releasenotes/source/v23.0.0.rst
@@ -0,0 +1,6 @@
+=====================
+v23.0.0 Release Notes
+=====================
+
+.. release-notes:: 23.0.0 Release Notes
+   :version: 23.0.0
diff --git a/roles/run-tempest/README.rst b/roles/run-tempest/README.rst
index d4b253a..1f7fb70 100644
--- a/roles/run-tempest/README.rst
+++ b/roles/run-tempest/README.rst
@@ -72,3 +72,16 @@
    :default: ''
 
    The timeout (in seconds) for each test.
+
+.. zuul:rolevar:: stable_constraints_file
+   :default: ''
+
+   Upper constraints file to be used for stable branch till stable/rocky.
+
+.. zuul:rolevar:: tempest_tox_environment
+   :default: ''
+
+   Environment variable to set for run-tempst task.
+
+   Env variables set in this variable will be combined with some more
+   defaults env variable set at runtime.
diff --git a/roles/run-tempest/defaults/main.yaml b/roles/run-tempest/defaults/main.yaml
index 79df3e1..5867b6c 100644
--- a/roles/run-tempest/defaults/main.yaml
+++ b/roles/run-tempest/defaults/main.yaml
@@ -4,3 +4,6 @@
 tempest_black_regex: ''
 tox_extra_args: ''
 tempest_test_timeout: ''
+stable_constraints_file: "{{ devstack_base_dir }}/requirements/upper-constraints.txt"
+target_branch: "{{ zuul.branch }}"
+tempest_tox_environment: {}
diff --git a/roles/run-tempest/tasks/main.yaml b/roles/run-tempest/tasks/main.yaml
index 24bd4db..8686f9a 100644
--- a/roles/run-tempest/tasks/main.yaml
+++ b/roles/run-tempest/tasks/main.yaml
@@ -20,6 +20,21 @@
     default_concurrency: "{{ num_cores|int // 2 }}"
   when: num_cores|int > 3
 
+- name: Override target branch
+  set_fact:
+    target_branch: "{{ zuul.override_checkout }}"
+  when: zuul.override_checkout is defined
+
+- name: Use stable branch upper-constraints till stable/rocky
+  set_fact:
+    tempest_tox_environment: "{{ tempest_tox_environment | combine({'UPPER_CONSTRAINTS_FILE': stable_constraints_file}) }}"
+  when: target_branch in ["stable/ocata", "stable/pike", "stable/queens", "stable/rocky"]
+
+- name: Set OS_TEST_TIMEOUT if requested
+  set_fact:
+    tempest_tox_environment: "{{ tempest_tox_environment | combine({'OS_TEST_TIMEOUT': tempest_test_timeout}) }}"
+  when: tempest_test_timeout != ''
+
 - when:
     - tempest_test_blacklist is defined
   block:
@@ -42,4 +57,4 @@
     chdir: "{{devstack_base_dir}}/tempest"
   become: true
   become_user: tempest
-  environment: '{{ {"OS_TEST_TIMEOUT": tempest_test_timeout} if tempest_test_timeout else {} }}'
+  environment: "{{ tempest_tox_environment }}"
diff --git a/setup.cfg b/setup.cfg
index 1e9b8e9..dd30069 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -16,7 +16,6 @@
     Programming Language :: Python :: 2
     Programming Language :: Python :: 2.7
     Programming Language :: Python :: 3
-    Programming Language :: Python :: 3.5
     Programming Language :: Python :: 3.6
     Programming Language :: Python :: 3.7
 
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index b1a7c52..836b975 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -31,6 +31,13 @@
 
 class LiveMigrationTestBase(base.BaseV2ComputeAdminTest):
 
+    # These tests don't attempt any SSH validation nor do they use
+    # floating IPs on the instance, so all we need is a network and
+    # a subnet so the instance being migrated has a single port, but
+    # we need that to make sure we are properly updating the port
+    # host bindings during the live migration.
+    create_default_network = True
+
     @classmethod
     def skip_checks(cls):
         super(LiveMigrationTestBase, cls).skip_checks()
@@ -44,16 +51,6 @@
                 "Less than 2 compute nodes, skipping migration test.")
 
     @classmethod
-    def setup_credentials(cls):
-        # These tests don't attempt any SSH validation nor do they use
-        # floating IPs on the instance, so all we need is a network and
-        # a subnet so the instance being migrated has a single port, but
-        # we need that to make sure we are properly updating the port
-        # host bindings during the live migration.
-        cls.set_network_resources(network=True, subnet=True)
-        super(LiveMigrationTestBase, cls).setup_credentials()
-
-    @classmethod
     def setup_clients(cls):
         super(LiveMigrationTestBase, cls).setup_clients()
         cls.admin_migration_client = cls.os_admin.migrations_client
diff --git a/tempest/api/compute/admin/test_security_group_default_rules.py b/tempest/api/compute/admin/test_security_group_default_rules.py
deleted file mode 100644
index bca6a22..0000000
--- a/tempest/api/compute/admin/test_security_group_default_rules.py
+++ /dev/null
@@ -1,132 +0,0 @@
-# Copyright 2014 NEC 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 testtools
-
-from tempest.api.compute import base
-from tempest import config
-from tempest.lib import decorators
-from tempest.lib import exceptions as lib_exc
-
-CONF = config.CONF
-
-
-class SecurityGroupDefaultRulesTest(base.BaseV2ComputeAdminTest):
-    max_microversion = '2.35'
-
-    @classmethod
-    # TODO(GMann): Once Bug# 1311500 is fixed, these test can run
-    # for Neutron also.
-    @testtools.skipIf(CONF.service_available.neutron,
-                      "Skip as this functionality is not yet "
-                      "implemented in Neutron. Related Bug#1311500")
-    def setup_credentials(cls):
-        # A network and a subnet will be created for these tests
-        cls.set_network_resources(network=True, subnet=True)
-        super(SecurityGroupDefaultRulesTest, cls).setup_credentials()
-
-    @classmethod
-    def setup_clients(cls):
-        super(SecurityGroupDefaultRulesTest, cls).setup_clients()
-        cls.adm_client = cls.os_admin.security_group_default_rules_client
-
-    def _create_security_group_default_rules(self, ip_protocol='tcp',
-                                             from_port=22, to_port=22,
-                                             cidr='10.10.0.0/24'):
-        # Create Security Group default rule
-        rule = self.adm_client.create_security_default_group_rule(
-            ip_protocol=ip_protocol,
-            from_port=from_port,
-            to_port=to_port,
-            cidr=cidr)['security_group_default_rule']
-        self.assertEqual(ip_protocol, rule['ip_protocol'])
-        self.assertEqual(from_port, rule['from_port'])
-        self.assertEqual(to_port, rule['to_port'])
-        self.assertEqual(cidr, rule['ip_range']['cidr'])
-        return rule
-
-    @decorators.idempotent_id('6d880615-eec3-4d29-97c5-7a074dde239d')
-    def test_create_delete_security_group_default_rules(self):
-        # Create and delete Security Group default rule
-        ip_protocols = ['tcp', 'udp', 'icmp']
-        for ip_protocol in ip_protocols:
-            rule = self._create_security_group_default_rules(ip_protocol)
-            # Delete Security Group default rule
-            self.adm_client.delete_security_group_default_rule(rule['id'])
-            self.assertRaises(lib_exc.NotFound,
-                              self.adm_client.show_security_group_default_rule,
-                              rule['id'])
-
-    @decorators.idempotent_id('4d752e0a-33a1-4c3a-b498-ff8667ca22e5')
-    def test_create_security_group_default_rule_without_cidr(self):
-        ip_protocol = 'udp'
-        from_port = 80
-        to_port = 80
-        rule = self.adm_client.create_security_default_group_rule(
-            ip_protocol=ip_protocol,
-            from_port=from_port,
-            to_port=to_port)['security_group_default_rule']
-        self.addCleanup(self.adm_client.delete_security_group_default_rule,
-                        rule['id'])
-        self.assertNotEqual(0, rule['id'])
-        self.assertEqual('0.0.0.0/0', rule['ip_range']['cidr'])
-
-    @decorators.idempotent_id('29f2d218-69b0-4a95-8f3d-6bd0ef732b3a')
-    def test_create_security_group_default_rule_with_blank_cidr(self):
-        ip_protocol = 'icmp'
-        from_port = 10
-        to_port = 10
-        cidr = ''
-        rule = self.adm_client.create_security_default_group_rule(
-            ip_protocol=ip_protocol,
-            from_port=from_port,
-            to_port=to_port,
-            cidr=cidr)['security_group_default_rule']
-        self.addCleanup(self.adm_client.delete_security_group_default_rule,
-                        rule['id'])
-        self.assertNotEqual(0, rule['id'])
-        self.assertEqual('0.0.0.0/0', rule['ip_range']['cidr'])
-
-    @decorators.idempotent_id('6e6de55e-9146-4ae0-89f2-3569586e0b9b')
-    def test_security_group_default_rules_list(self):
-        ip_protocol = 'tcp'
-        from_port = 22
-        to_port = 22
-        cidr = '10.10.0.0/24'
-        rule = self._create_security_group_default_rules(ip_protocol,
-                                                         from_port,
-                                                         to_port,
-                                                         cidr)
-        self.addCleanup(self.adm_client.delete_security_group_default_rule,
-                        rule['id'])
-        rules = (self.adm_client.list_security_group_default_rules()
-                 ['security_group_default_rules'])
-        self.assertNotEmpty(rules)
-        self.assertIn(rule, rules)
-
-    @decorators.idempotent_id('15cbb349-86b4-4f71-a048-04b7ef3f150b')
-    def test_default_security_group_default_rule_show(self):
-        ip_protocol = 'tcp'
-        from_port = 22
-        to_port = 22
-        cidr = '10.10.0.0/24'
-        rule = self._create_security_group_default_rules(ip_protocol,
-                                                         from_port,
-                                                         to_port,
-                                                         cidr)
-        self.addCleanup(self.adm_client.delete_security_group_default_rule,
-                        rule['id'])
-        fetched_rule = self.adm_client.show_security_group_default_rule(
-            rule['id'])['security_group_default_rule']
-        self.assertEqual(rule, fetched_rule)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index aaf7a5a..dd6d593 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -39,6 +39,9 @@
     """Base test case class for all Compute API tests."""
 
     force_tenant_isolation = False
+    # Set this to True in subclasses to create a default network. See
+    # https://bugs.launchpad.net/tempest/+bug/1844568
+    create_default_network = False
 
     # TODO(andreaf) We should care also for the alt_manager here
     # but only once client lazy load in the manager is done
@@ -49,16 +52,22 @@
         super(BaseV2ComputeTest, cls).skip_checks()
         if not CONF.service_available.nova:
             raise cls.skipException("Nova is not available")
-        cfg_min_version = CONF.compute.min_microversion
-        cfg_max_version = CONF.compute.max_microversion
-        api_version_utils.check_skip_with_microversion(cls.min_microversion,
-                                                       cls.max_microversion,
-                                                       cfg_min_version,
-                                                       cfg_max_version)
+        api_version_utils.check_skip_with_microversion(
+            cls.min_microversion, cls.max_microversion,
+            CONF.compute.min_microversion, CONF.compute.max_microversion)
+        api_version_utils.check_skip_with_microversion(
+            cls.volume_min_microversion, cls.volume_max_microversion,
+            CONF.volume.min_microversion, CONF.volume.max_microversion)
+        api_version_utils.check_skip_with_microversion(
+            cls.placement_min_microversion, cls.placement_max_microversion,
+            CONF.placement.min_microversion, CONF.placement.max_microversion)
 
     @classmethod
     def setup_credentials(cls):
-        cls.set_network_resources()
+        # Setting network=True, subnet=True creates a default network
+        cls.set_network_resources(
+            network=cls.create_default_network,
+            subnet=cls.create_default_network)
         super(BaseV2ComputeTest, cls).setup_credentials()
 
     @classmethod
@@ -145,6 +154,14 @@
             api_version_utils.select_request_microversion(
                 cls.min_microversion,
                 CONF.compute.min_microversion))
+        cls.volume_request_microversion = (
+            api_version_utils.select_request_microversion(
+                cls.volume_min_microversion,
+                CONF.volume.min_microversion))
+        cls.placement_request_microversion = (
+            api_version_utils.select_request_microversion(
+                cls.placement_min_microversion,
+                CONF.placement.min_microversion))
         cls.build_interval = CONF.compute.build_interval
         cls.build_timeout = CONF.compute.build_timeout
         cls.image_ref = CONF.compute.image_ref
@@ -470,7 +487,9 @@
     def setUp(self):
         super(BaseV2ComputeTest, self).setUp()
         self.useFixture(api_microversion_fixture.APIMicroversionFixture(
-            compute_microversion=self.request_microversion))
+            compute_microversion=self.request_microversion,
+            volume_microversion=self.volume_request_microversion,
+            placement_microversion=self.placement_request_microversion))
 
     @classmethod
     def create_volume(cls, image_ref=None, **kwargs):
diff --git a/tempest/api/compute/security_groups/base.py b/tempest/api/compute/security_groups/base.py
index 49125d1..ef69a13 100644
--- a/tempest/api/compute/security_groups/base.py
+++ b/tempest/api/compute/security_groups/base.py
@@ -24,18 +24,14 @@
 class BaseSecurityGroupsTest(base.BaseV2ComputeTest):
     max_microversion = '2.35'
 
+    create_default_network = True
+
     @classmethod
     def skip_checks(cls):
         super(BaseSecurityGroupsTest, cls).skip_checks()
         if not utils.get_service_list()['network']:
             raise cls.skipException("network service not enabled.")
 
-    @classmethod
-    def setup_credentials(cls):
-        # A network and a subnet will be created for these tests
-        cls.set_network_resources(network=True, subnet=True)
-        super(BaseSecurityGroupsTest, cls).setup_credentials()
-
     @staticmethod
     def generate_random_security_group_id():
         if (CONF.service_available.neutron and
diff --git a/tempest/api/compute/servers/test_delete_server.py b/tempest/api/compute/servers/test_delete_server.py
index 0263b81..a7db88a 100644
--- a/tempest/api/compute/servers/test_delete_server.py
+++ b/tempest/api/compute/servers/test_delete_server.py
@@ -26,6 +26,7 @@
 
 
 class DeleteServersTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     # NOTE: Server creations of each test class should be under 10
     # for preventing "Quota exceeded for instances"
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index bc48069..5b8e7ab 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -24,6 +24,7 @@
 
 
 class ServerDiskConfigTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index b916a42..00837eb 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -19,6 +19,7 @@
 
 
 class InstanceActionsTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
@@ -54,6 +55,7 @@
 
 
 class InstanceActionsV221TestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     min_microversion = '2.21'
     max_microversion = 'latest'
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
index 1d3a790..4b5a2c3 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -20,6 +20,7 @@
 
 
 class InstanceActionsNegativeTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index f0915de..b95db5c 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -20,6 +20,7 @@
 
 
 class ListServersNegativeTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 059454d..e176251 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -19,6 +19,7 @@
 
 
 class MultipleCreateTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @decorators.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
     def test_multiple_create(self):
diff --git a/tempest/api/compute/servers/test_novnc.py b/tempest/api/compute/servers/test_novnc.py
index 7cf6d83..68e09e7 100644
--- a/tempest/api/compute/servers/test_novnc.py
+++ b/tempest/api/compute/servers/test_novnc.py
@@ -33,6 +33,7 @@
 
 
 class NoVNCConsoleTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index f79b05f..c936ce5 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -19,12 +19,7 @@
 
 
 class ServerAddressesTestJSON(base.BaseV2ComputeTest):
-
-    @classmethod
-    def setup_credentials(cls):
-        # This test module might use a network and a subnet
-        cls.set_network_resources(network=True, subnet=True)
-        super(ServerAddressesTestJSON, cls).setup_credentials()
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index b2b3cc0..f33c6d9 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -20,11 +20,7 @@
 
 
 class ServerAddressesNegativeTestJSON(base.BaseV2ComputeTest):
-
-    @classmethod
-    def setup_credentials(cls):
-        cls.set_network_resources(network=True, subnet=True)
-        super(ServerAddressesNegativeTestJSON, cls).setup_credentials()
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_server_group.py b/tempest/api/compute/servers/test_server_group.py
index 1b7cb96..4b5efaa 100644
--- a/tempest/api/compute/servers/test_server_group.py
+++ b/tempest/api/compute/servers/test_server_group.py
@@ -29,6 +29,7 @@
     policies = affinity/anti-affinity
     It also adds the tests for list and get details of server-groups
     """
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index fe95018..9d87e1c 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -18,6 +18,7 @@
 
 
 class ServerMetadataTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_server_password.py b/tempest/api/compute/servers/test_server_password.py
index e6a668a..7b31ede 100644
--- a/tempest/api/compute/servers/test_server_password.py
+++ b/tempest/api/compute/servers/test_server_password.py
@@ -19,6 +19,7 @@
 
 
 class ServerPasswordTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/compute/servers/test_server_tags.py b/tempest/api/compute/servers/test_server_tags.py
index 8d0a4e3..3893b01 100644
--- a/tempest/api/compute/servers/test_server_tags.py
+++ b/tempest/api/compute/servers/test_server_tags.py
@@ -26,6 +26,8 @@
     min_microversion = '2.26'
     max_microversion = 'latest'
 
+    create_default_network = True
+
     @classmethod
     def skip_checks(cls):
         super(ServerTagsTestJSON, cls).skip_checks()
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 1e3e966..3a4bd6d 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -25,6 +25,7 @@
 
 
 class ServersTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 1759d64..7fa30b0 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -30,6 +30,7 @@
 
 
 class ServersNegativeTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     def setUp(self):
         super(ServersNegativeTestJSON, self).setUp()
@@ -47,11 +48,6 @@
         self.server_check_teardown()
 
     @classmethod
-    def setup_credentials(cls):
-        cls.set_network_resources(network=True, subnet=True)
-        super(ServersNegativeTestJSON, cls).setup_credentials()
-
-    @classmethod
     def setup_clients(cls):
         super(ServersNegativeTestJSON, cls).setup_clients()
         cls.client = cls.servers_client
@@ -559,6 +555,7 @@
 
 
 class ServersNegativeTestMultiTenantJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     credentials = ['primary', 'alt']
 
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index f810ec5..dfd6ca4 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -32,11 +32,7 @@
 
     depends_on_nova_network = True
 
-    @classmethod
-    def setup_credentials(cls):
-        # This test needs a network and a subnet
-        cls.set_network_resources(network=True, subnet=True)
-        super(VirtualInterfacesTestJSON, cls).setup_credentials()
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 92524fc..97813a5 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -28,6 +28,7 @@
 
 class BaseAttachVolumeTest(base.BaseV2ComputeTest):
     """Base class for the attach volume tests in this module."""
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
@@ -79,7 +80,7 @@
             # NOTE(andreaf) We need to ensure the ssh key has been
             # injected in the guest before we power cycle
             linux_client.validate_authentication()
-            disks_before_attach = linux_client.count_disks()
+            disks_before_attach = linux_client.list_disks()
 
         volume = self.create_volume()
 
@@ -101,8 +102,10 @@
                                        'ACTIVE')
 
         if CONF.validation.run_validation:
-            disks_after_attach = linux_client.count_disks()
-            self.assertGreater(disks_after_attach, disks_before_attach)
+            disks_after_attach = linux_client.list_disks()
+            self.assertGreater(
+                len(disks_after_attach),
+                len(disks_before_attach))
 
         self.servers_client.detach_volume(server['id'], attachment['volumeId'])
         waiters.wait_for_volume_resource_status(
@@ -117,8 +120,8 @@
                                        'ACTIVE')
 
         if CONF.validation.run_validation:
-            disks_after_detach = linux_client.count_disks()
-            self.assertEqual(disks_before_attach, disks_after_detach)
+            disks_after_detach = linux_client.list_disks()
+            self.assertEqual(len(disks_before_attach), len(disks_after_detach))
 
     @decorators.idempotent_id('7fa563fe-f0f7-43eb-9e22-a1ece036b513')
     def test_list_get_volume_attachments(self):
diff --git a/tempest/api/compute/volumes/test_attach_volume_negative.py b/tempest/api/compute/volumes/test_attach_volume_negative.py
index 6d08f90..9a506af 100644
--- a/tempest/api/compute/volumes/test_attach_volume_negative.py
+++ b/tempest/api/compute/volumes/test_attach_volume_negative.py
@@ -21,6 +21,7 @@
 
 
 class AttachVolumeNegativeTest(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
index f61d9f8..1567e06 100644
--- a/tempest/api/object_storage/test_crossdomain.py
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -34,13 +34,12 @@
     def setUp(self):
         super(CrossdomainTest, self).setUp()
 
-        # Turning http://.../v1/foobar into http://.../
-        self.account_client.skip_path()
-
     @decorators.idempotent_id('d1b8b031-b622-4010-82f9-ff78a9e915c7')
     @utils.requires_ext(extension='crossdomain', service='object')
     def test_get_crossdomain_policy(self):
-        resp, body = self.account_client.get("crossdomain.xml", {})
+        url = self.account_client._get_base_version_url() + "crossdomain.xml"
+        resp, body = self.account_client.raw_request(url, "GET")
+        self.account_client._error_checker(resp, body)
         body = body.decode()
 
         self.assertTrue(body.startswith(self.xml_start) and
diff --git a/tempest/api/object_storage/test_healthcheck.py b/tempest/api/object_storage/test_healthcheck.py
index a186f9e..8e9e406 100644
--- a/tempest/api/object_storage/test_healthcheck.py
+++ b/tempest/api/object_storage/test_healthcheck.py
@@ -22,13 +22,12 @@
 
     def setUp(self):
         super(HealthcheckTest, self).setUp()
-        # Turning http://.../v1/foobar into http://.../
-        self.account_client.skip_path()
 
     @decorators.idempotent_id('db5723b1-f25c-49a9-bfeb-7b5640caf337')
     def test_get_healthcheck(self):
-
-        resp, _ = self.account_client.get("healthcheck", {})
+        url = self.account_client._get_base_version_url() + "healthcheck"
+        resp, body = self.account_client.raw_request(url, "GET")
+        self.account_client._error_checker(resp, body)
 
         # The target of the request is not any Swift resource. Therefore, the
         # existence of response header is checked without a custom matcher.
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 5875da3..b68a879 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -73,12 +73,12 @@
             msg = "'TYPE' column is required but the output doesn't have it: "
             raise tempest.lib.exceptions.TempestException(msg + output)
 
-    def count_disks(self):
+    def list_disks(self):
         disks_list = self.get_disks()
         disks_list = [line[0] for line in
                       [device_name.split()
                        for device_name in disks_list.splitlines()][1:]]
-        return len(disks_list)
+        return disks_list
 
     def get_boot_time(self):
         cmd = 'cut -f1 -d. /proc/uptime'
diff --git a/tempest/config.py b/tempest/config.py
index 32cebc5..4e08a11 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -390,7 +390,7 @@
                default='placement',
                help="Catalog type of the Placement service."),
     cfg.StrOpt('region',
-               default='RegionOne',
+               default='',
                help="The placement region name to use. If empty, the value "
                     "of [identity]/region is used instead. If no such region "
                     "is found in the service catalog, the first region found "
diff --git a/tempest/lib/api_schema/response/compute/v2_71/servers.py b/tempest/lib/api_schema/response/compute/v2_71/servers.py
index 0c526fb..5cf0f8a 100644
--- a/tempest/lib/api_schema/response/compute/v2_71/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_71/servers.py
@@ -69,7 +69,7 @@
 # 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.70 ***
-list_servers_details = copy.deepcopy(servers270.list_servers_detail)
+list_servers_detail = copy.deepcopy(servers270.list_servers_detail)
 list_servers = copy.deepcopy(servers270.list_servers)
 show_server_diagnostics = copy.deepcopy(servers270.show_server_diagnostics)
 get_remote_consoles = copy.deepcopy(servers270.get_remote_consoles)
diff --git a/tempest/lib/common/api_version_utils.py b/tempest/lib/common/api_version_utils.py
index d29362d..80dbc1d 100644
--- a/tempest/lib/common/api_version_utils.py
+++ b/tempest/lib/common/api_version_utils.py
@@ -32,6 +32,10 @@
     # (min_microversion, max_microversion) on each test class if necessary.
     min_microversion = None
     max_microversion = LATEST_MICROVERSION
+    volume_min_microversion = None
+    volume_max_microversion = LATEST_MICROVERSION
+    placement_min_microversion = None
+    placement_max_microversion = LATEST_MICROVERSION
 
 
 def check_skip_with_microversion(test_min_version, test_max_version,
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index 13af890..b25b4b2 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -280,3 +280,12 @@
 
 class InvalidParam(TempestException):
     message = ("Invalid Parameter passed: %(invalid_param)s")
+
+
+class ConsistencyGroupException(TempestException):
+    message = "Consistency group %(cg_id)s failed and is in ERROR status"
+
+
+class ConsistencyGroupSnapshotException(TempestException):
+    message = ("Consistency group snapshot %(cgsnapshot_id)s failed and is "
+               "in ERROR status")
diff --git a/tempest/lib/services/object_storage/capabilities_client.py b/tempest/lib/services/object_storage/capabilities_client.py
index d31bbc2..f08bd9a 100644
--- a/tempest/lib/services/object_storage/capabilities_client.py
+++ b/tempest/lib/services/object_storage/capabilities_client.py
@@ -21,9 +21,10 @@
 class CapabilitiesClient(rest_client.RestClient):
 
     def list_capabilities(self):
-        self.skip_path()
         try:
-            resp, body = self.get('info')
+            url = self._get_base_version_url() + 'info'
+            resp, body = self.raw_request(url, 'GET')
+            self._error_checker(resp, body)
         finally:
             self.reset_path()
         body = json.loads(body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 3d04187..cb7acbf 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -634,8 +634,7 @@
 
     def nova_volume_attach(self, server, volume_to_attach):
         volume = self.servers_client.attach_volume(
-            server['id'], volumeId=volume_to_attach['id'], device='/dev/%s'
-            % CONF.compute.volume_device_name)['volumeAttachment']
+            server['id'], volumeId=volume_to_attach['id'])['volumeAttachment']
         self.assertEqual(volume_to_attach['id'], volume['id'])
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume['id'], 'in-use')
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index af79ea0..c3b3670 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -55,20 +55,24 @@
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
 
-    def _wait_for_volume_available_on_the_system(self, ip_address,
-                                                 private_key):
+    def _attached_volume_name(
+            self, disks_list_before_attach, ip_address, private_key):
         ssh = self.get_remote_client(ip_address, private_key=private_key)
 
-        def _func():
-            disks = ssh.get_disks()
-            LOG.debug("Disks: %s", disks)
-            return CONF.compute.volume_device_name in disks
+        def _wait_for_volume_available_on_system():
+            disks_list_after_attach = ssh.list_disks()
+            return len(disks_list_after_attach) > len(disks_list_before_attach)
 
-        if not test_utils.call_until_true(_func,
+        if not test_utils.call_until_true(_wait_for_volume_available_on_system,
                                           CONF.compute.build_timeout,
                                           CONF.compute.build_interval):
             raise lib_exc.TimeoutException
 
+        disks_list_after_attach = ssh.list_disks()
+        volume_name = [item for item in disks_list_after_attach
+                       if item not in disks_list_before_attach][0]
+        return volume_name
+
     @decorators.attr(type='slow')
     @decorators.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
@@ -91,15 +95,16 @@
         ip_for_server = self.get_server_ip(server)
 
         # Make sure the machine ssh-able before attaching the volume
-        self.get_remote_client(ip_for_server,
-                               private_key=keypair['private_key'],
-                               server=server)
-
+        linux_client = self.get_remote_client(
+            ip_for_server, private_key=keypair['private_key'],
+            server=server)
+        disks_list_before_attach = linux_client.list_disks()
         self.nova_volume_attach(server, volume)
-        self._wait_for_volume_available_on_the_system(ip_for_server,
-                                                      keypair['private_key'])
+        volume_device_name = self._attached_volume_name(
+            disks_list_before_attach, ip_for_server, keypair['private_key'])
+
         timestamp = self.create_timestamp(ip_for_server,
-                                          CONF.compute.volume_device_name,
+                                          volume_device_name,
                                           private_key=keypair['private_key'],
                                           server=server)
         self.nova_volume_detach(server, volume)
@@ -126,18 +131,19 @@
         # Make sure the machine ssh-able before attaching the volume
         # Just a live machine is responding
         # for device attache/detach as expected
-        self.get_remote_client(ip_for_snapshot,
-                               private_key=keypair['private_key'],
-                               server=server_from_snapshot)
+        linux_client = self.get_remote_client(
+            ip_for_snapshot, private_key=keypair['private_key'],
+            server=server_from_snapshot)
+        disks_list_before_attach = linux_client.list_disks()
 
         # attach volume2 to instance2
         self.nova_volume_attach(server_from_snapshot, volume_from_snapshot)
-        self._wait_for_volume_available_on_the_system(ip_for_snapshot,
-                                                      keypair['private_key'])
+        volume_device_name = self._attached_volume_name(
+            disks_list_before_attach, ip_for_snapshot, keypair['private_key'])
 
         # check the existence of the timestamp file in the volume2
         timestamp2 = self.get_timestamp(ip_for_snapshot,
-                                        CONF.compute.volume_device_name,
+                                        volume_device_name,
                                         private_key=keypair['private_key'],
                                         server=server_from_snapshot)
         self.assertEqual(timestamp, timestamp2)
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index 02e1c99..6275f22 100755
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -54,44 +54,6 @@
                           waiters.wait_for_image_status,
                           self.client, 'fake_image_id', 'active')
 
-    @mock.patch.object(time, 'sleep')
-    def test_wait_for_volume_status_error_restoring(self, mock_sleep):
-        # Tests that the wait method raises VolumeRestoreErrorException if
-        # the volume status is 'error_restoring'.
-        client = mock.Mock(spec=volumes_client.VolumesClient,
-                           resource_type="volume",
-                           build_interval=1)
-        volume1 = {'volume': {'status': 'restoring-backup'}}
-        volume2 = {'volume': {'status': 'error_restoring'}}
-        mock_show = mock.Mock(side_effect=(volume1, volume2))
-        client.show_volume = mock_show
-        volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
-        self.assertRaises(exceptions.VolumeRestoreErrorException,
-                          waiters.wait_for_volume_resource_status,
-                          client, volume_id, 'available')
-        mock_show.assert_has_calls([mock.call(volume_id),
-                                    mock.call(volume_id)])
-        mock_sleep.assert_called_once_with(1)
-
-    @mock.patch.object(time, 'sleep')
-    def test_wait_for_volume_status_error_extending(self, mock_sleep):
-        # Tests that the wait method raises VolumeExtendErrorException if
-        # the volume status is 'error_extending'.
-        client = mock.Mock(spec=volumes_client.VolumesClient,
-                           resource_type="volume",
-                           build_interval=1)
-        volume1 = {'volume': {'status': 'extending'}}
-        volume2 = {'volume': {'status': 'error_extending'}}
-        mock_show = mock.Mock(side_effect=(volume1, volume2))
-        client.show_volume = mock_show
-        volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
-        self.assertRaises(exceptions.VolumeExtendErrorException,
-                          waiters.wait_for_volume_resource_status,
-                          client, volume_id, 'available')
-        mock_show.assert_has_calls([mock.call(volume_id),
-                                    mock.call(volume_id)])
-        mock_sleep.assert_called_once_with(1)
-
 
 class TestInterfaceWaiters(base.TestCase):
 
@@ -232,3 +194,41 @@
         show_volume.assert_has_calls([mock.call(mock.sentinel.volume_id),
                                       mock.call(mock.sentinel.volume_id),
                                       mock.call(mock.sentinel.volume_id)])
+
+    @mock.patch.object(time, 'sleep')
+    def test_wait_for_volume_status_error_restoring(self, mock_sleep):
+        # Tests that the wait method raises VolumeRestoreErrorException if
+        # the volume status is 'error_restoring'.
+        client = mock.Mock(spec=volumes_client.VolumesClient,
+                           resource_type="volume",
+                           build_interval=1)
+        volume1 = {'volume': {'status': 'restoring-backup'}}
+        volume2 = {'volume': {'status': 'error_restoring'}}
+        mock_show = mock.Mock(side_effect=(volume1, volume2))
+        client.show_volume = mock_show
+        volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
+        self.assertRaises(exceptions.VolumeRestoreErrorException,
+                          waiters.wait_for_volume_resource_status,
+                          client, volume_id, 'available')
+        mock_show.assert_has_calls([mock.call(volume_id),
+                                    mock.call(volume_id)])
+        mock_sleep.assert_called_once_with(1)
+
+    @mock.patch.object(time, 'sleep')
+    def test_wait_for_volume_status_error_extending(self, mock_sleep):
+        # Tests that the wait method raises VolumeExtendErrorException if
+        # the volume status is 'error_extending'.
+        client = mock.Mock(spec=volumes_client.VolumesClient,
+                           resource_type="volume",
+                           build_interval=1)
+        volume1 = {'volume': {'status': 'extending'}}
+        volume2 = {'volume': {'status': 'error_extending'}}
+        mock_show = mock.Mock(side_effect=(volume1, volume2))
+        client.show_volume = mock_show
+        volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
+        self.assertRaises(exceptions.VolumeExtendErrorException,
+                          waiters.wait_for_volume_resource_status,
+                          client, volume_id, 'available')
+        mock_show.assert_has_calls([mock.call(volume_id),
+                                    mock.call(volume_id)])
+        mock_sleep.assert_called_once_with(1)
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index caad41c..937f93a 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -106,14 +106,15 @@
         self.assertEqual(self.conn.get_disks(), result)
         self._assert_exec_called_with('lsblk -lb --nodeps')
 
-    def test_count_disk(self):
+    def test_list_disks(self):
         output_lsblk = """\
 NAME       MAJ:MIN    RM          SIZE RO TYPE MOUNTPOINT
 sda          8:0       0  128035676160  0 disk
 sdb          8:16      0 1000204886016  0 disk
 sr0         11:0       1    1073741312  0 rom"""
+        disk_list = ['sda', 'sdb']
         self.ssh_mock.mock.exec_command.return_value = output_lsblk
-        self.assertEqual(self.conn.count_disks(), 2)
+        self.assertEqual(self.conn.list_disks(), disk_list)
 
     def test_get_boot_time(self):
         booted_at = 10000
diff --git a/tempest/tests/lib/services/object_storage/test_capabilities_client.py b/tempest/tests/lib/services/object_storage/test_capabilities_client.py
index b7f972a..9df7c7c 100644
--- a/tempest/tests/lib/services/object_storage/test_capabilities_client.py
+++ b/tempest/tests/lib/services/object_storage/test_capabilities_client.py
@@ -43,7 +43,7 @@
         }
         self.check_service_client_function(
             self.client.list_capabilities,
-            'tempest.lib.common.rest_client.RestClient.get',
+            'tempest.lib.common.rest_client.RestClient.raw_request',
             resp,
             bytes_body)
 
diff --git a/tox.ini b/tox.ini
index effd400..401bbfe 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,9 +1,11 @@
 [tox]
 envlist = pep8,py36,py37,py27,bashate,pip-check-reqs
-minversion = 2.3.1
+minversion = 3.1.1
 skipsdist = True
+ignore_basepython_conflict = True
 
 [tempestenv]
+basepython = python3
 sitepackages = False
 setenv =
     VIRTUAL_ENV={envdir}
@@ -13,6 +15,7 @@
     -r{toxinidir}/requirements.txt
 
 [testenv]
+basepython = python3
 setenv =
     VIRTUAL_ENV={envdir}
     OS_LOG_CAPTURE=1
@@ -49,12 +52,12 @@
   coverage report
 
 [testenv:debug]
-basepython = python3
 commands = oslo_debug_helper -t tempest/tests {posargs}
 
 [testenv:all]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 # 'all' includes slow tests
 setenv =
     {[tempestenv]setenv}
@@ -77,6 +80,7 @@
 setenv =
     {[tempestenv]setenv}
     OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:1200}
+basepython = {[tempestenv]basepython}
 deps = {[tempestenv]deps}
 commands =
     echo "WARNING: The all-plugin env is deprecated and will be removed"
@@ -90,6 +94,7 @@
 setenv =
     {[tempestenv]setenv}
     OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:1200}
+basepython = {[tempestenv]basepython}
 deps = {[tempestenv]deps}
 commands =
     find . -type f -name "*.pyc" -delete
@@ -98,6 +103,7 @@
 [testenv:full]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select which tests to run and exclude the slow tag:
@@ -111,6 +117,7 @@
 [testenv:full-parallel]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select all tempest scenario and including the non slow api tests
@@ -121,6 +128,7 @@
 [testenv:integrated-network]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select which tests to run and exclude the slow tag and
@@ -133,6 +141,7 @@
 [testenv:integrated-compute]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select which tests to run and exclude the slow tag and
@@ -145,6 +154,7 @@
 [testenv:integrated-placement]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select which tests to run and exclude the slow tag and
@@ -157,6 +167,7 @@
 [testenv:integrated-storage]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select which tests to run and exclude the slow tag and
@@ -169,6 +180,7 @@
 [testenv:integrated-object-storage]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select which tests to run and exclude the slow tag and
@@ -181,6 +193,7 @@
 [testenv:full-serial]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select which tests to run and exclude the slow tag:
@@ -193,6 +206,7 @@
 [testenv:scenario]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select all scenario tests
@@ -203,6 +217,7 @@
 [testenv:smoke]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 commands =
@@ -212,6 +227,7 @@
 [testenv:smoke-serial]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # This is still serial because neutron doesn't work with parallel. See:
@@ -224,6 +240,7 @@
 [testenv:slow-serial]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # The regex below is used to select the slow tagged tests to run serially:
@@ -234,6 +251,7 @@
 [testenv:ipv6-only]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 # Run only smoke and ipv6 tests. This env is used to tests
@@ -253,12 +271,12 @@
 [testenv:venv-tempest]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 commands = {posargs}
 
 [testenv:docs]
-basepython = python3
 deps =
   -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
   -r{toxinidir}/requirements.txt
@@ -269,7 +287,6 @@
 whitelist_externals = rm
 
 [testenv:pdf-docs]
-basepython = python3
 deps = {[testenv:docs]deps}
 whitelist_externals =
    make
@@ -281,7 +298,6 @@
 deps =
     -r{toxinidir}/test-requirements.txt
     autopep8
-basepython = python3
 commands =
     autopep8 --exit-code --max-line-length=79 --experimental --diff -r tempest setup.py
     flake8 {posargs}
@@ -289,7 +305,6 @@
 
 [testenv:autopep8]
 deps = autopep8
-basepython = python3
 commands =
     {toxinidir}/tools/format.sh
 
@@ -313,7 +328,6 @@
 import-order-style = pep8
 
 [testenv:releasenotes]
-basepython = python3
 deps =
   -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
   -r{toxinidir}/requirements.txt
@@ -325,7 +339,6 @@
 whitelist_externals = rm
 
 [testenv:bashate]
-basepython = python3
 # if you want to test out some changes you have made to bashate
 # against tempest, just set BASHATE_INSTALL_PATH=/path/... to your
 # modified bashate tree
@@ -360,7 +373,6 @@
 
 [testenv:plugin-sanity-check]
 # perform tempest plugin sanity
-basepython = python3
 whitelist_externals = bash
 commands =
   bash tools/tempest-plugin-sanity.sh