Merge "[TF] Add support of tungstenfabric driver for octavia" into mcp/epoxy
diff --git a/octavia_tempest_plugin/config.py b/octavia_tempest_plugin/config.py
index 78f57ed..0eb773a 100644
--- a/octavia_tempest_plugin/config.py
+++ b/octavia_tempest_plugin/config.py
@@ -294,6 +294,9 @@
                      "specified in the tempest configuration."),
     cfg.BoolOpt('prometheus_listener_enabled', default=True,
                 help="Whether the PROMETHEUS listener tests will run."),
+    cfg.BoolOpt('force_cleanup_enabled',
+                default=False,
+                help="Whether to delete loadbalancers with force on cleanup."),
 ]
 
 # Extending this enforce_scope group defined in tempest
diff --git a/octavia_tempest_plugin/services/load_balancer/v2/base_client.py b/octavia_tempest_plugin/services/load_balancer/v2/base_client.py
index 96ea33c..de464c3 100644
--- a/octavia_tempest_plugin/services/load_balancer/v2/base_client.py
+++ b/octavia_tempest_plugin/services/load_balancer/v2/base_client.py
@@ -403,10 +403,18 @@
             LOG.error("Cleanup encountered an unknown exception while waiting "
                       "for %s %s: %s", wait_client.root_tag, wait_id, e)
 
-        if cascade:
-            uri = '{0}/{1}?cascade=true'.format(uri, obj_id)
-        else:
-            uri = '{0}/{1}'.format(uri, obj_id)
+        uri = "{0}/{1}".format(uri, obj_id)
+        query_params = {"cascade": cascade}
+        if (
+            CONF.loadbalancer_feature_enabled.force_cleanup_enabled
+            and self.root_tag == const.LOADBALANCER
+        ):
+            query_params.update({"force": True, "cascade": True})
+        query_string = "&".join(
+            [f"{k}={v}" for k, v in query_params.items() if v]
+        )
+        if query_string:
+            uri += f"?{query_string}"
         LOG.info("Cleaning up %s %s...", self.root_tag, obj_id)
         return_status = test_utils.call_and_ignore_notfound_exc(
             self.delete, uri)
diff --git a/octavia_tempest_plugin/tests/act_stdby_scenario/v2/test_active_standby.py b/octavia_tempest_plugin/tests/act_stdby_scenario/v2/test_active_standby.py
index 4f5830c..9907ca8 100644
--- a/octavia_tempest_plugin/tests/act_stdby_scenario/v2/test_active_standby.py
+++ b/octavia_tempest_plugin/tests/act_stdby_scenario/v2/test_active_standby.py
@@ -32,6 +32,8 @@
 LOG = logging.getLogger(__name__)
 
 
+@testtools.skipIf(CONF.load_balancer.provider == 'tungstenfabric',
+                  "Not supported by TungstenFabric")
 @testtools.skipUnless(
     CONF.validation.run_validation,
     'Active-Standby tests will not work without run_validation enabled.')
@@ -63,6 +65,16 @@
             cls.mem_lb_client.cleanup_loadbalancer,
             cls.lb_id)
 
+        # (gzimin): Add additional waiter in case of TungstenFabric
+        # because for correct assignment of Floating IP for loadbalancer
+        # we need to wait for amphora port
+        if config.is_tungstenfabric_backend_enabled():
+            waiters.wait_for_status(cls.mem_lb_client.show_loadbalancer,
+                                    cls.lb_id, const.PROVISIONING_STATUS,
+                                    const.ACTIVE,
+                                    CONF.load_balancer.lb_build_interval,
+                                    CONF.load_balancer.lb_build_timeout)
+
         if CONF.validation.connect_method == 'floating':
             port_id = lb[const.VIP_PORT_ID]
             result = cls.lb_mem_float_ip_client.create_floatingip(
diff --git a/octavia_tempest_plugin/tests/api/v2/test_amphora.py b/octavia_tempest_plugin/tests/api/v2/test_amphora.py
index 06f93ac..ac8c635 100644
--- a/octavia_tempest_plugin/tests/api/v2/test_amphora.py
+++ b/octavia_tempest_plugin/tests/api/v2/test_amphora.py
@@ -105,9 +105,9 @@
         # Test filtering by loadbalancer_id
         amphorae = self.lb_admin_amphora_client.list_amphorae(
             query_params='{loadbalancer_id}={lb_id}'.format(
-                loadbalancer_id=const.LOADBALANCER_ID, lb_id=self.lb_id))
+                loadbalancer_id=const.LOADBALANCER_ID, lb_id=lb_id))
         self.assertEqual(self._expected_amp_count(amphorae), len(amphorae))
