VOL-1144: Alarm upload frame and count issues

Change-Id: I5aa39922b5290e78f755747c5962bca450a27019
diff --git a/voltha/extensions/omci/database/alarm_db_ext.py b/voltha/extensions/omci/database/alarm_db_ext.py
index c4054d3..699f9b7 100644
--- a/voltha/extensions/omci/database/alarm_db_ext.py
+++ b/voltha/extensions/omci/database/alarm_db_ext.py
@@ -233,9 +233,9 @@
         root_proxy = self._core.get_proxy('/')
 
         data = AlarmDeviceData(device_id=device_id,
-                             created=self._time_to_string(now),
-                             version=AlarmDbExternal.CURRENT_VERSION,
-                             last_alarm_sequence=0)
+                               created=self._time_to_string(now),
+                               version=AlarmDbExternal.CURRENT_VERSION,
+                               last_alarm_sequence=0)
         try:
             dev_proxy = self._device_proxy(device_id)
             found = True
@@ -408,7 +408,7 @@
             data.last_sync_time = self._time_to_string(value)
 
             # Update
-            self._root_proxy.update(MibDbExternal.DEVICE_PATH.format(device_id),
+            self._root_proxy.update(AlarmDbExternal.DEVICE_PATH.format(device_id),
                                     data)
             self._modified = now
             self.log.debug('save-sync-time-complete', device_id=device_id)
@@ -440,17 +440,16 @@
 
     def save_alarm_last_sync(self, device_id, value):
         """
-        Save the Last Sync time to the database in an easy location to access
+        Save the Last Alarm Sequence value to the database in an easy location to access
 
         :param device_id: (str) ONU Device ID
-        :param value: (DateTime) Value to save
+        :param value: (int) Value to save
         """
         self.log.debug('save-last-sync', device_id=device_id, seq=str(value))
 
         try:
-            if not isinstance(value, datetime):
-                raise TypeError('Expected a datetime object, got {}'.
-                                format(type(datetime)))
+            if not isinstance(value, int):
+                raise TypeError('Expected a integer, got {}'.format(type(value)))
 
             device_proxy = self._device_proxy(device_id)
             data = device_proxy.get(depth=0)
diff --git a/voltha/extensions/omci/me_frame.py b/voltha/extensions/omci/me_frame.py
index ce8f146..71cab33 100644
--- a/voltha/extensions/omci/me_frame.py
+++ b/voltha/extensions/omci/me_frame.py
@@ -346,6 +346,7 @@
         :return: (OmciFrame) OMCI Frame
         """
         self._check_operation(OP.GetAllAlarms)
+        assert 0 <= alarm_retrieval_mode <= 1, 'Alarm retrieval mode must be 0..1'
 
         return OmciFrame(
             transaction_id=None,
@@ -353,7 +354,7 @@
             omci_message=OmciGetAllAlarms(
                 entity_class=getattr(self.entity_class, 'class_id'),
                 entity_id=getattr(self, 'entity_id'),
-                alarm_retrieval_mode=self._entity_id.mask_for(alarm_retrieval_mode)
+                alarm_retrieval_mode=alarm_retrieval_mode
             ))
 
     def get_all_alarm_next(self, command_sequence_number):
diff --git a/voltha/extensions/omci/omci_cc.py b/voltha/extensions/omci/omci_cc.py
index c89aded..90b4b2a 100644
--- a/voltha/extensions/omci/omci_cc.py
+++ b/voltha/extensions/omci/omci_cc.py
@@ -1,5 +1,5 @@
 #
-# Copyright 2017 the original author or authors.
+# Copyright 2017-present Open Networking Foundation
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -75,7 +75,6 @@
         OmciSetResponse.message_id: RxEvent.Set,
         OmciGetAllAlarmsResponse.message_id: RxEvent.Get_ALARM_Get,
         OmciGetAllAlarmsNextResponse.message_id: RxEvent.Get_ALARM_Get_Next
-
     }
 
     def __init__(self, adapter_agent, device_id, me_map=None,
@@ -661,10 +660,10 @@
         frame = OntGFrame().reboot()
         return self.send(frame, timeout)
 
-    def send_get_all_alarm(self, alarm_retrival_mode=0, timeout=DEFAULT_OMCI_TIMEOUT):
+    def send_get_all_alarm(self, alarm_retrieval_mode=0, timeout=DEFAULT_OMCI_TIMEOUT):
         self.log.debug('send_get_alarm')
 
-        frame = OntDataFrame().get_all_alarm(alarm_retrival_mode)
+        frame = OntDataFrame().get_all_alarm(alarm_retrieval_mode)
         return self.send(frame, timeout)
 
     def send_get_all_alarm_next(self, seq_no, timeout=DEFAULT_OMCI_TIMEOUT):
diff --git a/voltha/extensions/omci/onu_device_entry.py b/voltha/extensions/omci/onu_device_entry.py
index d3fd68b..c73ea99 100644
--- a/voltha/extensions/omci/onu_device_entry.py
+++ b/voltha/extensions/omci/onu_device_entry.py
@@ -53,7 +53,7 @@
     An ONU Device entry in the MIB
     """
     def __init__(self, omci_agent, device_id, adapter_agent, custom_me_map,
-                 mib_db, support_classes):
+                 mib_db, alarm_db, support_classes):
         """
         Class initializer
 
@@ -62,6 +62,7 @@
         :param adapter_agent: (AdapterAgent) Adapter agent for ONU
         :param custom_me_map: (dict) Additional/updated ME to add to class map
         :param mib_db: (MibDbApi) MIB Database reference
+        :param alarm_db: (MibDbApi) Alarm Table/Database reference
         :param support_classes: (dict) State machines and tasks for this ONU
         """
         self.log = structlog.get_logger(device_id=device_id)
