Merge "Unmark port_forwarding tests as unstable"
diff --git a/neutron_tempest_plugin/api/admin/test_ports.py b/neutron_tempest_plugin/api/admin/test_ports.py
index 9c94322..6f51b1c 100644
--- a/neutron_tempest_plugin/api/admin/test_ports.py
+++ b/neutron_tempest_plugin/api/admin/test_ports.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 import netaddr
-import six
 
 from neutron_lib import constants as const
 from tempest.common import utils
@@ -123,8 +122,8 @@
         self.assertIn('resource_request', port)
         vnic_trait = 'CUSTOM_VNIC_TYPE_%s' % vnic_type.upper()
         physnet_trait = 'CUSTOM_PHYSNET_%s' % self.physnet_name.upper()
-        six.assertCountEqual(self, [physnet_trait, vnic_trait],
-                             port['resource_request']['required'])
+        self.assertCountEqual([physnet_trait, vnic_trait],
+                              port['resource_request']['required'])
 
         self.assertEqual(
             {'NET_BW_EGR_KILOBIT_PER_SEC': self.EGRESS_KBPS,
diff --git a/neutron_tempest_plugin/api/admin/test_quotas.py b/neutron_tempest_plugin/api/admin/test_quotas.py
index ae773c8..0cf474e 100644
--- a/neutron_tempest_plugin/api/admin/test_quotas.py
+++ b/neutron_tempest_plugin/api/admin/test_quotas.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import six
 from tempest.common import utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
@@ -145,7 +144,7 @@
         # as requested for tenant
         quota_set = self.admin_client.show_details_quota(tenant_id)
         quota_set = quota_set['quota']
-        for key, value in six.iteritems(new_quotas):
+        for key, value in new_quotas.items():
             self.assertEqual(new_quotas[key]['limit'],
                              quota_set[key]['limit'])
             self.assertEqual(new_quotas[key]['reserved'],
@@ -155,5 +154,5 @@
 
         # validate 'default' action for old extension
         quota_limit = self.admin_client.show_quotas(tenant_id)['quota']
-        for key, value in six.iteritems(new_quotas):
+        for key, value in new_quotas.items():
             self.assertEqual(new_quotas[key]['limit'], quota_limit[key])
diff --git a/neutron_tempest_plugin/common/ssh.py b/neutron_tempest_plugin/common/ssh.py
index fa731d8..c6204a4 100644
--- a/neutron_tempest_plugin/common/ssh.py
+++ b/neutron_tempest_plugin/common/ssh.py
@@ -19,7 +19,6 @@
 
 from oslo_log import log
 import paramiko
-import six
 from tempest.lib.common import ssh
 from tempest.lib import exceptions
 import tenacity
@@ -33,13 +32,7 @@
 
 
 RETRY_EXCEPTIONS = (exceptions.TimeoutException, paramiko.SSHException,
-                    socket.error)
-if six.PY2:
-    # NOTE(ralonsoh): TimeoutError was added in 3.3 and corresponds to
-    # OSError(errno.ETIMEDOUT)
-    RETRY_EXCEPTIONS += (OSError, )
-else:
-    RETRY_EXCEPTIONS += (TimeoutError, )
+                    socket.error, TimeoutError)
 
 
 class Client(ssh.Client):
diff --git a/neutron_tempest_plugin/fwaas/api/test_fwaasv2_extensions.py b/neutron_tempest_plugin/fwaas/api/test_fwaasv2_extensions.py
index f085e6d..0dd18f1 100644
--- a/neutron_tempest_plugin/fwaas/api/test_fwaasv2_extensions.py
+++ b/neutron_tempest_plugin/fwaas/api/test_fwaasv2_extensions.py
@@ -13,7 +13,6 @@
 #    under the License.
 
 import netaddr
-import six
 
 from tempest.common import utils
 from tempest import config
@@ -212,7 +211,7 @@
         # show a created firewall rule
         fw_rule = self.firewall_rules_client.show_firewall_rule(
             self.fw_rule_1['id'])
-        for key, value in six.iteritems(fw_rule['firewall_rule']):
+        for key, value in fw_rule['firewall_rule'].items():
             if key != 'firewall_policy_id':
                 self.assertEqual(self.fw_rule_1[key], value)
             # This check is placed because we cannot modify policy during
@@ -258,7 +257,7 @@
         fw_policy = self.firewall_policies_client.show_firewall_policy(
             self.fw_policy_1['id'])
         fw_policy = fw_policy['firewall_policy']
-        for key, value in six.iteritems(fw_policy):
+        for key, value in fw_policy.items():
             self.assertEqual(self.fw_policy_1[key], value)
 
     @decorators.idempotent_id('48dfcd75-3924-479d-bb65-b3ed33397663')
@@ -283,7 +282,7 @@
             fwg_id)
         fwg = firewall_group['firewall_group']
 
-        for key, value in six.iteritems(fwg):
+        for key, value in fwg.items():
             if key == 'status':
                 continue
             self.assertEqual(created_firewall_group[key], value)
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py
index f752436..b4be57b 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py
@@ -19,7 +19,6 @@
 import time
 
 import netaddr
-import six
 
 from os_ken.tests.integrated.common import docker_base as ctn_base
 from tempest.common import utils
@@ -125,10 +124,10 @@
         while True:
             with self.lock:
                 try:
-                    yield (i, str(six.next(subnet_gen)))
+                    yield (i, str(next(subnet_gen)))
                 except StopIteration:
                     subnet_gen = netaddr.iter_iprange(start, end, step=step)
-                    yield (i, str(six.next(subnet_gen)))
+                    yield (i, str(next(subnet_gen)))
                 i += 1
 
     def net_resource_cleanup(self):
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base_test_proto.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base_test_proto.py
index 1bcf5b1..643620f 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base_test_proto.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base_test_proto.py
@@ -14,7 +14,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import six
 from tempest import config
 
 from neutron_tempest_plugin.neutron_dynamic_routing.scenario import base
@@ -28,7 +27,7 @@
 
     def _test_check_neighbor_established(self, ip_version):
         self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
-        num, subnet = six.next(self.tnet_gen)
+        num, subnet = next(self.tnet_gen)
         mask = '/' + str(self.TPool.prefixlen)
         TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
                         cidr=subnet + mask, router=None)
