Fix incorrect ERROR status with IPv6 UDP members

Some IPv6 UDP members were incorrectly marked in ERROR status because of
a formatting issue between the keepalived configuration file and the
ipvsadm output. Both are used to compute the state of the members and
when a member's address contained '*:0:*', parsing was incorrect. Now
the health message generation function uses only the compressed IPv6
notation instead of mixing notations.

Story: 2008604
Task: 41783

Conflicts:
    octavia/amphorae/backends/utils/keepalivedlvs_query.py

Change-Id: I2fe94cd4c000f143c59c69e82d03c690acf5e0c3
(cherry picked from commit e5f9f6708c)
(cherry picked from commit 8b210bb52a)
(cherry picked from commit 4b8de86cf3)
This commit is contained in:
Gregory Thiemonge 2021-02-05 22:03:21 +01:00
parent 93eb3c8cd9
commit 411a0b7bef
3 changed files with 36 additions and 8 deletions

View File

@ -207,19 +207,21 @@ def get_udp_listener_resource_ipports_nsname(listener_id):
if rs_ip_port_list: if rs_ip_port_list:
rs_ip_port_count = len(rs_ip_port_list) rs_ip_port_count = len(rs_ip_port_list)
for index in range(rs_ip_port_count): for index in range(rs_ip_port_count):
if ipaddress.ip_address( member_ip = ipaddress.ip_address(
six.text_type(rs_ip_port_list[index][0])).version == 6: six.text_type(rs_ip_port_list[index][0]))
if member_ip.version == 6:
rs_ip_port_list[index] = ( rs_ip_port_list[index] = (
'[' + rs_ip_port_list[index][0] + ']', '[' + member_ip.compressed + ']',
rs_ip_port_list[index][1]) rs_ip_port_list[index][1])
resource_ipport_mapping['Members'][index]['ipport'] = ( resource_ipport_mapping['Members'][index]['ipport'] = (
rs_ip_port_list[index][0] + ':' + rs_ip_port_list[index][0] + ':' +
rs_ip_port_list[index][1]) rs_ip_port_list[index][1])
if ipaddress.ip_address( listener_ip = ipaddress.ip_address(
six.text_type(listener_ip_port[0])).version == 6: six.text_type(listener_ip_port[0]))
if listener_ip.version == 6:
listener_ip_port = ( listener_ip_port = (
'[' + listener_ip_port[0] + ']', listener_ip_port[1]) '[' + listener_ip.compressed + ']', listener_ip_port[1])
resource_ipport_mapping['Listener']['ipport'] = ( resource_ipport_mapping['Listener']['ipport'] = (
listener_ip_port[0] + ':' + listener_ip_port[1]) listener_ip_port[0] + ':' + listener_ip_port[1])

View File

@ -48,6 +48,8 @@ KERNAL_FILE_SAMPLE_V6 = (
" -> [fd79:35e2:9963:0000:f816:3eff:feca:b7bf]:08AE " " -> [fd79:35e2:9963:0000:f816:3eff:feca:b7bf]:08AE "
"Masq 3 0 0\n" "Masq 3 0 0\n"
" -> [fd79:35e2:9963:0000:f816:3eff:fe9d:94df]:0D05 " " -> [fd79:35e2:9963:0000:f816:3eff:fe9d:94df]:0D05 "
"Masq 2 0 0\n"
" -> [fd79:35e2::8f3f]:115C "
"Masq 2 0 0") "Masq 2 0 0")
CFG_FILE_TEMPLATE_v4 = ( CFG_FILE_TEMPLATE_v4 = (
@ -124,6 +126,14 @@ CFG_FILE_TEMPLATE_v6 = (
" }\n\n" " }\n\n"
" }\n\n" " }\n\n"
" # Member %(member_id4)s is disabled\n\n" " # Member %(member_id4)s is disabled\n\n"
" # Configuration for Member %(member_id5)s\n"
" real_server fd79:35e2:0:0:0:0:0: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"
"}") "}")
CFG_FILE_TEMPLATE_DISABLED_LISTENER = ( CFG_FILE_TEMPLATE_DISABLED_LISTENER = (
@ -167,6 +177,7 @@ class LvsQueryTestCase(base.TestCase):
self.member_id2_v6 = uuidutils.generate_uuid() self.member_id2_v6 = uuidutils.generate_uuid()
self.member_id3_v6 = uuidutils.generate_uuid() self.member_id3_v6 = uuidutils.generate_uuid()
self.member_id4_v6 = uuidutils.generate_uuid() self.member_id4_v6 = uuidutils.generate_uuid()
self.member_id5_v6 = uuidutils.generate_uuid()
self.disabled_listener_id = uuidutils.generate_uuid() self.disabled_listener_id = uuidutils.generate_uuid()
cfg_content_v4 = CFG_FILE_TEMPLATE_v4 % { cfg_content_v4 = CFG_FILE_TEMPLATE_v4 % {
'listener_id': self.listener_id_v4, 'listener_id': self.listener_id_v4,
@ -184,7 +195,8 @@ class LvsQueryTestCase(base.TestCase):
'member_id1': self.member_id1_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_id3': self.member_id3_v6,
'member_id4': self.member_id4_v6 'member_id4': self.member_id4_v6,
'member_id5': self.member_id5_v6
} }
cfg_content_disabled_listener = ( cfg_content_disabled_listener = (
CFG_FILE_TEMPLATE_DISABLED_LISTENER % { CFG_FILE_TEMPLATE_DISABLED_LISTENER % {
@ -234,6 +246,12 @@ class LvsQueryTestCase(base.TestCase):
'ActiveConn': '0', 'ActiveConn': '0',
'InActConn': '0'}, 'InActConn': '0'},
'[fd79:35e2:9963:0:f816:3eff:fe9d:94df]:3333': '[fd79:35e2:9963:0:f816:3eff:fe9d:94df]:3333':
{'status': constants.UP,
'Forward': 'Masq',
'Weight': '2',
'ActiveConn': '0',
'InActConn': '0'},
'[fd79:35e2::8f3f]:4444':
{'status': constants.UP, {'status': constants.UP,
'Forward': 'Masq', 'Forward': 'Masq',
'Weight': '2', 'Weight': '2',
@ -289,6 +307,8 @@ class LvsQueryTestCase(base.TestCase):
'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, {'id': self.member_id3_v6,
'ipport': '[fd79:35e2:9963:0:f816:3eff:fe9d:8f3f]:4444'}, 'ipport': '[fd79:35e2:9963:0:f816:3eff:fe9d:8f3f]:4444'},
{'id': self.member_id5_v6,
'ipport': '[fd79:35e2::8f3f]:4444'},
{'id': self.member_id4_v6, {'id': self.member_id4_v6,
'ipport': None}]} 'ipport': None}]}
self.assertEqual((expected, constants.AMPHORA_NAMESPACE), res) self.assertEqual((expected, constants.AMPHORA_NAMESPACE), res)
@ -334,7 +354,8 @@ class LvsQueryTestCase(base.TestCase):
'members': {self.member_id1_v6: 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_id3_v6: constants.DOWN,
self.member_id4_v6: constants.MAINT}}} self.member_id4_v6: constants.MAINT,
self.member_id5_v6: constants.UP}}}
self.assertEqual(expected, res) self.assertEqual(expected, res)
@mock.patch('os.stat') @mock.patch('os.stat')

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Some IPv6 UDP members were incorrectly marked in ERROR status, because of
a formatting issue while generating the health message in the amphora.