From: Oleg Bondarev Date: Thu, 28 Feb 2013 09:35:01 +0000 (+0400) Subject: Add session persistence support to LBaaS HAProxy driver X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=7d961093ee95cf0d0d2effae2b3ceccdd2fb7ecc;p=openstack-build%2Fneutron-build.git Add session persistence support to LBaaS HAProxy driver fixes bug 1135324 Change-Id: I5bcd6c84d6b402adecfb5a4cf81925ddbefccbb0 --- diff --git a/quantum/plugins/services/agent_loadbalancer/drivers/haproxy/cfg.py b/quantum/plugins/services/agent_loadbalancer/drivers/haproxy/cfg.py index 936bcff30..10a5f33cc 100644 --- a/quantum/plugins/services/agent_loadbalancer/drivers/haproxy/cfg.py +++ b/quantum/plugins/services/agent_loadbalancer/drivers/haproxy/cfg.py @@ -117,13 +117,18 @@ def _build_backend(config): server_addon, health_opts = _get_server_health_option(config) opts.extend(health_opts) + # add session persistence (if available) + persist_opts = _get_session_persistence(config) + opts.extend(persist_opts) + # add the members - opts.extend( - (('server %(id)s %(address)s:%(protocol_port)s ' - 'weight %(weight)s') % member) + server_addon - for member in config['members'] - if (member['status'] == ACTIVE and member['admin_state_up']) - ) + for member in config['members']: + if member['status'] == ACTIVE and member['admin_state_up']: + server = (('server %(id)s %(address)s:%(protocol_port)s ' + 'weight %(weight)s') % member) + server_addon + if _has_http_cookie_persistence(config): + server += ' cookie %d' % config['members'].index(member) + opts.append(server) return itertools.chain( ['backend %s' % config['pool']['id']], @@ -163,6 +168,31 @@ def _get_server_health_option(config): return server_addon, opts +def _get_session_persistence(config): + persistence = config['vip'].get('session_persistence') + if not persistence: + return [] + + opts = [] + if persistence['type'] == constants.SESSION_PERSISTENCE_SOURCE_IP: + opts.append('stick-table type ip size 10k') + opts.append('stick on src') + elif persistence['type'] == constants.SESSION_PERSISTENCE_HTTP_COOKIE: + opts.append('cookie SRV insert indirect nocache') + elif (persistence['type'] == constants.SESSION_PERSISTENCE_APP_COOKIE and + persistence.get('cookie_name')): + opts.append('appsession %s len 56 timeout 3h' % + persistence['cookie_name']) + + return opts + + +def _has_http_cookie_persistence(config): + return (config['vip'].get('session_persistence') and + config['vip']['session_persistence']['type'] == + constants.SESSION_PERSISTENCE_HTTP_COOKIE) + + def _expand_expected_codes(codes): """Expand the expected code string in set of codes. diff --git a/quantum/tests/unit/services/agent_loadbalancer/driver/haproxy/test_cfg.py b/quantum/tests/unit/services/agent_loadbalancer/driver/haproxy/test_cfg.py new file mode 100644 index 000000000..8bddcb997 --- /dev/null +++ b/quantum/tests/unit/services/agent_loadbalancer/driver/haproxy/test_cfg.py @@ -0,0 +1,55 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Mirantis, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# @author: Oleg Bondarev (obondarev@mirantis.com) + +import testtools + +from quantum.plugins.services.agent_loadbalancer.drivers.haproxy import cfg + + +class TestHaproxyCfg(testtools.TestCase): + + def test_has_http_cookie_persistence(self): + config = {'vip': {'session_persistence': {'type': 'HTTP_COOKIE'}}} + self.assertTrue(cfg._has_http_cookie_persistence(config)) + + config = {'vip': {'session_persistence': {'type': 'SOURCE_IP'}}} + self.assertFalse(cfg._has_http_cookie_persistence(config)) + + config = {'vip': {'session_persistence': {}}} + self.assertFalse(cfg._has_http_cookie_persistence(config)) + + def test_get_session_persistence(self): + config = {'vip': {'session_persistence': {'type': 'SOURCE_IP'}}} + self.assertEqual(cfg._get_session_persistence(config), + ['stick-table type ip size 10k', 'stick on src']) + + config = {'vip': {'session_persistence': {'type': 'HTTP_COOKIE'}}} + self.assertEqual(cfg._get_session_persistence(config), + ['cookie SRV insert indirect nocache']) + + config = {'vip': {'session_persistence': {'type': 'APP_COOKIE', + 'cookie_name': 'test'}}} + self.assertEqual(cfg._get_session_persistence(config), + ['appsession test len 56 timeout 3h']) + + config = {'vip': {'session_persistence': {'type': 'APP_COOKIE'}}} + self.assertEqual(cfg._get_session_persistence(config), []) + + config = {'vip': {'session_persistence': {'type': 'UNSUPPORTED'}}} + self.assertEqual(cfg._get_session_persistence(config), [])