Add new PROXY protocol to lbaas pool

This patch enable configure PROXY protocol informs to backend
server about the lay 3/4 address of the incoming connections.

Close-Bug: #1677987

Change-Id: Idc9a5718dddbaaaec251c9a0673c74e4132c5f54
Signed-off-by: cheng <tangch318@gmail.com>
This commit is contained in:
cheng 2017-04-21 03:20:33 -04:00 committed by Michael Johnson
parent 3098cf18fb
commit 7100872ddb
10 changed files with 137 additions and 6 deletions

View File

@ -826,7 +826,7 @@ Pools
+---------------------+---------------+------------------------------------+
| protocol | String | Network protocol from the \ |
| | | following: ``TCP``, ``HTTP``, \ |
| | | ``HTTPS`` |
| | | ``HTTPS``, ``PROXY`` |
+---------------------+---------------+------------------------------------+
| lb_algorithm | UUID | Load balancing algorithm from \ |
| | | the following: \ |

View File

@ -58,8 +58,9 @@ PROTOCOL_TCP = 'TCP'
PROTOCOL_HTTP = 'HTTP'
PROTOCOL_HTTPS = 'HTTPS'
PROTOCOL_TERMINATED_HTTPS = 'TERMINATED_HTTPS'
PROTOCOL_PROXY = 'PROXY'
SUPPORTED_PROTOCOLS = (PROTOCOL_TCP, PROTOCOL_HTTPS, PROTOCOL_HTTP,
PROTOCOL_TERMINATED_HTTPS)
PROTOCOL_TERMINATED_HTTPS, PROTOCOL_PROXY)
# API Integer Ranges
MIN_PORT_NUMBER = 1

View File

@ -26,6 +26,7 @@ PROTOCOL_MAP = {
constants.PROTOCOL_TCP: 'tcp',
constants.PROTOCOL_HTTP: 'http',
constants.PROTOCOL_HTTPS: 'tcp',
constants.PROTOCOL_PROXY: 'proxy',
constants.PROTOCOL_TERMINATED_HTTPS: 'http'
}

View File

