Handle feature compatibility of HAProxy server-state-file option

https://review.opendev.org/c/openstack/octavia/+/805955 introduced
a new feature that requires HAProxy 1.6 or higher to work. This change
ensures that with older HAProxy version this feature does not get
enabled to avoid errors.

 Conflicts:
	octavia/common/jinja/haproxy/combined_listeners/jinja_cfg.py
	octavia/tests/unit/common/jinja/haproxy/combined_listeners/test_jinja_cfg.py

Story: 2010254
Task: 46145
Change-Id: Icc7dc9bb22187f908852c20415227574ded347aa
(cherry picked from commit 69ecdb1908)
(cherry picked from commit 7f220d41ad)
(cherry picked from commit 6346341b8e)
This commit is contained in:
Tom Weininger 2022-08-25 12:47:38 +02:00 committed by Michael Johnson
parent 28a6f28702
commit bc2bded8c2
9 changed files with 28 additions and 46 deletions

View File

@ -792,6 +792,7 @@ AMP_NETNS_SVC_PREFIX = 'amphora-netns'
# Amphora Feature Compatibility
HTTP_REUSE = 'has_http_reuse'
SERVER_STATE_FILE = 'has_server_state_file'
POOL_ALPN = 'has_pool_alpn'
# TODO(johnsom) convert these to octavia_lib constants

View File

