VOL-720: Integrated OpenOMCI Alarms with the Alarm Manager/Kafka

Change-Id: Ifecee4420903f0d844822436b7e790c723c89adc
diff --git a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
index 4254bf9..146253d 100644
--- a/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
+++ b/voltha/adapters/brcm_openomci_onu/brcm_openomci_onu_handler.py
@@ -25,6 +25,7 @@
 from heartbeat import HeartBeat
 from voltha.extensions.kpi.onu.onu_pm_metrics import OnuPmMetrics
 from voltha.extensions.kpi.onu.onu_omci_pm import OnuOmciPmMetrics
+from voltha.extensions.alarms.adapter_alarms import AdapterAlarms
 
 from common.utils.indexpool import IndexPool
 import voltha.core.flow_decomposer as fd
@@ -71,6 +72,7 @@
         self.proxy_address = None
         self.tx_id = 0
         self._enabled = False
+        self.alarms = None
         self.pm_metrics = None
         self._omcc_version = OMCCVersion.Unknown
         self._total_tcont_count = 0  # From ANI-G ME
@@ -197,6 +199,12 @@
             self.log.info("initial-pm-config", pm_config=pm_config)
             self.adapter_agent.update_device_pm_config(pm_config, init=True)
 
+            ############################################################################
+            # Setup Alarm handler
+            self.alarms = AdapterAlarms(self.adapter_agent, device.id, self.logical_device_id)
+            # Note, ONU ID and UNI intf set in add_uni_port method
+            self._onu_omci_device.alarm_synchronizer.set_alarm_params(mgr=self.alarms,
+                                                                      ani_ports=[self._pon])
             self.enabled = True
         else:
             self.log.info('onu-already-activated')
@@ -877,6 +885,8 @@
 
         self._unis[uni_port.port_number] = uni_port
 
