Pass timeout_dict to _get_haproxy_versions

The timeout_dict args was ignored when calling _get_haproxy_versions

_get_haproxy_versions might be the first function (that uses the amphora
API) that is called from rest_api_driver, it should respect the
timeout_dict passed by the tasks of the controller (for instance during
a failover a custom timeout_dict is used in order to optimize the
failover of missing amphorae)

Story 2009761
Task 44232

Change-Id: I48a02780adf54b8d6d3bedada448a4f91e0539ed
(cherry picked from commit 6d6a8bdf6c)
(cherry picked from commit 1da04d126a)
(cherry picked from commit 4e1cc209f7)
(cherry picked from commit f0720d67c6)
(cherry picked from commit bab9a45325)
(cherry picked from commit 94dea3a4e8)
This commit is contained in:
Gregory Thiemonge 2022-01-04 09:31:08 +01:00
parent bbf18f97ea
commit ebde499ddf
5 changed files with 109 additions and 16 deletions

View File

@ -78,15 +78,17 @@ class HaproxyAmphoraLoadBalancerDriver(
connection_logging=CONF.haproxy_amphora.connection_logging)
self.udp_jinja = jinja_udp_cfg.LvsJinjaTemplater()
def _get_haproxy_versions(self, amphora):
def _get_haproxy_versions(self, amphora, timeout_dict=None):
"""Get major and minor version number from haproxy
Example: ['1', '6']
:returns version_list: A list with the major and minor numbers
"""
self._populate_amphora_api_version(amphora)
amp_info = self.clients[amphora.api_version].get_info(amphora)
self._populate_amphora_api_version(
amphora, timeout_dict=timeout_dict)
amp_info = self.clients[amphora.api_version].get_info(
amphora, timeout_dict=timeout_dict)
haproxy_version_string = amp_info['haproxy_version']
return haproxy_version_string.split('.')[:2]
@ -136,7 +138,8 @@ class HaproxyAmphoraLoadBalancerDriver(
return
# Check which HAProxy version is on the amp
haproxy_versions = self._get_haproxy_versions(amphora)
haproxy_versions = self._get_haproxy_versions(
amphora, timeout_dict=timeout_dict)
# Check which config style to use
api_version = self._populate_amphora_api_version(amphora)
if api_version[0] == 0 and api_version[1] <= 5: # 0.5 or earlier
@ -259,15 +262,18 @@ class HaproxyAmphoraLoadBalancerDriver(
self._populate_amphora_api_version(amp)
self.clients[amp.api_version].update_cert_for_rotation(amp, pem)
def _apply(self, func_name, loadbalancer, amphora=None, *args):
def _apply(self, func_name, loadbalancer, amphora=None, *args, **kwargs):
if amphora is None:
amphorae = loadbalancer.amphorae
else:
amphorae = [amphora]
timeout_dict = args[0]
for amp in amphorae:
if amp.status != consts.DELETED:
api_version = self._populate_amphora_api_version(amp)
api_version = self._populate_amphora_api_version(
amp, timeout_dict=timeout_dict)
# Check which config style to use
if api_version[0] == 0 and api_version[1] <= 5:
# 0.5 or earlier
@ -369,11 +375,14 @@ class HaproxyAmphoraLoadBalancerDriver(
self.clients[amphora.api_version].delete_listener(
amphora, listener.load_balancer.id)
def get_info(self, amphora, raise_retry_exception=False):
def get_info(self, amphora, raise_retry_exception=False,
timeout_dict=None):
self._populate_amphora_api_version(
amphora, raise_retry_exception=raise_retry_exception)
amphora, raise_retry_exception=raise_retry_exception,
timeout_dict=timeout_dict)
return self.clients[amphora.api_version].get_info(
amphora, raise_retry_exception=raise_retry_exception)
amphora, raise_retry_exception=raise_retry_exception,
timeout_dict=timeout_dict)
def get_diagnostics(self, amphora):
pass
@ -803,8 +812,10 @@ class AmphoraAPIClient0_5(AmphoraAPIClientBase):
amp, 'listeners/{listener_id}'.format(listener_id=listener_id))
return exc.check_exception(r, (404,))
def get_info(self, amp, raise_retry_exception=False):
r = self.get(amp, "info", raise_retry_exception=raise_retry_exception)
def get_info(self, amp, raise_retry_exception=False,
timeout_dict=None):
r = self.get(amp, "info", raise_retry_exception=raise_retry_exception,
timeout_dict=timeout_dict)
if exc.check_exception(r):
return r.json()
return None
@ -932,8 +943,10 @@ class AmphoraAPIClient1_0(AmphoraAPIClientBase):
amp, 'listeners/{object_id}'.format(object_id=object_id))
return exc.check_exception(r, (404,))
def get_info(self, amp, raise_retry_exception=False):
r = self.get(amp, "info", raise_retry_exception=raise_retry_exception)
def get_info(self, amp, raise_retry_exception=False,
timeout_dict=None):
r = self.get(amp, "info", raise_retry_exception=raise_retry_exception,
timeout_dict=timeout_dict)
if exc.check_exception(r):
return r.json()
return None

View File

@ -51,7 +51,8 @@ class KeepalivedAmphoraDriverMixin(driver_base.VRRPDriverMixin):
LOG.debug("Update amphora %s VRRP configuration.", amphora.id)
self._populate_amphora_api_version(amphora)
self._populate_amphora_api_version(amphora,
timeout_dict=timeout_dict)
# Get the VIP subnet prefix for the amphora
vip_cidr = amphorae_network_config[amphora.id].vip_subnet.cidr

