UDP jinja template
This is the jinja template[1] for keepalived to enable lvs configuration. And including some transform function from obj to rendered configuration. These files will split with the current Octavia repo, before other parts are ok. Patch List: [1] Finish keepalived LVS jinja template for UDP support [2] Extend the ability of amp agent for upload/refresh the keepalived process [3] Extend the db model and db table with necessary fields for met the new udp backend [4] Add logic/workflow elements process in UDP cases [5] Extend the existing API to access udp parameters in Listener API [6] Extend the existing pool API to access the new option in session_persistence fields Story: 1657091 Task: 23208 Change-Id: Ib23edb7190ffb777e4a95f45a253e8a632beb046
This commit is contained in:
parent
06c6131bff
commit
008ccb652d
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
nc_cmd=`which nc`
|
||||
$nc_cmd -uzv -w1 $1 $2 > /dev/null
|
||||
exit $?
|
|
@ -31,6 +31,7 @@ HEALTH_MONITOR_TCP = 'TCP'
|
|||
HEALTH_MONITOR_HTTP = 'HTTP'
|
||||
HEALTH_MONITOR_HTTPS = 'HTTPS'
|
||||
HEALTH_MONITOR_TLS_HELLO = 'TLS-HELLO'
|
||||
HEALTH_MONITOR_UDP_CONNECT = 'UDP-CONNECT'
|
||||
SUPPORTED_HEALTH_MONITOR_TYPES = (HEALTH_MONITOR_HTTP, HEALTH_MONITOR_HTTPS,
|
||||
HEALTH_MONITOR_PING, HEALTH_MONITOR_TCP,
|
||||
HEALTH_MONITOR_TLS_HELLO)
|
||||
|
@ -65,6 +66,7 @@ UPDATE_STATS = 'UPDATE_STATS'
|
|||
UPDATE_HEALTH = 'UPDATE_HEALTH'
|
||||
|
||||
PROTOCOL_TCP = 'TCP'
|
||||
PROTOCOL_UDP = 'UDP'
|
||||
PROTOCOL_HTTP = 'HTTP'
|
||||
PROTOCOL_HTTPS = 'HTTPS'
|
||||
PROTOCOL_TERMINATED_HTTPS = 'TERMINATED_HTTPS'
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
# Copyright (c) 2018 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
|
||||
import os
|
||||
|
||||
import jinja2
|
||||
|
||||
from octavia.common.config import cfg
|
||||
from octavia.common import constants
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
PROTOCOL_MAP = {
|
||||
constants.PROTOCOL_UDP: 'udp'
|
||||
}
|
||||
|
||||
BALANCE_MAP = {
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN: 'rr',
|
||||
constants.LB_ALGORITHM_LEAST_CONNECTIONS: 'lc',
|
||||
constants.LB_ALGORITHM_SOURCE_IP: 'sh'
|
||||
}
|
||||
|
||||
BASE_PATH = CONF.haproxy_amphora.base_path
|
||||
|
||||
CHECK_SCRIPT_NAME = 'udp_check.sh'
|
||||
|
||||
KEEPALIVED_LVS_TEMPLATE = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__),
|
||||
'templates/keepalivedlvs.cfg.j2'))
|
||||
|
||||
JINJA_ENV = None
|
||||
|
||||
|
||||
class LvsJinjaTemplater(object):
|
||||
|
||||
def __init__(self, base_amp_path=None, keepalivedlvs_template=None):
|
||||
"""Keepalived LVS configuration generation
|
||||
|
||||
:param base_amp_path: Base path for amphora data
|
||||
:param keepalivedlvs_template: Absolute path to Jinja template
|
||||
"""
|
||||
|
||||
self.base_amp_path = base_amp_path or BASE_PATH
|
||||
self.keepalivedlvs_template = (keepalivedlvs_template or
|
||||
KEEPALIVED_LVS_TEMPLATE)
|
||||
|
||||
def build_config(self, listener, **kwargs):
|
||||
"""Convert a logical configuration to the Keepalived LVS version
|
||||
|
||||
:param listener: The listener configuration
|
||||
:return: Rendered configuration
|
||||
"""
|
||||
return self.render_loadbalancer_obj(listener)
|
||||
|
||||
def _get_template(self):
|
||||
"""Returns the specified Jinja configuration template."""
|
||||
global JINJA_ENV
|
||||
if not JINJA_ENV:
|
||||
template_loader = jinja2.FileSystemLoader(
|
||||
searchpath=os.path.dirname(self.keepalivedlvs_template))
|
||||
JINJA_ENV = jinja2.Environment(
|
||||
autoescape=True,
|
||||
loader=template_loader,
|
||||
trim_blocks=True,
|
||||
lstrip_blocks=True,
|
||||
extensions=['jinja2.ext.do'])
|
||||
return JINJA_ENV.get_template(os.path.basename(
|
||||
self.keepalivedlvs_template))
|
||||
|
||||
def render_loadbalancer_obj(self, listener, **kwargs):
|
||||
"""Renders a templated configuration from a load balancer object
|
||||
|
||||
:param host_amphora: The Amphora this configuration is hosted on
|
||||
:param listener: The listener configuration
|
||||
:return: Rendered configuration
|
||||
"""
|
||||
loadbalancer = self._transform_loadbalancer(
|
||||
listener.load_balancer,
|
||||
listener)
|
||||
return self._get_template().render(
|
||||
{'loadbalancer': loadbalancer},
|
||||
constants=constants)
|
||||
|
||||
def _transform_loadbalancer(self, loadbalancer, listener):
|
||||
"""Transforms a load balancer into an object that will
|
||||
|
||||
be processed by the templating system
|
||||
"""
|
||||
t_listener = self._transform_listener(listener)
|
||||
ret_value = {
|
||||
'vip_address': loadbalancer.vip.ip_address,
|
||||
'listener': t_listener,
|
||||
'enabled': loadbalancer.enabled
|
||||
}
|
||||
return ret_value
|
||||
|
||||
def _transform_listener(self, listener):
|
||||
"""Transforms a listener into an object that will
|
||||
|
||||
be processed by the templating system
|
||||
"""
|
||||
ret_value = {
|
||||
'id': listener.id,
|
||||
'protocol_port': listener.protocol_port,
|
||||
'protocol_mode': PROTOCOL_MAP[listener.protocol],
|
||||
'enabled': listener.enabled
|
||||
}
|
||||
if listener.connection_limit and listener.connection_limit > -1:
|
||||
ret_value['connection_limit'] = listener.connection_limit
|
||||
if listener.default_pool:
|
||||
ret_value['default_pool'] = self._transform_pool(
|
||||
listener.default_pool)
|
||||
return ret_value
|
||||
|
||||
def _transform_pool(self, pool):
|
||||
"""Transforms a pool into an object that will
|
||||
|
||||
be processed by the templating system
|
||||
"""
|
||||
ret_value = {
|
||||
'id': pool.id,
|
||||
'protocol': PROTOCOL_MAP[pool.protocol],
|
||||
'lb_algorithm': BALANCE_MAP.get(pool.lb_algorithm,
|
||||
'roundrobin'),
|
||||
'members': [],
|
||||
'health_monitor': '',
|
||||
'session_persistence': '',
|
||||
'enabled': pool.enabled
|
||||
}
|
||||
members = [self._transform_member(x) for x in pool.members]
|
||||
ret_value['members'] = members
|
||||
if pool.health_monitor:
|
||||
ret_value['health_monitor'] = self._transform_health_monitor(
|
||||
pool.health_monitor)
|
||||
if pool.session_persistence:
|
||||
func = self._transform_session_persistence
|
||||
ret_value['session_persistence'] = func(
|
||||
pool.session_persistence)
|
||||
return ret_value
|
||||
|
||||
@staticmethod
|
||||
def _transform_session_persistence(persistence):
|
||||
"""Transforms session persistence into an object that will
|
||||
|
||||
be processed by the templating system
|
||||
"""
|
||||
return {
|
||||
'type': persistence.type,
|
||||
'persistence_timeout': persistence.persistence_timeout,
|
||||
'persistence_granularity': persistence.persistence_granularity
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _transform_member(member):
|
||||
"""Transforms a member into an object that will
|
||||
|
||||
be processed by the templating system
|
||||
"""
|
||||
return {
|
||||
'id': member.id,
|
||||
'address': member.ip_address,
|
||||
'protocol_port': member.protocol_port,
|
||||
'weight': member.weight,
|
||||
'enabled': member.enabled
|
||||
}
|
||||
|
||||
def _get_default_lvs_check_script_path(self):
|
||||
return (CONF.haproxy_amphora.base_path +
|
||||
'/lvs/check/' + CHECK_SCRIPT_NAME)
|
||||
|
||||
def _transform_health_monitor(self, monitor):
|
||||
"""Transforms a health monitor into an object that will
|
||||
|
||||
be processed by the templating system
|
||||
"""
|
||||
return {
|
||||
'id': monitor.id,
|
||||
'type': monitor.type,
|
||||
'delay': monitor.delay,
|
||||
'timeout': monitor.timeout,
|
||||
'enabled': monitor.enabled,
|
||||
'fall_threshold': monitor.fall_threshold,
|
||||
'check_script_path': (self._get_default_lvs_check_script_path()
|
||||
if monitor.type ==
|
||||
constants.HEALTH_MONITOR_UDP_CONNECT else
|
||||
None)
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{# Copyright (c) 2018 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#}
|
||||
# Configuration for Listener {{ udp_listener_id }}
|
||||
|
||||
{% block global_definitions %}{% endblock global_definitions %}
|
||||
|
||||
{% block proxies %}{% endblock proxies %}
|
|
@ -0,0 +1,28 @@
|
|||
{# Copyright (c) 2018 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#}
|
||||
{% extends 'base.j2' %}
|
||||
{% from 'macros.j2' import virtualserver_macro %}
|
||||
{% set udp_listener_id = loadbalancer.listener.id %}
|
||||
{% block global_definitions %}
|
||||
net_namespace amphora-haproxy
|
||||
{% endblock global_definitions %}
|
||||
{% block proxies %}
|
||||
{% if loadbalancer.enabled and loadbalancer.listener.enabled %}
|
||||
{{- virtualserver_macro(constants, loadbalancer.listener,
|
||||
loadbalancer.vip_address,
|
||||
loadbalancer.listener.get('default_pool', None)) }}
|
||||
{% endif %}
|
||||
{% endblock proxies %}
|
|
@ -0,0 +1,105 @@
|
|||
{# Copyright (c) 2018 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#}
|
||||
|
||||
{%- macro lb_algo_macro(pool) -%}
|
||||
lb_algo {{ pool.lb_algorithm }}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% macro misc_path_macro(member, health_monitor) -%}
|
||||
misc_path "{{ health_monitor.check_script_path }} {{ member.address }} {{ member.protocol_port }}"
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro misc_check_macro(pool, member, health_monitor) -%}
|
||||
MISC_CHECK {
|
||||
{{ misc_path_macro(member, health_monitor) }}
|
||||
misc_timeout {{ pool.health_monitor.delay }}
|
||||
misc_dynamic
|
||||
}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% macro health_monitor_rs_macro(constants, pool, member) %}
|
||||
{% if pool.health_monitor and pool.health_monitor.enabled %}
|
||||
{% if pool.health_monitor.timeout %}
|
||||
delay_before_retry {{ pool.health_monitor.timeout }}
|
||||
{% endif %}
|
||||
{% if pool.health_monitor.fall_threshold %}
|
||||
retry {{ pool.health_monitor.fall_threshold }}
|
||||
{% endif %}
|
||||
{% if pool.health_monitor.type == constants.HEALTH_MONITOR_UDP_CONNECT %}
|
||||
{{ misc_check_macro(pool, member, pool.health_monitor) -}}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro realserver_macro(constants, pool, member, listener) %}
|
||||
# Configuration for Member {{ member.id }}
|
||||
real_server {{ member.address }} {{ member.protocol_port }} {
|
||||
weight {{ member.weight }}
|
||||
inhibit_on_failure
|
||||
{% if listener.connection_limit %}
|
||||
uthreshold {{ listener.connection_limit }}
|
||||
{% endif %}
|
||||
{% if pool.session_persistence and pool.session_persistence.type == constants.SESSION_PERSISTENCE_SOURCE_IP %}
|
||||
persistence_timeout {{ pool.session_persistence.persistence_timeout }}
|
||||
persistence_granularity {{ pool.session_persistence.persistence_granularity }}
|
||||
{% endif %}
|
||||
{{- health_monitor_rs_macro(constants, pool, member) }}
|
||||
}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro health_monitor_vs_macro(default_pool) %}
|
||||
{% if default_pool and default_pool.health_monitor and default_pool.health_monitor.enabled %}
|
||||
{% if default_pool.health_monitor.delay %}
|
||||
delay_loop {{ default_pool.health_monitor.delay }}
|
||||
{% endif %}
|
||||
{% if default_pool.health_monitor.timeout %}
|
||||
delay_before_retry {{ default_pool.health_monitor.timeout }}
|
||||
{% endif %}
|
||||
{% if default_pool.health_monitor.fall_threshold %}
|
||||
retry {{ default_pool.health_monitor.fall_threshold }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro virtualserver_macro(constants, listener, lb_vip_address, default_pool) %}
|
||||
{% set need_render = [] %}
|
||||
{% if default_pool and default_pool.enabled and default_pool.members %}
|
||||
{% for member in default_pool.members if member.enabled %}
|
||||
{% do need_render.append(member.enabled) %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if need_render|length > 0 %}
|
||||
virtual_server {{ lb_vip_address }} {{ listener.protocol_port }} {
|
||||
{{ lb_algo_macro(default_pool) }}
|
||||
{% if not default_pool.session_persistence %}
|
||||
ops
|
||||
{% endif %}
|
||||
lb_kind NAT
|
||||
protocol {{ listener.protocol_mode }}
|
||||
{{ health_monitor_vs_macro(default_pool) }}
|
||||
|
||||
{% if default_pool.protocol.lower() == "udp" %}
|
||||
# Configuration for Pool {{ default_pool.id }}
|
||||
{% if default_pool.health_monitor and default_pool.health_monitor.enabled %}
|
||||
# Configuration for HealthMonitor {{ default_pool.health_monitor.id }}
|
||||
{% endif %}
|
||||
{% for member in default_pool.members if member.enabled %}
|
||||
{{- realserver_macro(constants, default_pool, member, listener) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
|
@ -0,0 +1,270 @@
|
|||
# Copyright 2018 OpenStack Foundation
|
||||
# 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.
|
||||
|
||||
from octavia.common import constants
|
||||
from octavia.common.jinja.lvs import jinja_cfg
|
||||
from octavia.tests.unit import base
|
||||
from octavia.tests.unit.common.sample_configs import sample_configs
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_config import fixture as oslo_fixture
|
||||
|
||||
BASE_PATH = '/var/lib/octavia'
|
||||
|
||||
|
||||
class TestLvsCfg(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TestLvsCfg, self).setUp()
|
||||
self.udp_jinja_cfg = jinja_cfg.LvsJinjaTemplater()
|
||||
conf = oslo_fixture.Config(cfg.CONF)
|
||||
conf.config(group="haproxy_amphora", base_path=BASE_PATH)
|
||||
|
||||
def test_udp_get_template(self):
|
||||
template = self.udp_jinja_cfg._get_template()
|
||||
self.assertEqual('keepalivedlvs.cfg.j2', template.name)
|
||||
|
||||
def test_render_template_udp_source_ip(self):
|
||||
exp = ("# Configuration for Listener sample_listener_id_1\n\n"
|
||||
"net_namespace amphora-haproxy\n\n"
|
||||
"virtual_server 10.0.0.2 80 {\n"
|
||||
" lb_algo rr\n"
|
||||
" lb_kind NAT\n"
|
||||
" protocol udp\n"
|
||||
" delay_loop 30\n"
|
||||
" delay_before_retry 31\n"
|
||||
" retry 3\n\n\n"
|
||||
" # Configuration for Pool sample_pool_id_1\n"
|
||||
" # Configuration for HealthMonitor sample_monitor_id_1\n"
|
||||
" # Configuration for Member sample_member_id_1\n"
|
||||
" real_server 10.0.0.99 82 {\n"
|
||||
" weight 13\n"
|
||||
" inhibit_on_failure\n"
|
||||
" uthreshold 98\n"
|
||||
" persistence_timeout 33\n"
|
||||
" persistence_granularity 255.255.0.0\n"
|
||||
" delay_before_retry 31\n"
|
||||
" retry 3\n"
|
||||
" MISC_CHECK {\n"
|
||||
" misc_path \"/var/lib/octavia/lvs/check/"
|
||||
"udp_check.sh 10.0.0.99 82\"\n"
|
||||
" misc_timeout 30\n"
|
||||
" misc_dynamic\n"
|
||||
" }\n"
|
||||
" }\n\n"
|
||||
" # Configuration for Member sample_member_id_2\n"
|
||||
" real_server 10.0.0.98 82 {\n"
|
||||
" weight 13\n"
|
||||
" inhibit_on_failure\n"
|
||||
" uthreshold 98\n"
|
||||
" persistence_timeout 33\n"
|
||||
" persistence_granularity 255.255.0.0\n"
|
||||
" delay_before_retry 31\n"
|
||||
" retry 3\n"
|
||||
" MISC_CHECK {\n"
|
||||
" misc_path \"/var/lib/octavia/lvs/check/"
|
||||
"udp_check.sh 10.0.0.98 82\"\n"
|
||||
" misc_timeout 30\n"
|
||||
" misc_dynamic\n"
|
||||
" }\n"
|
||||
" }\n\n"
|
||||
"}\n\n")
|
||||
rendered_obj = self.udp_jinja_cfg.render_loadbalancer_obj(
|
||||
sample_configs.sample_listener_tuple(
|
||||
proto=constants.PROTOCOL_UDP,
|
||||
persistence_type=constants.SESSION_PERSISTENCE_SOURCE_IP,
|
||||
persistence_timeout=33,
|
||||
persistence_granularity='255.255.0.0',
|
||||
monitor_proto=constants.HEALTH_MONITOR_UDP_CONNECT,
|
||||
connection_limit=98))
|
||||
self.assertEqual(exp, rendered_obj)
|
||||
|
||||
def test_render_template_udp_one_packet(self):
|
||||
exp = ("# Configuration for Listener sample_listener_id_1\n\n"
|
||||
"net_namespace amphora-haproxy\n\n"
|
||||
"virtual_server 10.0.0.2 80 {\n"
|
||||
" lb_algo rr\n"
|
||||
" ops\n"
|
||||
" lb_kind NAT\n"
|
||||
" protocol udp\n"
|
||||
" delay_loop 30\n"
|
||||
" delay_before_retry 31\n"
|
||||
" retry 3\n\n\n"
|
||||
" # Configuration for Pool sample_pool_id_1\n"
|
||||
" # Configuration for HealthMonitor sample_monitor_id_1\n"
|
||||
" # Configuration for Member sample_member_id_1\n"
|
||||
" real_server 10.0.0.99 82 {\n"
|
||||
" weight 13\n"
|
||||
" inhibit_on_failure\n"
|
||||
" uthreshold 98\n"
|
||||
" delay_before_retry 31\n"
|
||||
" retry 3\n"
|
||||
" MISC_CHECK {\n"
|
||||
" misc_path \"/var/lib/octavia/lvs/check/"
|
||||
"udp_check.sh 10.0.0.99 82\"\n"
|
||||
" misc_timeout 30\n"
|
||||
" misc_dynamic\n"
|
||||
" }\n"
|
||||
" }\n\n"
|
||||
" # Configuration for Member sample_member_id_2\n"
|
||||
" real_server 10.0.0.98 82 {\n"
|
||||
" weight 13\n"
|
||||
" inhibit_on_failure\n"
|
||||
" uthreshold 98\n"
|
||||
" delay_before_retry 31\n"
|
||||
" retry 3\n"
|
||||
" MISC_CHECK {\n"
|
||||
" misc_path \"/var/lib/octavia/lvs/check/"
|
||||
"udp_check.sh 10.0.0.98 82\"\n"
|
||||
" misc_timeout 30\n"
|
||||
" misc_dynamic\n"
|
||||
" }\n"
|
||||
" }\n\n"
|
||||
"}\n\n")
|
||||
|
||||
listener = sample_configs.sample_listener_tuple(
|
||||
proto=constants.PROTOCOL_UDP,
|
||||
monitor_proto=constants.HEALTH_MONITOR_UDP_CONNECT,
|
||||
connection_limit=98,
|
||||
persistence=False)
|
||||
rendered_obj = self.udp_jinja_cfg.render_loadbalancer_obj(listener)
|
||||
self.assertEqual(exp, rendered_obj)
|
||||
|
||||
def test_render_template_udp_with_health_monitor(self):
|
||||
exp = ("# Configuration for Listener sample_listener_id_1\n\n"
|
||||
"net_namespace amphora-haproxy\n\n"
|
||||
"virtual_server 10.0.0.2 80 {\n"
|
||||
" lb_algo rr\n"
|
||||
" ops\n"
|
||||
" lb_kind NAT\n"
|
||||
" protocol udp\n"
|
||||
" delay_loop 30\n"
|
||||
" delay_before_retry 31\n"
|
||||
" retry 3\n\n\n"
|
||||
" # Configuration for Pool sample_pool_id_1\n"
|
||||
" # Configuration for HealthMonitor sample_monitor_id_1\n"
|
||||
" # Configuration for Member sample_member_id_1\n"
|
||||
" real_server 10.0.0.99 82 {\n"
|
||||
" weight 13\n"
|
||||
" inhibit_on_failure\n"
|
||||
" uthreshold 98\n"
|
||||
" delay_before_retry 31\n"
|
||||
" retry 3\n"
|
||||
" MISC_CHECK {\n"
|
||||
" misc_path \"/var/lib/octavia/lvs/check/"
|
||||
"udp_check.sh 10.0.0.99 82\"\n"
|
||||
" misc_timeout 30\n"
|
||||
" misc_dynamic\n"
|
||||
" }\n"
|
||||
" }\n\n"
|
||||
" # Configuration for Member sample_member_id_2\n"
|
||||
" real_server 10.0.0.98 82 {\n"
|
||||
" weight 13\n"
|
||||
" inhibit_on_failure\n"
|
||||
" uthreshold 98\n"
|
||||
" delay_before_retry 31\n"
|
||||
" retry 3\n"
|
||||
" MISC_CHECK {\n"
|
||||
" misc_path \"/var/lib/octavia/lvs/check/"
|
||||
"udp_check.sh 10.0.0.98 82\"\n"
|
||||
" misc_timeout 30\n"
|
||||
" misc_dynamic\n"
|
||||
" }\n"
|
||||
" }\n\n"
|
||||
"}\n\n")
|
||||
|
||||
rendered_obj = self.udp_jinja_cfg.render_loadbalancer_obj(
|
||||
sample_configs.sample_listener_tuple(
|
||||
proto=constants.PROTOCOL_UDP,
|
||||
monitor_proto=constants.HEALTH_MONITOR_UDP_CONNECT,
|
||||
persistence=False,
|
||||
connection_limit=98))
|
||||
self.assertEqual(exp, rendered_obj)
|
||||
|
||||
def test_render_template_udp_no_other_resources(self):
|
||||
exp = ("# Configuration for Listener sample_listener_id_1\n\n"
|
||||
"net_namespace amphora-haproxy\n\n\n")
|
||||
|
||||
rendered_obj = self.udp_jinja_cfg.render_loadbalancer_obj(
|
||||
sample_configs.sample_listener_tuple(
|
||||
proto=constants.PROTOCOL_UDP, monitor=False,
|
||||
persistence=False, alloc_default_pool=False))
|
||||
self.assertEqual(exp, rendered_obj)
|
||||
|
||||
def test_udp_transform_session_persistence(self):
|
||||
persistence_src_ip = sample_configs.sample_session_persistence_tuple(
|
||||
persistence_type=constants.SESSION_PERSISTENCE_SOURCE_IP,
|
||||
persistence_cookie=None,
|
||||
persistence_timeout=33,
|
||||
persistence_granularity='255.0.0.0'
|
||||
)
|
||||
exp = sample_configs.UDP_SOURCE_IP_BODY
|
||||
ret = self.udp_jinja_cfg._transform_session_persistence(
|
||||
persistence_src_ip)
|
||||
self.assertEqual(exp, ret)
|
||||
|
||||
def test_udp_transform_health_monitor(self):
|
||||
in_hm = sample_configs.sample_health_monitor_tuple(
|
||||
proto=constants.HEALTH_MONITOR_UDP_CONNECT
|
||||
)
|
||||
ret = self.udp_jinja_cfg._transform_health_monitor(in_hm)
|
||||
self.assertEqual(sample_configs.RET_UDP_HEALTH_MONITOR, ret)
|
||||
|
||||
def test_udp_transform_member(self):
|
||||
in_member = sample_configs.sample_member_tuple('member_id_1',
|
||||
'192.0.2.10')
|
||||
ret = self.udp_jinja_cfg._transform_member(in_member)
|
||||
self.assertEqual(sample_configs.RET_UDP_MEMBER, ret)
|
||||
|
||||
def test_udp_transform_pool(self):
|
||||
in_pool = sample_configs.sample_pool_tuple(
|
||||
proto=constants.PROTOCOL_UDP,
|
||||
persistence_type=constants.SESSION_PERSISTENCE_SOURCE_IP,
|
||||
persistence_timeout=33, persistence_granularity='255.0.0.0',
|
||||
)
|
||||
ret = self.udp_jinja_cfg._transform_pool(in_pool)
|
||||
self.assertEqual(sample_configs.RET_UDP_POOL, ret)
|
||||
|
||||
in_pool = sample_configs.sample_pool_tuple(
|
||||
proto=constants.PROTOCOL_UDP,
|
||||
persistence_type=constants.SESSION_PERSISTENCE_SOURCE_IP,
|
||||
persistence_timeout=33, persistence_granularity='255.0.0.0',
|
||||
monitor=False)
|
||||
sample_configs.RET_UDP_POOL['health_monitor'] = ''
|
||||
ret = self.udp_jinja_cfg._transform_pool(in_pool)
|
||||
self.assertEqual(sample_configs.RET_UDP_POOL, ret)
|
||||
|
||||
def test_udp_transform_listener(self):
|
||||
in_listener = sample_configs.sample_listener_tuple(
|
||||
proto=constants.PROTOCOL_UDP,
|
||||
persistence_type=constants.SESSION_PERSISTENCE_SOURCE_IP,
|
||||
persistence_timeout=33,
|
||||
persistence_granularity='255.0.0.0',
|
||||
monitor_proto=constants.HEALTH_MONITOR_UDP_CONNECT,
|
||||
connection_limit=98
|
||||
)
|
||||
ret = self.udp_jinja_cfg._transform_listener(in_listener)
|
||||
self.assertEqual(sample_configs.RET_UDP_LISTENER, ret)
|
||||
|
||||
in_listener = sample_configs.sample_listener_tuple(
|
||||
proto=constants.PROTOCOL_UDP,
|
||||
persistence_type=constants.SESSION_PERSISTENCE_SOURCE_IP,
|
||||
persistence_timeout=33,
|
||||
persistence_granularity='255.0.0.0',
|
||||
monitor_proto=constants.HEALTH_MONITOR_UDP_CONNECT,
|
||||
connection_limit=-1)
|
||||
|
||||
ret = self.udp_jinja_cfg._transform_listener(in_listener)
|
||||
sample_configs.RET_UDP_LISTENER.pop('connection_limit')
|
||||
self.assertEqual(sample_configs.RET_UDP_LISTENER, ret)
|
|
@ -15,10 +15,13 @@
|
|||
|
||||
import collections
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from octavia.common import constants
|
||||
from octavia.tests.unit.common.sample_configs import sample_certs
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def sample_amphora_tuple():
|
||||
in_amphora = collections.namedtuple(
|
||||
|
@ -336,6 +339,84 @@ RET_LB_L7 = {
|
|||
'enabled': True,
|
||||
'global_connection_limit': constants.HAPROXY_MAX_MAXCONN}
|
||||
|
||||
UDP_SOURCE_IP_BODY = {
|
||||
'type': constants.SESSION_PERSISTENCE_SOURCE_IP,
|
||||
'persistence_timeout': 33,
|
||||
'persistence_granularity': '255.0.0.0'
|
||||
}
|
||||
|
||||
RET_UDP_HEALTH_MONITOR = {
|
||||
'id': 'sample_monitor_id_1',
|
||||
'type': constants.HEALTH_MONITOR_UDP_CONNECT,
|
||||
'delay': 30,
|
||||
'timeout': 31,
|
||||
'enabled': True,
|
||||
'fall_threshold': 3,
|
||||
'check_script_path': (CONF.haproxy_amphora.base_path +
|
||||
'/lvs/check/udp_check.sh')
|
||||
}
|
||||
|
||||
UDP_HEALTH_MONITOR_NO_SCRIPT = {
|
||||
'id': 'sample_monitor_id_1',
|
||||
'check_script_path': None,
|
||||
'delay': 30,
|
||||
'enabled': True,
|
||||
'fall_threshold': 3,
|
||||
'timeout': 31,
|
||||
'type': 'UDP'
|
||||
}
|
||||
|
||||
RET_UDP_MEMBER = {
|
||||
'id': 'member_id_1',
|
||||
'address': '192.0.2.10',
|
||||
'protocol_port': 82,
|
||||
'weight': 13,
|
||||
'enabled': True
|
||||
}
|
||||
|
||||
UDP_MEMBER_1 = {
|
||||
'id': 'sample_member_id_1',
|
||||
'address': '10.0.0.99',
|
||||
'enabled': True,
|
||||
'protocol_port': 82,
|
||||
'weight': 13
|
||||
}
|
||||
|
||||
UDP_MEMBER_2 = {
|
||||
'id': 'sample_member_id_2',
|
||||
'address': '10.0.0.98',
|
||||
'enabled': True,
|
||||
'protocol_port': 82,
|
||||
'weight': 13
|
||||
}
|
||||
|
||||
RET_UDP_POOL = {
|
||||
'id': 'sample_pool_id_1',
|
||||
'enabled': True,
|
||||
'health_monitor': UDP_HEALTH_MONITOR_NO_SCRIPT,
|
||||
'lb_algorithm': 'rr',
|
||||
'members': [UDP_MEMBER_1, UDP_MEMBER_2],
|
||||
'protocol': 'udp',
|
||||
'session_persistence': UDP_SOURCE_IP_BODY
|
||||
}
|
||||
|
||||
RET_UDP_LISTENER = {
|
||||
'connection_limit': 98,
|
||||
'default_pool': {
|
||||
'id': 'sample_pool_id_1',
|
||||
'enabled': True,
|
||||
'health_monitor': RET_UDP_HEALTH_MONITOR,
|
||||
'lb_algorithm': 'rr',
|
||||
'members': [UDP_MEMBER_1, UDP_MEMBER_2],
|
||||
'protocol': 'udp',
|
||||
'session_persistence': UDP_SOURCE_IP_BODY
|
||||
},
|
||||
'enabled': True,
|
||||
'id': 'sample_listener_id_1',
|
||||
'protocol_mode': 'udp',
|
||||
'protocol_port': '80'
|
||||
}
|
||||
|
||||
|
||||
def sample_loadbalancer_tuple(proto=None, monitor=True, persistence=True,
|
||||
persistence_type=None, tls=False, sni=False,
|
||||
|
@ -400,8 +481,10 @@ def sample_vip_tuple():
|
|||
return vip(ip_address='10.0.0.2')
|
||||
|
||||
|
||||
def sample_listener_tuple(proto=None, monitor=True, persistence=True,
|
||||
persistence_type=None, persistence_cookie=None,
|
||||
def sample_listener_tuple(proto=None, monitor=True, alloc_default_pool=True,
|
||||
persistence=True, persistence_type=None,
|
||||
persistence_cookie=None, persistence_timeout=None,
|
||||
persistence_granularity=None,
|
||||
tls=False, sni=False, peer_port=None, topology=None,
|
||||
l7=False, enabled=True, insert_headers=None,
|
||||
be_proto=None, monitor_ip_port=False,
|
||||
|
@ -466,7 +549,10 @@ def sample_listener_tuple(proto=None, monitor=True, persistence=True,
|
|||
proto=be_proto, monitor=monitor, persistence=persistence,
|
||||
persistence_type=persistence_type,
|
||||
persistence_cookie=persistence_cookie,
|
||||
monitor_ip_port=monitor_ip_port, monitor_proto=monitor_proto),
|
||||
persistence_timeout=persistence_timeout,
|
||||
persistence_granularity=persistence_granularity,
|
||||
monitor_ip_port=monitor_ip_port,
|
||||
monitor_proto=monitor_proto) if alloc_default_pool else '',
|
||||
connection_limit=connection_limit,
|
||||
tls_certificate_id='cont_id_1' if tls else '',
|
||||
sni_container_ids=['cont_id_2', 'cont_id_3'] if sni else [],
|
||||
|
@ -527,6 +613,7 @@ def sample_tls_container_tuple(id='cont_id_1', certificate=None,
|
|||
|
||||
def sample_pool_tuple(proto=None, monitor=True, persistence=True,
|
||||
persistence_type=None, persistence_cookie=None,
|
||||
persistence_timeout=None, persistence_granularity=None,
|
||||
sample_pool=1, monitor_ip_port=False,
|
||||
monitor_proto=None, backup_member=False,
|
||||
disabled_member=False):
|
||||
|
@ -535,9 +622,15 @@ def sample_pool_tuple(proto=None, monitor=True, persistence=True,
|
|||
in_pool = collections.namedtuple(
|
||||
'pool', 'id, protocol, lb_algorithm, members, health_monitor,'
|
||||
'session_persistence, enabled, operating_status')
|
||||
persis = sample_session_persistence_tuple(
|
||||
persistence_type=persistence_type,
|
||||
persistence_cookie=persistence_cookie) if persistence is True else None
|
||||
if (proto == constants.PROTOCOL_UDP and
|
||||
persistence_type == constants.SESSION_PERSISTENCE_SOURCE_IP):
|
||||
kwargs = {'persistence_type': persistence_type,
|
||||
'persistence_timeout': persistence_timeout,
|
||||
'persistence_granularity': persistence_granularity}
|
||||
else:
|
||||
kwargs = {'persistence_type': persistence_type,
|
||||
'persistence_cookie': persistence_cookie}
|
||||
persis = sample_session_persistence_tuple(**kwargs)
|
||||
mon = None
|
||||
if sample_pool == 1:
|
||||
id = 'sample_pool_id_1'
|
||||
|
@ -561,7 +654,7 @@ def sample_pool_tuple(proto=None, monitor=True, persistence=True,
|
|||
lb_algorithm='ROUND_ROBIN',
|
||||
members=members,
|
||||
health_monitor=mon,
|
||||
session_persistence=persis,
|
||||
session_persistence=persis if persistence is True else None,
|
||||
enabled=True,
|
||||
operating_status='ACTIVE')
|
||||
|
||||
|
@ -590,19 +683,26 @@ def sample_member_tuple(id, ip, enabled=True, operating_status='ACTIVE',
|
|||
|
||||
|
||||
def sample_session_persistence_tuple(persistence_type=None,
|
||||
persistence_cookie=None):
|
||||
persistence_cookie=None,
|
||||
persistence_timeout=None,
|
||||
persistence_granularity=None):
|
||||
spersistence = collections.namedtuple('SessionPersistence',
|
||||
'type, cookie_name')
|
||||
'type, cookie_name, '
|
||||
'persistence_timeout, '
|
||||
'persistence_granularity')
|
||||
pt = 'HTTP_COOKIE' if persistence_type is None else persistence_type
|
||||
return spersistence(type=pt,
|
||||
cookie_name=persistence_cookie)
|
||||
cookie_name=persistence_cookie,
|
||||
persistence_timeout=persistence_timeout,
|
||||
persistence_granularity=persistence_granularity)
|
||||
|
||||
|
||||
def sample_health_monitor_tuple(proto='HTTP', sample_hm=1):
|
||||
proto = 'HTTP' if proto is 'TERMINATED_HTTPS' else proto
|
||||
monitor = collections.namedtuple(
|
||||
'monitor', 'id, type, delay, timeout, fall_threshold, rise_threshold,'
|
||||
'http_method, url_path, expected_codes, enabled')
|
||||
'http_method, url_path, expected_codes, enabled, '
|
||||
'check_script_path')
|
||||
|
||||
if sample_hm == 1:
|
||||
id = 'sample_monitor_id_1'
|
||||
|
@ -610,10 +710,24 @@ def sample_health_monitor_tuple(proto='HTTP', sample_hm=1):
|
|||
elif sample_hm == 2:
|
||||
id = 'sample_monitor_id_2'
|
||||
url_path = '/healthmon.html'
|
||||
return monitor(id=id, type=proto, delay=30,
|
||||
timeout=31, fall_threshold=3, rise_threshold=2,
|
||||
http_method='GET', url_path=url_path,
|
||||
expected_codes='418', enabled=True)
|
||||
kwargs = {
|
||||
'id': id,
|
||||
'type': proto,
|
||||
'delay': 30,
|
||||
'timeout': 31,
|
||||
'fall_threshold': 3,
|
||||
'rise_threshold': 2,
|
||||
'http_method': 'GET',
|
||||
'url_path': url_path,
|
||||
'expected_codes': '418',
|
||||
'enabled': True
|
||||
}
|
||||
if proto == constants.HEALTH_MONITOR_UDP_CONNECT:
|
||||
kwargs['check_script_path'] = (CONF.haproxy_amphora.base_path +
|
||||
'lvs/check/' + 'udp_check.sh')
|
||||
else:
|
||||
kwargs['check_script_path'] = None
|
||||
return monitor(**kwargs)
|
||||
|
||||
|
||||
def sample_l7policy_tuple(id,
|
||||
|
|
Loading…
Reference in New Issue