Merge "Fix operational status for disabled UDP listeners" into stable/train

This commit is contained in:
Zuul 2021-01-14 03:52:10 +00:00 committed by Gerrit Code Review
commit e561409b12
5 changed files with 75 additions and 3 deletions

View File

@ -35,8 +35,8 @@ 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")
DISABLED_CONFIG_COMMENT_REGEX = re.compile(
r"#\s(\w+)\s(\w{8}-\w{4}-\w{4}-\w{4}-\w{12}) is disabled")
CHECKER_REGEX = re.compile(r"MISC_CHECK")
@ -152,6 +152,14 @@ def get_udp_listener_resource_ipports_nsname(listener_id):
listener_ip_port = V6_VS_REGEX.findall(cfg)
listener_ip_port = listener_ip_port[0] if listener_ip_port else []
disabled_resource_ids = DISABLED_CONFIG_COMMENT_REGEX.findall(cfg)
listener_disabled = any(True
for resource in disabled_resource_ids
if resource[0] == 'Listener')
if listener_disabled:
return None, ns_name
if not listener_ip_port:
# If not get listener_ip_port from the lvs config file,
# that means the udp listener's default pool have no enabled member
@ -181,7 +189,11 @@ 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)
disabled_member_ids = [
resource[1]
for resource in disabled_resource_ids
if resource[0] == 'Member'
]
resource_type = 'Members'
for member_id in disabled_member_ids:
@ -363,6 +375,10 @@ def get_udp_listeners_stats():
(resource_ipport_mapping,
ns_name) = get_udp_listener_resource_ipports_nsname(check_listener_id)
# Listener is disabled, we don't need to send an update
if resource_ipport_mapping is None:
continue
# Since we found the keepalived running, acknowledge the listener
# in the heartbeat. If this listener has a pool and members,
# the stats will be updated later in the code flow.

View File

@ -14,7 +14,11 @@
#
#}
# Configuration for Loadbalancer {{ loadbalancer.id }}
{% if loadbalancer.listener.enabled %}
# Configuration for Listener {{ udp_listener_id }}
{% else %}
# Listener {{ udp_listener_id }} is disabled
{% endif %}
{% block global_definitions %}{% endblock global_definitions %}

View File

@ -126,6 +126,11 @@ CFG_FILE_TEMPLATE_v6 = (
" # Member %(member_id4)s is disabled\n\n"
"}")
CFG_FILE_TEMPLATE_DISABLED_LISTENER = (
"# Listener %(listener_id)s is disabled \n\n"
"net_namespace %(ns_name)s\n\n"
)
IPVSADM_OUTPUT_TEMPLATE = (
"IP Virtual Server version 1.2.1 (size=4096)\n"
"Prot LocalAddress:Port Scheduler Flags\n"
@ -162,6 +167,7 @@ class LvsQueryTestCase(base.TestCase):
self.member_id2_v6 = uuidutils.generate_uuid()
self.member_id3_v6 = uuidutils.generate_uuid()
self.member_id4_v6 = uuidutils.generate_uuid()
self.disabled_listener_id = uuidutils.generate_uuid()
cfg_content_v4 = CFG_FILE_TEMPLATE_v4 % {
'listener_id': self.listener_id_v4,
'ns_name': constants.AMPHORA_NAMESPACE,
@ -180,10 +186,19 @@ class LvsQueryTestCase(base.TestCase):
'member_id3': self.member_id3_v6,
'member_id4': self.member_id4_v6
}
cfg_content_disabled_listener = (
CFG_FILE_TEMPLATE_DISABLED_LISTENER % {
'listener_id': self.listener_id_v6,
'ns_name': constants.AMPHORA_NAMESPACE,
}
)
self.useFixture(test_utils.OpenFixture(
util.keepalived_lvs_cfg_path(self.listener_id_v4), cfg_content_v4))
self.useFixture(test_utils.OpenFixture(
util.keepalived_lvs_cfg_path(self.listener_id_v6), cfg_content_v6))
self.useFixture(test_utils.OpenFixture(
util.keepalived_lvs_cfg_path(self.disabled_listener_id),
cfg_content_disabled_listener))
@mock.patch('subprocess.check_output')
def test_get_listener_realserver_mapping(self, mock_check_output):
@ -278,6 +293,11 @@ class LvsQueryTestCase(base.TestCase):
'ipport': None}]}
self.assertEqual((expected, constants.AMPHORA_NAMESPACE), res)
# disabled
res = lvs_query.get_udp_listener_resource_ipports_nsname(
self.disabled_listener_id)
self.assertEqual((None, constants.AMPHORA_NAMESPACE), res)
@mock.patch('subprocess.check_output')
def test_get_udp_listener_pool_status(self, mock_check_output):
# test with ipv4 and ipv6
@ -456,3 +476,14 @@ class LvsQueryTestCase(base.TestCase):
mock_is_running.return_value = False
res = lvs_query.get_udp_listeners_stats()
self.assertEqual({}, res)
@mock.patch('subprocess.check_output')
@mock.patch("octavia.amphorae.backends.agent.api_server.util."
"is_udp_listener_running", return_value=True)
@mock.patch("octavia.amphorae.backends.agent.api_server.util."
"get_udp_listeners")
def test_get_udp_listeners_stats_disabled_listener(
self, mock_get_listener, mock_is_running, mock_check_output):
mock_get_listener.return_value = [self.disabled_listener_id]
res = lvs_query.get_udp_listeners_stats()
self.assertEqual({}, res)

View File

@ -297,3 +297,18 @@ class TestLvsCfg(base.TestCase):
ret = self.udp_jinja_cfg._transform_listener(in_listener)
sample_configs_combined.RET_UDP_LISTENER.pop('connection_limit')
self.assertEqual(sample_configs_combined.RET_UDP_LISTENER, ret)
def test_render_template_disabled_udp_listener(self):
exp = ("# Configuration for Loadbalancer sample_loadbalancer_id_1\n"
"# Listener sample_listener_id_1 is disabled\n\n"
"net_namespace amphora-haproxy\n\n")
rendered_obj = self.udp_jinja_cfg.render_loadbalancer_obj(
sample_configs_combined.sample_listener_tuple(
enabled=False,
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)

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Fix operational status for disabled UDP listeners. The operating status of
disabled UDP listeners is now OFFLINE instead of ONLINE, the behavior is now
similary to the behavior of HTTP/HTTPS/TCP/... listeners.