Merge "Chunked GET request support"
diff --git a/releasenotes/notes/add-ssh-allow-agent-2dee6448fd250e50.yaml b/releasenotes/notes/add-ssh-allow-agent-2dee6448fd250e50.yaml
new file mode 100644
index 0000000..33f11ce
--- /dev/null
+++ b/releasenotes/notes/add-ssh-allow-agent-2dee6448fd250e50.yaml
@@ -0,0 +1,10 @@
+---
+features:
+  - |
+    Adds a ``ssh_allow_agent`` parameter to the ``RemoteClient`` class
+    wrapper and the direct ssh ``Client`` class to allow a caller to
+    explicitly request that the SSH Agent is not consulted for
+    authentication. This is useful if your attempting explicit password
+    based authentication as ``paramiko``, the underlying library used for
+    SSH, defaults to utilizing an ssh-agent process before attempting
+    password authentication.
diff --git a/roles/run-tempest-26/tasks/main.yaml b/roles/run-tempest-26/tasks/main.yaml
index f846006..7423bfb 100644
--- a/roles/run-tempest-26/tasks/main.yaml
+++ b/roles/run-tempest-26/tasks/main.yaml
@@ -62,7 +62,9 @@
       when: blacklist_stat.stat.exists
 
 - name: Run Tempest
-  command: tox -e {{tox_envlist}} {{tox_extra_args}} -- {{tempest_test_regex|quote}} {{blacklist_option|default('')}} \
+  command: tox -e {{tox_envlist}} {{tox_extra_args}} -- \
+            {{tempest_test_regex|quote if (tempest_test_regex|length>0)|default(None, True)}} \
+            {{blacklist_option|default(None)}} \
             --concurrency={{tempest_concurrency|default(default_concurrency)}} \
             --black-regex={{tempest_black_regex|quote}}
   args:
diff --git a/roles/run-tempest/tasks/main.yaml b/roles/run-tempest/tasks/main.yaml
index f302fa5..3fb494f 100644
--- a/roles/run-tempest/tasks/main.yaml
+++ b/roles/run-tempest/tasks/main.yaml
@@ -25,11 +25,11 @@
     target_branch: "{{ zuul.override_checkout }}"
   when: zuul.override_checkout is defined
 
-- name: Use stable branch upper-constraints till stable/victoria
+- name: Use stable branch upper-constraints till stable/wallaby
   set_fact:
     # TOX_CONSTRAINTS_FILE is new name, UPPER_CONSTRAINTS_FILE is old one, best to set both
     tempest_tox_environment: "{{ tempest_tox_environment | combine({'UPPER_CONSTRAINTS_FILE': stable_constraints_file}) | combine({'TOX_CONSTRAINTS_FILE': stable_constraints_file}) }}"
-  when: target_branch in ["stable/ocata", "stable/pike", "stable/queens", "stable/rocky", "stable/stein", "stable/train", "stable/ussuri", "stable/victoria"]
+  when: target_branch in ["stable/ocata", "stable/pike", "stable/queens", "stable/rocky", "stable/stein", "stable/train", "stable/ussuri", "stable/victoria", "stable/wallaby"]
 
 - name: Use Configured upper-constraints for non-master Tempest
   set_fact:
@@ -120,10 +120,11 @@
     - target_branch in ["stable/train", "stable/ussuri", "stable/victoria"]
 
 - name: Run Tempest
-  command: tox -e {{tox_envlist}} {{tox_extra_args}} -- {{tempest_test_regex|quote}} \
-           {{blacklist_option|default('')}}  {{exclude_list_option|default('')}} \
+  command: tox -e {{tox_envlist}} {{tox_extra_args}} -- \
+           {{tempest_test_regex|quote if (tempest_test_regex|length>0)|default(None, True)}} \
+           {{blacklist_option|default(None)}}  {{exclude_list_option|default(None)}} \
             --concurrency={{tempest_concurrency|default(default_concurrency)}} \
-           {{tempest_test_exclude_regex|default('')}}
+           {{tempest_test_exclude_regex|default(None)}}
   args:
     chdir: "{{devstack_base_dir}}/tempest"
   register: tempest_run_result
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index d590668..e8734e0 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -14,8 +14,10 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import contextlib
 import io
 import random