+        self._onu_omci_device.alarm_synchronizer.set_alarm_params(onu_id=self._onu_indication.onu_id,
+                                                                  uni_ports=self._unis.values())
         # TODO: this should be in the PonPortclass
         pon_port = self._pon.get_port()
         self.adapter_agent.delete_port_reference_from_parent(self.device_id,
diff --git a/voltha/extensions/alarms/onu/onu_equipment_alarm.py b/voltha/extensions/alarms/onu/onu_equipment_alarm.py
new file mode 100644
index 0000000..e7e3a7a
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_equipment_alarm.py
@@ -0,0 +1,45 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuEquipmentAlarm(AlarmBase):
+    """
+    The ONU Equipment Alarm is reported by both the CircuitPack (ME #6) and
+    the ONT-G (ME # 256) to indicate failure on an internal interface or
+    failed self-test.
+
+    For CircuitPack equipment alarms, the intf_id reported is that of the
+    UNI's logical port number
+
+    For ONT-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+
+    Note: Some ONUs may use this alarm to report a self-test failure or may
+          may report it with a different alarm number specifically for a
+          self-test failure.
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuEquipmentAlarm, self).__init__(alarm_mgr, object_type='onu equipment',
+                                                alarm='ONU_EQUIPMENT',
+                                                alarm_category=AlarmEventCategory.ONU,
+                                                alarm_type=AlarmEventType.EQUIPTMENT,
+                                                alarm_severity=AlarmEventSeverity.CRITICAL)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_high_rx_optical_power_alarm.py b/voltha/extensions/alarms/onu/onu_high_rx_optical_power_alarm.py
new file mode 100644
index 0000000..7b59d55
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_high_rx_optical_power_alarm.py
@@ -0,0 +1,37 @@
+# Copyright 2018 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuHighRxOpticalAlarm(AlarmBase):
+    """
+    The ONU High Tx Optical Power Alarm is reported by the ANI-G (ME # 263) to
+    indicate that the received downstream optical power above threshold..
+
+    For ANI-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuHighRxOpticalAlarm, self).__init__(alarm_mgr, object_type='onu high rx optical power',
+                                                    alarm='ONU_HIGH_RX_OPTICAL',
+                                                    alarm_category=AlarmEventCategory.ONU,
+                                                    alarm_type=AlarmEventType.COMMUNICATION,
+                                                    alarm_severity=AlarmEventSeverity.MAJOR)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_high_tx_optical_power_alarm.py b/voltha/extensions/alarms/onu/onu_high_tx_optical_power_alarm.py
new file mode 100644
index 0000000..64caefe
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_high_tx_optical_power_alarm.py
@@ -0,0 +1,37 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuHighTxOpticalAlarm(AlarmBase):
+    """
+    The ONU High Tx Optical Power Alarm is reported by the ANI-G (ME # 263) to
+    indicate that the received downstream optical power above upper threshold.
+
+    For ANI-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuHighTxOpticalAlarm, self).__init__(alarm_mgr, object_type='onu high tx optical power',
+                                                    alarm='ONU_HIGH_TX_OPTICAL',
+                                                    alarm_category=AlarmEventCategory.ONU,
+                                                    alarm_type=AlarmEventType.COMMUNICATION,
+                                                    alarm_severity=AlarmEventSeverity.MAJOR)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
\ No newline at end of file
diff --git a/voltha/extensions/alarms/onu/onu_laser_bias_current_alarm.py b/voltha/extensions/alarms/onu/onu_laser_bias_current_alarm.py
new file mode 100644
index 0000000..8daf5a6
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_laser_bias_current_alarm.py
@@ -0,0 +1,38 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuLaserBiasAlarm(AlarmBase):
+    """
+    The ONU Laser Bias Current Alarm is reported by the ANI-G (ME # 263) to
+    indicate that the laser bias current above threshold determined by
+    vendor and that laser end of life is pending
+
+    For ANI-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuLaserBiasAlarm, self).__init__(alarm_mgr, object_type='onu laser bias current',
+                                                alarm='ONU_LASER_BIAS_CURRENT',
+                                                alarm_category=AlarmEventCategory.ONU,
+                                                alarm_type=AlarmEventType.EQUIPTMENT,
+                                                alarm_severity=AlarmEventSeverity.MAJOR)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_laser_eol_alarm.py b/voltha/extensions/alarms/onu/onu_laser_eol_alarm.py
new file mode 100644
index 0000000..fa5039c
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_laser_eol_alarm.py
@@ -0,0 +1,36 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuLaserEolAlarm(AlarmBase):
+    """
+    The ONU Laser End-of-Lifer Alarm is reported by both the CircuitPack (ME #6)
+    to indicate that failure of transmit laser imminent
+
+    The intf_id reported is that of the UNI's logical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuLaserEolAlarm, self).__init__(alarm_mgr, object_type='onu laser EOL',
+                                               alarm='ONU_LASER_EOL',
+                                               alarm_category=AlarmEventCategory.ONU,
+                                               alarm_type=AlarmEventType.EQUIPTMENT,
+                                               alarm_severity=AlarmEventSeverity.MAJOR)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_low_rx_optical_power_alarm.py b/voltha/extensions/alarms/onu/onu_low_rx_optical_power_alarm.py
new file mode 100644
index 0000000..ee6f4d2
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_low_rx_optical_power_alarm.py
@@ -0,0 +1,37 @@
+# Copyright 2018 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuLowRxOpticalAlarm(AlarmBase):
+    """
+    The ONU Low Rx Optical Power Alarm is reported by the ANI-G (ME # 263) to
+    indicate that the received downstream optical power below threshold.
+
+    For ANI-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuLowRxOpticalAlarm, self).__init__(alarm_mgr, object_type='onu low rx optical power',
+                                                   alarm='ONU_LOW_RX_OPTICAL',
+                                                   alarm_category=AlarmEventCategory.ONU,
+                                                   alarm_type=AlarmEventType.COMMUNICATION,
+                                                   alarm_severity=AlarmEventSeverity.MAJOR)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_low_tx_optical_power_alarm.py b/voltha/extensions/alarms/onu/onu_low_tx_optical_power_alarm.py
new file mode 100644
index 0000000..e28a556
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_low_tx_optical_power_alarm.py
@@ -0,0 +1,37 @@
+# Copyright 2018 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuLowTxOpticalAlarm(AlarmBase):
+    """
+    The ONU Low Tx Optical Power Alarm is reported by the ANI-G (ME # 263) to
+    indicate that the transmit optical power below lower threshold
+
+    For ANI-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuLowTxOpticalAlarm, self).__init__(alarm_mgr, object_type='onu low tx optical power',
+                                                   alarm='ONU_LOW_TX_OPTICAL',
+                                                   alarm_category=AlarmEventCategory.ONU,
+                                                   alarm_type=AlarmEventType.COMMUNICATION,
+                                                   alarm_severity=AlarmEventSeverity.MAJOR)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_selftest_failure_alarm.py b/voltha/extensions/alarms/onu/onu_selftest_failure_alarm.py
new file mode 100644
index 0000000..c742762
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_selftest_failure_alarm.py
@@ -0,0 +1,44 @@
+# Copyright 2018 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuSelfTestFailureAlarm(AlarmBase):
+    """
+    The ONU Self Test Failure Alarm is reported by both the CircuitPack (ME #6)
+    and the ONT-G (ME # 256) to indicate failure a failed autonomous self-test.
+
+    For CircuitPack equipment alarms, the intf_id reported is that of the
+    UNI's logical port number
+
+    For ONT-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+
+    Note: Some ONUs may use this alarm to report a self-test failure or may
+          may report it with the ONU Equipment Alarm which can also cover a
+          self-test failure.
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuSelfTestFailureAlarm, self).__init__(alarm_mgr, object_type='onu self-test failure',
+                                                      alarm='ONU_SELF_TEST_FAIL',
+                                                      alarm_category=AlarmEventCategory.ONU,
+                                                      alarm_type=AlarmEventType.EQUIPTMENT,
+                                                      alarm_severity=AlarmEventSeverity.CRITICAL)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_temp_red_alarm.py b/voltha/extensions/alarms/onu/onu_temp_red_alarm.py
new file mode 100644
index 0000000..bfa1623
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_temp_red_alarm.py
@@ -0,0 +1,42 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuTempRedAlarm(AlarmBase):
+    """
+    The ONU Temperature Yellow Alarm is reported by both the CircuitPack
+    (ME #6) and the ONT-G (ME # 256) to indicate no service has been shut
+    down to avoid equipment damage. The operational state of the affected
+    PPTPs indicates the affected services.
+
+    For CircuitPack equipment alarms, the intf_id reported is that of the
+    UNI's logical port number
+
+    For ONT-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuTempRedAlarm, self).__init__(alarm_mgr, object_type='onu temperature red',
+                                              alarm='ONU_TEMP_RED',
+                                              alarm_category=AlarmEventCategory.ONU,
+                                              alarm_type=AlarmEventType.ENVIRONMENT,
+                                              alarm_severity=AlarmEventSeverity.CRITICAL)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_temp_yellow_alarm.py b/voltha/extensions/alarms/onu/onu_temp_yellow_alarm.py
new file mode 100644
index 0000000..7a28f81
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_temp_yellow_alarm.py
@@ -0,0 +1,41 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuTempYellowAlarm(AlarmBase):
+    """
+    The ONU Temperature Yellow Alarm is reported by both the CircuitPack
+    (ME #6) and the ONT-G (ME # 256) to indicate no service shutdown at
+    present, but the circuit pack is operating beyond its recommended range.
+
+    For CircuitPack equipment alarms, the intf_id reported is that of the
+    UNI's logical port number
+
+    For ONT-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuTempYellowAlarm, self).__init__(alarm_mgr, object_type='onu temperature yellow',
+                                                 alarm='ONU_TEMP_YELLOW',
+                                                 alarm_category=AlarmEventCategory.ONU,
+                                                 alarm_type=AlarmEventType.ENVIRONMENT,
+                                                 alarm_severity=AlarmEventSeverity.MAJOR)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_voltage_red_alarm.py b/voltha/extensions/alarms/onu/onu_voltage_red_alarm.py
new file mode 100644
index 0000000..506351c
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_voltage_red_alarm.py
@@ -0,0 +1,39 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuVoltageRedAlarm(AlarmBase):
+    """
+    The ONU Voltage Red Alarm is reported by the ONT-G (ME # 256) to
+    indicate some services have been shut down to avoid power collapse.
+    The operational state of the affected PPTPs indicates the affected
+    services.
+
+    For ONT-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuVoltageRedAlarm, self).__init__(alarm_mgr, object_type='onu voltage red',
+                                                 alarm='ONU_VOLTAGE_RED',
+                                                 alarm_category=AlarmEventCategory.ONU,
+                                                 alarm_type=AlarmEventType.COMMUNICATION,
+                                                 alarm_severity=AlarmEventSeverity.CRITICAL)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/alarms/onu/onu_voltage_yellow_alarm.py b/voltha/extensions/alarms/onu/onu_voltage_yellow_alarm.py
new file mode 100644
index 0000000..1bb3ef6
--- /dev/null
+++ b/voltha/extensions/alarms/onu/onu_voltage_yellow_alarm.py
@@ -0,0 +1,39 @@
+# Copyright 2017-present Adtran, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+from voltha.protos.events_pb2 import AlarmEventType, AlarmEventSeverity, AlarmEventCategory
+from voltha.extensions.alarms.adapter_alarms import AlarmBase
+
+
+class OnuVoltageYellowAlarm(AlarmBase):
+    """
+    The ONU Voltage Red Alarm is reported by the ONT-G (ME # 256) to
+    indicate some services have been shut down to avoid power collapse.
+    The operational state of the affected PPTPs indicates the affected
+    services.
+
+    For ONT-G equipment alarms, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, alarm_mgr, onu_id, intf_id):
+        super(OnuVoltageYellowAlarm, self).__init__(alarm_mgr, object_type='onu voltage yellow',
+                                                    alarm='ONU_VOLTAGE_YELLOW',
+                                                    alarm_category=AlarmEventCategory.ONU,
+                                                    alarm_type=AlarmEventType.COMMUNICATION,
+                                                    alarm_severity=AlarmEventSeverity.MAJOR)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id}
diff --git a/voltha/extensions/omci/database/alarm_db_ext.py b/voltha/extensions/omci/database/alarm_db_ext.py
index 699f9b7..2af6923 100644
--- a/voltha/extensions/omci/database/alarm_db_ext.py
+++ b/voltha/extensions/omci/database/alarm_db_ext.py
@@ -16,8 +16,6 @@
 from mib_db_api import *
 from voltha.protos.omci_alarm_db_pb2 import AlarmInstanceData, AlarmClassData, \
     AlarmDeviceData, AlarmAttributeData
-from voltha.extensions.omci.omci_entities import *
-from scapy.fields import StrField, FieldListField
 
 
 class AlarmDbExternal(MibDbApi):
@@ -25,6 +23,7 @@
     A persistent external OpenOMCI Alarm Database
     """
     CURRENT_VERSION = 1                       # VOLTHA v1.3.0 release
+    ALARM_BITMAP_KEY = 'alarm_bit_map'
 
     _TIME_FORMAT = '%Y%m%d-%H%M%S.%f'
 
@@ -33,8 +32,8 @@
     DEVICE_PATH = ALARM_PATH + '/{}'            # .format(device_id)
 
     # Classes, Instances, and Attributes as lists from root proxy
-    CLASSES_PATH = DEVICE_PATH + '/classes'                               # .format(device_id)
-    INSTANCES_PATH = DEVICE_PATH +'/classes/{}/instances'                 # .format(device_id, class_id)
+    CLASSES_PATH = DEVICE_PATH + '/classes'                                # .format(device_id)
+    INSTANCES_PATH = DEVICE_PATH + '/classes/{}/instances'                 # .format(device_id, class_id)
     ATTRIBUTES_PATH = DEVICE_PATH + '/classes/{}/instances/{}/attributes'  # .format(device_id, class_id, instance_id)
 
     # Single Class, Instance, and Attribute as objects from device proxy
@@ -85,76 +84,16 @@
     def _string_to_time(self, time):
         return datetime.strptime(time, AlarmDbExternal._TIME_FORMAT) if len(time) else None
 
-    def _attribute_to_string(self, device_id, class_id, attr_name, value):
+    def _attribute_to_string(self, value):
         """
         Convert an ME's attribute value to string representation
 
-        :param device_id: (str) ONU Device ID
-        :param class_id: (int) Class ID
-        :param attr_name: (str) Attribute Name (see EntityClasses)
-        :param value: (various) Attribute Value
-
+        :param value: (long) Alarm bitmaps are always a Long
         :return: (str) String representation of the value
-        :raises KeyError: Device, Class ID, or Attribute does not exist
         """
-        try:
-            me_map = self._omci_agent.get_device(device_id).me_map
+        return str(value)
 
-            if class_id in me_map:
-                entity = me_map[class_id]
-                attr_index = entity.attribute_name_to_index_map[attr_name]
-                eca = entity.attributes[attr_index]
-                field = eca.field
-            else:
-                # Here for auto-defined MEs (ones not defined in ME Map)
-                from voltha.extensions.omci.omci_cc import UNKNOWN_CLASS_ATTRIBUTE_KEY
-                field = StrFixedLenField(UNKNOWN_CLASS_ATTRIBUTE_KEY, None, 24)
-
-            if isinstance(field, StrFixedLenField):
-                from scapy.base_classes import Packet_metaclass
-                #  For StrFixedLenField, value is a str already (or possibly JSON encoded)
-                if hasattr(value, 'to_json'):
-                    # Packet Class to string
-                    str_value = value.to_json()
-                elif isinstance(field.default, Packet_metaclass) \
-                        and hasattr(field.default, 'json_from_value'):
-                    # Value/hex of Packet Class to string
-                    str_value = field.default.json_from_value(value)
-                else:
-                    str_value = str(value)
-
-            elif isinstance(field, (StrField, MACField, IPField)):
-                #  For StrField, value is an str already
-                #  For MACField, value is a string in ':' delimited form
-                #  For IPField, value is a string in '.' delimited form
-                str_value = str(value)
-
-            elif isinstance(field, (ByteField, ShortField, IntField, LongField)):
-                #  For ByteField, ShortField, IntField, and LongField value is an int
-                str_value = str(value)
-
-            elif isinstance(field, BitField):
-                # For BitField, value is a long
-                #
-                str_value = str(value)
-
-            elif isinstance(field, FieldListField):
-                str_value = json.dumps(value, separators=(',', ':'))
-
-            else:
-                self.log.warning('default-conversion', type=type(field),
-                                 class_id=class_id, attribute=attr_name, value=str(value))
-                str_value = str(value)
-
-            return str_value
-
-        except Exception as e:
-            self.log.exception('attr-to-string', device_id=device_id,
-                               class_id=class_id, attr=attr_name,
-                               value=value, e=e)
-            raise
-
-    def _string_to_attribute(self, device_id, class_id, attr_name, str_value):
+    def _string_to_attribute(self, str_value):
         """
         Convert an ME's attribute value-string to its Scapy decode equivalent
 
@@ -166,56 +105,8 @@
         :return: (various) String representation of the value
         :raises KeyError: Device, Class ID, or Attribute does not exist
         """
-        try:
-            me_map = self._omci_agent.get_device(device_id).me_map
-
-            if class_id in me_map:
-                entity = me_map[class_id]
-                attr_index = entity.attribute_name_to_index_map[attr_name]
-                eca = entity.attributes[attr_index]
-                field = eca.field
-            else:
-                # Here for auto-defined MEs (ones not defined in ME Map)
-                from voltha.extensions.omci.omci_cc import UNKNOWN_CLASS_ATTRIBUTE_KEY
-                field = StrFixedLenField(UNKNOWN_CLASS_ATTRIBUTE_KEY, None, 24)
-
-            if isinstance(field, StrFixedLenField):
-                from scapy.base_classes import Packet_metaclass
-                if isinstance(field.default, Packet_metaclass) and \
-                        hasattr(field.default, 'to_json'):
-                    value = json.loads(str_value)
-                else:
-                    value = str_value
-
-            elif isinstance(field, MACField):
-                value = str_value
-
-            elif isinstance(field, IPField):
-                value = str_value
-
-            elif isinstance(field, (ByteField, ShortField, IntField, LongField)):
-                if str_value.lower() in ('true', 'false'):
-                    str_value = '1' if str_value.lower() == 'true' else '0'
-                value = int(str_value)
-
-            elif isinstance(field, BitField):
-                value = long(str_value)
-
-            elif isinstance(field, FieldListField):
-                value = json.loads(str_value)
-
-            else:
-                self.log.warning('default-conversion', type=type(field),
-                                 class_id=class_id, attribute=attr_name, value=str_value)
-                value = None
-
-            return value
-
-        except Exception as e:
-            self.log.exception('attr-to-string', device_id=device_id,
-                               class_id=class_id, attr=attr_name,
-                               value=str_value, e=e)
-            raise
+        # Alarms are always a bitmap which is a long
+        return long(str_value) if len(str_value) else 0L
 
     def add(self, device_id, overwrite=False):
         """
@@ -505,15 +396,12 @@
 
         now = self._time_to_string(datetime.utcnow())
         attrs = [AlarmAttributeData(name=k,
-                                  value=self._attribute_to_string(device_id,
-                                                                  class_id,
-                                                                  k,
-                                                                  v)) for k, v in attributes.items()]
+                                    value=self._attribute_to_string(v)) for k, v in attributes.items()]
         class_data = AlarmClassData(class_id=class_id,
-                                  instances=[AlarmInstanceData(instance_id=instance_id,
-                                                             created=now,
-                                                             modified=now,
-                                                             attributes=attrs)])
+                                    instances=[AlarmInstanceData(instance_id=instance_id,
+                                                                 created=now,
+                                                                 modified=now,
+                                                                 attributes=attrs)])
 
         self._root_proxy.add(AlarmDbExternal.CLASSES_PATH.format(device_id), class_data)
         self.log.debug('set-complete', device_id=device_id, class_id=class_id,
@@ -537,14 +425,11 @@
 
         now = self._time_to_string(datetime.utcnow())
         attrs = [AlarmAttributeData(name=k,
-                                  value=self._attribute_to_string(device_id,
-                                                                  class_id,
-                                                                  k,
-                                                                  v)) for k, v in attributes.items()]
+                                    value=self._attribute_to_string(v)) for k, v in attributes.items()]
         instance_data = AlarmInstanceData(instance_id=instance_id,
-                                        created=now,
-                                        modified=now,
-                                        attributes=attrs)
+                                          created=now,
+                                          modified=now,
+                                          attributes=attrs)
 
         self._root_proxy.add(AlarmDbExternal.INSTANCES_PATH.format(device_id, class_id),
                              instance_data)