@@ -106,12 +107,12 @@
 
             # ONU ALARM Synchronization state machine
             self._alarm_db_in_sync = False
-            alarm_synchronizer_info = support_classes.get('alarm-syncronizer')
+            alarm_synchronizer_info = support_classes.get('alarm-synchronizer')
             advertise = alarm_synchronizer_info['advertise-events']
             self._alarm_sync_sm = alarm_synchronizer_info['state-machine'](self._omci_agent,
                                                                            device_id,
                                                                            alarm_synchronizer_info['tasks'],
-                                                                           mib_db,
+                                                                           alarm_db,
                                                                            advertise_events=advertise)
         except Exception as e:
             self.log.exception('state-machine-create-failed', e=e)
@@ -191,7 +192,6 @@
         Set PM interval configuration
 
         :param pm_config: (OnuPmIntervalMetrics) PM Interval configuration
-        :return:
         """
         self._pm_intervals_sm.set_pm_config(pm_config)
 
diff --git a/voltha/extensions/omci/openomci_agent.py b/voltha/extensions/omci/openomci_agent.py
index 76a8076..c7f3eca 100644
--- a/voltha/extensions/omci/openomci_agent.py
+++ b/voltha/extensions/omci/openomci_agent.py
@@ -65,17 +65,17 @@
             'delete-pm': OmciDeletePMRequest,
         },
     },
-     'alarm-syncronizer': {
-         'state-machine': AlarmSynchronizer,    # Implements the Alarm sync state machine
-         'database': AlarmDbExternal,           # For any State storage needs
-         'advertise-events': True,             # Advertise events on OpenOMCI event bus
-         'tasks': {
-             'alarm-sync': AlarmSyncDataTask,
-             'alarm-check': AlarmDataTask,
-             'alarm-resync': AlarmResyncTask,
-             'alarm-audit': AlarmDataTask
-         }
-     }
+    'alarm-synchronizer': {
+        'state-machine': AlarmSynchronizer,    # Implements the Alarm sync state machine
+        'database': AlarmDbExternal,           # For any State storage needs
+        'advertise-events': True,              # Advertise events on OpenOMCI event bus
+        'tasks': {
+            'alarm-sync': AlarmSyncDataTask,
+            'alarm-check': AlarmDataTask,
+            'alarm-resync': AlarmResyncTask,
+            'alarm-audit': AlarmDataTask
+        }
+    }
 }
 
 
@@ -106,9 +106,9 @@
         self._mib_db = None
         self._mib_database_cls = support_classes['mib-synchronizer']['database']
 
-        # Alarm Synchronization Database # TODO: Stretch goal for VOLTHA v1.3.0
+        # Alarm Synchronization Database
         self._alarm_db = None
-        self._alarm_database_cls = support_classes['alarm-syncronizer']['database']
+        self._alarm_database_cls = support_classes['alarm-synchronizer']['database']
 
     @property
     def core(self):
@@ -136,7 +136,6 @@
             if self._mib_db is None:
                 self._mib_db = self._mib_database_cls(self)
 
-            # TODO Alarm DB
             if self._alarm_db is None:
                 self._alarm_db = self._alarm_database_cls(self)
 
@@ -216,7 +215,7 @@
 
         if device is None:
             device = OnuDeviceEntry(self, device_id, adapter_agent, custom_me_map,
-                                    self._mib_db, support_classes)
+                                    self._mib_db, self._alarm_db, support_classes)
 
             self._devices[device_id] = device
 
diff --git a/voltha/extensions/omci/state_machines/Alarm_sync.py b/voltha/extensions/omci/state_machines/Alarm_sync.py
index 6ad46c9..15c06d0 100644
--- a/voltha/extensions/omci/state_machines/Alarm_sync.py
+++ b/voltha/extensions/omci/state_machines/Alarm_sync.py
@@ -81,7 +81,7 @@
 
         :param agent: (OpenOmciAgent) Agent
         :param device_id: (str) ONU Device ID
-        :param db: (MibDbVolatileDict) MIB/Alarm Database
+        :param db: (MibDbApi) MIB/Alarm Database
         :param advertise_events: (bool) Advertise events on OpenOMCI Event Bus
         :param alarm_sync_tasks: (dict) Tasks to run
         :param states: (list) List of valid states
@@ -176,10 +176,11 @@
         return self._last_alarm_sequence_value
 
     @last_alarm_sequence.setter
-    def last_alarm_seuence(self, value):
-        self._last_alarm_sequence_value = value
-        if self._database is not None:
-            self._database.save_alarm_last_sync(self.device_id, value)
+    def last_alarm_sequence(self, value):
+        if self._last_alarm_sequence_value != value:
+            self._last_alarm_sequence_value = value
+            if self._database is not None:
+                self._database.save_alarm_last_sync(self.device_id, value)
 
     @property
     def last_alarm_sync_time(self):
@@ -251,7 +252,7 @@
                 except KeyError:
                     # Device already is in database
                     self.log.debug('seed-db-exist', device_id=self._device_id)
-                    self.last_alarm_sequence = \
+                    self._last_alarm_sequence_value = \
                         self._database.get_alarm_last_sync(self._device_id)
 
                 self._device_in_db = True
@@ -284,9 +285,9 @@
         except Exception as e:
             self.log.exception('dev-subscription-setup', e=e)
 
+        # Determine if this ONU has ever synchronized
         if self.is_updated_alarm:
             self._deferred = reactor.callLater(0, self.update_alarm)
-        # Determine if this ONU has ever synchronized
         else:
             self._deferred = reactor.callLater(0, self.sync_alarm)
 
@@ -300,8 +301,7 @@
             self.log.debug('alarm-update-success', results='the sequence_number is {}'.
                                                            format(results))
             self._current_task = None
-            # The new ONU is up, save the first updated alarm sequence number
-            self.last_alarm_sequence = results
+            # The new ONU is up
             self._deferred = reactor.callLater(0, self.success)
 
         def failure(reason):
@@ -320,8 +320,6 @@
         """
         self.advertise(AlarmOpenOmciEventType.state_change, self.state)
 