+import time
 
 from oslo_log import log as logging
 from tempest.api.image import base
@@ -29,6 +31,19 @@
 LOG = logging.getLogger(__name__)
 
 
+@contextlib.contextmanager
+def retry_bad_request(fn):
+    retries = 3
+    for i in range(retries):
+        try:
+            yield
+        except lib_exc.BadRequest:
+            if i < retries:
+                time.sleep(1)
+            else:
+                raise
+
+
 class ImportImagesTest(base.BaseV2ImageTest):
     """Here we test the import operations for image"""
 
@@ -817,8 +832,14 @@
         # Add a new location
         new_loc = {'metadata': {'foo': 'bar'},
                    'url': CONF.image.http_image}
-        self.client.update_image(image['id'], [
-            dict(add='/locations/-', value=new_loc)])
+
+        # NOTE(danms): If glance was unable to fetch the remote image via
+        # HTTP, it will return BadRequest. Because this can be transient in
+        # CI, we try this a few times before we agree that it has failed
+        # for a reason worthy of failing the test.
+        with retry_bad_request():
+            self.client.update_image(image['id'], [
+                dict(add='/locations/-', value=new_loc)])
 
         # The image should now be active, with one location that looks
         # like we expect
@@ -848,8 +869,14 @@
 
         new_loc = {'metadata': {'speed': '88mph'},
                    'url': '%s#new' % CONF.image.http_image}
-        self.client.update_image(image['id'], [
-            dict(add='/locations/-', value=new_loc)])
+
+        # NOTE(danms): If glance was unable to fetch the remote image via
+        # HTTP, it will return BadRequest. Because this can be transient in
+        # CI, we try this a few times before we agree that it has failed
+        # for a reason worthy of failing the test.
+        with retry_bad_request():
+            self.client.update_image(image['id'], [
+                dict(add='/locations/-', value=new_loc)])
 
         # The image should now have two locations and the last one
         # (locations are ordered) should have the new URL.
diff --git a/tempest/api/network/admin/test_dhcp_agent_scheduler.py b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
index 2506185..3c0efee 100644
--- a/tempest/api/network/admin/test_dhcp_agent_scheduler.py
+++ b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
@@ -14,6 +14,7 @@
 
 from tempest.api.network import base
 from tempest.common import utils
+from tempest.common import waiters
 from tempest.lib import decorators
 
 
@@ -36,6 +37,16 @@
         cls.create_subnet(cls.network)
         cls.port = cls.create_port(cls.network)
 
+    @decorators.idempotent_id('f164801e-1dd8-4b8b-b5d3-cc3ac77cfaa5')
+    def test_dhcp_port_status_active(self):
+        ports = self.admin_ports_client.list_ports(
+            network_id=self.network['id'])['ports']
+        for port in ports:
+            waiters.wait_for_port_status(
+                client=self.admin_ports_client,
+                port_id=port['id'],
+                status='ACTIVE')
+
     @decorators.idempotent_id('5032b1fe-eb42-4a64-8f3b-6e189d8b5c7d')
     def test_list_dhcp_agent_hosting_network(self):
         """Test Listing DHCP agents hosting a network"""
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index 0b96d9e..a8a344a 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -90,7 +90,6 @@
 from tempest import clients
 from tempest.cmd import cleanup_service
 from tempest.common import credentials_factory as credentials
-from tempest.common import identity
 from tempest import config
 from tempest.lib import exceptions
 
@@ -140,11 +139,6 @@
         self.dry_run_data = {}
         self.json_data = {}
 
-        self.admin_id = ""
-        self.admin_role_id = ""
-        self.admin_project_id = ""
-        self._init_admin_ids()
-
         # available services
         self.project_associated_services = (
             cleanup_service.get_project_associated_cleanup_services())
@@ -227,26 +221,6 @@
             svc = service(self.admin_mgr, **kwargs)
             svc.run()
 