@@ -609,11 +494,12 @@
                     exist_attr_indexes[inst_data.attributes[index].name] = index
 
                 modified = False
+                str_value = ''
                 new_attributes = []
 
                 for k, v in attributes.items():
                     try:
-                        str_value = self._attribute_to_string(device_id, class_id, k, v)
+                        str_value = self._attribute_to_string(v)
                         new_attributes.append(AlarmAttributeData(name=k, value=str_value))
 
                     except Exception as e:
@@ -627,12 +513,12 @@
                 if modified:
                     now = datetime.utcnow()
                     new_data = AlarmInstanceData(instance_id=instance_id,
-                                               created=inst_data.created,
-                                               modified=self._time_to_string(now),
-                                               attributes=new_attributes)
+                                                 created=inst_data.created,
+                                                 modified=self._time_to_string(now),
+                                                 attributes=new_attributes)
                     dev_proxy.remove(AlarmDbExternal.INSTANCE_PATH.format(class_id, instance_id))
                     self._root_proxy.add(AlarmDbExternal.INSTANCES_PATH.format(device_id,
-                                                                             class_id), new_data)
+                                                                               class_id), new_data)
 
                 self.log.debug('set-complete', device_id=device_id, class_id=class_id,
                                entity_id=instance_id, attributes=attributes, modified=modified)