View File

@ -488,6 +488,16 @@ class TestHaproxyAmphoraLoadBalancerDriverTest(base.TestCase):
API_VERSION].reload_listener.assert_called_once_with(
amp1, listener.id, None)
self.driver.clients[
API_VERSION].reload_listener.reset_mock()
timeout_dict = {
'elem1': 1000
}
self.driver.reload(loadbalancer, timeout_dict=timeout_dict)
self.driver.clients[
API_VERSION].reload_listener.assert_called_once_with(
amp1, listener.id, timeout_dict)
def test_start_with_amphora(self):
# Execute driver method
amp = mock.MagicMock()
@ -657,7 +667,19 @@ class TestHaproxyAmphoraLoadBalancerDriverTest(base.TestCase):
ref_haproxy_versions = ['1', '6']
result = self.driver._get_haproxy_versions(self.amp)
self.driver.clients[API_VERSION].get_info.assert_called_once_with(
self.amp)
self.amp, timeout_dict=None)
self.assertEqual(ref_haproxy_versions, result)
def test_get_haproxy_versions_with_timeout_dict(self):
ref_haproxy_versions = ['1', '6']
timeout_dict = {
constants.CONN_MAX_RETRIES: 100,
constants.CONN_RETRY_INTERVAL: 1
}
result = self.driver._get_haproxy_versions(self.amp,
timeout_dict=timeout_dict)
self.driver.clients[API_VERSION].get_info.assert_called_once_with(
self.amp, timeout_dict=timeout_dict)
self.assertEqual(ref_haproxy_versions, result)
def test_populate_amphora_api_version(self):
@ -750,6 +772,19 @@ class TestAmphoraAPIClientTest(base.TestCase):
information = self.driver.get_info(self.amp)
self.assertEqual(info, information)
@requests_mock.mock()
def test_get_info_with_timeout_dict(self, m):
info = {"hostname": "some_hostname", "version": "some_version",
"api_version": "0.5", "uuid": FAKE_UUID_1}
m.get("{base}/info".format(base=self.base_url_ver),
json=info)
timeout_dict = {
constants.CONN_MAX_RETRIES: 100,
constants.CONN_RETRY_INTERVAL: 1
}
information = self.driver.get_info(self.amp, timeout_dict=timeout_dict)
self.assertEqual(info, information)
@requests_mock.mock()
def test_get_info_unauthorized(self, m):
m.get("{base}/info".format(base=self.base_url_ver),

View File

@ -490,6 +490,16 @@ class TestHaproxyAmphoraLoadBalancerDriverTest(base.TestCase):
API_VERSION].reload_listener.assert_called_once_with(
amp1, loadbalancer.id, None)
self.driver.clients[
API_VERSION].reload_listener.reset_mock()
timeout_dict = {
'elem1': 1000
}
self.driver.reload(loadbalancer, timeout_dict=timeout_dict)
self.driver.clients[
API_VERSION].reload_listener.assert_called_once_with(
amp1, loadbalancer.id, timeout_dict)
def test_start_with_amphora(self):
# Execute driver method
amp = mock.MagicMock()
@ -752,7 +762,19 @@ class TestHaproxyAmphoraLoadBalancerDriverTest(base.TestCase):
ref_haproxy_versions = ['1', '6']
result = self.driver._get_haproxy_versions(self.amp)
self.driver.clients[API_VERSION].get_info.assert_called_once_with(
self.amp)
self.amp, timeout_dict=None)
self.assertEqual(ref_haproxy_versions, result)
def test_get_haproxy_versions_with_timeout_dict(self):
ref_haproxy_versions = ['1', '6']
timeout_dict = {
constants.CONN_MAX_RETRIES: 100,
constants.CONN_RETRY_INTERVAL: 1
}
result = self.driver._get_haproxy_versions(self.amp,
timeout_dict=timeout_dict)
self.driver.clients[API_VERSION].get_info.assert_called_once_with(
self.amp, timeout_dict=timeout_dict)
self.assertEqual(ref_haproxy_versions, result)
def test_populate_amphora_api_version(self):
@ -839,6 +861,19 @@ class TestAmphoraAPIClientTest(base.TestCase):
information = self.driver.get_info(self.amp)
self.assertEqual(info, information)
@requests_mock.mock()
def test_get_info_with_timeout_dict(self, m):
info = {"hostname": "some_hostname", "version": "some_version",
"api_version": "0.5", "uuid": FAKE_UUID_1}
m.get("{base}/info".format(base=self.base_url_ver),
json=info)
timeout_dict = {
constants.CONN_MAX_RETRIES: 100,
constants.CONN_RETRY_INTERVAL: 1
}
information = self.driver.get_info(self.amp, timeout_dict=timeout_dict)
self.assertEqual(info, information)
@requests_mock.mock()
def test_get_info_unauthorized(self, m):
m.get("{base}/info".format(base=self.base_url_ver),

View File

@ -0,0 +1,9 @@
---
fixes:
- |
Fix an issue when Octavia performs a failover of an ACTIVE-STANDBY load
balancer that has both amphorae missing.
Some tasks in the controller took too much time to timeout because the
timeout value defined in
``[haproxy_amphora].active_connection_max_retries`` and
``[haproxy_amphora].active_connection_rety_interval`` was not used.