diff --git a/neutron_lbaas/drivers/haproxy/jinja_cfg.py b/neutron_lbaas/drivers/haproxy/jinja_cfg.py index 5b8c36a39..a18ed277e 100644 --- a/neutron_lbaas/drivers/haproxy/jinja_cfg.py +++ b/neutron_lbaas/drivers/haproxy/jinja_cfg.py @@ -248,14 +248,25 @@ def _transform_loadbalancer(loadbalancer, haproxy_base_dir): listeners = [_transform_listener(x, haproxy_base_dir) for x in loadbalancer.listeners if x.admin_state_up] pools = [_transform_pool(x) for x in loadbalancer.pools] + connection_limit = _compute_global_connection_limit(listeners) return { 'name': loadbalancer.name, 'vip_address': loadbalancer.vip_address, + 'connection_limit': connection_limit, 'listeners': listeners, 'pools': pools } +def _compute_global_connection_limit(listeners): + # NOTE(dlundquist): HAProxy has a global default connection limit + # of 2000, so we will include 2000 connections for each listener + # without a connection limit specified. This way we provide the + # same behavior as a default haproxy configuration without + # connection limit specified in the case of a single load balancer. + return sum([x.get('connection_limit', 2000) for x in listeners]) + + def _transform_listener(listener, haproxy_base_dir): """Transforms listener object diff --git a/neutron_lbaas/drivers/haproxy/templates/haproxy.loadbalancer.j2 b/neutron_lbaas/drivers/haproxy/templates/haproxy.loadbalancer.j2 index 21250d6fa..2cedb326e 100644 --- a/neutron_lbaas/drivers/haproxy/templates/haproxy.loadbalancer.j2 +++ b/neutron_lbaas/drivers/haproxy/templates/haproxy.loadbalancer.j2 @@ -17,6 +17,7 @@ {% set loadbalancer_name = loadbalancer.name %} {% set usergroup = user_group %} {% set sock_path = stats_sock %} +{% set connection_limit = loadbalancer.connection_limit %} {% block proxies %} {% from 'haproxy_proxies.j2' import frontend_macro as frontend_macro, backend_macro%} diff --git a/neutron_lbaas/drivers/haproxy/templates/haproxy_base.j2 b/neutron_lbaas/drivers/haproxy/templates/haproxy_base.j2 index e405c959b..830580140 100644 --- a/neutron_lbaas/drivers/haproxy/templates/haproxy_base.j2 +++ b/neutron_lbaas/drivers/haproxy/templates/haproxy_base.j2 @@ -20,6 +20,7 @@ global group {{ usergroup }} log /dev/log local0 log /dev/log local1 notice + maxconn {{ connection_limit }} stats socket {{ sock_path }} mode 0666 level user defaults diff --git a/neutron_lbaas/tests/unit/drivers/haproxy/sample_configs/sample_configs.py b/neutron_lbaas/tests/unit/drivers/haproxy/sample_configs/sample_configs.py index c23176b6f..dbb3bc7a6 100644 --- a/neutron_lbaas/tests/unit/drivers/haproxy/sample_configs/sample_configs.py +++ b/neutron_lbaas/tests/unit/drivers/haproxy/sample_configs/sample_configs.py @@ -102,18 +102,21 @@ RET_LB = { 'name': 'test-lb', 'vip_address': '10.0.0.2', 'listeners': [RET_LISTENER], + 'connection_limit': RET_LISTENER['connection_limit'], 'pools': [RET_POOL]} RET_LB_TLS = { 'name': 'test-lb', 'vip_address': '10.0.0.2', 'listeners': [RET_LISTENER_TLS], + 'connection_limit': RET_LISTENER_TLS['connection_limit'], 'pools': [RET_POOL]} RET_LB_TLS_SNI = { 'name': 'test-lb', 'vip_address': '10.0.0.2', 'listeners': [RET_LISTENER_TLS_SNI], + 'connection_limit': RET_LISTENER_TLS_SNI['connection_limit'], 'pools': [RET_POOL]} @@ -148,7 +151,8 @@ def sample_vip_port_tuple(): def sample_listener_tuple(proto=None, monitor=True, persistence=True, - persistence_type=None, tls=False, sni=False): + persistence_type=None, tls=False, sni=False, + connection_limit=98): proto = 'HTTP' if proto is None else proto port = '443' if proto is 'HTTPS' or proto is 'TERMINATED_HTTPS' else '80' in_listener = collections.namedtuple( @@ -164,7 +168,7 @@ def sample_listener_tuple(proto=None, monitor=True, persistence=True, default_pool=sample_pool_tuple( proto=proto, monitor=monitor, persistence=persistence, persistence_type=persistence_type), - connection_limit=98, + connection_limit=connection_limit, admin_state_up=True, default_tls_container_id='cont_id_1' if tls else '', sni_container_ids=['cont_id_2', 'cont_id_3'] if sni else [], @@ -284,6 +288,7 @@ def sample_base_expected_config(backend, frontend=None): " group nogroup\n" " log /dev/log local0\n" " log /dev/log local1 notice\n" + " maxconn 98\n" " stats socket /sock_path mode 0666 level user\n\n" "defaults\n" " log global\n" diff --git a/neutron_lbaas/tests/unit/drivers/haproxy/test_jinja_cfg.py b/neutron_lbaas/tests/unit/drivers/haproxy/test_jinja_cfg.py index b06bb8fe9..f384e529f 100644 --- a/neutron_lbaas/tests/unit/drivers/haproxy/test_jinja_cfg.py +++ b/neutron_lbaas/tests/unit/drivers/haproxy/test_jinja_cfg.py @@ -447,6 +447,14 @@ class TestHaproxyCfg(base.BaseTestCase): ret = jinja_cfg._transform_loadbalancer(in_lb, '/v2') self.assertEqual(sample_configs.RET_LB, ret) + def test_compute_global_connection_limit(self): + lts = [ + sample_configs.sample_listener_tuple(connection_limit=None), + sample_configs.sample_listener_tuple()] + in_listeners = [jinja_cfg._transform_listener(x, '/v2') for x in lts] + ret = jinja_cfg._compute_global_connection_limit(in_listeners) + self.assertEqual(2098, ret) + def test_include_member(self): ret = jinja_cfg._include_member( sample_configs.sample_member_tuple('sample_member_id_1',