@@ -47,7 +46,7 @@
 
     def _test_check_advertised_tenant_network(self, ip_version):
         self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
-        num, subnet = six.next(self.tnet_gen)
+        num, subnet = next(self.tnet_gen)
         mask = '/' + str(self.TPool.prefixlen)
         TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
                         cidr=subnet + mask, router=None)
@@ -73,7 +72,7 @@
         tnets = []
         tnets_cidr = []
         for i in range(0, 3):
-            num, subnet = six.next(self.tnet_gen)
+            num, subnet = next(self.tnet_gen)
             mask = '/' + str(self.TPool.prefixlen)
             TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
                             cidr=subnet + mask, router=None)
@@ -102,7 +101,7 @@
         for (bgp_peer_args, r_as_ip) in zip(self.bgp_peer_args,
                                             self.r_as_ip):
             bgp_peer_args['peer_ip'] = r_as_ip.split('/')[0]
-        num, subnet = six.next(self.tnet_gen)
+        num, subnet = next(self.tnet_gen)
         mask = '/' + str(self.TPool.prefixlen)
         TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
                         cidr=subnet + mask, router=None)
@@ -124,7 +123,7 @@
         for (bgp_peer_args, r_as_ip) in zip(self.bgp_peer_args,
                                             self.r_as_ip):
             bgp_peer_args['peer_ip'] = r_as_ip.split('/')[0]
-        num, subnet = six.next(self.tnet_gen)
+        num, subnet = next(self.tnet_gen)
         mask = '/' + str(self.TPool.prefixlen)
         TNet = base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
                         cidr=subnet + mask, router=None)
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_basic.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_basic.py
index 1c680f9..90a6815 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_basic.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_basic.py
@@ -15,7 +15,6 @@
 #    under the License.
 
 from os_ken.tests.integrated.common import docker_base as ctn_base
-import six
 from tempest import config
 from tempest.lib import decorators
 