-    def _init_admin_ids(self):
-        pr_cl = self.admin_mgr.projects_client
-        rl_cl = self.admin_mgr.roles_v3_client
-        rla_cl = self.admin_mgr.role_assignments_client
-        us_cl = self.admin_mgr.users_v3_client
-
-        project = identity.get_project_by_name(pr_cl,
-                                               CONF.auth.admin_project_name)
-        self.admin_project_id = project['id']
-        user = identity.get_user_by_project(us_cl, rla_cl,
-                                            self.admin_project_id,
-                                            CONF.auth.admin_username)
-        self.admin_id = user['id']
-
-        roles = rl_cl.list_roles()['roles']
-        for role in roles:
-            if role['name'] == CONF.identity.admin_role:
-                self.admin_role_id = role['id']
-                break
-
     def get_parser(self, prog_name):
         parser = super(TempestCleanup, self).get_parser(prog_name)
         parser.add_argument('--init-saved-state', action="store_true",
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 7c55115..4fdf6a4 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -109,6 +109,15 @@
         LOG.debug('(get_nic_name_by_ip) Command result: %s', nic)
         return nic.strip().strip(":").split('@')[0].lower()
 
+    def get_nic_ip_addresses(self, nic_name, ip_version=None):
+        cmd = "ip "
+        if ip_version:
+            cmd += "-%s " % ip_version
+        cmd += "-o addr | awk '/%s/ {print $4}'" % nic_name
+        ip_addresses = self.exec_command(cmd)
+        LOG.debug('(get_nic_ip_address): Command result: %s', ip_addresses)
+        return ip_addresses.strip().split()
+
     def _get_dns_servers(self):
         cmd = 'cat /etc/resolv.conf'
         resolve_file = self.exec_command(cmd).strip().split('\n')
diff --git a/tempest/config.py b/tempest/config.py
index f1eb647..00b394e 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -1200,7 +1200,6 @@
                help='Image container format'),
     cfg.DictOpt('img_properties', help='Glance image properties. '
                 'Use for custom images which require them'),
-    # TODO(yfried): add support for dhcpcd
     cfg.StrOpt('dhcp_client',
                default='udhcpc',
                choices=["udhcpc", "dhclient", "dhcpcd", ""],
diff --git a/tempest/lib/common/ssh.py b/tempest/lib/common/ssh.py
index cb59a82..aad04b8 100644
--- a/tempest/lib/common/ssh.py
+++ b/tempest/lib/common/ssh.py
@@ -53,7 +53,8 @@
 
     def __init__(self, host, username, password=None, timeout=300, pkey=None,
                  channel_timeout=10, look_for_keys=False, key_filename=None,
-                 port=22, proxy_client=None, ssh_key_type='rsa'):
+                 port=22, proxy_client=None, ssh_key_type='rsa',
+                 ssh_allow_agent=True):
         """SSH client.
 
         Many of parameters are just passed to the underlying implementation
@@ -76,6 +77,9 @@
             for ssh-over-ssh.  The default is None, which means
             not to use ssh-over-ssh.
         :param ssh_key_type: ssh key type (rsa, ecdsa)
+        :param ssh_allow_agent: boolean, default True, if the SSH client is
+            allowed to also utilize the ssh-agent. Explicit use of passwords
+            in some tests may need this set as False.
         :type proxy_client: ``tempest.lib.common.ssh.Client`` object
         """
         self.host = host
@@ -105,6 +109,7 @@
             raise exceptions.SSHClientProxyClientLoop(
                 host=self.host, port=self.port, username=self.username)
         self._proxy_conn = None
+        self.ssh_allow_agent = ssh_allow_agent
 
     def _get_ssh_connection(self, sleep=1.5, backoff=1):
         """Returns an ssh connection to the specified host."""
@@ -133,7 +138,7 @@
                             look_for_keys=self.look_for_keys,
                             key_filename=self.key_filename,
                             timeout=self.channel_timeout, pkey=self.pkey,
-                            sock=proxy_chan)
+                            sock=proxy_chan, allow_agent=self.ssh_allow_agent)
                 LOG.info("ssh connection to %s@%s successfully created",
                          self.username, self.host)
                 return ssh
