VOL-245, VOL-246: Fix for alarm filter deletion and suppression

Change-Id: I034a3d8267ae4370656f672fa5b2f22abe2b089c
diff --git a/voltha/core/alarm_filter_agent.py b/voltha/core/alarm_filter_agent.py
index 51afba9..b4f3865 100644
--- a/voltha/core/alarm_filter_agent.py
+++ b/voltha/core/alarm_filter_agent.py
@@ -40,7 +40,6 @@
 
         self.log = structlog.get_logger()
 
-    @inlineCallbacks
     def add_filter(self, alarm_filter):
         self.log.debug('starting')
 
@@ -52,15 +51,16 @@
         self.self_proxies[alarm_filter.id].register_callback(
             CallbackType.POST_UPDATE, self._process_filter)
 
-        yield self._process_filter(alarm_filter)
+        self._process_filter(alarm_filter)
 
         self.log.info('started')
 
-    @inlineCallbacks
+        return self
+
     def remove_filter(self, alarm_filter):
         self.log.debug('stopping')
 
-        yield self._review_filter(alarm_filter)
+        self._review_filter(alarm_filter, teardown=True)
 
         self.self_proxies[alarm_filter.id].unregister_callback(
             CallbackType.PRE_UPDATE, self._review_filter)
@@ -83,11 +83,12 @@
 
         self.log.debug('cleaned')
 
-    def _review_filter(self, alarm_filter=None):
+    def _review_filter(self, alarm_filter=None, teardown=False):
         # UPDATE scenario:
         #
         # When a filter is updated, we need to review the content of the previous filter
-        # to ensure that nothing is left un-managed and not cleaned up.
+        # to ensure that nothing is left un-managed and not cleaned up.  If the filter
+        # actually changed, it will be re-applied (including suppression)
         #
         # TEAR DOWN scenario:
         # When a filter is deleted, we need to go through the rules
@@ -96,11 +97,10 @@
         if alarm_filter is not None:
             current_filter = self.self_proxies[alarm_filter.id].get()
 
-            # Find any device id rules contained in the filter that might have changed
-            rules_to_clean = [r for r in current_filter.rules if
-                              r.key == AlarmFilterRuleKey.device_id and r not in alarm_filter.rules]
+            # Find any rules contained in the filter that might have changed
+            rules_to_clean = [r for r in current_filter.rules if r not in alarm_filter.rules]
 
-            if not rules_to_clean:
+            if not rules_to_clean and not teardown:
                 # There are no rules from the current filter that require a clean up
                 return
 
diff --git a/voltha/core/core.py b/voltha/core/core.py
index ae81306..6d82d31 100644
--- a/voltha/core/core.py
+++ b/voltha/core/core.py
@@ -182,7 +182,10 @@
     @inlineCallbacks
     def _handle_remove_device(self, device):
         if device.id in self.device_agents:
-            AlarmFilterAgent(self).remove_device_filters(device)
+            if self.alarm_filter_agent is not None:
+                self.alarm_filter_agent.remove_device_filters(device)
+
+            log.debug('removed-device-filter', device)
 
             yield self.device_agents[device.id].stop(device)
             del self.device_agents[device.id]
@@ -223,9 +226,14 @@
     @inlineCallbacks
     def _handle_add_alarm_filter(self, alarm_filter):
         assert isinstance(alarm_filter, AlarmFilter)
-        yield AlarmFilterAgent(self).add_filter(alarm_filter)
+        # Create an agent if it does not yet exist
+        if self.alarm_filter_agent is None:
+            self.alarm_filter_agent = AlarmFilterAgent(self)
+
+        yield self.alarm_filter_agent.add_filter(alarm_filter)
 
     @inlineCallbacks
     def _handle_remove_alarm_filter(self, alarm_filter):
         assert isinstance(alarm_filter, AlarmFilter)
-        yield AlarmFilterAgent(self).remove_filter(alarm_filter)
+        if self.alarm_filter_agent is not None:
+            yield self.alarm_filter_agent.remove_filter(alarm_filter)