From f5655b5eeec9bc1e59407b307233e9e6cdfc3896 Mon Sep 17 00:00:00 2001 From: Gregory Thiemonge Date: Fri, 10 Sep 2021 10:55:24 +0200 Subject: [PATCH] Ignore status update on deleted objects in driver-agent When receiving 2 DELETE updates on the same object, ignore the 2nd update. It avoids throwing exceptions because the object no longer exists in the DB. Story 2009202 Task 43259 Change-Id: I387d9a3ad2197f6b59cd12db5f7643484c98fcd2 --- .../drivers/driver_agent/driver_updater.py | 14 ++++++- .../drivers/driver_agent/test_driver_agent.py | 37 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/octavia/api/drivers/driver_agent/driver_updater.py b/octavia/api/drivers/driver_agent/driver_updater.py index 912e392a7e..af90d34079 100644 --- a/octavia/api/drivers/driver_agent/driver_updater.py +++ b/octavia/api/drivers/driver_agent/driver_updater.py @@ -58,6 +58,13 @@ class DriverUpdater(object): def _decrement_quota(self, repo, object_name, record_id): lock_session = db_apis.get_session(autocommit=False) db_object = repo.get(lock_session, id=record_id) + if db_object is None: + lock_session.rollback() + msg = ('{} with ID of {} is not present in the ' + 'database, it might have already been deleted. ' + 'Skipping quota update.'.format( + object_name, record_id)) + raise driver_exceptions.NotFound(msg) try: if db_object.provisioning_status == consts.DELETED: LOG.info('%(name)s with ID of %(id)s is already in the ' @@ -91,7 +98,12 @@ class DriverUpdater(object): if object_name == consts.LOADBALANCERS: self._check_for_lb_vip_deallocate(repo, record_id) - self._decrement_quota(repo, object_name, record_id) + try: + self._decrement_quota(repo, object_name, record_id) + except driver_exceptions.NotFound: + # prov_status is DELETED and the object no longer + # exists in the DB, ignore the update. + return if delete_record and object_name != consts.LOADBALANCERS: repo.delete(self.db_session, id=record_id) diff --git a/octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py b/octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py index 24e77ce03c..6d16c25e08 100644 --- a/octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py +++ b/octavia/tests/functional/api/drivers/driver_agent/test_driver_agent.py @@ -342,3 +342,40 @@ class DriverAgentTest(base.OctaviaDBTestBase): # Test non-existent L7 rule result = self.driver_lib.get_l7rule('bogus') self.assertIsNone(result) + + def test_update_load_balancer_status(self): + # Add a new member + member_dict = copy.deepcopy(self.sample_data.test_member2_dict) + self.repos.member.create(self.session, **member_dict) + + result = self.driver_lib.get_member(member_dict[lib_consts.ID]) + self.assertEqual(self.sample_data.provider_member2_dict, + result.to_dict(render_unsets=True)) + + # Test deleting a member + status = { + "loadbalancers": [ + {"id": self.sample_data.lb_id, + "provisioning_status": "ACTIVE", + "operating_status": "ONLINE"} + ], + "healthmonitors": [], + "l7policies": [], + "l7rules": [], + "listeners": [], + "members": [ + {"id": member_dict[lib_consts.ID], + "provisioning_status": "DELETED"} + ], + "pools": [] + } + + self.driver_lib.update_loadbalancer_status(status) + result = self.driver_lib.get_member(member_dict[lib_consts.ID]) + self.assertIsNone(result) + + # Test deleting an already deleted member + # It should be silently ignored + self.driver_lib.update_loadbalancer_status(status) + result = self.driver_lib.get_member(member_dict[lib_consts.ID]) + self.assertIsNone(result)