-        self.last_alarm_sequence = self._database.get_alarm_last_sync(self._device_id) or 0
-
         def success(sequence):
             self.log.debug('sync-alarm-success', sequence_value=sequence)
             self._current_task = None
@@ -347,8 +345,10 @@
         Schedule a tick to occur to in the future to request an audit
         """
         self.advertise(AlarmOpenOmciEventType.state_change, self.state)
-        self.last_alarm_sync_time = datetime.utcnow()
-        self._device.alarm_db_in_sync = True
+
+        if not self._device.alarm_db_in_sync:
+            self.last_alarm_sync_time = datetime.utcnow()
+            self._device.alarm_db_in_sync = True
 
         if self._audit_delay > 0:
             self._deferred = reactor.callLater(self._audit_delay, self.audit_alarm)
@@ -463,7 +463,7 @@
 
     def on_alarm_update_next_response(self, _topic, msg):
         """
-        Process a Alarm update Next response
+        Process a Get All Alarm Next response
 
         :param _topic: (str) OMCI-RX topic
         :param msg: (dict) Dictionary with 'rx-response' and 'tx-request' (if any)
@@ -507,7 +507,7 @@
 
     def on_alarm_update_response(self, _topic, msg):
         """
-        Process a Set response
+        Process a Get All Alarms response
 
         :param _topic: (str) OMCI-RX topic
         :param msg: (dict) Dictionary with 'rx-response' and 'tx-request' (if any)
@@ -523,22 +523,16 @@
                 omci_msg = response.fields['omci_message'].fields
                 class_id = omci_msg['entity_class']
                 entity_id = omci_msg['entity_id']
-                number_of_commands = omci_msg.fields['number_of_commands']
+                number_of_commands = omci_msg['number_of_commands']
 
-
-                self.last_alarm_sequence = number_of_commands
+                # ONU will reset its last alarm sequence number to 0 on receipt of the
+                # Get All Alarms request
+                self.last_alarm_sequence = 0
 
                 self.log.info('received alarm response',
                               class_id=class_id,
                               instance_id=entity_id,
                               number_of_commands=number_of_commands)
 
-                if class_id == OntData.class_id:
-                    return
-
-                # Save to the database
-                self._database.set(self._device_id, class_id, entity_id, number_of_commands)
-
-
-            except KeyError:
-                pass  # NOP
\ No newline at end of file
+            except Exception as e:
+                self.log.exception('upload-alarm-failure', e=e)
diff --git a/voltha/extensions/omci/tasks/alarm_check_task.py b/voltha/extensions/omci/tasks/alarm_check_task.py
index 9539996..d62d6ee 100644
--- a/voltha/extensions/omci/tasks/alarm_check_task.py
+++ b/voltha/extensions/omci/tasks/alarm_check_task.py
@@ -41,10 +41,10 @@
         :param entity_id: (int) ME entity ID
         """
         super(AlarmDataTask, self).__init__(AlarmDataTask.name,
-                                               omci_agent,
-                                               device_id,
-                                               priority=AlarmDataTask.task_priority,
-                                               exclusive=False)
+                                            omci_agent,
+                                            device_id,
+                                            priority=AlarmDataTask.task_priority,
+                                            exclusive=False)
         self._local_deferred = None
         self._class_id = class_id
         self._entity_id = entity_id