@@ -31,7 +30,7 @@
     @decorators.idempotent_id('cc615252-c6cb-4d75-a70e-608fb2c3736a')
     def test_schedule_added_speaker(self):
         self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
-        num, subnet = six.next(self.tnet_gen)
+        num, subnet = next(self.tnet_gen)
         mask = '/' + str(self.TPool.prefixlen)
         TNet = s_base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
                           cidr=subnet + mask, router=None)
@@ -51,7 +50,7 @@
     @decorators.idempotent_id('ce98c33c-0ffa-49ae-b365-da836406793b')
     def test_unschedule_deleted_speaker(self):
         self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
-        num, subnet = six.next(self.tnet_gen)
+        num, subnet = next(self.tnet_gen)
         mask = '/' + str(self.TPool.prefixlen)
         TNet = s_base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
                           cidr=subnet + mask, router=None)
@@ -77,7 +76,7 @@
     @decorators.idempotent_id('aa6c565c-ded3-413b-8dc9-3928b3b0e38f')
     def test_remove_add_speaker_agent(self):
         self.bgp_peer_args[0]['peer_ip'] = self.r_as_ip[0].split('/')[0]
-        num, subnet = six.next(self.tnet_gen)
+        num, subnet = next(self.tnet_gen)
         mask = '/' + str(self.TPool.prefixlen)
         TNet = s_base.Net(name='', net=subnet, mask=self.TPool.prefixlen,
                           cidr=subnet + mask, router=None)
diff --git a/neutron_tempest_plugin/scenario/base.py b/neutron_tempest_plugin/scenario/base.py
index 2eb45f8..c7c5459 100644
--- a/neutron_tempest_plugin/scenario/base.py
+++ b/neutron_tempest_plugin/scenario/base.py
@@ -264,10 +264,12 @@
                                                'server']['id'])['ports'][0]
         self.fip = self.create_floatingip(port=self.port)
 
-    def check_connectivity(self, host, ssh_user, ssh_key,
-                           servers=None, ssh_timeout=None):
-        ssh_client = ssh.Client(host, ssh_user,
-                                pkey=ssh_key, timeout=ssh_timeout)
+    def check_connectivity(self, host, ssh_user=None, ssh_key=None,
+                           servers=None, ssh_timeout=None, ssh_client=None):
+        # Either ssh_client or ssh_user+ssh_key is mandatory.
+        if ssh_client is None:
+            ssh_client = ssh.Client(host, ssh_user,
+                                    pkey=ssh_key, timeout=ssh_timeout)
         try:
             ssh_client.test_connection_auth()
         except (lib_exc.SSHTimeout, ssh_exc.AuthenticationException) as ssh_e:
@@ -473,7 +475,7 @@
     def wait_for_guest_os_ready(self, server, client=None):
         if not CONF.compute_feature_enabled.console_output:
             LOG.debug('Console output not supported, cannot check if server '
-                      '%s is ready.', server['server']['id'])
+                      '%s is ready.', server['id'])
             return
 
         client = client or self.os_primary.servers_client
diff --git a/neutron_tempest_plugin/scenario/test_floatingip.py b/neutron_tempest_plugin/scenario/test_floatingip.py
index 8c8d163..262f429 100644
--- a/neutron_tempest_plugin/scenario/test_floatingip.py
+++ b/neutron_tempest_plugin/scenario/test_floatingip.py
@@ -341,6 +341,15 @@
     def resource_setup(cls):
         super(FloatingIPQosTest, cls).resource_setup()
 
+    def skip_if_no_extension_enabled_in_l3_agents(self, extension):
+        l3_agents = self.os_admin.network_client.list_agents(
+                binary='neutron-l3-agent')['agents']
+        for agent in l3_agents:
+            if extension in agent['configurations'].get('extensions', []):
+                return
+        raise self.skipTest("No L3 agent with '%s' extension enabled found." %
+                            extension)
+
     @decorators.idempotent_id('5eb48aea-eaba-4c20-8a6f-7740070a0aa3')
     def test_qos(self):
         """Test floating IP is binding to a QoS policy with
@@ -351,6 +360,8 @@
            received / elapsed time.
         """
 
