[barbican] Retry on tls connection timeout

The GET request could get lost or stuck on the way to
loadbalancer->backend, so let's retry it.

Closes-Bug: PRODX-16055
Change-Id: Iab75cc251daba755dd248cda6b7b8c534283fc5d
(cherry picked from commit 01954d37942b7220243e914cecded8ac16d1a1c0)
(cherry picked from commit aa656cabf94e8a7679c06ad2e365b4e18caebf4d)
(cherry picked from commit 43441afb3719ae03d60e7f653009fb336c427254)
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 85fcef0..14468c8 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
@@ -22,6 +22,7 @@
 import httpx
 from OpenSSL.crypto import X509
 from OpenSSL import SSL
+import tenacity
 
 from oslo_log import log as logging
 from oslo_utils import uuidutils
@@ -350,9 +351,12 @@
                 # Make sure the certificate is the one we generated
                 self.assertEqual(expected_cn, received_cn, message=msg)
             else:
-                LOG.error('Certificate with CN: %s failed validation with '
-                          'OpenSSL verify errno %s',
-                          x509.get_subject().commonName, errno)
+                LOG.error(
+                    "Certificate with CN: %s failed validation with"
+                    " OpenSSL verify errno %s",
+                    x509.get_subject().commonName,
+                    errno
+                )
                 return False
             return True
 
@@ -488,9 +492,12 @@
                 # Make sure the certificate is the one we generated
                 self.assertEqual(expected_cn, received_cn, message=msg)
             else:
-                LOG.error('Certificate with CN: %s failed validation with '
-                          'OpenSSL verify errno %s',
-                          x509.get_subject().commonName, errno)
+                LOG.error(
+                    "Certificate with CN: %s failed validation with"
+                    " OpenSSL verify errno %s",
+                    x509.get_subject().commonName,
+                    errno
+                )
                 return False
             return True
 
@@ -661,9 +668,12 @@
                 # Make sure the certificate is the one we generated
                 self.assertEqual(expected_cn, received_cn, message=msg)
             else:
-                LOG.error('Certificate with CN: %s failed validation with '
-                          'OpenSSL verify errno %s',
-                          x509.get_subject().commonName, errno)
+                LOG.error(
+                    "Certificate with CN: %s failed validation with"
+                    " OpenSSL verify errno %s",
+                    x509.get_subject().commonName,
+                    errno
+                )
                 return False
             return True
 
@@ -1245,8 +1255,18 @@
 
         self.assertEqual(expected_proto, selected_proto)
 
-    def _test_http_versions_tls_traffic(self, http_version, alpn_protos,
-                                        hsts: bool = False):
+    def _test_http_versions_tls_traffic(self, http_version, alpn_protos):
+        @tenacity.retry(
+            retry=tenacity.retry_if_exception_type(httpx.ConnectTimeout),
+            wait=tenacity.wait_incrementing(
+                const.RETRY_INITIAL_DELAY, const.RETRY_BACKOFF, const.RETRY_MAX
+            ),
+            stop=tenacity.stop_after_attempt(const.RETRY_ATTEMPTS),
+            reraise=True,
+        )
+        def _get(client, url):
+            return client.get(url)
+
         if not self.mem_listener_client.is_version_supported(
                 self.api_version, '2.20'):
             raise self.skipException('ALPN protocols are only available on '
@@ -1261,12 +1281,6 @@
             const.DEFAULT_TLS_CONTAINER_REF: self.server_secret_ref,
             const.ALPN_PROTOCOLS: alpn_protos,
         }
-        if self.mem_listener_client.is_version_supported(
-                self.api_version, '2.27'):
-            listener_kwargs[const.HSTS_MAX_AGE] = 100 if hsts else None
-            listener_kwargs[const.HSTS_INCLUDE_SUBDOMAINS] = hsts
-            listener_kwargs[const.HSTS_PRELOAD] = hsts
-
         listener = self.mem_listener_client.create_listener(**listener_kwargs)
         self.listener_id = listener[const.ID]
         self.addCleanup(
@@ -1279,26 +1293,25 @@
                                 const.ACTIVE,
                                 CONF.load_balancer.build_interval,
                                 CONF.load_balancer.build_timeout)
+        # NOTE(pas-ha): depending on what other tempest plugins are installed
+        # the eventlet might've been imported by that time, and, since
+        # dnspython 2.2.0, importing eventlet or any part of it effectively
+        # instantiates a dummy httpx.Client instance, thus pinning the ssl
+        # implementation in httpx to the eventlet's one.
+        # This leads to error in the Client() call below, as the ssl lib in
+        # this module is different from ssl lib in httpx._config,
+        # which fails isinstance check for ssl.SSLContext.
+        # Use the ssl module that is actually used by httpx to instantiate
+        # the SSL context to be used with httpx.
+        ssl = httpx._config.ssl
         context = ssl.create_default_context(cadata=self.ca_cert.public_bytes(
             serialization.Encoding.PEM).decode('utf-8'))
         context.check_hostname = False
 
         url = 'https://%s:%s' % (self.lb_vip_address, 443)
-        client_kwargs = {
-            'verify': context
-        }
-        if http_version == 'HTTP/2':
-            client_kwargs['http1'] = False
-            client_kwargs['http2'] = True
-        client = httpx.Client(**client_kwargs)
-        r = client.get(url)
+        client = httpx.Client(http2=(http_version == 'HTTP/2'), verify=context)
+        r = _get(client, url)
         self.assertEqual(http_version, r.http_version)
-        if hsts:
-            self.assertIn('strict-transport-security', r.headers)
-            self.assertEqual('max-age=100; includeSubDomains; preload;',
-                             r.headers['strict-transport-security'])
-        else:
-            self.assertNotIn('strict-transport-security', r.headers)
 
     @decorators.idempotent_id('9965828d-24af-4fa0-91ae-21c6bc47ab4c')
     def test_http_2_tls_traffic(self):
@@ -1309,15 +1322,6 @@
         self._test_http_versions_tls_traffic(
             'HTTP/1.1', ['http/1.1', 'http/1.0'])
 
-    @decorators.idempotent_id('7436c6b7-44be-4544-a40b-31d2b7b2ad0b')
-    def test_http_1_1_tls_hsts_traffic(self):
-        if not self.mem_listener_client.is_version_supported(
-                self.api_version, '2.27'):
-            raise self.skipException('HSTS is only available on '
-                                     'Octavia API version 2.27 or newer.')
-        self._test_http_versions_tls_traffic(
-            'HTTP/1.1', ['http/1.1', 'http/1.0'], hsts=True)
-
     @decorators.idempotent_id('ee0faf71-d11e-4323-8673-e5e15779749b')
     def test_pool_reencryption(self):
         if not self.mem_listener_client.is_version_supported(