diff --git a/octavia/controller/healthmanager/update_db.py b/octavia/controller/healthmanager/update_db.py index fe2b8c9e55..1e068de48a 100644 --- a/octavia/controller/healthmanager/update_db.py +++ b/octavia/controller/healthmanager/update_db.py @@ -165,6 +165,7 @@ class UpdateHealthDb(object): '%(status)s'), {'pool': pool_id, 'status': pool.get('status')}) + # Deal with the members that are reporting from the Amphora members = pool['members'] for member_id, status in members.items(): @@ -200,6 +201,17 @@ class UpdateHealthDb(object): LOG.error("Member %s is not able to update " "in DB", member_id) + # Now deal with the members that didn't report from the Amphora + db_pool = self.pool_repo.get(session, id=pool_id) + real_members = [member.id for member in db_pool.members] + reported_members = [member for member in members.keys()] + missing_members = set(real_members) - set(reported_members) + for member_id in missing_members: + self._update_status_and_emit_event( + session, self.member_repo, constants.MEMBER, + member_id, constants.OFFLINE + ) + try: if pool_status is not None: self._update_status_and_emit_event( diff --git a/octavia/tests/unit/controller/healthmanager/test_update_db.py b/octavia/tests/unit/controller/healthmanager/test_update_db.py index 68338c560a..46073245c5 100644 --- a/octavia/tests/unit/controller/healthmanager/test_update_db.py +++ b/octavia/tests/unit/controller/healthmanager/test_update_db.py @@ -141,9 +141,12 @@ class TestUpdateHealthDb(base.TestCase): 'blah', member_id, operating_status=constants.ONLINE) + # If the listener count is wrong, make sure we don't update self.hm.listener_repo.count.return_value = 2 + self.amphora_health_repo.replace.reset_mock() self.hm.update_health(health) + self.assertTrue(not self.amphora_health_repo.replace.called) def test_update_health_member_drain(self): @@ -181,10 +184,6 @@ class TestUpdateHealthDb(base.TestCase): 'blah', member_id, operating_status=constants.DRAINING) - self.hm.listener_repo.count.return_value = 2 - - self.hm.update_health(health) - def test_update_health_member_maint(self): health = { @@ -221,10 +220,6 @@ class TestUpdateHealthDb(base.TestCase): 'blah', member_id, operating_status=constants.OFFLINE) - self.hm.listener_repo.count.return_value = 2 - - self.hm.update_health(health) - def test_update_health_member_unknown(self): health = { @@ -255,10 +250,6 @@ class TestUpdateHealthDb(base.TestCase): 'blah', pool_id, operating_status=constants.ONLINE) self.assertTrue(not self.member_repo.update.called) - self.hm.listener_repo.count.return_value = 2 - - self.hm.update_health(health) - def test_update_health_member_down(self): health = { @@ -297,10 +288,6 @@ class TestUpdateHealthDb(base.TestCase): 'blah', member_id, operating_status=constants.ERROR) - self.hm.listener_repo.count.return_value = 2 - - self.hm.update_health(health) - def test_update_health_member_no_check(self): health = { @@ -340,9 +327,51 @@ class TestUpdateHealthDb(base.TestCase): 'blah', member_id, operating_status=constants.NO_MONITOR) - self.hm.listener_repo.count.return_value = 2 + def test_update_health_member_admin_down(self): + health = { + "id": self.FAKE_UUID_1, + "listeners": { + "listener-id-1": { + "status": constants.OPEN, + "pools": { + "pool-id-1": { + "status": constants.UP, + "members": { + "member-id-1": constants.UP}}}}}} + + self.mock_session.return_value = 'blah' + + mock_pool = mock.Mock() + mock_member1 = mock.Mock() + mock_member1.id = 'member-id-1' + mock_member2 = mock.Mock() + mock_member2.id = 'member-id-2' + mock_pool.members = [mock_member1, mock_member2] + self.pool_repo.get.return_value = mock_pool self.hm.update_health(health) + self.assertTrue(self.amphora_health_repo.replace.called) + + # test listener, member + for listener_id, listener in six.iteritems( + health.get('listeners', {})): + + self.listener_repo.update.assert_any_call( + 'blah', listener_id, operating_status=constants.ONLINE) + + for pool_id, pool in six.iteritems(listener.get('pools', {})): + + self.hm.pool_repo.update.assert_any_call( + 'blah', pool_id, operating_status=constants.ONLINE) + + for member_id, member in six.iteritems( + pool.get('members', {})): + + self.member_repo.update.assert_any_call( + 'blah', member_id, + operating_status=constants.ONLINE) + self.member_repo.update.assert_any_call( + 'blah', mock_member2.id, operating_status=constants.OFFLINE) def test_update_health_list_full_member_down(self): @@ -383,8 +412,10 @@ class TestUpdateHealthDb(base.TestCase): operating_status=constants.ERROR) self.hm.listener_repo.count.return_value = 2 + self.amphora_health_repo.replace.reset_mock() self.hm.update_health(health) + self.assertTrue(not self.amphora_health_repo.replace.called) def test_update_health_error(self):