@@ -728,7 +614,7 @@
                 # Get all instances of the class
                 try:
                     cls_data = self._class_proxy(device_id, class_id).get('/', depth=-1)
-                    data = self._class_to_dict(device_id, cls_data)
+                    data = self._class_to_dict(cls_data)
 
                 except KeyError:
                     data = dict()
@@ -741,7 +627,7 @@
 
                     if attributes is None:
                         # All Attributes
-                        data = self._instance_to_dict(device_id, class_id, inst_data)
+                        data = self._instance_to_dict(inst_data)
 
                     else:
                         # Specific attribute(s)
@@ -749,10 +635,7 @@
                             attributes = {attributes}
 
                         data = {
-                            attr.name: self._string_to_attribute(device_id,
-                                                                 class_id,
-                                                                 attr.name,
-                                                                 attr.value)
+                            attr.name: self._string_to_attribute(attr.value)
                             for attr in inst_data.attributes if attr.name in attributes}
 
                 except KeyError:
@@ -768,7 +651,7 @@
             self.log.exception('get-last-sync-exception', device_id=device_id, e=e)
             raise
 
-    def _instance_to_dict(self, device_id, class_id, instance):
+    def _instance_to_dict(self, instance):
         if not isinstance(instance, AlarmInstanceData):
             raise TypeError('{} is not of type AlarmInstanceData'.format(type(instance)))
 
@@ -779,13 +662,10 @@
             ATTRIBUTES_KEY: dict()
         }
         for attribute in instance.attributes:
-            data[ATTRIBUTES_KEY][attribute.name] = self._string_to_attribute(device_id,
-                                                                             class_id,
-                                                                             attribute.name,
-                                                                             attribute.value)
+            data[ATTRIBUTES_KEY][attribute.name] = self._string_to_attribute(attribute.value)
         return data
 
-    def _class_to_dict(self, device_id, val):
+    def _class_to_dict(self, val):
         if not isinstance(val, AlarmClassData):
             raise TypeError('{} is not of type AlarmClassData'.format(type(val)))
 
@@ -793,9 +673,7 @@
             CLASS_ID_KEY: val.class_id,
         }
         for instance in val.instances:
-            data[instance.instance_id] = self._instance_to_dict(device_id,
-                                                                val.class_id,
-                                                                instance)
+            data[instance.instance_id] = self._instance_to_dict(instance)
         return data
 
     def _device_to_dict(self, val):
@@ -810,8 +688,7 @@
             MSG_TYPE_KEY: set()
         }
         for class_data in val.classes:
-            data[class_data.class_id] = self._class_to_dict(val.device_id,
-                                                            class_data)
+            data[class_data.class_id] = self._class_to_dict(class_data)
         for managed_entity in val.managed_entities:
             data[ME_KEY][managed_entity.class_id] = managed_entity.name
 
@@ -819,9 +696,3 @@
             data[MSG_TYPE_KEY].add(msg_type.message_type)
 
         return data
-
-    def _managed_entity_to_name(self, device_id, class_id):
-        me_map = self._omci_agent.get_device(device_id).me_map
-        entity = me_map.get(class_id)
-
-        return entity.__name__ if entity is not None else 'UnknownManagedEntity'
diff --git a/voltha/extensions/omci/database/mib_db_ext.py b/voltha/extensions/omci/database/mib_db_ext.py
index e12331f..0e1857a 100644
--- a/voltha/extensions/omci/database/mib_db_ext.py
+++ b/voltha/extensions/omci/database/mib_db_ext.py
@@ -167,8 +167,8 @@
                     # Packet Class to string
                     str_value = value.to_json()
                 elif isinstance(field.default, Packet_metaclass) \
-                        and hasattr(field.default, 'json_from_value')\
-                        and not isinstance(value, basestring):
+                        and hasattr(field.default, 'json_from_value'):
+                        #and not isinstance(value, basestring):
                     # Value/hex of Packet Class to string
                     str_value = field.default.json_from_value(value)
                 else:
@@ -382,7 +382,7 @@
 
         except KeyError:
             if not create:
-                self.log.error('class-proxy-does-not-exist', device_id=device_id,
+                self.log.debug('class-proxy-does-not-exist', device_id=device_id,
                                class_id=class_id)
                 raise
 
diff --git a/voltha/extensions/omci/omci_entities.py b/voltha/extensions/omci/omci_entities.py
index fa4f33a..bf47f8e 100644
--- a/voltha/extensions/omci/omci_entities.py
+++ b/voltha/extensions/omci/omci_entities.py
@@ -138,6 +138,7 @@
     mandatory_operations = set()
     optional_operations = set()
     notifications = set()
+    alarms = dict()       # Alarm Number -> Alarm Name
     hidden = False        # If true, this attribute is not reported by a MIB upload.
                           # This attribute is needed to be able to properly perform
                           # MIB Audits.
@@ -259,6 +260,13 @@
     ]
     mandatory_operations = {OP.Get, OP.Set}
     notifications = {OP.AttributeValueChange, OP.AlarmNotification}
+    alarms = {
+        0: 'Plug-in circuit pack missing',
+        1: 'Plug-in type mismatch alarm',
+        2: 'Improper card removal',
+        3: 'Plug-in equipment ID mismatch alarm',
+        4: 'Protection switch',
+    }
 
 
 class CircuitPack(EntityClass):
@@ -290,7 +298,14 @@
     mandatory_operations = {OP.Get, OP.Set, OP.Reboot}
     optional_operations = {OP.Create, OP.Delete, OP.Test}
     notifications = {OP.AttributeValueChange, OP.AlarmNotification}
-
+    alarms = {
+        0: 'Equipment alarm',
+        1: 'Powering alarm',
+        2: 'Self-test failure',
+        3: 'Laser end of life',
+        4: 'Temperature yellow',
+        5: 'Temperature red',
+    }
 
 class SoftwareImage(EntityClass):
     class_id = 7
@@ -347,6 +362,9 @@
     ]
     mandatory_operations = {OP.Get, OP.Set}
     notifications = {OP.AttributeValueChange, OP.AlarmNotification}