@ -153,15 +153,24 @@ frontend {{ listener.id }}
{% else %}
{% set persistence_opt = "" %}
{% endif %}
{{ "server %s %s:%d weight %s%s%s"|e|format(
{% if pool.protocol.lower() == constants.PROTOCOL_PROXY.lower() %}
{% set proxy_protocol_opt = " send-proxy" %}
{% else %}
{% set proxy_protocol_opt = "" %}
{% endif %}
{{ "server %s %s:%d weight %s%s%s%s"|e|format(
member.id, member.address, member.protocol_port, member.weight,
hm_opt, persistence_opt)|trim() }}
hm_opt, persistence_opt, proxy_protocol_opt)|trim() }}
{% endmacro %}
{% macro backend_macro(constants, listener, pool) %}
backend {{ pool.id }}
{% if pool.protocol.lower() == constants.PROTOCOL_PROXY.lower() %}
mode {{ listener.protocol_mode }}
{% else %}
mode {{ pool.protocol }}
{% endif %}
balance {{ pool.lb_algorithm }}
{% if pool.session_persistence %}
{% if (pool.session_persistence.type ==

View File

@ -0,0 +1,46 @@
# Copyright 2017 EayunStack, Inc.
#
# 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.
"""add proxy protocol for pool
Revision ID: 5309960964f8
Revises: 52377704420e
Create Date: 2017-04-27 01:13:38.064697
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import sql
# revision identifiers, used by Alembic.
revision = '5309960964f8'
down_revision = '52377704420e'
new_protocol = 'PROXY'
def upgrade():
insert_table = sql.table(
u'protocol',
sql.column(u'name', sa.String),
sql.column(u'description', sa.String)
)
op.bulk_insert(
insert_table,
[
{'name': new_protocol}
]
)

View File

@ -110,6 +110,31 @@ class TestPool(base.BaseAPITest):
self.listener.get('id'),
constants.ACTIVE, constants.ONLINE)
def test_create_with_proxy_protocol(self):
api_pool = self.create_pool(self.lb.get('id'),
self.listener.get('id'),
constants.PROTOCOL_PROXY,
constants.LB_ALGORITHM_ROUND_ROBIN)
self.assert_correct_lb_status(self.lb.get('id'),
constants.PENDING_UPDATE,
constants.ONLINE)
self.assert_correct_listener_status(self.lb.get('id'),
self.listener.get('id'),
constants.PENDING_UPDATE,
constants.ONLINE)
self.set_lb_status(self.lb.get('id'))
self.assertEqual(constants.PROTOCOL_PROXY, api_pool.get('protocol'))
self.assertEqual(constants.LB_ALGORITHM_ROUND_ROBIN,
api_pool.get('lb_algorithm'))
self.assertIsNotNone(api_pool.get('created_at'))
self.assertIsNone(api_pool.get('updated_at'))
self.assert_correct_lb_status(self.lb.get('id'),
constants.ACTIVE,
constants.ONLINE)
self.assert_correct_listener_status(self.lb.get('id'),
self.listener.get('id'),
constants.ACTIVE, constants.ONLINE)
def test_create_sans_listener(self):
api_pool = self.create_pool_sans_listener(
self.lb.get('id'), constants.PROTOCOL_HTTP,

View File

@ -217,6 +217,29 @@ class TestPool(base.BaseAPITest):
lb_id=self.lb_id, listener_id=self.listener_id,
pool_id=api_pool.get('id'))
def test_create_with_proxy_protocol(self):
api_pool = self.create_pool(
self.lb_id,
constants.PROTOCOL_PROXY,
constants.LB_ALGORITHM_ROUND_ROBIN,
listener_id=self.listener_id).get(self.root_tag)
self.assert_correct_status(
lb_id=self.lb_id, listener_id=self.listener_id,
pool_id=api_pool.get('id'),
lb_prov_status=constants.PENDING_UPDATE,
listener_prov_status=constants.PENDING_UPDATE,
pool_prov_status=constants.PENDING_CREATE,
pool_op_status=constants.OFFLINE)
self.set_lb_status(self.lb_id)
self.assertEqual(constants.PROTOCOL_PROXY, api_pool.get('protocol'))
self.assertEqual(constants.LB_ALGORITHM_ROUND_ROBIN,
api_pool.get('lb_algorithm'))
self.assertIsNotNone(api_pool.get('created_at'))
self.assertIsNone(api_pool.get('updated_at'))
self.assert_correct_status(
lb_id=self.lb_id, listener_id=self.listener_id,
pool_id=api_pool.get('id'))
def test_create_sans_listener(self):
api_pool = self.create_pool(
self.lb_id,

View File

@ -371,6 +371,27 @@ class TestHaproxyCfg(base.TestCase):
sample_configs.sample_base_expected_config(backend=be),
rendered_obj)
def test_render_template_pool_proxy_protocol(self):
be = ("backend sample_pool_id_1\n"
" mode http\n"
" balance roundrobin\n"
" cookie SRV insert indirect nocache\n"
" timeout check 31s\n"
" fullconn 98\n"
" server sample_member_id_1 10.0.0.99:82 "
"weight 13 check inter 30s fall 3 rise 2 "
"cookie sample_member_id_1 send-proxy\n"
" server sample_member_id_2 10.0.0.98:82 "
"weight 13 check inter 30s fall 3 rise 2 "
"cookie sample_member_id_2 send-proxy\n\n")
rendered_obj = self.jinja_cfg.render_loadbalancer_obj(
sample_configs.sample_amphora_tuple(),
sample_configs.sample_listener_tuple(
be_proto='PROXY'))
self.assertEqual(
sample_configs.sample_base_expected_config(backend=be),
rendered_obj)
def test_transform_session_persistence(self):
in_persistence = sample_configs.sample_session_persistence_tuple()
ret = self.jinja_cfg._transform_session_persistence(in_persistence)

View File

@ -398,9 +398,11 @@ def sample_vip_tuple():
def sample_listener_tuple(proto=None, monitor=True, persistence=True,
persistence_type=None, persistence_cookie=None,
tls=False, sni=False, peer_port=None, topology=None,
l7=False, enabled=True, insert_headers=None):
l7=False, enabled=True, insert_headers=None,
be_proto=None):
proto = 'HTTP' if proto is None else proto
be_proto = 'HTTP' if proto is 'TERMINATED_HTTPS' else proto
if be_proto is None:
be_proto = 'HTTP' if proto is 'TERMINATED_HTTPS' else proto
topology = 'SINGLE' if topology is None else topology
port = '443' if proto is 'HTTPS' or proto is 'TERMINATED_HTTPS' else '80'
peer_port = 1024 if peer_port is None else peer_port

View File

@ -0,0 +1,3 @@
---
features:
- Add support PROXY protocol for lbaas pool in octavia