diff --git a/tempest/lib/common/utils/linux/remote_client.py b/tempest/lib/common/utils/linux/remote_client.py
index d0cdc25..662b452 100644
--- a/tempest/lib/common/utils/linux/remote_client.py
+++ b/tempest/lib/common/utils/linux/remote_client.py
@@ -69,7 +69,8 @@
                  server=None, servers_client=None, ssh_timeout=300,
                  connect_timeout=60, console_output_enabled=True,
                  ssh_shell_prologue="set -eu -o pipefail; PATH=$PATH:/sbin;",
-                 ping_count=1, ping_size=56, ssh_key_type='rsa'):
+                 ping_count=1, ping_size=56, ssh_key_type='rsa',
+                 ssh_allow_agent=True):
         """Executes commands in a VM over ssh
 
         :param ip_address: IP address to ssh to
@@ -85,6 +86,8 @@
         :param ping_count: Number of ping packets
         :param ping_size: Packet size for ping packets
         :param ssh_key_type: ssh key type (rsa, ecdsa)
+        :param ssh_allow_agent: Boolean if ssh agent support is permitted.
+            Defaults to True.
         """
         self.server = server
         self.servers_client = servers_client
@@ -94,11 +97,14 @@
         self.ping_count = ping_count
         self.ping_size = ping_size
         self.ssh_key_type = ssh_key_type
+        self.ssh_allow_agent = ssh_allow_agent
 
         self.ssh_client = ssh.Client(ip_address, username, password,
                                      ssh_timeout, pkey=pkey,
                                      channel_timeout=connect_timeout,
-                                     ssh_key_type=ssh_key_type)
+                                     ssh_key_type=ssh_key_type,
+                                     ssh_allow_agent=ssh_allow_agent,
+                                     )
 
     @debug_ssh
     def exec_command(self, cmd):
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index cbe8c20..cbe4122 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -897,10 +897,17 @@
         self.check_remote_connectivity(ssh_client, dest=peer_address,
                                        nic=spoof_nic, should_succeed=True)
         # Set a mac address by making nic down temporary
+        spoof_ip_addresses = ssh_client.get_nic_ip_addresses(spoof_nic)
         cmd = ("sudo ip link set {nic} down;"
                "sudo ip link set dev {nic} address {mac};"
-               "sudo ip link set {nic} up").format(nic=spoof_nic,
-                                                   mac=spoof_mac)
+               "sudo ip link set {nic} up;"
+               "sudo ip address flush dev {nic};").format(nic=spoof_nic,
+                                                          mac=spoof_mac)
+        for ip_address in spoof_ip_addresses:
+            cmd += (
+                "sudo ip addr add {ip_address} dev {nic};"
+            ).format(ip_address=ip_address, nic=spoof_nic)
+
         ssh_client.exec_command(cmd)
 
         new_mac = ssh_client.get_mac_address(nic=spoof_nic)
diff --git a/tempest/tests/lib/test_ssh.py b/tempest/tests/lib/test_ssh.py
index 886d99c..13870ba 100644
--- a/tempest/tests/lib/test_ssh.py
+++ b/tempest/tests/lib/test_ssh.py
@@ -75,7 +75,8 @@
             look_for_keys=False,
             timeout=10.0,
             password=None,
-            sock=None
+            sock=None,
+            allow_agent=True
         )]
         self.assertEqual(expected_connect, client_mock.connect.mock_calls)
         self.assertEqual(0, s_mock.call_count)
@@ -91,7 +92,8 @@
 
         proxy_client = ssh.Client('proxy-host', 'proxy-user', timeout=2)
         client = ssh.Client('localhost', 'root', timeout=2,
-                            proxy_client=proxy_client)
+                            proxy_client=proxy_client,
+                            ssh_allow_agent=False)
         client._get_ssh_connection(sleep=1)
 
         aa_mock.assert_has_calls([mock.call(), mock.call()])
@@ -106,7 +108,8 @@
             look_for_keys=False,
             timeout=10.0,
             password=None,
-            sock=None
+            sock=None,
+            allow_agent=True
         )]
         self.assertEqual(proxy_expected_connect,
                          proxy_client_mock.connect.mock_calls)
@@ -121,7 +124,8 @@
             look_for_keys=False,
             timeout=10.0,
             password=None,