diff --git a/voltha/extensions/omci/tasks/alarm_sync_data.py b/voltha/extensions/omci/tasks/alarm_sync_data.py
index ed079dd..115ef9e 100644
--- a/voltha/extensions/omci/tasks/alarm_sync_data.py
+++ b/voltha/extensions/omci/tasks/alarm_sync_data.py
@@ -40,10 +40,10 @@
         :param device_id: (str) ONU Device ID
         """
         super(AlarmSyncDataTask, self).__init__(AlarmSyncDataTask.name,
-                                           omci_agent,
-                                           device_id,
-                                           priority=AlarmSyncDataTask.task_priority,
-                                           exclusive=False)
+                                                omci_agent,
+                                                device_id,
+                                                priority=AlarmSyncDataTask.task_priority,
+                                                exclusive=False)
         self._local_deferred = None
 
     def cancel_deferred(self):
@@ -88,8 +88,8 @@
 
             #########################################
             # ONU Data (ME #2)
-            # alarm_retrival_mode=1, time=DEFAULT_OMCI_TIMEOUT
-            results = yield device.omci_cc.send_get_all_alarm(alarm_retrival_mode=1)
+            # alarm_retrieval_mode=1, time=DEFAULT_OMCI_TIMEOUT
+            results = yield device.omci_cc.send_get_all_alarm(alarm_retrieval_mode=1)
             self.stop_if_not_running()
             command_sequence_number = results.fields['omci_message'].fields['number_of_commands']
 
@@ -114,7 +114,7 @@
                                       command_sequence_number=command_sequence_number)
                         if retry >= 2:
                             raise AlarmSyncDataFailure('Alarm timeout failure on req {} of {}'.
-                                                   format(seq_no + 1, command_sequence_number))
+                                                       format(seq_no + 1, command_sequence_number))
                         yield asleep(0.3)
                         self.stop_if_not_running()