Merge "Enable bridge flows and tcpdump in tempest multinode"
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 2826f56..1cb8004 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -140,6 +140,7 @@
             LOG.info("Live migrate back to source %s", source_host)
             self._live_migrate(server_id, source_host, state, volume_backed)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b')
     @testtools.skipUnless(CONF.compute_feature_enabled.
                           block_migration_for_live_migration,
@@ -148,6 +149,7 @@
         """Test live migrating an active server"""
         self._test_live_migration()
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('1e107f21-61b2-4988-8f22-b196e938ab88')
     @testtools.skipUnless(CONF.compute_feature_enabled.
                           block_migration_for_live_migration,
@@ -158,6 +160,7 @@
         """Test live migrating a paused server"""
         self._test_live_migration(state='PAUSED')
 
+    @decorators.attr(type='multinode')
     @testtools.skipUnless(CONF.compute_feature_enabled.
                           volume_backed_live_migration,
                           'Volume-backed live migration not available')
@@ -167,6 +170,7 @@
         """Test live migrating an active server booted from volume"""
         self._test_live_migration(volume_backed=True)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('e19c0cc6-6720-4ed8-be83-b6603ed5c812')
     @testtools.skipIf(not CONF.compute_feature_enabled.
                       block_migration_for_live_migration,
@@ -253,6 +257,7 @@
         port = self.ports_client.show_port(port_id)['port']
         return port['status'] == 'ACTIVE'
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('0022c12e-a482-42b0-be2d-396b5f0cffe3')
     @utils.requires_ext(service='network', extension='trunk')
     @utils.services('network')
@@ -297,6 +302,7 @@
     min_microversion = '2.6'
     max_microversion = 'latest'
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('6190af80-513e-4f0f-90f2-9714e84955d7')
     @testtools.skipUnless(CONF.compute_feature_enabled.serial_console,
                           'Serial console not supported.')
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index 89152d6..b3d2833 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -158,6 +158,7 @@
         dst_host = self.get_host_for_server(server['id'])
         assert_func(src_host, dst_host)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('4bf0be52-3b6f-4746-9a27-3143636fe30d')
     @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
                           'Cold migration not available.')
@@ -165,6 +166,7 @@
         """Test cold migrating server and then confirm the migration"""
         self._test_cold_migrate_server(revert=False)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('caa1aa8b-f4ef-4374-be0d-95f001c2ac2d')
     @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
                           'Cold migration not available.')
diff --git a/tempest/api/compute/admin/test_servers_on_multinodes.py b/tempest/api/compute/admin/test_servers_on_multinodes.py
index 9082306..013e7d8 100644
--- a/tempest/api/compute/admin/test_servers_on_multinodes.py
+++ b/tempest/api/compute/admin/test_servers_on_multinodes.py
@@ -61,6 +61,7 @@
 
         return hosts
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('26a9d5df-6890-45f2-abc4-a659290cb130')
     @testtools.skipUnless(
         compute.is_scheduler_filter_enabled("SameHostFilter"),
@@ -73,6 +74,7 @@
         host02 = self.get_host_for_server(server02)
         self.assertEqual(self.host01, host02)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('cc7ca884-6e3e-42a3-a92f-c522fcf25e8e')
     @testtools.skipUnless(
         compute.is_scheduler_filter_enabled("DifferentHostFilter"),
@@ -85,6 +87,7 @@
         host02 = self.get_host_for_server(server02)
         self.assertNotEqual(self.host01, host02)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('7869cc84-d661-4e14-9f00-c18cdc89cf57')
     @testtools.skipUnless(
         compute.is_scheduler_filter_enabled("DifferentHostFilter"),
@@ -97,6 +100,7 @@
         host02 = self.get_host_for_server(server02)
         self.assertNotEqual(self.host01, host02)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('f8bd0867-e459-45f5-ba53-59134552fe04')
     @testtools.skipUnless(
         compute.is_scheduler_filter_enabled("ServerGroupAntiAffinityFilter"),
@@ -112,6 +116,7 @@
         self.assertNotEqual(hostnames[0], hostnames[1],
                             'Servers are on the same host: %s' % hosts)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('9d2e924a-baf4-11e7-b856-fa163e65f5ce')
     @testtools.skipUnless(
         compute.is_scheduler_filter_enabled("ServerGroupAffinityFilter"),
@@ -152,6 +157,7 @@
         waiters.wait_for_server_status(self.servers_client, server['id'],
                                        'ACTIVE')
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('b5cc0889-50c2-46a0-b8ff-b5fb4c3a6e20')
     def test_unshelve_to_specific_host(self):
         """Test unshelve to a specific host, new behavior introduced in
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index e630e29..f4f37b0 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -218,7 +218,7 @@
     @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
                           'Less than 2 compute nodes, skipping multinode '
                           'tests.')
-    @decorators.attr(type='slow')
+    @decorators.attr(type=['slow', 'multinode'])
     @utils.services('compute', 'network')
     def test_server_connectivity_cold_migration(self):
         keypair = self.create_keypair()
@@ -244,7 +244,7 @@
     @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
                           'Less than 2 compute nodes, skipping multinode '
                           'tests.')
-    @decorators.attr(type='slow')
+    @decorators.attr(type=['slow', 'multinode'])
     @utils.services('compute', 'network')
     def test_server_connectivity_live_migration(self):
         keypair = self.create_keypair()
@@ -289,7 +289,7 @@
     @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
                           'Less than 2 compute nodes, skipping multinode '
                           'tests.')
-    @decorators.attr(type='slow')
+    @decorators.attr(type=['slow', 'multinode'])
     @utils.services('compute', 'network')
     def test_server_connectivity_cold_migration_revert(self):
         keypair = self.create_keypair()
diff --git a/tempest/scenario/test_network_qos_placement.py b/tempest/scenario/test_network_qos_placement.py
index 365eb1b..0b2cfcb 100644
--- a/tempest/scenario/test_network_qos_placement.py
+++ b/tempest/scenario/test_network_qos_placement.py
@@ -278,6 +278,7 @@
         port = self.os_admin.ports_client.show_port(not_valid_port['id'])
         self.assertEqual(0, len(port['port']['binding:profile']))
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('8a98150c-a506-49a5-96c6-73a5e7b04ada')
     @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
                           'Cold migration is not available.')
@@ -851,6 +852,7 @@
 
         self.assert_allocations(server, port, min_kbps, min_kpps)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('bdd0b31c-c8b0-4b7b-b80a-545a46b32abe')
     @testtools.skipUnless(
         CONF.compute_feature_enabled.cold_migration,
@@ -1033,6 +1035,7 @@
 
         self.assert_allocations(server, port2, 0, 0)
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('36ffdb85-6cc2-4cc9-a426-cad5bac8626b')
     @testtools.skipUnless(
         CONF.compute.min_compute_nodes > 1,
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index aff7509..2fc5f32 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -480,6 +480,7 @@
                            direction='ingress')
         return ruleset
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
     @utils.services('compute', 'network')
     def test_cross_tenant_traffic(self):
@@ -510,6 +511,7 @@
             self._log_console_output_for_all_tenants()
             raise
 
+    @decorators.attr(type='multinode')
     @decorators.idempotent_id('63163892-bbf6-4249-aa12-d5ea1f8f421b')
     @utils.services('compute', 'network')
     def test_in_tenant_traffic(self):
@@ -524,7 +526,7 @@
             raise
 
     @decorators.idempotent_id('f4d556d7-1526-42ad-bafb-6bebf48568f6')
-    @decorators.attr(type='slow')
+    @decorators.attr(type=['slow', 'multinode'])
     @utils.services('compute', 'network')
     def test_port_update_new_security_group(self):
         """Verifies the traffic after updating the vm port
@@ -578,7 +580,7 @@
             raise
 
     @decorators.idempotent_id('d2f77418-fcc4-439d-b935-72eca704e293')
-    @decorators.attr(type='slow')
+    @decorators.attr(type=['slow', 'multinode'])
     @utils.services('compute', 'network')
     def test_multiple_security_groups(self):
         """Verify multiple security groups and checks that rules
@@ -610,7 +612,7 @@
                                    private_key=private_key,
                                    should_connect=True)
 
-    @decorators.attr(type='slow')
+    @decorators.attr(type=['slow', 'multinode'])
     @utils.requires_ext(service='network', extension='port-security')
     @decorators.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c')
     @utils.services('compute', 'network')
@@ -650,7 +652,7 @@
             self._log_console_output_for_all_tenants()
             raise
 
-    @decorators.attr(type='slow')
+    @decorators.attr(type=['slow', 'multinode'])
     @utils.requires_ext(service='network', extension='port-security')
     @decorators.idempotent_id('13ccf253-e5ad-424b-9c4a-97b88a026699')
     # TODO(mriedem): We shouldn't actually need to check this since neutron
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index fdf875c..9285da2 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -35,7 +35,7 @@
                 "Less than 2 compute nodes, skipping multinode tests.")
 
     @decorators.idempotent_id('9cecbe35-b9d4-48da-a37e-7ce70aa43d30')
-    @decorators.attr(type='smoke')
+    @decorators.attr(type=['smoke', 'multinode'])
     @utils.services('compute', 'network')
     def test_schedule_to_all_nodes(self):
         available_zone = \
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 29612ec..204471e 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -119,7 +119,7 @@
     def test_shelve_volume_backed_instance(self):
         self._create_server_then_shelve_and_unshelve(boot_from_volume=True)
 
-    @decorators.attr(type='slow')
+    @decorators.attr(type=['slow', 'multinode'])
     @decorators.idempotent_id('1295fd9e-193a-4cf8-b211-55358e021bae')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
diff --git a/tools/tempest-extra-tests-list.txt b/tools/tempest-extra-tests-list.txt
new file mode 100644
index 0000000..9c88109
--- /dev/null
+++ b/tools/tempest-extra-tests-list.txt
@@ -0,0 +1,20 @@
+# This file includes the list of tests which need to be
+# excluded to run from integrated testing (tempest-full job
+# or other generic jobs. We will run these tests in a separate
+# jobs. This is needed to avoid the job timeout, details in
+# bug#2004780.
+# Basic criteria to add test in this list is:
+# * Admin test which are not needed for interop and most of them
+#   are running as part of other API and Scenario tests.
+# * Negative tests which are mostly covered in tempest API tests
+#   or service unit/functional tests.
+
+# All admin tests except keystone admin test which might not have much
+# coverage in existing other tests
+tempest.api.compute.admin
+tempest.api.volume.admin
+tempest.api.image.admin
+tempest.api.network.admin
+
+# All negative tests
+negative
diff --git a/tox.ini b/tox.ini
index d5b41af..47ef5eb 100644
--- a/tox.ini
+++ b/tox.ini
@@ -126,17 +126,49 @@
     tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.api)' {posargs}
     tempest run --combine --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)' {posargs}
 
+[testenv:integrated-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. It exclude the extra
+# tests mentioned in tools/tempest-extra-tests-list.txt and 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.
+regex1 = '(?!.*\[.*\bslow\b.*\])(^tempest\.api)'
+regex2 = '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)|(^tempest\.serial_tests)'
+commands =
+    find . -type f -name "*.pyc" -delete
+    tempest run --regex {[testenv:integrated-full]regex1} --exclude-list ./tools/tempest-extra-tests-list.txt {posargs}
+    tempest run --combine --serial --regex {[testenv:integrated-full]regex2} {posargs}
+
+[testenv:extra-tests]
+envdir = .tox/tempest
+sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
+setenv = {[tempestenv]setenv}
+deps = {[tempestenv]deps}
+# The regex below is used to select extra tests mentioned in
+# tools/tempest-extra-tests-list.txt and exclude slow tag tests:
+# 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.
+exclude-regex = '\[.*\bslow\b.*\]'
+commands =
+    find . -type f -name "*.pyc" -delete
+    tempest run --exclude-regex {[testenv:extra-tests]exclude-regex} --include-list ./tools/tempest-extra-tests-list.txt {posargs}
+
 [testenv:full-parallel]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
 basepython = {[tempestenv]basepython}
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
+# But exlcude the extra tests mentioned in tools/tempest-extra-tests-list.txt
 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 {[testenv:full-parallel]regex} {posargs}
+    tempest run --regex {[testenv:full-parallel]regex} --exclude-list ./tools/tempest-extra-tests-list.txt {posargs}
 
 [testenv:api-microversion-tests]
 envdir = .tox/tempest
@@ -301,6 +333,18 @@
     find . -type f -name "*.pyc" -delete
     tempest run --regex {[testenv:slow]regex} {posargs}
 
+[testenv:multinode]
+envdir = .tox/tempest
+sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
+setenv = {[tempestenv]setenv}
+deps = {[tempestenv]deps}
+# The regex below is used to select the multinode and smoke tagged tests
+regex = '\[.*\bsmoke|multinode\b.*\]'
+commands =
+    find . -type f -name "*.pyc" -delete
+    tempest run --regex {[testenv:multinode]regex} {posargs}
+
 [testenv:ipv6-only]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}
diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml
index 3deb944..2d978c0 100644
--- a/zuul.d/base.yaml
+++ b/zuul.d/base.yaml
@@ -72,7 +72,8 @@
       and a tempest one exist.
     timeout: 10800
     vars:
-      tox_envlist: full
+      # This job run multinode and smoke tests.
+      tox_envlist: multinode
       devstack_localrc:
         FORCE_CONFIG_DRIVE: false
         NOVA_ALLOW_MOVE_TO_SAME_HOST: false
diff --git a/zuul.d/integrated-gate.yaml b/zuul.d/integrated-gate.yaml
index 2c720d9..32c017a 100644
--- a/zuul.d/integrated-gate.yaml
+++ b/zuul.d/integrated-gate.yaml
@@ -60,6 +60,15 @@
         c-bak: false
 
 - job:
+    name: tempest-extra-tests
+    parent: devstack-tempest
+    description: |
+      This job runs the extra tests mentioned in
+      tools/tempest-extra-tests-list.txt.
+    vars:
+      tox_envlist: extra-tests
+
+- job:
     name: tempest-full-py3
     parent: devstack-tempest
     # This job version is with swift enabled on py3
@@ -74,7 +83,7 @@
     required-projects:
       - openstack/horizon
     vars:
-      tox_envlist: full
+      tox_envlist: integrated-full
       devstack_localrc:
         USE_PYTHON3: true
         FORCE_CONFIG_DRIVE: true
@@ -107,6 +116,7 @@
       # Required until bug/1949606 is resolved when using libvirt and QEMU
       # >=5.0.0 with a [libvirt]virt_type of qemu (TCG).
       configure_swap_size: 4096
+      tox_envlist: full
 
 - job:
     name: tempest-integrated-networking
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index e41a9f7..d20186e 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -26,6 +26,8 @@
               - ^.gitignore$
               - ^.gitreview$
               - ^.mailmap$
+        - tempest-extra-tests:
+            irrelevant-files: *tempest-irrelevant-files
         - tempest-full-ubuntu-focal:
             irrelevant-files: *tempest-irrelevant-files
         - glance-multistore-cinder-import:
@@ -35,11 +37,7 @@
             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
@@ -63,6 +61,7 @@
               - ^tools/tempest-integrated-gate-placement-exclude-list.txt
               - ^tools/tempest-integrated-gate-storage-blacklist.txt
               - ^tools/tempest-integrated-gate-storage-exclude-list.txt
+              - ^tools/tempest-extra-tests-list.txt
               - ^tools/verify-ipv6-only-deployments.sh
               - ^tools/with_venv.sh
               # tools/ is not here since this relies on a script in tools/.
@@ -86,6 +85,7 @@
               - ^tools/tempest-integrated-gate-placement-exclude-list.txt
               - ^tools/tempest-integrated-gate-storage-blacklist.txt
               - ^tools/tempest-integrated-gate-storage-exclude-list.txt
+              - ^tools/tempest-extra-tests-list.txt
               - ^tools/tempest-plugin-sanity.sh
               - ^tools/with_venv.sh
               - ^.coveragerc$
@@ -131,13 +131,14 @@
             irrelevant-files: *tempest-irrelevant-files
         - tempest-full-py3:
             irrelevant-files: *tempest-irrelevant-files
+        - tempest-extra-tests:
+            irrelevant-files: *tempest-irrelevant-files
         - grenade:
             irrelevant-files: *tempest-irrelevant-files
         - tempest-ipv6-only:
             irrelevant-files: *tempest-irrelevant-files-3
-        # https://bugs.launchpad.net/tempest/+bug/1998916
-        #- tempest-multinode-full-py3:
-        #    irrelevant-files: *tempest-irrelevant-files
+        - 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:
@@ -179,6 +180,9 @@
         - tempest-slow-zed
         - tempest-slow-yoga
         - tempest-slow-xena
+        - tempest-full-zed-extra-tests
+        - tempest-full-yoga-extra-tests
+        - tempest-full-xena-extra-tests
     periodic:
       jobs:
         - tempest-all
diff --git a/zuul.d/stable-jobs.yaml b/zuul.d/stable-jobs.yaml
index fb2300b..f70e79c 100644
--- a/zuul.d/stable-jobs.yaml
+++ b/zuul.d/stable-jobs.yaml
@@ -18,6 +18,24 @@
     override-checkout: stable/xena
 
 - job:
+    name: tempest-full-zed-extra-tests
+    parent: tempest-extra-tests
+    nodeset: openstack-single-node-focal
+    override-checkout: stable/zed
+
+- job:
+    name: tempest-full-yoga-extra-tests
+    parent: tempest-extra-tests
+    nodeset: openstack-single-node-focal
+    override-checkout: stable/yoga
+
+- job:
+    name: tempest-full-xena-extra-tests
+    parent: tempest-extra-tests
+    nodeset: openstack-single-node-focal
+    override-checkout: stable/xena
+
+- job:
     name: tempest-slow-zed
     parent: tempest-slow-py3
     nodeset: openstack-two-node-focal
diff --git a/zuul.d/tempest-specific.yaml b/zuul.d/tempest-specific.yaml
index 684270a..972123e 100644
--- a/zuul.d/tempest-specific.yaml
+++ b/zuul.d/tempest-specific.yaml
@@ -30,6 +30,8 @@
       - opendev.org/openstack/oslo.utils
       - opendev.org/openstack/oslo.versionedobjects
       - opendev.org/openstack/oslo.vmware
+    vars:
+      tox_envlist: full
 
 - job:
     name: tempest-full-parallel