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)