Skip to content

Commit f034bab

Browse files
Remove leftover OVN LB HM port upon deletion of a member
When a load balancer pool has a Health Monitor associated with it, an OVN LB Health Monitor port is created for each backend member subnet added. When removing backend members, the OVN LB Health Monitor port is cleaned up only if no more members are associated with the Health Monitor pool. However, this assumption is incorrect. This patch corrects this behavior by checking instead if there are more members from the same subnet associated with the pool. It ensures that the OVN LB Health Monitor port is deleted only when the last member from the subnet is deleted. If the port is being used by another different LB Health Monitor, `_clean_up_hm_port` will handle it. Closes-Bug: #2062965 Change-Id: I4c35cc5c6af14bb208f4313bb86e3519df0a30fa
1 parent 4dc7fc7 commit f034bab

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

ovn_octavia_provider/helper.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,20 +2189,32 @@ def _remove_member(self, member, ovn_lb, pool_key):
21892189
user_fault_string=msg,
21902190
operator_fault_string=msg)
21912191

2192+
def _members_in_subnet(self, ovn_lb, subnet_id):
2193+
for key, value in ovn_lb.external_ids.items():
2194+
if key.startswith(ovn_const.LB_EXT_IDS_POOL_PREFIX):
2195+
if value and len(value.split(',')) > 0:
2196+
for m_info in value.split(','):
2197+
mem_id, mem_ip_port, mem_subnet = m_info.split('_')[1:]
2198+
if mem_subnet == subnet_id:
2199+
return True
2200+
return False
2201+
21922202
def member_delete(self, member):
21932203
error_deleting_member = False
21942204
try:
21952205
pool_key, ovn_lb = self._find_ovn_lb_by_pool_id(
21962206
member[constants.POOL_ID])
21972207

2198-
pool_status = self._remove_member(member, ovn_lb, pool_key)
2208+
self._remove_member(member, ovn_lb, pool_key)
21992209

2200-
if ovn_lb.health_check and pool_status == constants.OFFLINE:
2201-
# NOTE(froyo): if the pool status is OFFLINE there are no more
2202-
# members. So we should ensure the hm-port is deleted if no
2203-
# more LB are using it. We need to do this call after the
2204-
# cleaning of the ip_port_mappings for the ovn LB.
2205-
self._clean_up_hm_port(member[constants.SUBNET_ID])
2210+
if ovn_lb.health_check:
2211+
mem_subnet = member[constants.SUBNET_ID]
2212+
if not self._members_in_subnet(ovn_lb, mem_subnet):
2213+
# NOTE(froyo): if member is last member from the subnet
2214+
# we should clean up the ovn-lb-hm-port.
2215+
# We need to do this call after the cleaning of the
2216+
# ip_port_mappings for the ovn LB.
2217+
self._clean_up_hm_port(member[constants.SUBNET_ID])
22062218
except Exception:
22072219
LOG.exception(ovn_const.EXCEPTION_MSG, "deletion of member")
22082220
error_deleting_member = True

ovn_octavia_provider/tests/unit/test_helper.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2177,6 +2177,30 @@ def test_member_delete_hm(self, uhm, folbpi):
21772177
self.member_address,
21782178
delete=True)
21792179

2180+
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_ovn_lb_by_pool_id')
2181+
@mock.patch.object(ovn_helper.OvnProviderHelper, '_update_hm_member')
2182+
@mock.patch.object(ovn_helper.OvnProviderHelper, '_clean_up_hm_port')
2183+
def test_member_delete_keep_hm_port(self, del_hm_port, uhm, folbpi):
2184+
pool_key = 'pool_%s' % self.pool_id
2185+
member2_id = uuidutils.generate_uuid()
2186+
member2_address = '192.168.2.150'
2187+
member2_line = (
2188+
'member_%s_%s:%s_%s' %
2189+
(member2_id, member2_address,
2190+
self.member_port, self.member_subnet_id))
2191+
self.ovn_hm_lb.external_ids[pool_key] = ','.join([self.member_line,
2192+
member2_line])
2193+
self.ovn_hm_lb.external_ids[ovn_const.OVN_MEMBER_STATUS_KEY] = \
2194+
'{"%s": "%s","%s": "%s"}' % (self.member_id, constants.ONLINE,
2195+
member2_id, constants.ONLINE)
2196+
folbpi.return_value = (pool_key, self.ovn_hm_lb)
2197+
self.helper.member_delete(self.member)
2198+
uhm.assert_called_once_with(self.ovn_hm_lb,
2199+
pool_key,
2200+
self.member_address,
2201+
delete=True)
2202+
del_hm_port.assert_not_called()
2203+
21802204
def test_member_delete_not_found_in_pool(self):
21812205
self.ovn_lb.external_ids.update({'pool_' + self.pool_id: ''})
21822206
self.ovn_lb.external_ids[ovn_const.OVN_MEMBER_STATUS_KEY] = '{}'

0 commit comments

Comments
 (0)