+    alarms = {
+        0: 'LAN Loss Of Signal',
+    }
 
 
 class MacBridgeServiceProfile(EntityClass):
@@ -403,6 +421,9 @@
     ]
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        0: 'Port blocking',
+    }
 
 
 class MacBridgePortFilterPreAssignTable(EntityClass):
@@ -431,7 +452,6 @@
             range_check=lambda x: 0 <= x <= 1)
     ]
     mandatory_operations = {OP.Get, OP.Set}
-    notifications = {OP.AlarmNotification}
 
 
 class VlanTaggingFilterData(EntityClass):
@@ -653,6 +673,24 @@
         OP.Get, OP.Set, OP.Reboot, OP.Test, OP.SynchronizeTime}
     notifications = {OP.TestResult, OP.AttributeValueChange,
                      OP.AlarmNotification}
+    alarms = {
+        0: 'Equipment alarm',
+        1: 'Powering alarm',
+        2: 'Battery missing',
+        3: 'Battery failure',
+        4: 'Battery low',
+        5: 'Physical intrusion',
+        6: 'Self-test failure',
+        7: 'Dying gasp',
+        8: 'Temperature yellow',
+        9: 'Temperature red',
+        10: 'Voltage yellow',
+        11: 'Voltage red',
+        12: 'ONU manual power off',
+        13: 'Invalid image',
+        14: 'PSE overload yellow',
+        15: 'PSE overload red',
+    }
 
 
 class Ont2G(EntityClass):
@@ -722,6 +760,15 @@
     ]
     mandatory_operations = {OP.Get, OP.Set, OP.Test}
     notifications = {OP.AttributeValueChange, OP.AlarmNotification}
+    alarms = {
+        0: 'Low received optical power',
+        1: 'High received optical power',
+        2: 'Signal fail',
+        3: 'Signal degrade',
+        4: 'Low transmit optical power',
+        5: 'High transmit optical power',
+        6: 'Laser bias current',
+    }
 
 
 class UniG(EntityClass):
@@ -759,6 +806,9 @@
     ]
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set}
     notifications = {OP.AttributeValueChange, OP.AlarmNotification}
+    alarms = {
+        6: 'Operational state change',
+    }
 
 
 class GemPortNetworkCtp(EntityClass):
@@ -784,6 +834,9 @@
     ]
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        5: 'End-to-end loss of continuity',
+    }
 
 
 class GalEthernetProfile(EntityClass):
@@ -823,6 +876,9 @@
     ]
     mandatory_operations = {OP.Get, OP.Set}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        0: 'Block loss',
+    }
 
 
 class TrafficSchedulerG(EntityClass):
@@ -861,6 +917,9 @@
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.GetNext, OP.Set}
     optional_operations = {OP.SetTable}
     notifications = {OP.AttributeValueChange, OP.AlarmNotification}
+    alarms = {
+        0: 'Deprecated',
+    }
 
 
 class AccessControlRow0(Packet):
@@ -965,6 +1024,9 @@
     mandatory_operations = {OP.Create, OP.Delete, OP.Set, OP.Get, OP.GetNext}
     optional_operations = {OP.SetTable}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        0: 'Lost multicast group',
+    }
 
 
 class MulticastServicePackage(Packet):
@@ -1060,6 +1122,9 @@
     ]
     mandatory_operations = {OP.Get, OP.Set}
     notifications = {OP.AttributeValueChange, OP.AlarmNotification}
+    alarms = {
+        0: 'Connecting function fail',
+    }
 
 
 class Omci(EntityClass):
@@ -1147,6 +1212,22 @@
     ]
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set, OP.GetCurrentData}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        0: 'FCS errors',
+        1: 'Excessive collision counter',
+        2: 'Late collision counter',
+        3: 'Frames too long',
+        4: 'Buffer overflows on receive',
+        5: 'Buffer overflows on transmit',
+        6: 'Single collision frame counter',
+        7: 'Multiple collision frame counter',
+        8: 'SQE counter',
+        9: 'Deferred transmission counter',
+        10: 'Internal MAC transmit error counter',
+        11: 'Carrier sense error counter',
+        12: 'Alignment error counter',
+        13: 'Internal MAC receive error counter',
+    }
 
 
 class FecPerformanceMonitoringHistoryData(EntityClass):
@@ -1164,6 +1245,12 @@
     ]
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set, OP.GetCurrentData}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        0: 'Corrected bytes',
+        1: 'Corrected code words',
+        2: 'Uncorrectable code words',
+        4: 'FEC seconds',
+    }
 
 
 class EthernetFrameDownstreamPerformanceMonitoringHistoryData(EntityClass):
@@ -1190,6 +1277,12 @@
     ]
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set, OP.GetCurrentData}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        0: 'Drop events',
+        1: 'CRC errored packets',
+        2: 'Undersize packets',
+        3: 'Oversize packets',
+    }
 
 
 class EthernetFrameUpstreamPerformanceMonitoringHistoryData(EntityClass):
@@ -1216,6 +1309,12 @@
     ]
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set, OP.GetCurrentData}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        0: 'Drop events',
+        1: 'CRC errored packets',
+        2: 'Undersize packets',
+        3: 'Oversize packets',
+    }
 
 
 class VeipUni(EntityClass):
@@ -1233,6 +1332,9 @@
     ]
     mandatory_operations = {OP.Get, OP.Set}
     notifications = {OP.AttributeValueChange, OP.AlarmNotification}
+    alarms = {
+        0: 'Connecting function fail'
+    }
 
 
 class EthernetFrameExtendedPerformanceMonitoring(EntityClass):
@@ -1269,6 +1371,12 @@
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set}
     optional_operations = {OP.GetCurrentData}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        0: 'Drop events',
+        1: 'CRC errored packets',
+        2: 'Undersize packets',
+        3: 'Oversize packets',
+    }
 
 
 class EthernetFrameExtendedPerformanceMonitoring64Bit(EntityClass):
@@ -1305,6 +1413,12 @@
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set}
     optional_operations = {OP.GetCurrentData}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        0: 'Drop events',
+        1: 'CRC errored packets',
+        2: 'Undersize packets',
+        3: 'Oversize packets',
+    }
 
 
 class GemPortNetworkCtpMonitoringHistoryData(EntityClass):
@@ -1322,6 +1436,9 @@
     ]
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set, OP.GetCurrentData}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        1: 'Encryption key errors',
+    }
 
 
 class XgPonTcPerformanceMonitoringHistoryData(EntityClass):
@@ -1343,6 +1460,14 @@
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set}
     optional_operations = {OP.GetCurrentData}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        1: 'PSBd HEC error count',
+        2: 'XGTC HEC error count',
+        3: 'Unknown profile count',
+        4: 'XGEM HEC loss count',
+        5: 'XGEM key errors',
+        6: 'XGEM HEC error count',
+    }
 
 
 class XgPonDownstreamPerformanceMonitoringHistoryData(EntityClass):
@@ -1370,6 +1495,10 @@
     mandatory_operations = {OP.Create, OP.Delete, OP.Get, OP.Set}
     optional_operations = {OP.GetCurrentData}
     notifications = {OP.AlarmNotification}
+    alarms = {
+        1: 'PLOAM MIC error count',
+        2: 'OMCI MIC error count',
+    }
 
 
 class XgPonUpstreamPerformanceMonitoringHistoryData(EntityClass):
