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.

Story: 2010254
Task: 46145
Change-Id: Icc7dc9bb22187f908852c20415227574ded347aa
This commit is contained in:
Tom Weininger 2022-08-25 12:47:38 +02:00 committed by Gregory Thiemonge
parent 6ec76b1282
commit 69ecdb1908
9 changed files with 43 additions and 53 deletions

View File

@ -804,6 +804,7 @@ AMP_NETNS_SVC_PREFIX = 'amphora-netns'
# Amphora Feature Compatibility # Amphora Feature Compatibility
HTTP_REUSE = 'has_http_reuse' HTTP_REUSE = 'has_http_reuse'
SERVER_STATE_FILE = 'has_server_state_file'
POOL_ALPN = 'has_pool_alpn' POOL_ALPN = 'has_pool_alpn'
INSECURE_FORK = 'requires_insecure_fork' INSECURE_FORK = 'requires_insecure_fork'

View File

@ -103,6 +103,7 @@ class JinjaTemplater(object):
# Is it newer than haproxy 1.5? # Is it newer than haproxy 1.5?
if versionutils.is_compatible("1.6.0", version, same_major=False): if versionutils.is_compatible("1.6.0", version, same_major=False):
feature_compatibility[constants.HTTP_REUSE] = True feature_compatibility[constants.HTTP_REUSE] = True
feature_compatibility[constants.SERVER_STATE_FILE] = True
if versionutils.is_compatible("1.9.0", version, same_major=False): if versionutils.is_compatible("1.9.0", version, same_major=False):
feature_compatibility[constants.POOL_ALPN] = True feature_compatibility[constants.POOL_ALPN] = True
if int(haproxy_versions[0]) >= 2: if int(haproxy_versions[0]) >= 2:
@ -172,7 +173,8 @@ class JinjaTemplater(object):
listeners[0].load_balancer.id) listeners[0].load_balancer.id)
state_file_path = '%s/%s/servers-state' % ( state_file_path = '%s/%s/servers-state' % (
self.base_amp_path, self.base_amp_path,
listeners[0].load_balancer.id) listeners[0].load_balancer.id) if feature_compatibility.get(
constants.SERVER_STATE_FILE) else ''
prometheus_listener = False prometheus_listener = False
for listener in listeners: for listener in listeners:
if listener.protocol == lib_consts.PROTOCOL_PROMETHEUS: if listener.protocol == lib_consts.PROTOCOL_PROMETHEUS:

View File

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

View File

@ -55,7 +55,7 @@ backend prometheus-exporter-internal
{{- frontend_macro(constants, lib_consts, listener, loadbalancer.vip_address, {{- frontend_macro(constants, lib_consts, listener, loadbalancer.vip_address,
loadbalancer.additional_vips) }} loadbalancer.additional_vips) }}
{% for pool in listener.pools if pool.enabled %} {% 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 %}
{% endfor %} {% endfor %}
{% endif %} {% endif %}

View File

