Merge "Fix loadbalancer stuck in cascade delete"

This commit is contained in:
Zuul 2024-09-05 13:56:36 +00:00 committed by Gerrit Code Review
commit 292bf442cc
4 changed files with 69 additions and 7 deletions

View File

@ -431,8 +431,8 @@ class ControllerWorker:
constants.SERVER_GROUP_ID: db_lb.server_group_id, constants.SERVER_GROUP_ID: db_lb.server_group_id,
constants.PROJECT_ID: db_lb.project_id} constants.PROJECT_ID: db_lb.project_id}
if cascade: if cascade:
listeners = flow_utils.get_listeners_on_lb(db_lb) listeners = flow_utils.get_listeners_on_lb(db_lb, True)
pools = flow_utils.get_pools_on_lb(db_lb) pools = flow_utils.get_pools_on_lb(db_lb, True)
self.run_flow( self.run_flow(
flow_utils.get_cascade_delete_load_balancer_flow, flow_utils.get_cascade_delete_load_balancer_flow,

View File

@ -40,29 +40,31 @@ def get_delete_load_balancer_flow(lb):
return LB_FLOWS.get_delete_load_balancer_flow(lb) return LB_FLOWS.get_delete_load_balancer_flow(lb)
def get_listeners_on_lb(db_lb): def get_listeners_on_lb(db_lb, for_delete=False):
"""Get a list of the listeners on a load balancer. """Get a list of the listeners on a load balancer.
:param db_lb: A load balancer database model object. :param db_lb: A load balancer database model object.
:param for_delete: Skip errors on tls certs loading.
:returns: A list of provider dict format listeners. :returns: A list of provider dict format listeners.
""" """
listener_dicts = [] listener_dicts = []
for listener in db_lb.listeners: for listener in db_lb.listeners:
prov_listener = provider_utils.db_listener_to_provider_listener( prov_listener = provider_utils.db_listener_to_provider_listener(
listener) listener, for_delete)
listener_dicts.append(prov_listener.to_dict()) listener_dicts.append(prov_listener.to_dict())
return listener_dicts return listener_dicts
def get_pools_on_lb(db_lb): def get_pools_on_lb(db_lb, for_delete=False):
"""Get a list of the pools on a load balancer. """Get a list of the pools on a load balancer.
:param db_lb: A load balancer database model object. :param db_lb: A load balancer database model object.
:param for_delete: Skip errors on tls certs loading.
:returns: A list of provider dict format pools. :returns: A list of provider dict format pools.
""" """
pool_dicts = [] pool_dicts = []
for pool in db_lb.pools: for pool in db_lb.pools:
prov_pool = provider_utils.db_pool_to_provider_pool(pool) prov_pool = provider_utils.db_pool_to_provider_pool(pool, for_delete)
pool_dicts.append(prov_pool.to_dict()) pool_dicts.append(prov_pool.to_dict())
return pool_dicts return pool_dicts

View File

@ -27,7 +27,7 @@ from octavia.controller.worker.v2 import controller_worker
from octavia.controller.worker.v2.flows import flow_utils from octavia.controller.worker.v2.flows import flow_utils
import octavia.tests.unit.base as base import octavia.tests.unit.base as base
TLS_CERT_ID = uuidutils.generate_uuid()
AMP_ID = uuidutils.generate_uuid() AMP_ID = uuidutils.generate_uuid()
LB_ID = uuidutils.generate_uuid() LB_ID = uuidutils.generate_uuid()
LISTENER_ID = uuidutils.generate_uuid() LISTENER_ID = uuidutils.generate_uuid()
@ -804,6 +804,61 @@ class TestControllerWorker(base.TestCase):
}) })
) )
@mock.patch(
"octavia.common.tls_utils.cert_parser.load_certificates_data",
side_effect=RuntimeError
)
def test_delete_load_balancer_with_cascade_tls_unavailable(
self,
mock_load_tls_cert,
mock_api_get_session,
mock_dyn_log_listener,
mock_taskflow_load,
mock_pool_repo_get,
mock_member_repo_get,
mock_l7rule_repo_get,
mock_l7policy_repo_get,
mock_listener_repo_get,
mock_lb_repo_get,
mock_health_mon_repo_get,
mock_amp_repo_get
):
_flow_mock.reset_mock()
_listener_mock.tls_certificate_id = TLS_CERT_ID
_listener_mock.to_dict.return_value[
constants.TLS_CERTIFICATE_ID] = TLS_CERT_ID
cw = controller_worker.ControllerWorker()
cw.delete_load_balancer(_load_balancer_mock, cascade=True)
mock_lb_repo_get.assert_called_once_with(
_db_session,
id=LB_ID)
# Check load_certificates_data called and error is raised
# Error must be ignored because it is not critical for current flow
mock_load_tls_cert.assert_called_once()
listener_list = [{constants.LISTENER_ID: LISTENER_ID,
constants.LOADBALANCER_ID: LB_ID,
constants.PROJECT_ID: PROJECT_ID,
"default_tls_container_ref": TLS_CERT_ID}]
(cw.services_controller.run_poster.
assert_called_once_with(
flow_utils.get_cascade_delete_load_balancer_flow,
_load_balancer_mock, listener_list, [],
store={constants.LOADBALANCER: _load_balancer_mock,
constants.LOADBALANCER_ID: LB_ID,
constants.SERVER_GROUP_ID:
_db_load_balancer_mock.server_group_id,
constants.PROJECT_ID: _db_load_balancer_mock.project_id,
})
)
_listener_mock.reset_mock()
@mock.patch('octavia.db.repositories.ListenerRepository.get_all', @mock.patch('octavia.db.repositories.ListenerRepository.get_all',
return_value=([_listener_mock], None)) return_value=([_listener_mock], None))
def test_update_load_balancer(self, def test_update_load_balancer(self,

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Fix load balancer stuck in PENDING_DELETE if TLS storage unavailable or
returns error