-            sock=proxy_client_mock.get_transport().open_session()
+            sock=proxy_client_mock.get_transport().open_session(),
+            allow_agent=False
         )]
         self.assertEqual(expected_connect, client_mock.connect.mock_calls)
         self.assertEqual(0, s_mock.call_count)
diff --git a/tox.ini b/tox.ini
index 618f9e0..e1c17df 100644
--- a/tox.ini
+++ b/tox.ini
@@ -132,10 +132,11 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex = '(^tempest\.scenario.*)|(^tempest\.serial_tests)|(?!.*\[.*\bslow\b.*\])(^tempest\.api)'
 # The regex below is used to select all tempest scenario and including the non slow api tests
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '(^tempest\.scenario.*)|(^tempest\.serial_tests)|(?!.*\[.*\bslow\b.*\])(^tempest\.api)' {posargs}
+    tempest run --regex {[testenv:full-parallel]regex} {posargs}
 
 [testenv:api-microversion-tests]
 envdir = .tox/tempest
@@ -143,11 +144,12 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex = '(^tempest\.api\.compute)|(^tempest\.api\.volume)'
 # The regex below is used to select all tempest api tests for services having API
 # microversion concept.
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '(^tempest\.api\.compute)|(^tempest\.api\.volume)' {posargs}
+    tempest run --regex {[testenv:api-microversion-tests]regex} {posargs}
 
 [testenv:integrated-network]
 envdir = .tox/tempest
@@ -155,12 +157,14 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex1 = '(?!.*\[.*\bslow\b.*\])(^tempest\.api)'
+regex2 = '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)'
 # The regex below is used to select which tests to run and exclude the slow tag and
 # tests listed in exclude-list file:
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.api)' --exclude-list ./tools/tempest-integrated-gate-networking-exclude-list.txt {posargs}
-    tempest run --combine --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)' --exclude-list ./tools/tempest-integrated-gate-networking-exclude-list.txt {posargs}
+    tempest run --regex {[testenv:integrated-network]regex1} --exclude-list ./tools/tempest-integrated-gate-networking-exclude-list.txt {posargs}
+    tempest run --combine --serial --regex {[testenv:integrated-network]regex2} --exclude-list ./tools/tempest-integrated-gate-networking-exclude-list.txt {posargs}
 
 [testenv:integrated-compute]
 envdir = .tox/tempest
@@ -168,12 +172,14 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex1 = '(?!.*\[.*\bslow\b.*\])(^tempest\.api)'
+regex2 = '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)'
 # The regex below is used to select which tests to run and exclude the slow tag and
 # tests listed in exclude-list file:
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.api)' --exclude-list ./tools/tempest-integrated-gate-compute-exclude-list.txt {posargs}
-    tempest run --combine --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)' --exclude-list ./tools/tempest-integrated-gate-compute-exclude-list.txt {posargs}
+    tempest run --regex {[testenv:integrated-compute]regex1} --exclude-list ./tools/tempest-integrated-gate-compute-exclude-list.txt {posargs}
+    tempest run --combine --serial --regex {[testenv:integrated-compute]regex2} --exclude-list ./tools/tempest-integrated-gate-compute-exclude-list.txt {posargs}
 
 [testenv:integrated-placement]
 envdir = .tox/tempest
@@ -181,12 +187,14 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex1 = '(?!.*\[.*\bslow\b.*\])(^tempest\.api)'
+regex2 = '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)'
 # The regex below is used to select which tests to run and exclude the slow tag and
 # tests listed in exclude-list file:
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.api)' --exclude-list ./tools/tempest-integrated-gate-placement-exclude-list.txt {posargs}
-    tempest run --combine --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)' --exclude-list ./tools/tempest-integrated-gate-placement-exclude-list.txt {posargs}
+    tempest run --regex {[testenv:integrated-placement]regex1} --exclude-list ./tools/tempest-integrated-gate-placement-exclude-list.txt {posargs}
+    tempest run --combine --serial --regex {[testenv:integrated-placement]regex2} --exclude-list ./tools/tempest-integrated-gate-placement-exclude-list.txt {posargs}
 
 [testenv:integrated-storage]
 envdir = .tox/tempest
