From 0a3dcb6b0bdb12888e8b677d1f25a4c71eda528f Mon Sep 17 00:00:00 2001 From: vpachchi Date: Mon, 11 Aug 2025 08:46:31 -0400 Subject: [PATCH] Stale subcloud alarms getting pruned handled - Prune stale alarms from all the resource/res pools Test Plan: PASS- Verify if the pruned alarms from source are not displayed PASS- Resgression tests are passed Change-Id: I3c1f55cf7390f0728413a7b193626b895d19ebc8 Signed-off-by: vpachchi --- o2ims/service/watcher/alarm_watcher.py | 70 +++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/o2ims/service/watcher/alarm_watcher.py b/o2ims/service/watcher/alarm_watcher.py index 51badc3..bd8967d 100644 --- a/o2ims/service/watcher/alarm_watcher.py +++ b/o2ims/service/watcher/alarm_watcher.py @@ -38,29 +38,53 @@ class AlarmWatcher(BaseWatcher): return "alarm" def _prune_stale_alarms(self): - """Prune alarms from DB that no longer exist in FM.""" - try: - current_alarms = self._client.list() - # Build set of current alarm IDs from FM - current_ids = set([a.id for a in current_alarms]) - logger.info(f'Current alarm IDs from FM: {current_ids}') - with self._bus.uow as uow: - db_alarms = list(uow.alarm_event_records.list().all()) - db_ids = set(a.alarmEventRecordId for a in db_alarms) - deleted_ids = db_ids - current_ids - - # TODO: When an alarm is deleted, the SMO must be notified. - - for del_id in deleted_ids: - alarm_obj = uow.alarm_event_records.get(del_id) - if alarm_obj: - uow.alarm_event_records.delete(alarm_obj) - if deleted_ids: - logger.info(f'Committing pruning of {deleted_ids} alarms \ - from DB') - uow.commit() - except Exception as e: - logger.error(f'Error pruning stale alarms: {str(e)}') + """Prune DB alarms that don't exist in FM for the current respool. + + Steps: + - Get FM alarm IDs for the configured resource pool(subcloud) + - Get DB alarm IDs for alarms whose resources belong to this res pool + - Find stale DB alarms that are not present in the source(fm alarms) + and delete them + """ + pool_id = getattr(self._client, '_pool_id', None) + if not pool_id: + return + + # FM alarm IDs for this pool with one quick retry on empty + fm_list = self._client.list() + + fm_ids = {a.id for a in fm_list} + + # DB alarm IDs for this pool via join + with self._bus.uow as uow: + rs = uow.session.execute( + ''' + SELECT a."alarmEventRecordId" + FROM "alarmEventRecord" a + JOIN "resource" r ON a."resourceId" = r."resourceId" + WHERE r."resourcePoolId" = :pool_id + ''', + dict(pool_id=pool_id) + ) + + db_ids = {row[0] for row in rs} + if not db_ids: + return # No results, exit early + + # Delete stale DB alarms that are not present in the source + to_delete = db_ids - fm_ids + + # No pruning of alarms required + if not to_delete: + return + + # TODO: When an alarm is deleted, the SMO must be notified. + for alarm_id in to_delete: + obj = uow.alarm_event_records.get(alarm_id) + if obj: + uow.alarm_event_records.delete(obj) + logger.info(f'Pruning alarm: {alarm_id}') + uow.commit() def _probe(self, parent: StxGenericModel, tags: object = None): -- 2.16.6