[VOL-1699] Fix data storage in OMCI Alarm, pass serial_number to AlarmSynchronizer and ONU Alarm Classes.

Change-Id: I462f98162292d5c536ca345fc87aeb40a64e115e
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_equipment_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_equipment_alarm.py
index 5d80c88..0c5fee4 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_equipment_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_equipment_alarm.py
@@ -31,15 +31,17 @@
           may report it with a different alarm number specifically for a
           self-test failure.
     """
-    def __init__(self, alarm_mgr, onu_id, intf_id):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuEquipmentAlarm, self).__init__(alarm_mgr, object_type='onu equipment',
                                                 alarm='ONU_EQUIPMENT',
                                                 alarm_category=AlarmEventCategory.ONU,
-                                                alarm_type=AlarmEventType.EQUIPTMENT,
+                                                alarm_type=AlarmEventType.EQUIPMENT,
                                                 alarm_severity=AlarmEventSeverity.CRITICAL)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_high_rx_optical_power_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_high_rx_optical_power_alarm.py
index ca23bd6..217db10 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_high_rx_optical_power_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_high_rx_optical_power_alarm.py
@@ -23,7 +23,7 @@
     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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuHighRxOpticalAlarm, self).__init__(alarm_mgr, object_type='onu high rx optical power',
                                                     alarm='ONU_HIGH_RX_OPTICAL',
                                                     alarm_category=AlarmEventCategory.ONU,
@@ -31,7 +31,9 @@
                                                     alarm_severity=AlarmEventSeverity.MAJOR)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_high_tx_optical_power_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_high_tx_optical_power_alarm.py
index ce9c543..623e0c5 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_high_tx_optical_power_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_high_tx_optical_power_alarm.py
@@ -23,7 +23,7 @@
     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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuHighTxOpticalAlarm, self).__init__(alarm_mgr, object_type='onu high tx optical power',
                                                     alarm='ONU_HIGH_TX_OPTICAL',
                                                     alarm_category=AlarmEventCategory.ONU,
@@ -31,7 +31,9 @@
                                                     alarm_severity=AlarmEventSeverity.MAJOR)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
\ No newline at end of file
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
\ No newline at end of file
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_laser_bias_current_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_laser_bias_current_alarm.py
index e74a83e..129340e 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_laser_bias_current_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_laser_bias_current_alarm.py
@@ -24,15 +24,17 @@
     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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         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_type=AlarmEventType.EQUIPMENT,
                                                 alarm_severity=AlarmEventSeverity.MAJOR)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_laser_eol_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_laser_eol_alarm.py
index 046296e..cbf8a87 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_laser_eol_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_laser_eol_alarm.py
@@ -22,15 +22,17 @@
 
     The intf_id reported is that of the UNI's logical port number
     """
-    def __init__(self, alarm_mgr, onu_id, intf_id):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuLaserEolAlarm, self).__init__(alarm_mgr, object_type='onu laser EOL',
                                                alarm='ONU_LASER_EOL',
                                                alarm_category=AlarmEventCategory.ONU,
-                                               alarm_type=AlarmEventType.EQUIPTMENT,
+                                               alarm_type=AlarmEventType.EQUIPMENT,
                                                alarm_severity=AlarmEventSeverity.MAJOR)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_low_rx_optical_power_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_low_rx_optical_power_alarm.py
index a76ab75..881f9d6 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_low_rx_optical_power_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_low_rx_optical_power_alarm.py
@@ -23,7 +23,7 @@
     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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuLowRxOpticalAlarm, self).__init__(alarm_mgr, object_type='onu low rx optical power',
                                                    alarm='ONU_LOW_RX_OPTICAL',
                                                    alarm_category=AlarmEventCategory.ONU,
@@ -31,7 +31,9 @@
                                                    alarm_severity=AlarmEventSeverity.MAJOR)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_low_tx_optical_power_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_low_tx_optical_power_alarm.py
index 8360bee..48a408a 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_low_tx_optical_power_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_low_tx_optical_power_alarm.py
@@ -23,7 +23,7 @@
     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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuLowTxOpticalAlarm, self).__init__(alarm_mgr, object_type='onu low tx optical power',
                                                    alarm='ONU_LOW_TX_OPTICAL',
                                                    alarm_category=AlarmEventCategory.ONU,
@@ -31,7 +31,9 @@
                                                    alarm_severity=AlarmEventSeverity.MAJOR)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_selftest_failure_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_selftest_failure_alarm.py
index 0465241..f411f9d 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_selftest_failure_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_selftest_failure_alarm.py
@@ -30,15 +30,17 @@
           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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         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_type=AlarmEventType.EQUIPMENT,
                                                       alarm_severity=AlarmEventSeverity.CRITICAL)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_temp_red_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_temp_red_alarm.py
index 5d34732..62a8293 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_temp_red_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_temp_red_alarm.py
@@ -28,7 +28,7 @@
     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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuTempRedAlarm, self).__init__(alarm_mgr, object_type='onu temperature red',
                                               alarm='ONU_TEMP_RED',
                                               alarm_category=AlarmEventCategory.ONU,
@@ -36,7 +36,9 @@
                                               alarm_severity=AlarmEventSeverity.CRITICAL)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_temp_yellow_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_temp_yellow_alarm.py
index 4c40881..4182bfe 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_temp_yellow_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_temp_yellow_alarm.py
@@ -27,7 +27,7 @@
     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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuTempYellowAlarm, self).__init__(alarm_mgr, object_type='onu temperature yellow',
                                                  alarm='ONU_TEMP_YELLOW',
                                                  alarm_category=AlarmEventCategory.ONU,
@@ -35,7 +35,9 @@
                                                  alarm_severity=AlarmEventSeverity.MAJOR)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_red_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_red_alarm.py
index 70eec8f..f428e2e 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_red_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_red_alarm.py
@@ -25,7 +25,7 @@
     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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuVoltageRedAlarm, self).__init__(alarm_mgr, object_type='onu voltage red',
                                                  alarm='ONU_VOLTAGE_RED',
                                                  alarm_category=AlarmEventCategory.ONU,
@@ -33,7 +33,9 @@
                                                  alarm_severity=AlarmEventSeverity.CRITICAL)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_yellow_alarm.py b/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_yellow_alarm.py
index ee65ed5..2555078 100644
--- a/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_yellow_alarm.py
+++ b/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_yellow_alarm.py
@@ -25,7 +25,7 @@
     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):
+    def __init__(self, alarm_mgr, onu_id, intf_id, serial_number):
         super(OnuVoltageYellowAlarm, self).__init__(alarm_mgr, object_type='onu voltage yellow',
                                                     alarm='ONU_VOLTAGE_YELLOW',
                                                     alarm_category=AlarmEventCategory.ONU,
@@ -33,7 +33,9 @@
                                                     alarm_severity=AlarmEventSeverity.MAJOR)
         self._onu_id = onu_id
         self._intf_id = intf_id
+        self._serial_number = serial_number
 
     def get_context_data(self):
         return {'onu-id': self._onu_id,
-                'onu-intf-id': self._intf_id}
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/omci/database/alarm_db_ext.py b/pyvoltha/adapters/extensions/omci/database/alarm_db_ext.py
index 01ecc1a..ed1a228 100644
--- a/pyvoltha/adapters/extensions/omci/database/alarm_db_ext.py
+++ b/pyvoltha/adapters/extensions/omci/database/alarm_db_ext.py
@@ -16,7 +16,8 @@
 from mib_db_api import *
 from voltha_protos.omci_alarm_db_pb2 import AlarmInstanceData, AlarmClassData, \
     AlarmDeviceData, AlarmAttributeData
-
+from pyvoltha.common.config.config_backend import EtcdStore
+from pyvoltha.common.utils.registry import registry
 
 class AlarmDbExternal(MibDbApi):
     """
@@ -29,18 +30,11 @@
 
     # Paths from root proxy
     ALARM_PATH = '/omci_alarms'
-    DEVICE_PATH = ALARM_PATH + '/{}'            # .format(device_id)
+    DEVICE_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)
-    ATTRIBUTES_PATH = DEVICE_PATH + '/classes/{}/instances/{}/attributes'  # .format(device_id, class_id, instance_id)
-
-    # Single Class, Instance, and Attribute as objects from device proxy
-    CLASS_PATH = '/classes/{}'                                 # .format(class_id)
-    INSTANCE_PATH = '/classes/{}/instances/{}'                 # .format(class_id, instance_id)
-    ATTRIBUTE_PATH = '/classes/{}/instances/{}/attributes/{}'  # .format(class_id, instance_id
-                                                               #         attribute_name)
+    CLASS_PATH = DEVICE_PATH + '/classes/{}'                                # .format(device_id, class_id)
+    INSTANCE_PATH = DEVICE_PATH + '/classes/{}/instances/{}'                 # .format(device_id, class_id, instance_id)
 
     def __init__(self, omci_agent):
         """
@@ -48,7 +42,10 @@
         :param omci_agent: (OpenOMCIAgent) OpenOMCI Agent
         """
         super(AlarmDbExternal, self).__init__(omci_agent)
-        self._core = omci_agent.core_proxy
+
+        self.args = registry('main').get_args()
+        host, port = self.args.etcd.split(':', 1)
+        self._kv_store = EtcdStore(host, port, AlarmDbExternal.ALARM_PATH)
 
     def start(self):
         """
@@ -58,15 +55,6 @@
 
         if not self._started:
             super(AlarmDbExternal, self).start()
-            root_proxy = self._core.get_proxy('/')
-
-            try:
-                base = root_proxy.get(AlarmDbExternal.ALARM_PATH)
-                self.log.info('db-exists', num_devices=len(base))
-
-            except Exception as e:
-                self.log.exception('start-failure', e=e)
-                raise
 
     def stop(self):
         """
@@ -121,14 +109,18 @@
 
         now = datetime.utcnow()
         found = False
-        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)
+        path = self._get_device_path(device_id)
+        self.log.debug("add-device-path", device_id=device_id, path=path)
         try:
-            dev_proxy = self._device_proxy(device_id)
+            #raises KeyError if not found
+            device = self._kv_store[path]
+
+            #device is found at this point
             found = True
 
             if not overwrite:
@@ -137,15 +129,14 @@
                                format(device_id))
 
             # Overwrite with new data
-            data = dev_proxy.get('/', depth=0)
-            self._root_proxy.update(AlarmDbExternal.DEVICE_PATH.format(device_id), data)
+            self._kv_store[path] = data.SerializeToString()
             self._modified = now
 
         except KeyError:
             if found:
                 raise
             # Did not exist, add it now
-            root_proxy.add(AlarmDbExternal.ALARM_PATH, data)
+            self._kv_store[path] = data.SerializeToString()
             self._created = now
             self._modified = now
 
@@ -164,8 +155,8 @@
             raise TypeError('Device ID should be an string')
 
         try:
-            # self._root_proxy.get(AlarmDbExternal.DEVICE_PATH.format(device_id))
-            self._root_proxy.remove(AlarmDbExternal.DEVICE_PATH.format(device_id))
+            path = self._get_device_path(device_id)
+            del self._kv_store[path]
             self._modified = datetime.utcnow()
 
         except KeyError:
@@ -176,74 +167,21 @@
             self.log.exception('remove-exception', device_id=device_id, e=e)
             raise
 
-    @property
-    def _root_proxy(self):
-        return self._core.get_proxy('/')
+    def _get_device_path(self, device_id):
+        return AlarmDbExternal.DEVICE_PATH.format(device_id)
 
-    def _device_proxy(self, device_id):
-        """
-        Return a config proxy to the OMCI Alarm_DB leaf for a given device
-
-        :param device_id: (str) ONU Device ID
-        :return: (ConfigProxy) Configuration proxy rooted at OMCI Alarm DB
-        :raises KeyError: If the device does not exist in the database
-        """
-        if not isinstance(device_id, basestring):
-            raise TypeError('Device ID should be an string')
-
-        if not self._started:
-            raise DatabaseStateError('The Database is not currently active')
-
-        return self._core.get_proxy(AlarmDbExternal.DEVICE_PATH.format(device_id))
-
-    def _class_proxy(self, device_id, class_id, create=False):
-        """
-        Get a config proxy to a specific managed entity class
-        :param device_id: (str) ONU Device ID
-        :param class_id: (int) Class ID
-        :param create: (bool) If true, create default instance (and class)
-        :return: (ConfigProxy) Class configuration proxy
-
-        :raises DatabaseStateError: If database is not started
-        :raises KeyError: If Instance does not exist and 'create' is False
-        """
+    def _get_class_path(self, device_id, class_id):
         if not self._started:
             raise DatabaseStateError('The Database is not currently active')
 
         if not 0 <= class_id <= 0xFFFF:
             raise ValueError('class-id is 0..0xFFFF')
 
-        fmt = AlarmDbExternal.DEVICE_PATH + AlarmDbExternal.CLASS_PATH
-        path = fmt.format(device_id, class_id)
+        fmt = AlarmDbExternal.CLASS_PATH
+        return fmt.format(device_id, class_id)
 
-        try:
-            return self._core.get_proxy(path)
 
-        except KeyError:
-            if not create:
-                self.log.error('class-proxy-does-not-exist', device_id=device_id,
-                               class_id=class_id)
-                raise
-
-        # Create class
-        data = AlarmClassData(class_id=class_id)
-        root_path = AlarmDbExternal.CLASSES_PATH.format(device_id)
-        self._root_proxy.add(root_path, data)
-
-        return self._core.get_proxy(path)
-
-    def _instance_proxy(self, device_id, class_id, instance_id, create=False):
-        """
-        Get a config proxy to a specific managed entity instance
-        :param device_id: (str) ONU Device ID
-        :param class_id: (int) Class ID
-        :param instance_id: (int) Instance ID
-        :param create: (bool) If true, create default instance (and class)
-        :return: (ConfigProxy) Instance configuration proxy
-
-        :raises DatabaseStateError: If database is not started
-        :raises KeyError: If Instance does not exist and 'create' is False
-        """
+    def _get_instance_path(self, device_id, class_id, instance_id):
         if not self._started:
             raise DatabaseStateError('The Database is not currently active')
 
@@ -256,27 +194,8 @@
         if not 0 <= instance_id <= 0xFFFF:
             raise ValueError('instance-id is 0..0xFFFF')
 
-        fmt = AlarmDbExternal.DEVICE_PATH + AlarmDbExternal.INSTANCE_PATH
-        path = fmt.format(device_id, class_id, instance_id)
-
-        try:
-            return self._core.get_proxy(path)
-
-        except KeyError:
-            if not create:
-                self.log.error('instance-proxy-does-not-exist', device_id=device_id,
-                               class_id=class_id, instance_id=instance_id)
-                raise
-
-        # Create instance, first make sure class exists
-        self._class_proxy(device_id, class_id, create=True)
-
-        now = self._time_to_string(datetime.utcnow())
-        data = AlarmInstanceData(instance_id=instance_id, created=now, modified=now)
-        root_path = AlarmDbExternal.INSTANCES_PATH.format(device_id, class_id)
-        self._root_proxy.add(root_path, data)
-
-        return self._core.get_proxy(path)
+        fmt = AlarmDbExternal.INSTANCE_PATH
+        return fmt.format(device_id, class_id, instance_id)
 
     def save_last_sync_time(self, device_id, value):
         """
@@ -292,15 +211,15 @@
                 raise TypeError('Expected a datetime object, got {}'.
                                 format(type(datetime)))
 
-            device_proxy = self._device_proxy(device_id)
-            data = device_proxy.get(depth=0)
+            data = AlarmDeviceData()
+            path = self._get_device_path(device_id)
+            data.ParseFromString(self._kv_store[path])
 
             now = datetime.utcnow()
             data.last_sync_time = self._time_to_string(value)
 
             # Update
-            self._root_proxy.update(AlarmDbExternal.DEVICE_PATH.format(device_id),
-                                    data)
+            self._kv_store[path] = data.SerializeToString()
             self._modified = now
             self.log.debug('save-sync-time-complete', device_id=device_id)
 
@@ -318,8 +237,9 @@
         self.log.debug('get-last-sync-time', device_id=device_id)
 
         try:
-            device_proxy = self._device_proxy(device_id)
-            data = device_proxy.get(depth=0)
+            data = AlarmDeviceData()
+            path = self._get_device_path(device_id)
+            data.ParseFromString(self._kv_store[path])
             return self._string_to_time(data.last_sync_time)
 
         except KeyError:
@@ -342,15 +262,15 @@
             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)
+            data = AlarmDeviceData()
+            path = self._get_device_path(device_id)
+            data.ParseFromString(self._kv_store[path])
 
             now = datetime.utcnow()
             data.last_alarm_sequence = int(value)
 
             # Update
-            self._root_proxy.update(AlarmDbExternal.DEVICE_PATH.format(device_id),
-                                    data)
+            self._kv_store[path] = data.SerializeToString()
             self._modified = now
             self.log.debug('save-sequence-complete', device_id=device_id)
 
@@ -368,8 +288,9 @@
         self.log.debug('get-last-sync', device_id=device_id)
 
         try:
-            device_proxy = self._device_proxy(device_id)
-            data = device_proxy.get(depth=0)
+            data = AlarmDeviceData()
+            path = self._get_device_path(device_id)
+            data.ParseFromString(self.kv_store[path])
             return int(data.last_alarm_sequence)
 
         except KeyError:
@@ -379,7 +300,7 @@
             self.log.exception('get-last-alarm-exception', e=e)
             raise
 
-    def _add_new_class(self, device_id, class_id, instance_id, attributes):
+    def _add_new_class_and_instance(self, device_id, class_id, instance_id, attributes):
         """
         Create an entry for a new class in the external database
 
@@ -391,24 +312,23 @@
         :returns: (bool) True if the value was saved to the database. False if the
                          value was identical to the current instance
         """
-        self.log.debug('add', device_id=device_id, class_id=class_id,
+        self.log.debug('add-new-class-and-instance', device_id=device_id, class_id=class_id,
                        instance_id=instance_id, attributes=attributes)
 
-        now = self._time_to_string(datetime.utcnow())
-        attrs = [AlarmAttributeData(name=k,
-                                    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)])
+        class_data = AlarmClassData(class_id=class_id)
 
-        self._root_proxy.add(AlarmDbExternal.CLASSES_PATH.format(device_id), class_data)
+        class_path = AlarmDbExternal.CLASS_PATH.format(device_id, class_id)
+        self._kv_store[class_path] = class_data.SerializeToString()
+
+        inst_data = self._create_new_instance(device_id, class_id, instance_id, attributes)
+        inst_path = AlarmDbExternal.INSTANCE_PATH.format(device_id, class_id, instance_id)
+        self._kv_store[inst_path] = inst_data.SerializeToString()
+
         self.log.debug('set-complete', device_id=device_id, class_id=class_id,
                        entity_id=instance_id, attributes=attributes)
         return True
 
-    def _add_new_instance(self,  device_id, class_id, instance_id, attributes):
+    def _create_new_instance(self,  device_id, class_id, instance_id, attributes):
         """
         Create an entry for a instance of an existing class in the external database
 
@@ -417,10 +337,9 @@
         :param instance_id: (int) ME Entity ID
         :param attributes: (dict) Attribute dictionary
 
-        :returns: (bool) True if the value was saved to the database. False if the
-                         value was identical to the current instance
+        :returns: (AlarmInstanceData) The new instance object
         """
-        self.log.debug('add', device_id=device_id, class_id=class_id,
+        self.log.debug('create-new-instance', device_id=device_id, class_id=class_id,
                        instance_id=instance_id, attributes=attributes)
 
         now = self._time_to_string(datetime.utcnow())
@@ -431,12 +350,9 @@
                                           modified=now,
                                           attributes=attrs)
 
-        self._root_proxy.add(AlarmDbExternal.INSTANCES_PATH.format(device_id, class_id),
-                             instance_data)
-
-        self.log.debug('set-complete', device_id=device_id, class_id=class_id,
+        self.log.debug('create-new-instance-complete', device_id=device_id, class_id=class_id,
                        entity_id=instance_id, attributes=attributes)
-        return True
+        return instance_data
 
     def set(self, device_id, class_id, instance_id, attributes):
         """
@@ -472,61 +388,62 @@
             if not self._started:
                 raise DatabaseStateError('The Database is not currently active')
 
-            # Determine the best strategy to add the information
-            dev_proxy = self._device_proxy(device_id)
-
             try:
-                class_data = dev_proxy.get(AlarmDbExternal.CLASS_PATH.format(class_id), deep=True)
-
-                inst_data = next((inst for inst in class_data.instances
-                                 if inst.instance_id == instance_id), None)
-
-                if inst_data is None:
-                    return self._add_new_instance(device_id, class_id, instance_id, attributes)
-
-                # Possibly adding to or updating an existing instance
-                # Get instance proxy, creating it if needed
-
-                exist_attr_indexes = dict()
-                attr_len = len(inst_data.attributes)
-
-                for index in xrange(0, attr_len):
-                    exist_attr_indexes[inst_data.attributes[index].name] = index
+                class_data = AlarmClassData()
+                class_path = AlarmDbExternal.CLASS_PATH.format(device_id, class_id)
+                class_data.ParseFromString(self._kv_store[class_path])
 
                 modified = False
-                str_value = ''
-                new_attributes = []
+                new_data = None
+                try:
+                    inst_data = AlarmInstanceData()
+                    inst_path = AlarmDbExternal.INSTANCE_PATH.format(device_id, class_id, instance_id)
+                    inst_data.ParseFromString(self._kv_store[inst_path])
 
-                for k, v in attributes.items():
-                    try:
-                        str_value = self._attribute_to_string(v)
-                        new_attributes.append(AlarmAttributeData(name=k, value=str_value))
+                    exist_attr_indexes = dict()
+                    attr_len = len(inst_data.attributes)
 
-                    except Exception as e:
-                        self.log.exception('save-error', e=e, class_id=class_id,
-                                           attr=k, value_type=type(v))
+                    for index in xrange(0, attr_len):
+                        exist_attr_indexes[inst_data.attributes[index].name] = index
 
-                    if k not in exist_attr_indexes or \
-                            inst_data.attributes[exist_attr_indexes[k]].value != str_value:
-                        modified = True
+                    str_value = ''
+                    new_attributes = []
+
+                    for k, v in attributes.items():
+                        try:
+                            str_value = self._attribute_to_string(v)
+                            new_attributes.append(AlarmAttributeData(name=k, value=str_value))
+
+                        except Exception as e:
+                            self.log.exception('save-error', e=e, class_id=class_id,
+                                            attr=k, value_type=type(v))
+
+                        if k not in exist_attr_indexes or \
+                                inst_data.attributes[exist_attr_indexes[k]].value != str_value:
+                            modified = True
+                            self.log.debug('different-attributes', device_id=device_id, class_id=class_id,
+                                    instance_id=instance_id, attributes=inst_data.attributes, new_attributes=new_attributes)
+
+                    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)
+
+                except KeyError:
+                    # Here if the instance_id does not yet exist in the database
+                    new_data = self._create_new_instance(device_id, class_id, instance_id, attributes)
+                    modified = True
 
                 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)
-                    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)
-
-                self.log.debug('set-complete', device_id=device_id, class_id=class_id,
-                               entity_id=instance_id, attributes=attributes, modified=modified)
+                    del self._kv_store[inst_path]
+                    self._kv_store[inst_path] = new_data.SerializeToString()
                 return modified
 
             except KeyError:
                 # Here if the class-id does not yet exist in the database
-                return self._add_new_class(device_id, class_id, instance_id,
+                return self._add_new_class_and_instance(device_id, class_id, instance_id,
                                            attributes)
         except Exception as e:
             self.log.exception('set-exception', device_id=device_id, class_id=class_id,
@@ -564,18 +481,10 @@
             raise ValueError('instance-id is 0..0xFFFF')
 
         try:
-            # Remove instance
-            self._instance_proxy(device_id, class_id, entity_id).remove('/')
-            now = datetime.utcnow()
+            instpath = self._get_instance_path(device_id, class_id, entity_id)
+            del self._kv_store[instpath]
 
-            # If resulting class has no instance, remove it as well
-            class_proxy = self._class_proxy(device_id, class_id)
-            class_data = class_proxy.get('/', depth=1)
-
-            if len(class_data.instances) == 0:
-                class_proxy.remove('/')
-
-            self._modified = now
+            self._modified = datetime.utcnow()
             return True
 
         except KeyError:
@@ -603,17 +512,29 @@
         :raises DatabaseStateError: If the database is not enabled
         """
         self.log.debug('query', device_id=device_id, class_id=class_id,
-                       instance_id=instance_id, attributes=attributes)
+                       entity_instance_id=instance_id, attributes=attributes)
+        data = dict()
+
         try:
             if class_id is None:
                 # Get full device info
-                dev_data = self._device_proxy(device_id).get('/', depth=-1)
-                data = self._device_to_dict(dev_data)
+                self.log.warn('get-all-instances-by-device-not-supported')
+                try:
+                    dev_data = AlarmDeviceData()
+                    device_path = self._get_device_path(device_id)
+                    dev_data.ParseFromString(self._kv_store[device_path])
+                    data = self._device_to_dict(dev_data)
+
+                except KeyError:
+                    data = dict()
 
             elif instance_id is None:
                 # Get all instances of the class
+                self.log.warn('get-all-instances-by-class-not-supported')
                 try:
-                    cls_data = self._class_proxy(device_id, class_id).get('/', depth=-1)
+                    cls_data = AlarmClassData()
+                    class_path = self._get_class_path(device_id, class_id)
+                    cls_data.ParseFromString(self._kv_store[class_path])
                     data = self._class_to_dict(cls_data)
 
                 except KeyError:
@@ -622,13 +543,14 @@
             else:
                 # Get all attributes of a specific ME
                 try:
-                    inst_data = self._instance_proxy(device_id, class_id, instance_id).\
-                        get('/', depth=-1)
+                    inst_data = AlarmInstanceData()
+                    inst_path = self._get_instance_path(device_id, class_id, instance_id)
+                    inst_data.ParseFromString(self._kv_store[inst_path])
 
                     if attributes is None:
                         # All Attributes
                         data = self._instance_to_dict(inst_data)
-
+                        self.log.debug('query-result-all', data=data)
                     else:
                         # Specific attribute(s)
                         if isinstance(attributes, basestring):
@@ -639,8 +561,14 @@
                             for attr in inst_data.attributes if attr.name in attributes}
 
                 except KeyError:
+                    self.log.debug('no-instance-data-keyError')
                     data = dict()
 
+                except Exception as e:
+                    self.log.exception('get-last-sync-exception', device_id=device_id, e=e)
+                    raise
+
+            self.log.debug('query-result', data=data)
             return data
 
         except KeyError:
diff --git a/pyvoltha/adapters/extensions/omci/state_machines/alarm_sync.py b/pyvoltha/adapters/extensions/omci/state_machines/alarm_sync.py
index 8f22796..1f1377e 100644
--- a/pyvoltha/adapters/extensions/omci/state_machines/alarm_sync.py
+++ b/pyvoltha/adapters/extensions/omci/state_machines/alarm_sync.py
@@ -96,6 +96,7 @@
         self._onu_id = None
         self._uni_ports = list()
         self._ani_ports = list()
+        self._serial_number = None
 
         self._deferred = None
         self._current_task = None
@@ -185,7 +186,7 @@
                                       'time': str(datetime.utcnow())
                                   })
 
-    def set_alarm_params(self, mgr=None, onu_id=None, uni_ports=None, ani_ports=None):
+    def set_alarm_params(self, mgr=None, onu_id=None, uni_ports=None, ani_ports=None, serial_number=None):
         if mgr is not None:
             self._alarm_manager = mgr
 
@@ -200,6 +201,9 @@
             assert isinstance(ani_ports, list)
             self._ani_ports = ani_ports
 
+        if serial_number is not None:
+            self._serial_number = serial_number
+
     def on_enter_disabled(self):
         """
         State machine is being stopped
@@ -448,6 +452,7 @@
         :param bitmap: (long) Alarm bitmap value
         :param msg_seq_no: (int) Alarm sequence number. -1 if generated during an audit
         """
+        self.log.debug('process-alarm-data', class_id=class_id, entity_id=entity_id, bitmap=hex(bitmap), msg_seq_no=msg_seq_no)
         if msg_seq_no > 0:
             # increment alarm number & compare to alarm # in message
             # Signal early audit if no match and audits are enabled
@@ -482,6 +487,9 @@
 
             newly_cleared = previously_raised - currently_raised
             newly_raised = currently_raised - previously_raised
+            self.log.debug('compare-bitmap', class_id=class_id, prev_bitmap=hex(prev_bitmap), bitmap=hex(bitmap),
+                            previously_raised=previously_raised, currently_raised=currently_raised,
+                            newly_cleared=newly_cleared, newly_raised=newly_raised)
 
             # Generate the set/clear alarms now
             for alarm_number in newly_cleared:
@@ -622,7 +630,7 @@
         }
         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
+        return alarm_cls(mgr, self._onu_id, intf_id, self._serial_number) if alarm_cls is not None else None
 
     def select_uni_port(self, class_id, entity_id):
         """
@@ -643,7 +651,8 @@
         #       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_port.port_number or uni_port._ofp_port_no replace uni.logical_port_number
+        return next((uni.port_number for uni in self._uni_ports if
                      uni.entity_id == entity_id), None)
 
     def select_ani_port(self, class_id, _entity_id):