-        self.assertEqual(self.lb_id, amphorae[0][const.LOADBALANCER_ID])
+        self.assertEqual(lb_id, amphorae[0][const.LOADBALANCER_ID])
 
         # Test RBAC for show amphora
         if expected_allowed:
@@ -165,9 +165,23 @@
             raise self.skipException('Amphora update is only available on '
                                      'Octavia API version 2.7 or newer.')
 
+        lb_name = data_utils.rand_name("lb_member_lb2_amphora-update")
+        lb = self.mem_lb_client.create_loadbalancer(
+            name=lb_name, provider=CONF.load_balancer.provider,
+            vip_network_id=self.lb_member_vip_net[const.ID])
+        lb_id = lb[const.ID]
+        self.addCleanup(self.mem_lb_client.cleanup_loadbalancer, lb_id)
+
+        waiters.wait_for_status(self.mem_lb_client.show_loadbalancer,
+                                lb_id,
+                                const.PROVISIONING_STATUS,
+                                const.ACTIVE,
+                                CONF.load_balancer.lb_build_interval,
+                                CONF.load_balancer.lb_build_timeout)
+
         amphorae = self.lb_admin_amphora_client.list_amphorae(
             query_params='{loadbalancer_id}={lb_id}'.format(
-                loadbalancer_id=const.LOADBALANCER_ID, lb_id=self.lb_id))
+                loadbalancer_id=const.LOADBALANCER_ID, lb_id=lb_id))
         amphora_1 = amphorae[0]
 
         # Test RBAC for update an amphora
@@ -218,6 +232,11 @@
 
         for new_amp in after_amphorae:
             self.assertNotEqual(amphora_1[const.ID], new_amp[const.ID])
+            waiters.wait_for_status(self.lb_admin_amphora_client.show_amphora,
+                                    new_amp[const.ID], const.STATUS,
+                                    const.STATUS_ALLOCATED,
+                                    CONF.load_balancer.build_interval,
+                                    CONF.load_balancer.build_timeout)
 
     @testtools.skipIf(CONF.load_balancer.test_with_noop,
                       'Log offload tests will not work in noop mode.')
diff --git a/octavia_tempest_plugin/tests/api/v2/test_listener.py b/octavia_tempest_plugin/tests/api/v2/test_listener.py
index 685ff2d..0bd4dd2 100644
--- a/octavia_tempest_plugin/tests/api/v2/test_listener.py
+++ b/octavia_tempest_plugin/tests/api/v2/test_listener.py
@@ -253,6 +253,8 @@
     def test_tcp_listener_create(self):
         self._test_listener_create(const.TCP, 8002)
 