@@ -194,12 +202,14 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex1 = '(?!.*\[.*\bslow\b.*\])(^tempest\.api)'
+regex2 = '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)'
 # The regex below is used to select which tests to run and exclude the slow tag and
 # tests listed in exclude-list file:
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.api)' --exclude-list ./tools/tempest-integrated-gate-storage-exclude-list.txt {posargs}
-    tempest run --combine --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)' --exclude-list ./tools/tempest-integrated-gate-storage-exclude-list.txt {posargs}
+    tempest run --regex {[testenv:integrated-storage]regex1} --exclude-list ./tools/tempest-integrated-gate-storage-exclude-list.txt {posargs}
+    tempest run --combine --serial --regex {[testenv:integrated-storage]regex2} --exclude-list ./tools/tempest-integrated-gate-storage-exclude-list.txt {posargs}
 
 [testenv:integrated-object-storage]
 envdir = .tox/tempest
@@ -207,12 +217,14 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex1 = '(?!.*\[.*\bslow\b.*\])(^tempest\.api)'
+regex2 = '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)'
 # The regex below is used to select which tests to run and exclude the slow tag and
 # tests listed in exclude-list file:
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.api)' --exclude-list ./tools/tempest-integrated-gate-object-storage-exclude-list.txt {posargs}
-    tempest run --combine --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)' --exclude-list ./tools/tempest-integrated-gate-object-storage-exclude-list.txt {posargs}
+    tempest run --regex {[testenv:integrated-object-storage]regex1} --exclude-list ./tools/tempest-integrated-gate-object-storage-exclude-list.txt {posargs}
+    tempest run --combine --serial --regex {[testenv:integrated-object-storage]regex2} --exclude-list ./tools/tempest-integrated-gate-object-storage-exclude-list.txt {posargs}
 
 [testenv:full-serial]
 envdir = .tox/tempest
@@ -220,12 +232,13 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex = '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|serial_tests))'
 # 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 `--exclude-regex` option to exclude tests now.
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|serial_tests))' {posargs}
+    tempest run --serial --regex {[testenv:full-serial]regex} {posargs}
 
 [testenv:scenario]
 envdir = .tox/tempest
@@ -233,10 +246,11 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex = '(^tempest\.scenario)'
 # The regex below is used to select all scenario tests
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --serial --regex '(^tempest\.scenario)' {posargs}
+    tempest run --serial --regex {[testenv:scenario]regex} {posargs}
 
 [testenv:smoke]
 envdir = .tox/tempest
@@ -244,9 +258,10 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex = '\[.*\bsmoke\b.*\]'
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '\[.*\bsmoke\b.*\]' {posargs}
+    tempest run --regex {[testenv:smoke]regex} {posargs}
 
 [testenv:smoke-serial]
 envdir = .tox/tempest
@@ -254,12 +269,13 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex = '\[.*\bsmoke\b.*\]'
 # This is still serial because neutron doesn't work with parallel. See:
 # https://bugs.launchpad.net/tempest/+bug/1216076 so the neutron smoke
 # job would fail if we moved it to parallel.
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --serial --regex '\[.*\bsmoke\b.*\]' {posargs}
+    tempest run --serial --regex {[testenv:smoke-serial]regex} {posargs}
 
 [testenv:slow-serial]
 envdir = .tox/tempest
@@ -267,10 +283,11 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex = '\[.*\bslow\b.*\]'
 # The regex below is used to select the slow tagged tests to run serially:
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --serial --regex '\[.*\bslow\b.*\]' {posargs}
+    tempest run --serial --regex {[testenv:slow-serial]regex} {posargs}
 
 [testenv:ipv6-only]
 envdir = .tox/tempest
@@ -278,12 +295,13 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex = '\[.*\bsmoke|ipv6|test_network_v6\b.*\]'
 # Run only smoke and ipv6 tests. This env is used to tests
 # the ipv6 deployments and basic tests run fine so that we can
 # verify that services listen on IPv6 address.
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '\[.*\bsmoke|ipv6|test_network_v6\b.*\]' {posargs}
+    tempest run --regex {[testenv:ipv6-only]regex} {posargs}
 
 [testenv:venv]
 deps =