+        self.skip_if_no_extension_enabled_in_l3_agents("fip_qos")
+
         self._test_basic_resources()
         policy_id = self._create_qos_policy()
         ssh_client = self._create_ssh_client()
diff --git a/neutron_tempest_plugin/scenario/test_trunk.py b/neutron_tempest_plugin/scenario/test_trunk.py
index 03bdd11..98fe6ae 100644
--- a/neutron_tempest_plugin/scenario/test_trunk.py
+++ b/neutron_tempest_plugin/scenario/test_trunk.py
@@ -269,6 +269,9 @@
             use_advanced_image=use_advanced_image)
 
         for vm in [vm1, vm2]:
+            self.check_connectivity(
+                host=vm.floating_ip['floating_ip_address'],
+                ssh_client=vm.ssh_client)
             self._configure_vlan_subport(vm=vm,
                                          vlan_tag=vlan_tag,
                                          vlan_subnet=vlan_subnet)
diff --git a/neutron_tempest_plugin/services/network/json/network_client.py b/neutron_tempest_plugin/services/network/json/network_client.py
index 0b2544b..e733cd0 100644
--- a/neutron_tempest_plugin/services/network/json/network_client.py
+++ b/neutron_tempest_plugin/services/network/json/network_client.py
@@ -11,9 +11,9 @@
 #    under the License.
 
 import time
+from urllib import parse as urlparse
 
 from oslo_serialization import jsonutils
-from six.moves.urllib import parse as urlparse
 from tempest.lib.common import rest_client as service_client
 from tempest.lib import exceptions as lib_exc
 
diff --git a/requirements.txt b/requirements.txt
index 3edf7dc..47dd923 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,7 +11,6 @@
 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
 oslo.utils>=3.33.0 # Apache-2.0
 paramiko>=2.0.0 # LGPLv2.1+
-six>=1.10.0 # MIT
 tempest>=17.1.0 # Apache-2.0
 tenacity>=3.2.1 # Apache-2.0
 ddt>=1.0.1 # MIT
diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml
index 2bd6f5a..28998cf 100644
--- a/zuul.d/base.yaml
+++ b/zuul.d/base.yaml
@@ -25,7 +25,6 @@
       tempest_plugins:
         - neutron-tempest-plugin
       devstack_services:
-        tls-proxy: false
         tempest: true
         neutron-dns: true
         neutron-qos: true
@@ -69,11 +68,6 @@
           $NEUTRON_DHCP_CONF:
             agent:
               availability_zone: nova
-          /etc/neutron/api-paste.ini:
-            composite:neutronapi_v2_0:
-              use: call:neutron.auth:pipeline_factory
-              noauth: cors request_id catch_errors osprofiler extensions neutronapiapp_v2_0
-              keystone: cors request_id catch_errors osprofiler authtoken keystonecontext extensions neutronapiapp_v2_0
         test-config:
           $TEMPEST_CONFIG:
             neutron_plugin_options:
diff --git a/zuul.d/master_jobs.yaml b/zuul.d/master_jobs.yaml
index 728eed8..072c8b4 100644
--- a/zuul.d/master_jobs.yaml
+++ b/zuul.d/master_jobs.yaml
@@ -196,9 +196,12 @@
       # TODO(slaweq): Remove test_trunk_subport_lifecycle test from the
       # blacklist when bug https://bugs.launchpad.net/neutron/+bug/1885900 will
       # be fixed
+      # TODO(jlibosva): Remove the NetworkWritableMtuTest test from the list
+      # once east/west fragmentation is supported in core OVN
       tempest_black_regex: "\
           (?:neutron_tempest_plugin.scenario.test_ipv6.IPv6Test)|\
-          (^neutron_tempest_plugin.scenario.test_trunk.TrunkTest.test_trunk_subport_lifecycle)"
+          (^neutron_tempest_plugin.scenario.test_trunk.TrunkTest.test_trunk_subport_lifecycle)|\
+          (^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest)"
       devstack_localrc:
         Q_AGENT: ovn
         NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"