@ -100,6 +100,7 @@ class JinjaTemplater(object):
# Is it newer than haproxy 1.5?
if not (int(haproxy_versions[0]) < 2 and int(haproxy_versions[1]) < 6):
feature_compatibility[constants.HTTP_REUSE] = True
feature_compatibility[constants.SERVER_STATE_FILE] = True
if not (int(haproxy_versions[0]) < 2 and int(haproxy_versions[1]) < 9):
feature_compatibility[constants.POOL_ALPN] = True
@ -164,7 +165,8 @@ class JinjaTemplater(object):
listeners[0].load_balancer.id)
state_file_path = '%s/%s/servers-state' % (
self.base_amp_path,
listeners[0].load_balancer.id)
listeners[0].load_balancer.id) if feature_compatibility.get(
constants.SERVER_STATE_FILE) else ''
return self._get_template().render(
{'loadbalancer': loadbalancer,
'stats_sock': socket_path,

View File

@ -20,7 +20,9 @@ global
log {{ log_http | default('/run/rsyslog/octavia/log', true)}} local{{ user_log_facility }}
log {{ log_server | default('/run/rsyslog/octavia/log', true)}} local{{ administrative_log_facility }} notice
stats socket {{ sock_path }} mode 0666 level user
{% if state_file %}
server-state-file {{ state_file }}
{% endif %}
{% if loadbalancer.global_connection_limit is defined %}
maxconn {{ loadbalancer.global_connection_limit }}
{% endif %}

View File

@ -33,7 +33,7 @@
{% for listener in loadbalancer.listeners if listener.enabled %}
{{- frontend_macro(constants, lib_consts, listener, loadbalancer.vip_address) }}
{% for pool in listener.pools if pool.enabled %}
{{- backend_macro(constants, lib_consts, listener, pool, loadbalancer) }}
{{- backend_macro(constants, lib_consts, listener, pool, loadbalancer, state_file) }}
{% endfor %}
{% endfor %}
{% endif %}

View File

@ -298,7 +298,7 @@ frontend {{ listener.id }}
{% endmacro %}
{% macro backend_macro(constants, lib_consts, listener, pool, loadbalancer) %}
{% macro backend_macro(constants, lib_consts, listener, pool, loadbalancer, state_file) %}
backend {{ pool.id }}:{{ listener.id }}
{% if pool.proxy_protocol is not none %}
mode {{ listener.protocol_mode }}
@ -340,7 +340,9 @@ backend {{ pool.id }}:{{ listener.id }}
{% endif %}
{% endif %}
{% if pool.health_monitor and pool.health_monitor.enabled %}
{% if state_file %}
load-server-state-from-file global
{% endif %}
timeout check {{ pool.health_monitor.timeout }}s
{% if (pool.health_monitor.type ==
constants.HEALTH_MONITOR_HTTP or pool.health_monitor.type ==

View File

@ -31,8 +31,6 @@ class HAProxyCompatTestCase(base.TestCase):
" log /run/rsyslog/octavia/log local1 notice\n"
" stats socket /var/lib/octavia/sample_loadbalancer_id_1.sock"
" mode 0666 level user\n"
" server-state-file /var/lib/octavia/sample_loadbalancer_id_1"
"/servers-state\n"
" maxconn {maxconn}\n\n"
"defaults\n"
" log global\n"

View File

@ -64,7 +64,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -119,7 +118,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -170,7 +168,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -226,7 +223,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -280,7 +276,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -334,7 +329,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -386,7 +380,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -422,7 +415,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -449,7 +441,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -486,7 +477,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -522,7 +512,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -551,7 +540,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -592,7 +580,6 @@ class TestHaproxyCfg(base.TestCase):
" mode tcp\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -629,7 +616,6 @@ class TestHaproxyCfg(base.TestCase):
" mode tcp\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option ssl-hello-chk\n"
" fullconn {maxconn}\n"
@ -697,7 +683,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option external-check\n"
" external-check command /var/lib/octavia/ping-wrapper.sh\n"
@ -758,7 +743,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.1\\r\\nHost:\\ "
"testlab.com\n"
@ -836,7 +820,6 @@ class TestHaproxyCfg(base.TestCase):
" balance roundrobin\n"
" stick-table type ip size 10k\n"
" stick on src\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -864,7 +847,6 @@ class TestHaproxyCfg(base.TestCase):
" stick-table type string len 64 size 10k\n"
" stick store-response res.cook(JSESSIONID)\n"
" stick match req.cook(JSESSIONID)\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -988,7 +970,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1005,7 +986,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /healthmon.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1027,7 +1007,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1056,7 +1035,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1087,7 +1065,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" fullconn {maxconn}\n"
" option allbackups\n"
@ -1115,7 +1092,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1156,7 +1132,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1196,7 +1171,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1237,7 +1211,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1275,7 +1248,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1309,7 +1281,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1340,7 +1311,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1543,7 +1513,7 @@ class TestHaproxyCfg(base.TestCase):
defaults=defaults, logging="\n"),
rendered_obj)
def test_http_reuse(self):
def test_haproxy_cfg_1_8_vs_1_5(self):
j_cfg = jinja_cfg.JinjaTemplater(
base_amp_path='/var/lib/octavia',
base_crt_dir='/var/lib/octavia/certs')
@ -1551,7 +1521,12 @@ class TestHaproxyCfg(base.TestCase):
sample_amphora = sample_configs_combined.sample_amphora_tuple()
sample_proxy_listener = sample_configs_combined.sample_listener_tuple(
be_proto='PROXY')
# With http-reuse
# With http-reuse and server-state-file
go = (
" server-state-file /var/lib/octavia/sample_loadbalancer_id_1/"
"servers-state\n"
" maxconn {maxconn}\n\n").format(
maxconn=constants.HAPROXY_DEFAULT_MAXCONN)
be = ("backend {pool_id}:{listener_id}\n"
" mode http\n"
" http-reuse safe\n"
@ -1578,15 +1553,15 @@ class TestHaproxyCfg(base.TestCase):
tls_certs=None,
haproxy_versions=("1", "8", "1"))
self.assertEqual(
sample_configs_combined.sample_base_expected_config(backend=be),
sample_configs_combined.sample_base_expected_config(
global_opts=go, backend=be),
rendered_obj)
# Without http-reuse
# Without http-reuse and server-state-file
be = ("backend {pool_id}:{listener_id}\n"
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" fullconn {maxconn}\n"
" option allbackups\n"
@ -1660,7 +1635,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1676,7 +1650,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /healthmon.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"

View File

@ -1213,7 +1213,6 @@ def sample_base_expected_config(frontend=None, logging=None, backend=None,
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n"
@ -1247,7 +1246,5 @@ def sample_base_expected_config(frontend=None, logging=None, backend=None,
" log /run/rsyslog/octavia/log local0\n"
" log /run/rsyslog/octavia/log local1 notice\n"
" stats socket /var/lib/octavia/sample_loadbalancer_id_1.sock"
" mode 0666 level user\n"
" server-state-file /var/lib/octavia/sample_loadbalancer_id_1"
"/servers-state\n" +
" mode 0666 level user\n" +
global_opts + defaults + peers + frontend + logging + backend)

View File

@ -0,0 +1,7 @@
---
fixes:
- |
Fixed backwards compatibility issue with the feature that preserves HAProxy
server states between reloads.
HAProxy version 1.5 or below do not support this feature, so Octavia
will not to activate it on amphorae with those versions.