From e20ceebcf245f3bb74b29287b138a3e42cc72a6c Mon Sep 17 00:00:00 2001 From: Omer Date: Tue, 20 Dec 2022 16:58:23 +0100 Subject: [PATCH] Fix hm operating status to ONLINE in single lb call So far, Health Monitor was not set to ONLINE when single-call-creates were used. This patch adds a database task which sets the operating status of all the enabled Health Monitors of a LB to ONLINE. Story 2008400 Task 41333 Change-Id: I9deaea182568a23e8c1104d806273dc87f5caa72 --- .../worker/v2/flows/listener_flows.py | 3 ++ .../worker/v2/tasks/database_tasks.py | 33 +++++++++++++ .../worker/v2/tasks/test_database_tasks.py | 47 +++++++++++++++++++ ...ne-in-single-lb-call-214a7ca22937a877.yaml | 5 ++ 4 files changed, 88 insertions(+) create mode 100644 releasenotes/notes/fix-hm-operating-status-online-in-single-lb-call-214a7ca22937a877.yaml diff --git a/octavia/controller/worker/v2/flows/listener_flows.py b/octavia/controller/worker/v2/flows/listener_flows.py index ae22835a96..cc80d8484b 100644 --- a/octavia/controller/worker/v2/flows/listener_flows.py +++ b/octavia/controller/worker/v2/flows/listener_flows.py @@ -60,6 +60,9 @@ class ListenerFlows(object): requires=constants.LOADBALANCER_ID)) create_all_listeners_flow.add(network_tasks.UpdateVIP( requires=constants.LISTENERS)) + create_all_listeners_flow.add( + database_tasks.MarkHealthMonitorsOnlineInDB( + requires=constants.LOADBALANCER)) return create_all_listeners_flow def get_delete_listener_flow(self): diff --git a/octavia/controller/worker/v2/tasks/database_tasks.py b/octavia/controller/worker/v2/tasks/database_tasks.py index 8f57b42202..baec38f7d2 100644 --- a/octavia/controller/worker/v2/tasks/database_tasks.py +++ b/octavia/controller/worker/v2/tasks/database_tasks.py @@ -1923,6 +1923,39 @@ class MarkHealthMonitorPendingUpdateInDB(BaseDatabaseTask): health_mon[constants.HEALTHMONITOR_ID]) +class MarkHealthMonitorsOnlineInDB(BaseDatabaseTask): + """Mark all enabled health monitors Online + + :param loadbalancer: Dictionary of a Load Balancer that has associated + health monitors + :returns: None + """ + + def execute(self, loadbalancer: dict): + db_lb = self.loadbalancer_repo.get( + db_apis.get_session(), + id=loadbalancer[constants.LOADBALANCER_ID]) + + # Update the healthmonitors of either attached listeners or l7policies + hms_to_update = [] + + for listener in db_lb.listeners: + if listener.default_pool and listener.default_pool.health_monitor: + hm = listener.default_pool.health_monitor + if hm.enabled: + hms_to_update.append(hm.id) + for l7policy in listener.l7policies: + if l7policy.redirect_pool and ( + l7policy.redirect_pool.health_monitor): + hm = l7policy.redirect_pool.health_monitor + if hm.enabled: + hms_to_update.append(hm.id) + + for hm_id in hms_to_update: + self.health_mon_repo.update(db_apis.get_session(), hm_id, + operating_status=constants.ONLINE) + + class MarkL7PolicyActiveInDB(BaseDatabaseTask): """Mark the l7policy ACTIVE in the DB. diff --git a/octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py b/octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py index 1984396444..c6185a7473 100644 --- a/octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py +++ b/octavia/tests/unit/controller/worker/v2/tasks/test_database_tasks.py @@ -2145,6 +2145,53 @@ class TestDatabaseTasks(base.TestCase): id=HM_ID, provisioning_status=constants.ERROR) + @mock.patch('octavia.db.repositories.LoadBalancerRepository.get') + @mock.patch('octavia.db.repositories.HealthMonitorRepository.update') + def test_mark_health_monitors_online_in_db(self, + mock_health_mon_repo_update, + mock_loadbalancer_repo_get, + mock_generate_uuid, + mock_LOG, + mock_get_session, + mock_loadbalancer_repo_update, + mock_listener_repo_update, + mock_amphora_repo_update, + mock_amphora_repo_delete): + # Creating a mock hm for a default pool + mock_lb = mock.MagicMock() + mock_listener = mock.MagicMock() + mock_default_pool = mock_listener.default_pool + mock_hm_def_pool = mock_default_pool.health_monitor + mock_hm_def_pool.id = uuidutils.generate_uuid() + mock_lb.listeners = [mock_listener] + + # Creating a mock hm for a redirect pool of an l7policy + mock_l7policy = mock.MagicMock() + mock_redirect_pool = mock_l7policy.redirect_pool + mock_hm_l7_policy = mock_redirect_pool.health_monitor + mock_hm_l7_policy.id = uuidutils.generate_uuid() + mock_listener.l7policies = [mock_l7policy] + + # Creating a mock hm for a non default pool - we check its health + # monitor won't be updated + mock_pool = mock.MagicMock() + mock_hm_non_def_pool = mock_pool.health_monitor + mock_hm_non_def_pool.id = uuidutils.generate_uuid() + mock_lb.pools = [mock_pool] + + mock_loadbalancer_repo_get.return_value = mock_lb + mark_health_mon_online = (database_tasks. + MarkHealthMonitorsOnlineInDB()) + mark_health_mon_online.execute(mock_lb) + + mock_session = 'TEST' + for mock_id in [mock_hm_def_pool.id, mock_hm_l7_policy.id]: + mock_health_mon_repo_update.assert_called_with( + mock_session, + mock_id, + operating_status=constants.ONLINE) + self.assertEqual(2, mock_health_mon_repo_update.call_count) + @mock.patch('octavia.db.repositories.L7PolicyRepository.update') @mock.patch('octavia.db.repositories.L7PolicyRepository.get') def test_mark_l7policy_active_in_db(self, diff --git a/releasenotes/notes/fix-hm-operating-status-online-in-single-lb-call-214a7ca22937a877.yaml b/releasenotes/notes/fix-hm-operating-status-online-in-single-lb-call-214a7ca22937a877.yaml new file mode 100644 index 0000000000..5e5a892514 --- /dev/null +++ b/releasenotes/notes/fix-hm-operating-status-online-in-single-lb-call-214a7ca22937a877.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed a bug that didn't set all the active load balancer Health Monitors + ONLINE in populated LB single-create calls.