diff --git a/voltha/extensions/omci/omci_messages.py b/voltha/extensions/omci/omci_messages.py
index 0fb2125..b836199 100644
--- a/voltha/extensions/omci/omci_messages.py
+++ b/voltha/extensions/omci/omci_messages.py
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 import structlog
-from scapy.fields import ByteField, StrFixedLenField, ConditionalField, Field
+from scapy.fields import ByteField, ThreeBytesField, ConditionalField, Field
 from scapy.fields import ShortField, BitField
 from scapy.packet import Packet
 
@@ -306,6 +306,7 @@
         ShortField("entity_class", None),
         ShortField("entity_id", 0),
         BitField("alarm_bit_map", 0, 224),
+        ThreeBytesField("zero_padding", 0),
         ByteField("alarm_sequence_number", None)
     ]
 
diff --git a/voltha/extensions/omci/onu_device_entry.py b/voltha/extensions/omci/onu_device_entry.py
index 8ddfe87..0d07522 100644
--- a/voltha/extensions/omci/onu_device_entry.py
+++ b/voltha/extensions/omci/onu_device_entry.py
@@ -288,8 +288,7 @@
             topic = OnuDeviceEntry.event_bus_topic(self.device_id,
                                                    OnuDeviceEvents.AlarmDatabaseSyncEvent)
             msg = {
-                IN_SYNC_KEY: self._alarm_db_in_sync,
-                LAST_IN_SYNC_KEY: self.alarm_synchronizer.last_alarm_sync_time
+                IN_SYNC_KEY: self._alarm_db_in_sync
             }
             self.event_bus.publish(topic=topic, msg=msg)
 
diff --git a/voltha/extensions/omci/state_machines/alarm_sync.py b/voltha/extensions/omci/state_machines/alarm_sync.py
index ea30b74..dee6d83 100644
--- a/voltha/extensions/omci/state_machines/alarm_sync.py
+++ b/voltha/extensions/omci/state_machines/alarm_sync.py
@@ -17,15 +17,20 @@
 from datetime import datetime
 from transitions import Machine
 from twisted.internet import reactor
-from voltha.extensions.omci.omci_defs import ReasonCodes
+from voltha.extensions.omci.omci_defs import ReasonCodes, EntityOperations
 from voltha.extensions.omci.omci_cc import OmciCCRxEvents, OMCI_CC, RX_RESPONSE_KEY
 from voltha.extensions.omci.omci_messages import OmciGetAllAlarmsResponse
 from voltha.extensions.omci.omci_frame import OmciFrame
+from voltha.extensions.omci.database.alarm_db_ext import AlarmDbExternal
+from voltha.extensions.omci.database.mib_db_api import ATTRIBUTES_KEY
+from voltha.extensions.omci.omci_entities import CircuitPack, PptpEthernetUni, OntG, AniG
+
 from common.event_bus import EventBusClient
 from voltha.protos.omci_alarm_db_pb2 import AlarmOpenOmciEventType
 
 RxEvent = OmciCCRxEvents
 RC = ReasonCodes
+OP = EntityOperations
 
 
 class AlarmSynchronizer(object):
@@ -50,7 +55,7 @@
         {'trigger': 'stop', 'source': '*', 'dest': 'disabled'},
     ]
     DEFAULT_TIMEOUT_RETRY = 15     # Seconds to delay after task failure/timeout
-    DEFAULT_AUDIT_DELAY = 0        # 300      # Periodic tick to audit the ONU's alarm table
+    DEFAULT_AUDIT_DELAY = 180      # Periodic tick to audit the ONU's alarm table
 
     def __init__(self, agent, device_id, alarm_sync_tasks, db,
                  advertise_events=False,
@@ -87,14 +92,16 @@
         self._audit_delay = audit_delay
         self._resync_task = alarm_sync_tasks['alarm-resync']
         self._advertise_events = advertise_events
+        self._alarm_manager = None
+        self._onu_id = None
+        self._uni_ports = list()
+        self._ani_ports = list()
 
         self._deferred = None
         self._current_task = None
         self._task_deferred = None
-        self._last_alarm_sequence_value = None
+        self._last_alarm_sequence_value = 0
         self._device_in_db = False
-        # self._alarm_bit_map_notification = dict()
-        # self._alarm_sequence_number_notification = dict()
 
         self._event_bus = EventBusClient()
         self._omci_cc_subscriptions = {               # RxEvent.enum -> Subscription Object
@@ -178,6 +185,21 @@
                                       'time': str(datetime.utcnow())
                                   })
 
+    def set_alarm_params(self, mgr=None, onu_id=None, uni_ports=None, ani_ports=None):
+        if mgr is not None:
+            self._alarm_manager = mgr
+
+        if onu_id is not None:
+            self._onu_id = onu_id
+
+        if uni_ports is not None:
+            assert isinstance(uni_ports, list)
+            self._uni_ports = uni_ports
+
+        if ani_ports is not None:
+            assert isinstance(ani_ports, list)
+            self._ani_ports = ani_ports
+
     def on_enter_disabled(self):
         """
         State machine is being stopped
@@ -288,24 +310,78 @@
         onu_only = results['onu-only']
         olt_only = results['olt-only']
         attr_diffs = results['attr-diffs']
+        onu_db = results['onu-db']
+        olt_db = results['olt-db']
+
+        if any(item is not None for item in (onu_only, olt_only, attr_diffs)):
+            self._device.alarm_db_in_sync = False
 
         # Compare the differences.  During upload, if there are no alarms at all,
         # then the ONU alarm table retrieved may be empty (instead of MEs with all
         # bits cleared) depending upon the ONU's OMCI Stack.
 
         if onu_only is not None:
-            pass
-            # ONU only alarms will typically occur when doing the first audit as our
-            # database is clear and we are seeding the alarm table. Save the entries
-            # and if any are set, we need to raise that alarm.
-            #
-            # self._database.set(self._device_id, class_id, entity_id, alarm_bit_map)
+            self.process_onu_only_diffs(onu_only, onu_db)
 
         if olt_only is not None:
-            pass
+            self.process_olt_only_diffs(olt_only)
 
         if attr_diffs is not None:
-            pass
+            self.process_attr_diffs(attr_diffs, olt_db, onu_db)
+
+    def process_onu_only_diffs(self, onu_only, onu_db):
+        """
+        ONU only alarms will typically occur when doing the first audit as our
+        database is clear and we are seeding the alarm table. Save the entries
+        and if any are set, we need to raise that alarm.
+
+        :param onu_only: (list) Tuples with [0]=class ID, [1]=entity ID
+        :param onu_db: (dict) ONU Alarm database from the alarm audit upload
+        """
+        for cid_eid in onu_only:
+            class_id = cid_eid[0]
+            entity_id = cid_eid[1]
+            try:
+                bitmap = onu_db[class_id][entity_id][ATTRIBUTES_KEY][AlarmDbExternal.ALARM_BITMAP_KEY]
+                self.process_alarm_data(class_id, entity_id, bitmap, -1)
+
+            except KeyError as e:
+                self.log.error('alarm-not-found', class_id=class_id, entity_id=entity_id, e=e)
+
+    def process_olt_only_diffs(self, olt_only):
+        """
+        OLT only alarms may occur if the alarm(s) are no longer active on the ONU
+        and the notification was missed. Process this by sending a cleared bitmap
+        for any alarm in the OLT database only
+
+        :param olt_only: (list) Tuples with [0]=class ID, [1]=entity ID
+        """
+        for cid_eid in olt_only:
+            # First process the alarm clearing
+            self.process_alarm_data(cid_eid[0], cid_eid[1], 0, -1)
+            # Now remove from alarm DB so we match the ONU alarm table
+            self._database.delete(self._device_id, cid_eid[0], cid_eid[1])
+
+    def process_attr_diffs(self, attr_diffs, onu_db):
+        """
+        Mismatch in alarm settings. Note that the attribute should always be the
+        alarm bitmap attribute (long).  For differences, the ONU is always right
+
+        :param attr_diffs: (list(int,int,str)) [0]=class ID, [1]=entity ID, [1]=attr
+        :param olt_db: (dict) OLT Alarm database snapshot from the alarm audit
+        :param onu_db: (dict) ONU Alarm database from the alarm audit upload
+        """
+        for cid_eid_attr in attr_diffs:
+            class_id = cid_eid_attr[0]
+            entity_id = cid_eid_attr[1]
+
+            try:
+                assert AlarmDbExternal.ALARM_BITMAP_KEY == cid_eid_attr[2]
+                bitmap = onu_db[class_id][entity_id][ATTRIBUTES_KEY][AlarmDbExternal.ALARM_BITMAP_KEY]
+                self.process_alarm_data(class_id, entity_id, bitmap, -1)
+
+            except KeyError as e:
+                self.log.error('alarm-not-found', class_id=class_id, entity_id=entity_id, e=e)
 
     def on_alarm_update_response(self, _topic, msg):
         """
@@ -347,23 +423,82 @@
 
         alarm_msg = msg.get(RX_RESPONSE_KEY)
         if alarm_msg is not None:
-            # TODO: Process alarm
-            #       decode message, note that the seq number should never
-            #       be zero.
+            omci_msg = alarm_msg.fields['omci_message'].fields
+            class_id = omci_msg['entity_class']
+            seq_no = omci_msg['alarm_sequence_number']
 
+            # Validate that this ME supports alarm notifications
+            if class_id not in self._device.me_map or \
+                    OP.AlarmNotification not in self._device.me_map[class_id].notifications or \
+                    len(self._device.me_map[class_id].alarms) == 0:
+                self.log.warn('invalid-alarm-notification', class_id=class_id)
+                return
+
+            self.process_alarm_data(class_id,
+                                    omci_msg['entity_id'],
+                                    omci_msg['alarm_bit_map'],
+                                    seq_no)
+
+    def process_alarm_data(self, class_id, entity_id, bitmap, msg_seq_no):
+        """
+        Process new alarm data
+
+        :param class_id: (int)  Class ID of alarm
+        :param entity_id: (int) Entity ID of alarm
+        :param bitmap: (long) Alarm bitmap value
+        :param msg_seq_no: (int) Alarm sequence number. -1 if generated during an audit
+        """
+        if msg_seq_no > 0:
             # increment alarm number & compare to alarm # in message
+            # Signal early audit if no match and audits are enabled
             self.increment_alarm_sequence()
 
-            # Signal early audit if no match and audits are enabled
-            # if self.last_alarm_sequence != msg_seq_no and self._audit_delay > 0:
-            #     self._deferred = reactor.callLater(0, self.audit_alarm)
+            if self.last_alarm_sequence != msg_seq_no and self._audit_delay > 0:
+                self._deferred = reactor.callLater(0, self.audit_alarm)
 
-            # update alarm table/db (compare current db with alarm msg)
-            # notify ONU Device Handler, ...
-            pass
-            #  Note that right now we do not alarm anyone or save it to the database, so
-            #  if we can create (or clear) an alarm on the ONU, then the audit logic
-            #  should detect the difference. So we can test the audit that way.
+        key = AlarmDbExternal.ALARM_BITMAP_KEY
+        prev_entry = self._database.query(class_id, entity_id)
+        prev_bitmap = 0 if len(prev_entry) == 0 else long(prev_entry(key, '0'))
+
+        # Save current entry before going on
+        try:
+            self._database.set(self._device_id, class_id, entity_id, {key: bitmap})
+
+        except Exception as e:
+            self.log.exception('alarm-save-failure', class_id=class_id,
+                               entity_id=entity_id, value=bitmap, e=e)
+
+        if self._alarm_manager is not None:
+            # Generate a set of alarm number that are raised in current and previous
+            previously_raised = {alarm_no for alarm_no in xrange(224)
+                                 if prev_bitmap & (1L << (223-alarm_no)) != 0L}
+
+            currently_raised = {alarm_no for alarm_no in xrange(224)
+                                if bitmap & (1L << (223-alarm_no)) != 0L}
+
+            newly_cleared = previously_raised - currently_raised
+            newly_raised = currently_raised - previously_raised
+
+            # Generate the set/clear alarms now
+            for alarm_number in newly_cleared:
+                reactor.callLater(0, self.clear_alarm, class_id, entity_id, alarm_number)
+
+            for alarm_number in newly_raised:
+                reactor.callLater(0, self.raise_alarm, class_id, entity_id, alarm_number)
+
+    def get_alarm_description(self, class_id, alarm_number):
+        """
+        Get the alarm description, both as a printable-string and also a CamelCase value
+        """
+        if alarm_number in self._device.me_map[class_id].alarms:
+            description = self._device.me_map[class_id].alarms[alarm_number]
+        elif alarm_number <= 207:
+            description = 'Reserved alarm {}'.format(alarm_number)
+        else:
+            description = 'Vendor specific alarm {}'.format(alarm_number)
+
+        # For CamelCase, replace hyphens with spaces before camel casing the string
+        return description, description.replace('-', ' ').title().replace(' ', '')
 
     def raise_alarm(self, class_id, entity_id, alarm_number):
         """
@@ -373,7 +508,15 @@
         :param entity_id: (int) Entity ID of the Alarm
         :param alarm_number: (int) Alarm number (bit) that is alarmed
         """
-        pass            # TODO: Implement this
+        description, name = self.get_alarm_description(class_id, alarm_number)
+
+        self.log.warn('alarm-set', class_id=class_id, entity_id=entity_id,
+                      alarm_number=alarm_number, name=name, description=description)
+
+        if self._alarm_manager is not None:
+            alarm = self.omci_alarm_to_onu_alarm(class_id, entity_id, alarm_number)
+            if alarm is not None:
+                alarm.raise_alarm()
 
     def clear_alarm(self, class_id, entity_id, alarm_number):
         """
@@ -383,7 +526,15 @@
         :param entity_id: (int) Entity ID of the Alarm
         :param alarm_number: (int) Alarm number (bit) that is alarmed
         """
-        pass            # TODO: Implement this
+        description, name = self.get_alarm_description(class_id, alarm_number)
+
+        self.log.info('alarm-cleared', class_id=class_id, entity_id=entity_id,
+                      alarm_number=alarm_number, name=name, description=description)
+
+        if self._alarm_manager is not None:
+            alarm = self.omci_alarm_to_onu_alarm(class_id, entity_id, alarm_number)
+            if alarm is not None:
+                alarm.clear_alarm()
 
     def query_mib(self, class_id=None, instance_id=None):
         """
@@ -406,3 +557,110 @@
             raise DatabaseStateError('Database does not yet exist')
 
         return self._database.query(self._device_id, class_id=class_id, instance_id=instance_id)
+
+    def omci_alarm_to_onu_alarm(self, class_id, entity_id, alarm_number):
+        """
+        Map an OMCI Alarm Notification alarm to the proper ONU Alarm Library alarm
+
+        :param class_id: (int) ME Class ID
+        :param entity_id: (int) ME Class instance ID
+        :param alarm_number: (int) Alarm Number
+        :return: (AlarmBase) Alarm library alarm or None if not supported/found
+        """
+        from voltha.extensions.alarms.onu.onu_dying_gasp_alarm import OnuDyingGaspAlarm
+        from voltha.extensions.alarms.onu.onu_los_alarm import OnuLosAlarm
+        from voltha.extensions.alarms.onu.onu_equipment_alarm import OnuEquipmentAlarm
+        from voltha.extensions.alarms.onu.onu_selftest_failure_alarm import OnuSelfTestFailureAlarm
+        from voltha.extensions.alarms.onu.onu_laser_eol_alarm import OnuLaserEolAlarm
+        from voltha.extensions.alarms.onu.onu_laser_bias_current_alarm import OnuLaserBiasAlarm
+        from voltha.extensions.alarms.onu.onu_temp_yellow_alarm import OnuTempYellowAlarm
+        from voltha.extensions.alarms.onu.onu_temp_red_alarm import OnuTempRedAlarm
+        from voltha.extensions.alarms.onu.onu_voltage_yellow_alarm import OnuVoltageYellowAlarm
+        from voltha.extensions.alarms.onu.onu_voltage_red_alarm import OnuVoltageRedAlarm
+        from voltha.extensions.alarms.onu.onu_low_rx_optical_power_alarm import OnuLowRxOpticalAlarm
+        from voltha.extensions.alarms.onu.onu_high_rx_optical_power_alarm import OnuHighRxOpticalAlarm
+        from voltha.extensions.alarms.onu.onu_low_tx_optical_power_alarm import OnuLowTxOpticalAlarm
+        from voltha.extensions.alarms.onu.onu_high_tx_optical_power_alarm import OnuHighTxOpticalAlarm
+
+        mgr = self._alarm_manager
+        if class_id in (CircuitPack.class_id, PptpEthernetUni.class_id):
+            intf_id = self.select_uni_port(class_id, entity_id)
+
+        elif class_id in (AniG.class_id, OntG.class_id):
+            intf_id = self.select_ani_port(class_id, entity_id)
+
+        else:
+            self.log.error('unsupported-class-id', class_id=class_id, alarm_number=alarm_number)
+            return
+
+        alarm_map = {
+            (CircuitPack.class_id, 0): OnuEquipmentAlarm,
+            (CircuitPack.class_id, 2): OnuSelfTestFailureAlarm,
+            (CircuitPack.class_id, 3): OnuLaserEolAlarm,
+            (CircuitPack.class_id, 4): OnuTempYellowAlarm,
+            (CircuitPack.class_id, 5): OnuTempRedAlarm,
+
+            (PptpEthernetUni.class_id, 0): OnuLosAlarm,
+
+            (OntG.class_id, 0): OnuEquipmentAlarm,
+            (OntG.class_id, 6): OnuSelfTestFailureAlarm,
+            (OntG.class_id, 7): OnuDyingGaspAlarm,
+            (OntG.class_id, 8): OnuTempYellowAlarm,
+            (OntG.class_id, 9): OnuTempRedAlarm,
+            (OntG.class_id, 10): OnuVoltageYellowAlarm,
+            (OntG.class_id, 11): OnuVoltageRedAlarm,
+
+            (AniG.class_id, 0): OnuLowRxOpticalAlarm,
+            (AniG.class_id, 1): OnuHighRxOpticalAlarm,
+            (AniG.class_id, 4): OnuLowTxOpticalAlarm,
+            (AniG.class_id, 5): OnuHighTxOpticalAlarm,
+            (AniG.class_id, 6): OnuLaserBiasAlarm,
+        }
+        alarm_cls = alarm_map.get((class_id, alarm_number))
+
+        return alarm_cls(mgr, self._onu_id, intf_id) if alarm_cls is not None else None
+
+    def select_uni_port(self, class_id, entity_id):
+        """
+        Select the best possible UNI Port (logical) interface number for this ME class and
+        entity ID.
+
+        This base implementation will assume that a UNI Port object has been registered
+        on startup and supports both an 'entity_id' and also 'logical_port_number'
+        property.  See both the Adtran and BroadCom OpenOMCI ONU DA for an example
+        of this UNI port object.
+
+        :param class_id: (int)  ME Class ID for which the alarms belongs to
+        :param entity_id: (int) Instance ID
+
+        :return: (int) Logical Port number for the UNI port
+        """
+        # NOTE: Of the three class ID's supported in this version of code, only the CircuitPack,
+        #       and PptpEthernetUni MEs will map to the UNI port
+        assert class_id in (CircuitPack.class_id, PptpEthernetUni.class_id)
+
+        return next((uni.logical_port_number for uni in self._uni_ports if
+                     uni.entity_id == entity_id), None)
+
+    def select_ani_port(self, class_id, _entity_id):
+        """
+        Select the best possible ANI Port (physical) interface number for this ME class and
+        entity ID.
+
+        Currently the base implementation assumes only a single PON port and it will be
+        chosen.  A future implementation may want to have a PON Port object (similar to
+        the BroadCom Open OMCI and Adtran ONU's UNI Port object) that provides a match
+        for entity ID.  This does assume that the PON port object supports a property
+        of 'port_number' to return the physical port number.
+
+        :param class_id: (int)  ME Class ID for which the alarms belongs to
+        :param _entity_id: (int) Instance ID
+
+        :return: (int) Logical Port number for the UNI port
+        """
+        # NOTE: Of the three class ID's supported in this version of code, only the AniG
+        #       MEs will map to the ANI port. For some the OntG alarms (Dying Gasp) the
+        #       PON interface will also be selected.
+        assert class_id in (AniG.class_id, OntG.class_id)
+
+        return self._ani_ports[0].port_number if len(self._ani_ports) else None
diff --git a/voltha/extensions/omci/tasks/alarm_resync_task.py b/voltha/extensions/omci/tasks/alarm_resync_task.py
index 826bf00..1007724 100644
--- a/voltha/extensions/omci/tasks/alarm_resync_task.py
+++ b/voltha/extensions/omci/tasks/alarm_resync_task.py
@@ -18,8 +18,9 @@
 from twisted.internet import reactor
 from common.utils.asleep import asleep
 from voltha.extensions.omci.database.mib_db_dict import *
-from voltha.extensions.omci.omci_entities import OntData
 from voltha.extensions.omci.omci_defs import AttributeAccess
+from voltha.extensions.omci.database.alarm_db_ext import AlarmDbExternal
+
 AA = AttributeAccess
 
 
@@ -128,8 +129,8 @@
                 self.deferred.errback(failure.Failure(e))
             else:
                 # Start the ALARM upload sequence, save alarms to the table
-
                 self.strobe_watchdog()
+
                 if number_of_commands > 0:
                     commands_retrieved = yield self.upload_alarm(number_of_commands)
                 else:
@@ -261,22 +262,8 @@
                     alarm_class_id = omci_msg['alarmed_entity_class']
                     alarm_entity_id = omci_msg['alarmed_entity_id']
 
-                    # Filter out the 'alarm_data_sync' from the database. We save that at
-                    # the device level and do not want it showing up during a re-sync
-                    # during data comparison
-
-                    if alarm_class_id == OntData.class_id:
-                        break
-
-                    bit_map = omci_msg['alarm_bit_map'].encode('hex')
-                    bit_map_hex = "{0:b}".format(int(bit_map, 16))
-                    alarm_bit_map = eval(bit_map_hex)
-
-                    # alarm bit map space is 28 bytes * 8 = 224 bits
-                    if len(bit_map_hex) != 224:
-                        continue
-
-                    attributes = alarm_bit_map
+                    alarm_bit_map = omci_msg['alarm_bit_map']
+                    attributes = {AlarmDbExternal.ALARM_BITMAP_KEY: alarm_bit_map}
 
                     # Save to the database
                     self._db_active.set(self.device_id, alarm_class_id,