+    @testtools.skipIf(CONF.load_balancer.provider == 'tungstenfabric',
+                      "Not supported by TungstenFabric")
     @decorators.idempotent_id('1a6ba0d0-f309-4088-a686-dda0e9ab7e43')
     @testtools.skipUnless(
         CONF.loadbalancer_feature_enabled.prometheus_listener_enabled,
@@ -687,6 +689,8 @@
     def test_https_listener_list(self):
         self._test_listener_list(const.HTTPS, 8030)
 
+    @testtools.skipIf(CONF.load_balancer.provider == 'tungstenfabric',
+                      "Not supported by TungstenFabric")
     @decorators.idempotent_id('5473e071-8277-4ac5-9277-01ecaf46e274')
     @testtools.skipUnless(
         CONF.loadbalancer_feature_enabled.prometheus_listener_enabled,
@@ -1114,6 +1118,8 @@
     def test_https_listener_show(self):
         self._test_listener_show(const.HTTPS, 8051)
 
+    @testtools.skipIf(CONF.load_balancer.provider == 'tungstenfabric',
+                      "Not supported by TungstenFabric")
     @decorators.idempotent_id('b851b754-4333-4115-9063-a9fce44c2e46')
     @testtools.skipUnless(
         CONF.loadbalancer_feature_enabled.prometheus_listener_enabled,
@@ -1319,6 +1325,8 @@
     def test_https_listener_update(self):
         self._test_listener_update(const.HTTPS, 8061)
 
+    @testtools.skipIf(CONF.load_balancer.provider == 'tungstenfabric',
+                      "Not supported by TungstenFabric")
     @decorators.idempotent_id('cbba6bf8-9184-4da5-95e9-5efe1f89ddf0')
     @testtools.skipUnless(
         CONF.loadbalancer_feature_enabled.prometheus_listener_enabled,
@@ -1635,6 +1643,8 @@
     def test_https_listener_delete(self):
         self._test_listener_delete(const.HTTPS, 8071)
 
+    @testtools.skipIf(CONF.load_balancer.provider == 'tungstenfabric',
+                      "Not supported by TungstenFabric")
     @decorators.idempotent_id('322a6372-6b56-4a3c-87e3-dd82074bc83e')
     @testtools.skipUnless(
         CONF.loadbalancer_feature_enabled.prometheus_listener_enabled,
diff --git a/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py b/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py
index 7938c31..85fcef0 100644
--- a/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py
+++ b/octavia_tempest_plugin/tests/barbican_scenario/v2/test_tls_barbican.py
@@ -301,6 +301,7 @@
             CONF.load_balancer.check_interval,
             CONF.load_balancer.check_timeout)
 
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('887ece26-0f7b-4933-89ab-5bb00b106ee0')
     def test_basic_tls_traffic(self):
 
@@ -874,6 +875,14 @@
                                 CONF.load_balancer.build_interval,
                                 CONF.load_balancer.build_timeout)
 
+        if not CONF.load_balancer.test_with_noop:
+            waiters.wait_for_status(
+                self.mem_listener_client.show_listener,
+                self.listener_id, const.OPERATING_STATUS,
+                const.ONLINE,
+                CONF.load_balancer.build_interval,
+                CONF.load_balancer.build_timeout)
+
         # Test that no client certificate connects
         response = requests.get(
             'https://{0}:{1}'.format(self.lb_vip_address, LISTENER1_TCP_PORT),
@@ -979,6 +988,14 @@
                                 CONF.load_balancer.build_interval,
                                 CONF.load_balancer.build_timeout)
 
+        if not CONF.load_balancer.test_with_noop:
+            waiters.wait_for_status(
+                self.mem_listener_client.show_listener,
+                self.listener_id, const.OPERATING_STATUS,
+                const.ONLINE,
+                CONF.load_balancer.build_interval,
+                CONF.load_balancer.build_timeout)
+
         LISTENER2_TCP_PORT = '8443'
         listener_name = data_utils.rand_name(
             "lb_member_listener2-multi-list-client-auth")
@@ -1005,7 +1022,13 @@
                                 const.ACTIVE,
                                 CONF.load_balancer.build_interval,
                                 CONF.load_balancer.build_timeout)
-
+        if not CONF.load_balancer.test_with_noop:
+            waiters.wait_for_status(
+                self.mem_listener_client.show_listener,
+                self.listener2_id, const.OPERATING_STATUS,
+                const.ONLINE,
+                CONF.load_balancer.build_interval,
+                CONF.load_balancer.build_timeout)
         # Test that no client certificate fails to connect to listener1
         self.assertRaises(
             requests.exceptions.SSLError,
diff --git a/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py b/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py
index ee3327f..a5b0465 100644
--- a/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py
+++ b/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py
@@ -1123,17 +1123,17 @@
     @decorators.idempotent_id('04399db0-04f0-4cb5-bb27-a12bf18bfe08')
     def test_http_LC_listener_with_allowed_cidrs(self):
         self._test_listener_with_allowed_cidrs(
-            const.HTTP, 90, const.LB_ALGORITHM_LEAST_CONNECTIONS)
+            const.HTTP, 90, const.LB_ALGORITHM_LEAST_CONNECTIONS, delay=1)
 
     @decorators.idempotent_id('3d8d95b6-55e8-4bb9-b474-4ac35abaff22')
     def test_tcp_LC_listener_with_allowed_cidrs(self):
         self._test_listener_with_allowed_cidrs(
-            const.TCP, 91, const.LB_ALGORITHM_LEAST_CONNECTIONS, delay=0.2)
+            const.TCP, 91, const.LB_ALGORITHM_LEAST_CONNECTIONS, delay=1)
 
     @decorators.idempotent_id('7456b558-9add-4e0e-988e-06803f8047f7')
     def test_udp_LC_listener_with_allowed_cidrs(self):
         self._test_listener_with_allowed_cidrs(
-            const.UDP, 92, const.LB_ALGORITHM_LEAST_CONNECTIONS)
+            const.UDP, 92, const.LB_ALGORITHM_LEAST_CONNECTIONS, delay=1)
 
     @decorators.idempotent_id('13b0f2de-9934-457b-8be0-f1bffc6915a0')
     def test_http_RR_listener_with_allowed_cidrs(self):