@ -305,7 +305,7 @@ frontend {{ listener.id }}
{% endmacro %} {% 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 }} backend {{ pool.id }}:{{ listener.id }}
{% if pool.proxy_protocol is not none %} {% if pool.proxy_protocol is not none %}
mode {{ listener.protocol_mode }} mode {{ listener.protocol_mode }}
@ -347,7 +347,9 @@ backend {{ pool.id }}:{{ listener.id }}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if pool.health_monitor and pool.health_monitor.enabled %} {% if pool.health_monitor and pool.health_monitor.enabled %}
{% if state_file %}
load-server-state-from-file global load-server-state-from-file global
{% endif %}
timeout check {{ pool.health_monitor.timeout }}s timeout check {{ pool.health_monitor.timeout }}s
{% if (pool.health_monitor.type == {% if (pool.health_monitor.type ==
constants.HEALTH_MONITOR_HTTP or 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" " log /run/rsyslog/octavia/log local1 notice\n"
" stats socket /var/lib/octavia/sample_loadbalancer_id_1.sock" " stats socket /var/lib/octavia/sample_loadbalancer_id_1.sock"
" mode 0666 level user\n" " mode 0666 level user\n"
" server-state-file /var/lib/octavia/sample_loadbalancer_id_1"
"/servers-state\n"
" maxconn {maxconn}\n\n" " maxconn {maxconn}\n\n"
"defaults\n" "defaults\n"
" log global\n" " log global\n"

View File

@ -66,7 +66,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -121,7 +120,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -172,7 +170,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -228,7 +225,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -282,7 +278,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -336,7 +331,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -388,7 +382,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -424,7 +417,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -518,7 +510,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -555,7 +546,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -591,7 +581,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -620,7 +609,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -661,7 +649,6 @@ class TestHaproxyCfg(base.TestCase):
" mode tcp\n" " mode tcp\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -698,7 +685,6 @@ class TestHaproxyCfg(base.TestCase):
" mode tcp\n" " mode tcp\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option ssl-hello-chk\n" " option ssl-hello-chk\n"
" fullconn {maxconn}\n" " fullconn {maxconn}\n"
@ -766,7 +752,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option external-check\n" " option external-check\n"
" external-check command /var/lib/octavia/ping-wrapper.sh\n" " external-check command /var/lib/octavia/ping-wrapper.sh\n"
@ -810,14 +795,18 @@ class TestHaproxyCfg(base.TestCase):
"weight 13 check inter 30s fall 3 rise 2 " "weight 13 check inter 30s fall 3 rise 2 "
"cookie sample_member_id_2\n\n").format( "cookie sample_member_id_2\n\n").format(
maxconn=constants.HAPROXY_DEFAULT_MAXCONN) maxconn=constants.HAPROXY_DEFAULT_MAXCONN)
go = (f" maxconn {constants.HAPROXY_DEFAULT_MAXCONN}\n" go = (
" server-state-file /var/lib/octavia/sample_loadbalancer_id_1/"
"servers-state\n"
f" maxconn {constants.HAPROXY_DEFAULT_MAXCONN}\n"
" external-check\n insecure-fork-wanted\n\n") " external-check\n insecure-fork-wanted\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj( rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs_combined.sample_amphora_tuple(), sample_configs_combined.sample_amphora_tuple(),
[sample_configs_combined.sample_listener_tuple( [sample_configs_combined.sample_listener_tuple(
proto='HTTP', monitor_proto='PING')], proto='HTTP', monitor_proto='PING')],
feature_compatibility={ feature_compatibility={
"requires_insecure_fork": True}) "requires_insecure_fork": True,
constants.SERVER_STATE_FILE: True})
self.assertEqual(sample_configs_combined.sample_base_expected_config( self.assertEqual(sample_configs_combined.sample_base_expected_config(
backend=be, global_opts=go), rendered_obj) backend=be, global_opts=go), rendered_obj)
@ -858,7 +847,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.1\\r\\nHost:\\ " " option httpchk GET /index.html HTTP/1.1\\r\\nHost:\\ "
"testlab.com\n" "testlab.com\n"
@ -936,7 +924,6 @@ class TestHaproxyCfg(base.TestCase):
" balance roundrobin\n" " balance roundrobin\n"
" stick-table type ip size 10k\n" " stick-table type ip size 10k\n"
" stick on src\n" " stick on src\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -964,7 +951,6 @@ class TestHaproxyCfg(base.TestCase):
" stick-table type string len 64 size 10k\n" " stick-table type string len 64 size 10k\n"
" stick store-response res.cook(JSESSIONID)\n" " stick store-response res.cook(JSESSIONID)\n"
" stick match req.cook(JSESSIONID)\n" " stick match req.cook(JSESSIONID)\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1088,7 +1074,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1105,7 +1090,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /healthmon.html HTTP/1.0\\r\\n\n" " option httpchk GET /healthmon.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1127,7 +1111,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1156,7 +1139,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1187,7 +1169,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" fullconn {maxconn}\n" " fullconn {maxconn}\n"
" option allbackups\n" " option allbackups\n"
@ -1215,7 +1196,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1256,7 +1236,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1296,7 +1275,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1337,7 +1315,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1375,7 +1352,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1409,7 +1385,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1440,7 +1415,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1652,7 +1626,7 @@ class TestHaproxyCfg(base.TestCase):
defaults=defaults, logging="\n"), defaults=defaults, logging="\n"),
rendered_obj) rendered_obj)
def test_http_reuse(self): def test_haproxy_cfg_1_8_vs_1_5(self):
j_cfg = jinja_cfg.JinjaTemplater( j_cfg = jinja_cfg.JinjaTemplater(
base_amp_path='/var/lib/octavia', base_amp_path='/var/lib/octavia',
base_crt_dir='/var/lib/octavia/certs') base_crt_dir='/var/lib/octavia/certs')
@ -1660,7 +1634,12 @@ class TestHaproxyCfg(base.TestCase):
sample_amphora = sample_configs_combined.sample_amphora_tuple() sample_amphora = sample_configs_combined.sample_amphora_tuple()
sample_proxy_listener = sample_configs_combined.sample_listener_tuple( sample_proxy_listener = sample_configs_combined.sample_listener_tuple(
be_proto='PROXY') 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" be = ("backend {pool_id}:{listener_id}\n"
" mode http\n" " mode http\n"
" http-reuse safe\n" " http-reuse safe\n"
@ -1687,15 +1666,15 @@ class TestHaproxyCfg(base.TestCase):
tls_certs=None, tls_certs=None,
haproxy_versions=("1", "8", "1")) haproxy_versions=("1", "8", "1"))
self.assertEqual( 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) rendered_obj)
# Without http-reuse # Without http-reuse and server-state-file
be = ("backend {pool_id}:{listener_id}\n" be = ("backend {pool_id}:{listener_id}\n"
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" fullconn {maxconn}\n" " fullconn {maxconn}\n"
" option allbackups\n" " option allbackups\n"
@ -1769,7 +1748,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /index.html HTTP/1.0\\r\\n\n" " option httpchk GET /index.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1785,7 +1763,6 @@ class TestHaproxyCfg(base.TestCase):
" mode http\n" " mode http\n"
" balance roundrobin\n" " balance roundrobin\n"
" cookie SRV insert indirect nocache\n" " cookie SRV insert indirect nocache\n"
" load-server-state-from-file global\n"
" timeout check 31s\n" " timeout check 31s\n"
" option httpchk GET /healthmon.html HTTP/1.0\\r\\n\n" " option httpchk GET /healthmon.html HTTP/1.0\\r\\n\n"
" http-check expect rstatus 418\n" " http-check expect rstatus 418\n"
@ -1835,7 +1812,8 @@ class TestHaproxyCfg(base.TestCase):
socket_path=mock_socket_path) socket_path=mock_socket_path)
expected_fc = { expected_fc = {
constants.HTTP_REUSE: True constants.HTTP_REUSE: True,
constants.SERVER_STATE_FILE: True
} }
mock_render_loadbalancer_obj.assert_called_once_with( mock_render_loadbalancer_obj.assert_called_once_with(
mock_amp, mock_listeners, tls_certs=mock_tls_certs, mock_amp, mock_listeners, tls_certs=mock_tls_certs,
@ -1850,7 +1828,8 @@ class TestHaproxyCfg(base.TestCase):
expected_fc = { expected_fc = {
constants.HTTP_REUSE: True, constants.HTTP_REUSE: True,
constants.POOL_ALPN: True constants.POOL_ALPN: True,
constants.SERVER_STATE_FILE: True
} }
mock_render_loadbalancer_obj.assert_called_once_with( mock_render_loadbalancer_obj.assert_called_once_with(
mock_amp, mock_listeners, tls_certs=mock_tls_certs, mock_amp, mock_listeners, tls_certs=mock_tls_certs,
@ -1866,7 +1845,8 @@ class TestHaproxyCfg(base.TestCase):
expected_fc = { expected_fc = {
constants.HTTP_REUSE: True, constants.HTTP_REUSE: True,
constants.POOL_ALPN: True, constants.POOL_ALPN: True,
lib_consts.PROTOCOL_PROMETHEUS: True lib_consts.PROTOCOL_PROMETHEUS: True,
constants.SERVER_STATE_FILE: True
} }
mock_render_loadbalancer_obj.assert_called_once_with( mock_render_loadbalancer_obj.assert_called_once_with(
mock_amp, mock_listeners, tls_certs=mock_tls_certs, mock_amp, mock_listeners, tls_certs=mock_tls_certs,
@ -1883,7 +1863,8 @@ class TestHaproxyCfg(base.TestCase):
constants.HTTP_REUSE: True, constants.HTTP_REUSE: True,
constants.POOL_ALPN: True, constants.POOL_ALPN: True,
lib_consts.PROTOCOL_PROMETHEUS: True, lib_consts.PROTOCOL_PROMETHEUS: True,
constants.INSECURE_FORK: True constants.INSECURE_FORK: True,
constants.SERVER_STATE_FILE: True
} }
mock_render_loadbalancer_obj.assert_called_once_with( mock_render_loadbalancer_obj.assert_called_once_with(
mock_amp, mock_listeners, tls_certs=mock_tls_certs, mock_amp, mock_listeners, tls_certs=mock_tls_certs,

View File

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