Fixed pool and members status with UDP loadbalancers
This commit fixes pool and members status when using UDP loadbalancers. Story: 2005736 Task: 33394 Change-Id: I75cde3ff820f085aebbdffd1e40c5ff40f16835d
This commit is contained in:
parent
65e132a734
commit
4decb6d53c
@ -35,6 +35,10 @@ V6_VS_REGEX = re.compile(r"virtual_server\s([\w*:]+\b)\s(\d{1,5})")
|
||||
V6_RS_REGEX = re.compile(r"real_server\s([\w*:]+\b)\s(\d{1,5})")
|
||||
CONFIG_COMMENT_REGEX = re.compile(
|
||||
r"#\sConfiguration\sfor\s(\w+)\s(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})")
|
||||
DISABLED_MEMBER_COMMENT_REGEX = re.compile(
|
||||
r"#\sMember\s(\w{8}-\w{4}-\w{4}-\w{4}-\w{12}) is disabled")
|
||||
|
||||
CHECKER_REGEX = re.compile(r"MISC_CHECK")
|
||||
|
||||
|
||||
def read_kernel_file(ns_name, file_path):
|
||||
@ -55,7 +59,8 @@ def read_kernel_file(ns_name, file_path):
|
||||
return output
|
||||
|
||||
|
||||
def get_listener_realserver_mapping(ns_name, listener_ip_port):
|
||||
def get_listener_realserver_mapping(ns_name, listener_ip_port,
|
||||
health_monitor_enabled):
|
||||
# returned result:
|
||||
# actual_member_result = {'rs_ip:listened_port': {
|
||||
# 'status': 'UP',
|
||||
@ -74,6 +79,11 @@ def get_listener_realserver_mapping(ns_name, listener_ip_port):
|
||||
port_hex_format = "%.4X" % int(listener_port)
|
||||
idex = ip_to_hex_format + ':' + port_hex_format
|
||||
|
||||
if health_monitor_enabled:
|
||||
member_status = constants.UP
|
||||
else:
|
||||
member_status = constants.NO_CHECK
|
||||
|
||||
actual_member_result = {}
|
||||
find_target_block = False
|
||||
result_keys = []
|
||||
@ -111,7 +121,7 @@ def get_listener_realserver_mapping(ns_name, listener_ip_port):
|
||||
for index in range(result_key_count):
|
||||
if member_ip_port_string not in actual_member_result:
|
||||
actual_member_result[
|
||||
member_ip_port_string] = {'status': constants.UP,
|
||||
member_ip_port_string] = {'status': member_status,
|
||||
result_keys[index]:
|
||||
result_values[index]}
|
||||
else:
|
||||
@ -171,6 +181,16 @@ def get_udp_listener_resource_ipports_nsname(listener_id):
|
||||
elif resource_type == 'Members':
|
||||
resource_ipport_mapping[resource_type].append(value)
|
||||
|
||||
disabled_member_ids = DISABLED_MEMBER_COMMENT_REGEX.findall(cfg)
|
||||
|
||||
resource_type = 'Members'
|
||||
for member_id in disabled_member_ids:
|
||||
value = {'id': member_id,
|
||||
'ipport': None}
|
||||
if resource_type not in resource_ipport_mapping:
|
||||
resource_ipport_mapping[resource_type] = []
|
||||
resource_ipport_mapping[resource_type].append(value)
|
||||
|
||||
if rs_ip_port_list:
|
||||
rs_ip_port_count = len(rs_ip_port_list)
|
||||
for index in range(rs_ip_port_count):
|
||||
@ -205,8 +225,13 @@ def get_udp_listener_pool_status(listener_id):
|
||||
'members': {}
|
||||
}}
|
||||
|
||||
with open(util.keepalived_lvs_cfg_path(listener_id), 'r') as f:
|
||||
cfg = f.read()
|
||||
hm_enabled = len(CHECKER_REGEX.findall(cfg)) > 0
|
||||
|
||||
_, realserver_result = get_listener_realserver_mapping(
|
||||
ns_name, resource_ipport_mapping['Listener']['ipport'])
|
||||
ns_name, resource_ipport_mapping['Listener']['ipport'],
|
||||
hm_enabled)
|
||||
pool_status = constants.UP
|
||||
member_results = {}
|
||||
if realserver_result:
|
||||
@ -220,7 +245,9 @@ def get_udp_listener_pool_status(listener_id):
|
||||
for member in resource_ipport_mapping['Members']:
|
||||
if member['ipport'] == member_ip_port:
|
||||
member_id = member['id']
|
||||
if member_ip_port in down_member_ip_port_set:
|
||||
if member_ip_port is None:
|
||||
status = constants.MAINT
|
||||
elif member_ip_port in down_member_ip_port_set:
|
||||
status = constants.DOWN
|
||||
elif int(realserver_result[member_ip_port]['Weight']) == 0:
|
||||
status = constants.DRAIN
|
||||
@ -230,9 +257,16 @@ def get_udp_listener_pool_status(listener_id):
|
||||
if member_id:
|
||||
member_results[member_id] = status
|
||||
else:
|
||||
pool_status = constants.DOWN
|
||||
if hm_enabled:
|
||||
pool_status = constants.DOWN
|
||||
|
||||
for member in resource_ipport_mapping['Members']:
|
||||
member_results[member['id']] = constants.DOWN
|
||||
if member['ipport'] is None:
|
||||
member_results[member['id']] = constants.MAINT
|
||||
elif hm_enabled:
|
||||
member_results[member['id']] = constants.DOWN
|
||||
else:
|
||||
member_results[member['id']] = constants.NO_CHECK
|
||||
|
||||
return {
|
||||
'lvs':
|
||||
|
@ -44,6 +44,7 @@ MISC_CHECK {
|
||||
{% endmacro %}
|
||||
|
||||
{% macro realserver_macro(constants, pool, member, listener) %}
|
||||
{% if member.enabled %}
|
||||
# Configuration for Member {{ member.id }}
|
||||
real_server {{ member.address }} {{ member.protocol_port }} {
|
||||
weight {{ member.weight }}
|
||||
@ -52,6 +53,9 @@ MISC_CHECK {
|
||||
{% endif %}
|
||||
{{- health_monitor_rs_macro(constants, pool, member) }}
|
||||
}
|
||||
{% else %}
|
||||
# Member {{ member.id }} is disabled
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro health_monitor_vs_macro(default_pool) %}
|
||||
@ -71,7 +75,7 @@ MISC_CHECK {
|
||||
{% 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 %}
|
||||
{% for member in default_pool.members %}
|
||||
{% do need_render.append(member.enabled) %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@ -101,7 +105,7 @@ virtual_server {{ lb_vip_address }} {{ listener.protocol_port }} {
|
||||
{% 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 %}
|
||||
{% for member in default_pool.members %}
|
||||
{{- realserver_macro(constants, default_pool, member, listener) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
@ -22,6 +22,7 @@ from octavia.tests.unit import base
|
||||
# Kernal_file_sample which is in /proc/net/ip_vs
|
||||
# The realservers and the listened ports are
|
||||
# 10.0.0.25:2222, 10.0.0.35:3333.
|
||||
# Realserver 10.0.0.45:4444 is not listed because healthcheck failed.
|
||||
# The virtual server and the listened port is
|
||||
# 10.0.0.37:7777.
|
||||
KERNAL_FILE_SAMPLE_V4 = (
|
||||
@ -35,6 +36,8 @@ KERNAL_FILE_SAMPLE_V4 = (
|
||||
# The realservers and the listened ports are
|
||||
# [fd79:35e2:9963:0:f816:3eff:feca:b7bf]:2222,
|
||||
# [fd79:35e2:9963:0:f816:3eff:fe9d:94df]:3333.
|
||||
# Readlserver [fd79:35e2:9963:0:f816:3eff:fe9d:8f3f]:4444 is not listed
|
||||
# because healthcheck failed.
|
||||
# The virtual server and the listened port is
|
||||
# [fd79:35e2:9963:0:f816:3eff:fe6d:7a2a]:7777.
|
||||
KERNAL_FILE_SAMPLE_V6 = (
|
||||
@ -60,13 +63,32 @@ CFG_FILE_TEMPLATE_v4 = (
|
||||
" weight 3\n"
|
||||
" persistence_timeout 5\n"
|
||||
" persistence_granularity 255.0.0.0\n\n"
|
||||
" MISC_CHECK {\n\n"
|
||||
" misc_path \"/usr/bin/check_script.sh\"\n\n"
|
||||
" misc_timeout 5\n\n"
|
||||
" }\n\n"
|
||||
" }\n\n"
|
||||
" # Configuration for Member %(member_id2)s\n"
|
||||
" real_server 10.0.0.35 3333 {\n"
|
||||
" weight 2\n"
|
||||
" persistence_timeout 5\n"
|
||||
" persistence_granularity 255.0.0.0\n\n"
|
||||
" MISC_CHECK {\n\n"
|
||||
" misc_path \"/usr/bin/check_script.sh\"\n\n"
|
||||
" misc_timeout 5\n\n"
|
||||
" }\n\n"
|
||||
" }\n\n"
|
||||
" # Configuration for Member %(member_id3)s\n"
|
||||
" real_server 10.0.0.45 4444 {\n"
|
||||
" weight 2\n"
|
||||
" persistence_timeout 5\n"
|
||||
" persistence_granularity 255.0.0.0\n\n"
|
||||
" MISC_CHECK {\n\n"
|
||||
" misc_path \"/usr/bin/check_script.sh\"\n\n"
|
||||
" misc_timeout 5\n\n"
|
||||
" }\n\n"
|
||||
" }\n\n"
|
||||
" # Member %(member_id4)s is disabled\n\n"
|
||||
"}")
|
||||
|
||||
CFG_FILE_TEMPLATE_v6 = (
|
||||
@ -80,11 +102,28 @@ CFG_FILE_TEMPLATE_v6 = (
|
||||
" # Configuration for Member %(member_id1)s\n"
|
||||
" real_server fd79:35e2:9963:0:f816:3eff:feca:b7bf 2222 {\n"
|
||||
" weight 3\n"
|
||||
" MISC_CHECK {\n\n"
|
||||
" misc_path \"/usr/bin/check_script.sh\"\n\n"
|
||||
" misc_timeout 5\n\n"
|
||||
" }\n\n"
|
||||
" }\n\n"
|
||||
" # Configuration for Member %(member_id2)s\n"
|
||||
" real_server fd79:35e2:9963:0:f816:3eff:fe9d:94df 3333 {\n"
|
||||
" weight 2\n"
|
||||
" MISC_CHECK {\n\n"
|
||||
" misc_path \"/usr/bin/check_script.sh\"\n\n"
|
||||
" misc_timeout 5\n\n"
|
||||
" }\n\n"
|
||||
" }\n\n"
|
||||
" # Configuration for Member %(member_id3)s\n"
|
||||
" real_server fd79:35e2:9963:0:f816:3eff:fe9d:8f3f 4444 {\n"
|
||||
" weight 2\n"
|
||||
" MISC_CHECK {\n\n"
|
||||
" misc_path \"/usr/bin/check_script.sh\"\n\n"
|
||||
" misc_timeout 5\n\n"
|
||||
" }\n\n"
|
||||
" }\n\n"
|
||||
" # Member %(member_id4)s is disabled\n\n"
|
||||
"}")
|
||||
|
||||
IPVSADM_OUTPUT_TEMPLATE = (
|
||||
@ -115,23 +154,31 @@ class LvsQueryTestCase(base.TestCase):
|
||||
self.pool_id_v4 = uuidutils.generate_uuid()
|
||||
self.member_id1_v4 = uuidutils.generate_uuid()
|
||||
self.member_id2_v4 = uuidutils.generate_uuid()
|
||||
self.member_id3_v4 = uuidutils.generate_uuid()
|
||||
self.member_id4_v4 = uuidutils.generate_uuid()
|
||||
self.listener_id_v6 = uuidutils.generate_uuid()
|
||||
self.pool_id_v6 = uuidutils.generate_uuid()
|
||||
self.member_id1_v6 = uuidutils.generate_uuid()
|
||||
self.member_id2_v6 = uuidutils.generate_uuid()
|
||||
self.member_id3_v6 = uuidutils.generate_uuid()
|
||||
self.member_id4_v6 = uuidutils.generate_uuid()
|
||||
cfg_content_v4 = CFG_FILE_TEMPLATE_v4 % {
|
||||
'listener_id': self.listener_id_v4,
|
||||
'ns_name': constants.AMPHORA_NAMESPACE,
|
||||
'pool_id': self.pool_id_v4,
|
||||
'member_id1': self.member_id1_v4,
|
||||
'member_id2': self.member_id2_v4
|
||||
'member_id2': self.member_id2_v4,
|
||||
'member_id3': self.member_id3_v4,
|
||||
'member_id4': self.member_id4_v4,
|
||||
}
|
||||
cfg_content_v6 = CFG_FILE_TEMPLATE_v6 % {
|
||||
'listener_id': self.listener_id_v6,
|
||||
'ns_name': constants.AMPHORA_NAMESPACE,
|
||||
'pool_id': self.pool_id_v6,
|
||||
'member_id1': self.member_id1_v6,
|
||||
'member_id2': self.member_id2_v6
|
||||
'member_id2': self.member_id2_v6,
|
||||
'member_id3': self.member_id3_v6,
|
||||
'member_id4': self.member_id4_v6
|
||||
}
|
||||
self.useFixture(test_utils.OpenFixture(
|
||||
util.keepalived_lvs_cfg_path(self.listener_id_v4), cfg_content_v4))
|
||||
@ -145,7 +192,8 @@ class LvsQueryTestCase(base.TestCase):
|
||||
target_ns = constants.AMPHORA_NAMESPACE
|
||||
mock_check_output.return_value = KERNAL_FILE_SAMPLE_V4
|
||||
result = lvs_query.get_listener_realserver_mapping(
|
||||
target_ns, input_listener_ip_port)
|
||||
target_ns, input_listener_ip_port,
|
||||
health_monitor_enabled=True)
|
||||
expected = {'10.0.0.25:2222': {'status': 'UP',
|
||||
'Forward': 'Masq',
|
||||
'Weight': '3',
|
||||
@ -162,7 +210,8 @@ class LvsQueryTestCase(base.TestCase):
|
||||
input_listener_ip_port = '[fd79:35e2:9963:0:f816:3eff:fe6d:7a2a]:7777'
|
||||
mock_check_output.return_value = KERNAL_FILE_SAMPLE_V6
|
||||
result = lvs_query.get_listener_realserver_mapping(
|
||||
target_ns, input_listener_ip_port)
|
||||
target_ns, input_listener_ip_port,
|
||||
health_monitor_enabled=True)
|
||||
expected = {'[fd79:35e2:9963:0:f816:3eff:feca:b7bf]:2222':
|
||||
{'status': constants.UP,
|
||||
'Forward': 'Masq',
|
||||
@ -181,7 +230,8 @@ class LvsQueryTestCase(base.TestCase):
|
||||
mock_check_output.return_value = KERNAL_FILE_SAMPLE_V4
|
||||
for listener_ip_port in ['10.0.0.37:7776', '10.0.0.31:7777']:
|
||||
result = lvs_query.get_listener_realserver_mapping(
|
||||
target_ns, listener_ip_port)
|
||||
target_ns, listener_ip_port,
|
||||
health_monitor_enabled=True)
|
||||
self.assertEqual((False, {}), result)
|
||||
|
||||
mock_check_output.return_value = KERNAL_FILE_SAMPLE_V6
|
||||
@ -189,7 +239,8 @@ class LvsQueryTestCase(base.TestCase):
|
||||
'[fd79:35e2:9963:0:f816:3eff:fe6d:7a2a]:7776',
|
||||
'[fd79:35e2:9973:0:f816:3eff:fe6d:7a2a]:7777']:
|
||||
result = lvs_query.get_listener_realserver_mapping(
|
||||
target_ns, listener_ip_port)
|
||||
target_ns, listener_ip_port,
|
||||
health_monitor_enabled=True)
|
||||
self.assertEqual((False, {}), result)
|
||||
|
||||
def test_get_udp_listener_resource_ipports_nsname(self):
|
||||
@ -202,7 +253,11 @@ class LvsQueryTestCase(base.TestCase):
|
||||
'Members': [{'id': self.member_id1_v4,
|
||||
'ipport': '10.0.0.25:2222'},
|
||||
{'id': self.member_id2_v4,
|
||||
'ipport': '10.0.0.35:3333'}]}
|
||||
'ipport': '10.0.0.35:3333'},
|
||||
{'id': self.member_id3_v4,
|
||||
'ipport': '10.0.0.45:4444'},
|
||||
{'id': self.member_id4_v4,
|
||||
'ipport': None}]}
|
||||
self.assertEqual((expected, constants.AMPHORA_NAMESPACE), res)
|
||||
|
||||
# ipv6
|
||||
@ -216,7 +271,11 @@ class LvsQueryTestCase(base.TestCase):
|
||||
{'id': self.member_id1_v6,
|
||||
'ipport': '[fd79:35e2:9963:0:f816:3eff:feca:b7bf]:2222'},
|
||||
{'id': self.member_id2_v6,
|
||||
'ipport': '[fd79:35e2:9963:0:f816:3eff:fe9d:94df]:3333'}]}
|
||||
'ipport': '[fd79:35e2:9963:0:f816:3eff:fe9d:94df]:3333'},
|
||||
{'id': self.member_id3_v6,
|
||||
'ipport': '[fd79:35e2:9963:0:f816:3eff:fe9d:8f3f]:4444'},
|
||||
{'id': self.member_id4_v6,
|
||||
'ipport': None}]}
|
||||
self.assertEqual((expected, constants.AMPHORA_NAMESPACE), res)
|
||||
|
||||
@mock.patch('subprocess.check_output')
|
||||
@ -229,7 +288,9 @@ class LvsQueryTestCase(base.TestCase):
|
||||
{'uuid': self.pool_id_v4,
|
||||
'status': constants.UP,
|
||||
'members': {self.member_id1_v4: constants.UP,
|
||||
self.member_id2_v4: constants.UP}}}
|
||||
self.member_id2_v4: constants.UP,
|
||||
self.member_id3_v4: constants.DOWN,
|
||||
self.member_id4_v4: constants.MAINT}}}
|
||||
self.assertEqual(expected, res)
|
||||
|
||||
mock_check_output.return_value = KERNAL_FILE_SAMPLE_V6
|
||||
@ -239,7 +300,9 @@ class LvsQueryTestCase(base.TestCase):
|
||||
{'uuid': self.pool_id_v6,
|
||||
'status': constants.UP,
|
||||
'members': {self.member_id1_v6: constants.UP,
|
||||
self.member_id2_v6: constants.UP}}}
|
||||
self.member_id2_v6: constants.UP,
|
||||
self.member_id3_v6: constants.DOWN,
|
||||
self.member_id4_v6: constants.MAINT}}}
|
||||
self.assertEqual(expected, res)
|
||||
|
||||
@mock.patch('octavia.amphorae.backends.utils.keepalivedlvs_query.'
|
||||
@ -298,7 +361,9 @@ class LvsQueryTestCase(base.TestCase):
|
||||
{'uuid': self.pool_id_v4,
|
||||
'status': constants.DOWN,
|
||||
'members': {self.member_id1_v4: constants.DOWN,
|
||||
self.member_id2_v4: constants.DOWN}}}
|
||||
self.member_id2_v4: constants.DOWN,
|
||||
self.member_id3_v4: constants.DOWN,
|
||||
self.member_id4_v4: constants.MAINT}}}
|
||||
self.assertEqual(expected, res)
|
||||
|
||||
@mock.patch('subprocess.check_output')
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Fix operating_status for pools and members that use UDP protocol.
|
||||
operating_status values are now consistant with the values of non-UDP
|
||||
load balancers.
|
Loading…
x
Reference in New Issue
Block a user