@@ -1493,6 +1493,8 @@
             number_of_retries=3),
             'Failed - all UDP retries to LB VIP has failed')
 
+    @testtools.skipIf(CONF.load_balancer.provider == 'tungstenfabric',
+                      "Not supported by TungstenFabric")
     @decorators.attr(type='slow')
     @decorators.idempotent_id('cd5aeefa-0e16-11eb-b8dc-74e5f9e2a801')
     def test_hm_op_status_changed_as_expected_on_update(self):
@@ -1579,6 +1581,8 @@
                     CONF.load_balancer.check_timeout,
                     error_ok=True, pool_id=pool_id)
 
+    @testtools.skipIf(CONF.load_balancer.provider == 'tungstenfabric',
+                      "Not supported by TungstenFabric")
     @decorators.idempotent_id('05e99fb3-2b37-478e-889b-77f1c731a471')
     @testtools.skipUnless(
         CONF.loadbalancer_feature_enabled.prometheus_listener_enabled,
diff --git a/octavia_tempest_plugin/tests/test_base.py b/octavia_tempest_plugin/tests/test_base.py
index 2ffa689..284c449 100644
--- a/octavia_tempest_plugin/tests/test_base.py
+++ b/octavia_tempest_plugin/tests/test_base.py
@@ -342,9 +342,9 @@
             cls.lb_member_2_subnet = override_subnet
 
             if (CONF.load_balancer.test_with_ipv6 and
-                    conf_lb.test_IPv6_subnet_override):
+                    conf_lb.test_ipv6_subnet_override):
                 override_ipv6_subnet = show_subnet(
-                    conf_lb.test_IPv6_subnet_override)
+                    conf_lb.test_ipv6_subnet_override)
                 cls.lb_member_vip_ipv6_subnet = override_ipv6_subnet
                 cls.lb_member_1_ipv6_subnet = override_ipv6_subnet
                 cls.lb_member_2_ipv6_subnet = override_ipv6_subnet
diff --git a/octavia_tempest_plugin/tests/waiters.py b/octavia_tempest_plugin/tests/waiters.py
index 820831a..7cd9fef 100644
--- a/octavia_tempest_plugin/tests/waiters.py
+++ b/octavia_tempest_plugin/tests/waiters.py
@@ -76,8 +76,8 @@
             if caller:
                 message = '({caller}) {message}'.format(caller=caller,
                                                         message=message)
-            raise exceptions.UnexpectedResponseCode(message)
-
+            if not error_ok:
+                raise exceptions.UnexpectedResponseCode(message)
         if int(time.time()) - start >= check_timeout:
             message = (
                 '{name} {field} failed to update to {expected_status} within '
@@ -165,7 +165,7 @@
             LOG.info('%s\'s status updated to DELETED.',
                      show_client.__name__)
             return
-        elif int(time.time()) - start >= check_timeout:
+        if int(time.time()) - start >= check_timeout:
             message = (
                 '{name} {field} failed to update to DELETED or become not '
                 'found (404) within the required time {timeout}. Current '