@@ -442,8 +460,9 @@
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+regex = '\[.*\bsmoke\b.*\]'
 # The below command install stestr master version and run smoke tests
 commands =
     find . -type f -name "*.pyc" -delete
     pip install -U git+https://github.com/mtreinish/stestr
-    tempest run --regex '\[.*\bsmoke\b.*\]' {posargs}
+    tempest run --regex {[testenv:stestr-master]regex} {posargs}
diff --git a/zuul.d/integrated-gate.yaml b/zuul.d/integrated-gate.yaml
index 5adf89e..f379041 100644
--- a/zuul.d/integrated-gate.yaml
+++ b/zuul.d/integrated-gate.yaml
@@ -383,16 +383,20 @@
         - tempest-integrated-networking
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
+        # and job is broken on wallaby branch due to the issue
+        # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|wallaby)).*$
     gate:
       jobs:
         - grenade
         - tempest-integrated-networking
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
+        # and job is broken on wallaby branch due to the issue
+        # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|wallaby)).*$
 
 - project-template:
     name: integrated-gate-compute
@@ -416,13 +420,15 @@
             branches: ^stable/(wallaby|xena|yoga).*$
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
+        # and job is broken on wallaby branch due to the issue
+        # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|wallaby)).*$
     gate:
       jobs:
         - tempest-integrated-compute
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|wallaby)).*$
     periodic-weekly:
       jobs:
         # centos-9-stream is tested from zed release onwards
@@ -444,6 +450,8 @@
         - tempest-integrated-placement
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
+        # and job is broken on wallaby branch due to the issue
+        # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
             branches: ^(?!stable/ussuri).*$
     gate:
@@ -452,8 +460,10 @@
         - tempest-integrated-placement
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
+        # and job is broken on wallaby branch due to the issue
+        # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|wallaby)).*$
 
 - project-template:
     name: integrated-gate-storage
@@ -470,16 +480,20 @@
         - tempest-integrated-storage
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
+        # and job is broken on wallaby branch due to the issue
+        # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|wallaby)).*$
     gate:
       jobs:
         - grenade
         - tempest-integrated-storage
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
+        # and job is broken on wallaby branch due to the issue
+        # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|wallaby)).*$
 
 - project-template:
     name: integrated-gate-object-storage
@@ -494,13 +508,17 @@
         - tempest-integrated-object-storage
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
+        # and job is broken on wallaby branch due to the issue
+        # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|wallaby)).*$
     gate:
       jobs:
         - grenade
         - tempest-integrated-object-storage
         # Do not run it on ussuri until below issue is fixed
         # https://storyboard.openstack.org/#!/story/2010057
+        # and job is broken on wallaby branch due to the issue
+        # described in https://review.opendev.org/872341
         - openstacksdk-functional-devstack:
-            branches: ^(?!stable/ussuri).*$
+            branches: ^(?!stable/(ussuri|wallaby)).*$
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 966cc9a..68fd14f 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -42,7 +42,11 @@
             irrelevant-files: *tempest-irrelevant-files
         - tempest-full-xena:
             irrelevant-files: *tempest-irrelevant-files
+        # Temporarily marked as n-v due to the below bug which blocks
+        # the CI and complicates merging of patches.
+        # https://bugs.launchpad.net/tempest/+bug/1998916
         - tempest-multinode-full-py3:
+            voting: false
             irrelevant-files: *tempest-irrelevant-files
         - tempest-tox-plugin-sanity-check:
             irrelevant-files: &tempest-irrelevant-files-2
@@ -146,8 +150,9 @@
             irrelevant-files: *tempest-irrelevant-files
         - tempest-ipv6-only:
             irrelevant-files: *tempest-irrelevant-files-3
-        - tempest-multinode-full-py3:
-            irrelevant-files: *tempest-irrelevant-files
+        # https://bugs.launchpad.net/tempest/+bug/1998916
+        #- tempest-multinode-full-py3:
+        #    irrelevant-files: *tempest-irrelevant-files
         - tempest-full-enforce-scope-new-defaults:
             irrelevant-files: *tempest-irrelevant-files
         #- devstack-plugin-ceph-tempest-py3: