Remove amphora_health record on revert CreateAmphoraInDB

Record in amphora_health created by first UDP request from booted
amphora.
It's possible to run creation/failover LB where Amphora will be booted
and reverted on the final tasks (e.g. AmphoraPostVIPPlug) as result
record in amphora_health will be created, but not be removed on revert.
This patch adds logic to remove amphora_health record on revert flow.

Closes-Bug: 2085530

Change-Id: Ia8b4612cd25a68b44d55b113f704756818eb8a5b
This commit is contained in:
Sergey Kraynev 2024-10-23 17:57:44 +04:00
parent fd071d3391
commit f76fa1ae33
No known key found for this signature in database
GPG Key ID: 23F0753A8D7AA3B1
3 changed files with 45 additions and 12 deletions

View File

@ -132,13 +132,17 @@ class CreateAmphoraInDB(BaseDatabaseTask):
LOG.warning("Reverting create amphora in DB for amp id %s ", result) LOG.warning("Reverting create amphora in DB for amp id %s ", result)
# Delete the amphora for now. May want to just update status later # Delete the amphora for now. May want to just update status later
try: with db_apis.session().begin() as session:
with db_apis.session().begin() as session: try:
self.amphora_repo.delete(session, id=result) self.amphora_repo.delete(session, id=result)
except Exception as e: except Exception as e:
LOG.error("Failed to delete amphora %(amp)s " LOG.error("Failed to delete amphora %(amp)s "
"in the database due to: " "in the database due to: "
"%(except)s", {'amp': result, 'except': str(e)}) "%(except)s", {'amp': result, 'except': str(e)})
try:
self.amp_health_repo.delete(session, amphora_id=result)
except Exception:
pass
class MarkLBAmphoraeDeletedInDB(BaseDatabaseTask): class MarkLBAmphoraeDeletedInDB(BaseDatabaseTask):

View File

@ -184,7 +184,9 @@ class TestDatabaseTasks(base.TestCase):
@mock.patch('octavia.db.repositories.AmphoraRepository.create', @mock.patch('octavia.db.repositories.AmphoraRepository.create',
return_value=_db_amphora_mock) return_value=_db_amphora_mock)
@mock.patch('octavia.db.repositories.AmphoraHealthRepository.delete')
def test_create_amphora_in_db(self, def test_create_amphora_in_db(self,
mock_amphora_health_repo_delete,
mock_create, mock_create,
mock_generate_uuid, mock_generate_uuid,
mock_LOG, mock_LOG,
@ -210,23 +212,43 @@ class TestDatabaseTasks(base.TestCase):
# Test the revert # Test the revert
create_amp_in_db.revert(_tf_failure_mock) create_amp_in_db.revert(_tf_failure_mock)
self.assertFalse(mock_amphora_repo_delete.called) mock_amphora_repo_delete.assert_not_called()
mock_amphora_health_repo_delete.assert_not_called()
amp_id = 'AMP'
mock_amphora_repo_delete.reset_mock() mock_amphora_repo_delete.reset_mock()
create_amp_in_db.revert(result='AMP') mock_amphora_health_repo_delete.reset_mock()
create_amp_in_db.revert(result=amp_id)
self.assertTrue(mock_amphora_repo_delete.called) self.assertTrue(mock_amphora_repo_delete.called)
self.assertTrue(mock_amphora_health_repo_delete.called)
mock_amphora_repo_delete.assert_called_once_with( mock_amphora_repo_delete.assert_called_once_with(
mock_session, mock_session,
id='AMP') id=amp_id)
mock_amphora_health_repo_delete.assert_called_once_with(
mock_session,
amphora_id=amp_id)
mock_LOG.error.assert_not_called()
mock_LOG.debug.assert_not_called()
# Test revert with exception # Test revert with exception
mock_amphora_repo_delete.reset_mock() mock_amphora_repo_delete.reset_mock()
mock_amphora_repo_delete.side_effect = Exception('fail') mock_amphora_health_repo_delete.reset_mock()
create_amp_in_db.revert(result='AMP') err1_msg, err2_msg = ('fail', 'fail2')
mock_amphora_repo_delete.side_effect = Exception(err1_msg)
mock_amphora_health_repo_delete.side_effect = Exception(err2_msg)
create_amp_in_db.revert(result=amp_id)
self.assertTrue(mock_amphora_repo_delete.called) self.assertTrue(mock_amphora_repo_delete.called)
self.assertTrue(mock_amphora_health_repo_delete.called)
mock_amphora_repo_delete.assert_called_once_with( mock_amphora_repo_delete.assert_called_once_with(
mock_session, mock_session,
id='AMP') id=amp_id)
mock_amphora_health_repo_delete.assert_called_once_with(
mock_session,
amphora_id=amp_id)
mock_LOG.error.assert_called_once_with(
"Failed to delete amphora %(amp)s "
"in the database due to: "
"%(except)s", {'amp': amp_id, 'except': err1_msg})
@mock.patch('octavia.db.repositories.ListenerRepository.delete') @mock.patch('octavia.db.repositories.ListenerRepository.delete')
def test_delete_listener_in_db(self, def test_delete_listener_in_db(self,

View File

@ -0,0 +1,7 @@
---
fixes:
- |
Remove record in amphora_health table on revert. It's necessary, because
record in amphora table for corresponding amphora also deleted.
It allows to avoid false positive react of failover threshold due to
orphan records in amphora_health table.