Migration to new event defination for OpenONU adapter

     This commit is for the migation of alarms and kpi fw in
     pyvoltha to the new event fw and has the following changes:

     1. Alarms definations are changed to events and modified accordingly
        to incorporate the changes in event proto message

     2. Kpis module is also moved under the events fw

Change-Id: Icfbb28e364b662ea8483b7472fe21ddf4551372e
diff --git a/VERSION b/VERSION
index 3e3c2f1..eca07e4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.1
+2.1.2
diff --git a/pyvoltha/adapters/extensions/alarms/adapter_alarms.py b/pyvoltha/adapters/extensions/alarms/adapter_alarms.py
deleted file mode 100644
index 0ee5dab..0000000
--- a/pyvoltha/adapters/extensions/alarms/adapter_alarms.py
+++ /dev/null
@@ -1,202 +0,0 @@
-#
-# Copyright 2017 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.
-
-import structlog
-import arrow
-from twisted.internet.defer import inlineCallbacks, returnValue
-from voltha_protos.events_pb2 import AlarmEventType, AlarmEventSeverity,\
-    AlarmEventState, AlarmEventCategory
-log = structlog.get_logger()
-
-
-# TODO: In the device adapter, the following alarms are still TBD
-#       (Taken from openolt_alarms)
-# onu_alarm_ind
-# onu_startup_failure_indication
-# onu_signal_degrade_indication
-# onu_drift_of_window_ind
-# onu_loss_omci_ind
-# onu_signals_fail_ind
-# onu_tiwi_ind
-# onu_activation_fail_ind
-# onu_processing_error_ind
-
-
-class AdapterAlarms:
-    """
-    Class for managing Alarms within a given Device Handler instance
-    """
-    def __init__(self, core_proxy, device_id, logical_device_id, serial_number):
-        """
-        Adapter alarm manager initializer
-
-        :param core_proxy: (CoreProxy) Core proxy reference
-        :param device_id: (str) Device handler's unique device id
-        :param logical_device_id: (str) Logical Device that the device is a member of
-        :param serial_number: (str) Serial number of the device(OLT) that created this instance
-        """
-        self.log = structlog.get_logger(device_id=device_id)
-        self.core_proxy = core_proxy
-        self.device_id = device_id
-        self.logical_device_id = logical_device_id
-        self.serial_number = serial_number
-        self.adapter_name = core_proxy.listening_topic
-        self.lc = None
-
-    def format_id(self, alarm):
-        """
-        Format the Unique Alarm ID for this alarm.  This is provided in the alarms
-        'id' field
-
-        :param alarm: (str) The name of the alarm such as 'Discover' or 'LOS'
-
-        :return: (str) Alarm ID
-        """
-        return 'voltha.{}.{}.{}'.format(self.adapter_name,
-                                        self.device_id,
-                                        alarm)
-
-    def format_description(self, _object, alarm, status):
-        """
-        Format the textual description field of this alarm
-
-        :param _object: ()
-        :param alarm: (str) The name of the alarm such as 'Discover' or 'LOS'
-        :param status: (bool) If True, the alarm is active (it is being raised)
-
-        :return: (str) Alarm description
-        """
-        return '{} Alarm - {} - {}'.format(_object.upper(),
-                                           alarm.upper(),
-                                           'Raised' if status else 'Cleared')
-    @inlineCallbacks
-    def send_alarm(self, context_data, alarm_data):
-        """
-        Send the alarm to the event bus
-
-        :param context_data: (dict) Alarm specific context data
-        :param alarm_data: (dict) Common Alarm information dictionary
-        """
-        try:
-            current_context = {}
-            if isinstance(context_data, dict):
-                for key, value in context_data.iteritems():
-                    current_context[key] = str(value)
-            #Always insert serial number of the OLT, ONU serial number comes in the context
-            current_context["serial-number"] = self.serial_number
-
-            self.log.debug('send_alarm', alarm_data=alarm_data)
-            
-            alarm_event = self.core_proxy.create_alarm(
-                id=alarm_data.get('id', 'voltha.{}.{}.olt'.format(self.adapter_name,
-                                                                  self.device_id)),
-                resource_id=str(alarm_data.get('resource_id', self.device_id)),
-                description="{}.{} - {}".format(self.adapter_name, self.device_id,
-                                                alarm_data.get('description')),
-                type=alarm_data.get('type'),
-                category=alarm_data.get('category'),
-                severity=alarm_data.get('severity'),
-                state=alarm_data.get('state'),
-                raised_ts=alarm_data.get('ts', 0),
-                context=current_context,
-                logical_device_id=self.logical_device_id,
-                alarm_type_name=alarm_data.get('alarm_type_name')
-            )
-            yield self.core_proxy.submit_alarm(self.device_id, alarm_event)
-
-        except Exception as e:
-            self.log.exception('failed-to-send-alarm', e=e)
-            raise
-
-
-class AlarmBase(object):
-    """Base class for alarms"""
-    def __init__(self, alarm_mgr, object_type, alarm,
-                 alarm_category,
-                 resource_id=None,
-                 alarm_type=AlarmEventType.EQUIPMENT,
-                 alarm_severity=AlarmEventSeverity.CRITICAL):
-        """
-        Initializer for the Alarm base class
-
-        :param alarm_mgr: (AdapterAlarms) Reference to the device handler's Adapter
-                                          Alarm manager
-        :param object_type: (str) Type of device generating the alarm such as 'olt' or 'onu'
-        :param alarm: (str) A textual name for the alarm such as 'HeartBeat' or 'Discovery'
-        :param alarm_category: (AlarmEventCategory) Refers to functional category of
-                                                    the alarm
-        :param resource_id: (str) Identifier of the originating resource of the alarm
-        :param alarm_type: (AlarmEventType) Refers to the area of the system impacted
-                                            by the alarm
-        :param alarm_severity: (AlarmEventSeverity) Overall impact of the alarm on the
-                                                    system
-        """
-        self._alarm_mgr = alarm_mgr
-        self._object_type = object_type
-        self._alarm = alarm
-        self._alarm_category = alarm_category
-        self._alarm_type = alarm_type
-        self._alarm_severity = alarm_severity
-        self._resource_id = resource_id
-
-    def get_alarm_data(self, status):
-        """
-        Get the alarm specific data and format it into a dictionary.  When the alarm
-        is being sent to the event bus, this dictionary provides a majority of the
-        fields for the alarms.
-
-        :param status: (bool) True if the alarm is active/raised
-        :return: (dict) Alarm data
-        """
-        data = {
-            'ts': arrow.utcnow().timestamp,
-            'description': self._alarm_mgr.format_description(self._object_type,
-                                                              self._alarm,
-                                                              status),
-            'id': self._alarm_mgr.format_id(self._alarm),
-            'type': self._alarm_type,
-            'category': self._alarm_category,
-            'severity': self._alarm_severity,
-            'state': AlarmEventState.RAISED if status else AlarmEventState.CLEARED,
-            'alarm_type_name': self._alarm
-        }
-        if self._resource_id is not None:
-            data['resource_id'] = self._resource_id
-        return data
-
-    def get_context_data(self):
-        """
-        Get alarm specific context data. If an alarm has specific data to specify, it is
-        included in the context field in the published event
-
-        :return: (dict) Dictionary with alarm specific context data
-        """
-        return {}   # NOTE: You should override this if needed
-
-    def raise_alarm(self):
-        """
-        Called to set the state of an alarm to active and to send it to the event bus
-        """
-        alarm_data = self.get_alarm_data(True)
-        context_data = self.get_context_data()
-        self._alarm_mgr.send_alarm(context_data, alarm_data)
-
-    def clear_alarm(self):
-        """
-        Called to set the state of an alarm to inactive and to send it to the event bus
-        """
-        alarm_data = self.get_alarm_data(False)
-        context_data = self.get_context_data()
-        self._alarm_mgr.send_alarm(context_data, alarm_data)
diff --git a/pyvoltha/adapters/extensions/alarms/README.md b/pyvoltha/adapters/extensions/events/README.md
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/README.md
rename to pyvoltha/adapters/extensions/events/README.md
diff --git a/pyvoltha/adapters/extensions/alarms/__init__.py b/pyvoltha/adapters/extensions/events/__init__.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/__init__.py
rename to pyvoltha/adapters/extensions/events/__init__.py
diff --git a/pyvoltha/adapters/extensions/events/adapter_events.py b/pyvoltha/adapters/extensions/events/adapter_events.py
new file mode 100644
index 0000000..a5fd977
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/adapter_events.py
@@ -0,0 +1,199 @@
+#
+# Copyright 2017 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.
+
+import arrow
+import structlog
+from twisted.internet.task import LoopingCall
+from twisted.internet.defer import inlineCallbacks, returnValue
+from voltha_protos.events_pb2 import Event, EventType, EventCategory, EventSubCategory, DeviceEvent, EventHeader
+
+log = structlog.get_logger()
+
+
+# TODO: In the device adapter, the following events are still TBD
+#       (Taken from openolt_events)
+# onu_alarm_ind
+# onu_startup_failure_indication
+# onu_signal_degrade_indication
+# onu_drift_of_window_ind
+# onu_loss_omci_ind
+# onu_signals_fail_ind
+# onu_tiwi_ind
+# onu_activation_fail_ind
+# onu_processing_error_ind
+
+
+class AdapterEvents:
+    """
+    Class for managing Events within a given Device Handler instance
+    """
+    def __init__(self, core_proxy, device_id, logical_device_id, serial_number):
+        """
+        Adapter event manager initializer
+
+        :param core_proxy: (CoreProxy) Core proxy reference
+        :param device_id: (str) Device handler's unique device id
+        :param logical_device_id: (str) Logical Device that the device is a member of
+        :param serial_number: (str) Serial number of the device(OLT) that created this instance
+        """
+        self.lc = None
+        self.type_version = "0.1"
+        self.device_id = device_id
+        self.core_proxy = core_proxy
+        self.serial_number = serial_number
+        self.logical_device_id = logical_device_id
+        self.adapter_name = core_proxy.listening_topic
+        self.log = structlog.get_logger(device_id=device_id)
+
+    def format_id(self, event):
+        """
+        Format the Unique Event ID for this event.  This is provided in the events
+        'id' field
+
+        :param event: (str) The name of the event such as 'Discover' or 'LOS'
+
+        :return: (str) Event ID
+        """
+        return 'voltha.{}.{}.{}'.format(self.adapter_name,
+                                        self.device_id, event)
+
+    def get_event_header(self, _type, category, sub_category, event, raised_ts):
+        """
+
+        :return: (dict) Event header
+        """
+        return EventHeader(id=self.format_id(event),
+                           category=category,
+                           sub_category=sub_category,
+                           type=_type,
+                           type_version=self.type_version,
+                           raised_ts=raised_ts,
+                           reported_ts=arrow.utcnow().timestamp
+                           )
+
+    @inlineCallbacks
+    def send_event(self, event_header, event_body):
+        """
+        Send the event to the event bus
+
+        :param event_header: (dict) Event specific context data
+        :param event_body: (dict) Common Event information dictionary
+        """
+        event = None
+        try:
+            self.log.debug('send_event')
+
+            if event_header.type == EventType.DEVICE_EVENT:
+               event = Event(header=event_header, device_event=event_body)
+            elif event_header.type == EventType.KPI_EVENT:
+               event = Event(header=event_header, kpi_event=event_body)
+            elif event_header.type == EventType.KPI_EVENT2:
+               event = Event(header=event_header, kpi_event2=event_body)
+            elif event_header.type == EventType.CONFIG_EVENT:
+               event = Event(header=event_header, config_event=event_body)
+
+            if event is not None:
+               yield self.core_proxy.submit_event(event)
+
+        except Exception as e:
+            self.log.exception('failed-to-send-event', e=e)
+            raise
+        log.debug('event-sent-to-kafka', event_header=event_header, event_body=event_body)
+
+
+
+class DeviceEventBase(object):
+    """Base class for device events"""
+    def __init__(self, event_mgr, raised_ts, object_type, 
+                 event, resource_id=None,
+                 category=EventCategory.EQUIPMENT,
+                 sub_category=EventSubCategory.PON):
+        """
+        Initializer for the Event base class
+
+        :param event_mgr: (AdapterEvents) Reference to the device handler's Adapter
+                                          Event manager
+        :param object_type: (str) Type of device generating the event such as 'olt' or 'onu'
+        :param event: (str) A textual name for the event such as 'HeartBeat' or 'Discovery'
+        :param event_category: (EventCategory) Refers to functional category of
+                                                    the event
+        :param event_category: (EventSubCategory) Refers to functional sub category of
+                                                    the event
+        :param resource_id: (str) Identifier of the originating resource of the event
+        """
+        self.event_mgr = event_mgr
+        self._object_type = object_type
+        self._event = event
+        self._category = category
+        self._sub_category = sub_category
+        self._type = EventType.DEVICE_EVENT
+        self._resource_id = resource_id
+        self.raised_ts = raised_ts
+
+    def format_description(self, _object, device_event, status):
+        """
+        Format the textual description field of this event
+
+        :param _object: ()
+        :param device_event: (str) The name of the event such as 'Discover' or 'LOS'
+        :param status: (bool) If True, the event is active (it is being raised)
+
+        :return: (str) Event description
+        """
+        return '{} Event - {} - {}'.format(_object.upper(),
+                                           device_event.upper(),
+                                           'Raised' if status else 'Cleared')
+
+    def get_device_event_data(self, status):
+        """
+        Get the event specific data and format it into a dictionary.  When the event
+        is being sent to the event bus, this dictionary provides a majority of the
+        fields for the events.
+
+        :param status: (bool) True if the event is active/raised
+        :return: (dict) Event data
+        """
+        context_data = self.get_context_data()
+
+        current_context = {}
+        if isinstance(context_data, dict):
+            for key, value in context_data.iteritems():
+                current_context[key] = str(value)
+        # Always insert serial number of the OLT, ONU serial number comes in the context
+        current_context["serial-number"] = self.event_mgr.serial_number
+
+        return DeviceEvent(resource_id=self.event_mgr.device_id,
+                           device_event_name="{}_{}".format(self._event, "RAISE_EVENT"),
+                           description=self.format_description(self._object_type, self._event, status),
+                           context=current_context)
+
+    def get_context_data(self):
+        """
+        Get event specific context data. If an event has specific data to specify, it is
+        included in the context field in the published event
+
+        :return: (dict) Dictionary with event specific context data
+        """
+        return {}   # NOTE: You should override this if needed
+
+    def send(self, status):
+        """
+        Called to send a device event to the event bus
+        """
+        event_header = self.event_mgr.get_event_header(EventType.DEVICE_EVENT, self._category,
+                                                       self._sub_category, self._event, self.raised_ts)
+        device_event_data = self.get_device_event_data(status)
+        self.event_mgr.send_event(event_header, device_event_data)
+
diff --git a/pyvoltha/adapters/extensions/alarms/__init__.py b/pyvoltha/adapters/extensions/events/device_events/__init__.py
similarity index 100%
copy from pyvoltha/adapters/extensions/alarms/__init__.py
copy to pyvoltha/adapters/extensions/events/device_events/__init__.py
diff --git a/pyvoltha/adapters/extensions/events/device_events/heartbeat_events.py b/pyvoltha/adapters/extensions/events/device_events/heartbeat_events.py
new file mode 100644
index 0000000..39386f2
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/heartbeat_events.py
@@ -0,0 +1,27 @@
+# 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 EventCategory, EventSubCategory
+from adapter_events import DeviceEventBase
+
+
+class HeartbeatEvent(DeviceEventBase):
+    def __init__(self, event_mgr, raised_ts, object_type='olt', heartbeat_misses=0):
+        super(HeartbeatEvent, self).__init__(event_mgr, raised_ts, object_type,
+                                             event='Heartbeat',
+                                             category=EventCategory.EQUIPMENT,
+                                             sub_category=ventSubCategory.PON)
+        self._misses = heartbeat_misses
+
+    def get_context_data(self):
+        return {'heartbeats-missed': self._misses}
diff --git a/pyvoltha/adapters/extensions/alarms/olt/__init__.py b/pyvoltha/adapters/extensions/events/device_events/olt/__init__.py
similarity index 100%
copy from pyvoltha/adapters/extensions/alarms/olt/__init__.py
copy to pyvoltha/adapters/extensions/events/device_events/olt/__init__.py
diff --git a/pyvoltha/adapters/extensions/events/device_events/olt/olt_los_alarm.py b/pyvoltha/adapters/extensions/events/device_events/olt/olt_los_alarm.py
new file mode 100644
index 0000000..8afcfb1
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/olt/olt_los_alarm.py
@@ -0,0 +1,29 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OltLosEvent(DeviceEventBase):
+    def __init__(self, event_mgr, intf_id, port_type_name, raised_ts):
+        super(OltLosEvent, self).__init__(event_mgr, raised_ts, object_type='olt LOS',
+                                          event='OLT_LOS',
+                                          category=EventCategory.COMMUNICATION,
+                                          sub_category=EventSubCategory.ONU)
+        # Added port type to indicate if alarm was on NNI or PON
+        self._intf_id = intf_id
+        self._port_type_name = port_type_name
+
+    def get_context_data(self):
+        return {'olt-intf-id:': self._intf_id,
+                'olt-port-type-name': self._port_type_name}
diff --git a/pyvoltha/adapters/extensions/alarms/onu/__init__.py b/pyvoltha/adapters/extensions/events/device_events/onu/__init__.py
similarity index 100%
copy from pyvoltha/adapters/extensions/alarms/onu/__init__.py
copy to pyvoltha/adapters/extensions/events/device_events/onu/__init__.py
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_activation_fail_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_activation_fail_event.py
new file mode 100644
index 0000000..ab07d0e
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_activation_fail_event.py
@@ -0,0 +1,30 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuActivationFailEvent(DeviceEventBase):
+    def __init__(self, event_mgr, onu_id, intf_id, serial_number, raised_ts):
+        super(OnuActivationFailEvent, self).__init__(event_mgr, raised_ts, object_type='onu ACTIVATION FAIL',
+                                          event='ONU_ACTIVATION_FAIL',
+                                          category=EventCategory.EQUIPMENT,
+                                          sub_category=EventSubCategory.ONU)
+        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-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_active_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_active_event.py
new file mode 100644
index 0000000..2eb7252
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_active_event.py
@@ -0,0 +1,50 @@
+# 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 EventCategory, EventSubCategory, EventType
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+
+class OnuActiveEvent(DeviceEventBase):
+    def __init__(self, event_mgr, device_id, pon_id, onu_serial_number,
+                 reg_id, olt_serial_number, raised_ts, ipv4_address=None,
+                 onu_id=None):
+        super(OnuActiveEvent, self).__init__(event_mgr, raised_ts, object_type='ONU',
+                                             event='ONU_ACTIVATED',
+                                             resource_id=pon_id,
+                                             category=EventCategory.EQUIPMENT,
+                                             sub_category=EventSubCategory.PON,
+                                             )
+
+        self._pon_id = pon_id
+        self._onu_id = onu_id
+        self._onu_serial_number = onu_serial_number
+        self._device_id = device_id
+        self._olt_serial_number = olt_serial_number
+        self._host = ipv4_address
+        self._reg_id = reg_id
+
+    def get_context_data(self):
+        data = {
+            'pon-id': self._pon_id,
+            'onu-id': self._onu_id,
+            'serial-number': self._onu_serial_number,
+            'olt_serial_number': self._olt_serial_number,
+            'device_id': self._device_id,
+            'registration_id': self._reg_id
+        }
+        if self._host is not None:
+            data['host'] = self._host
+
+        return data
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_discovery_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_discovery_event.py
new file mode 100644
index 0000000..0e9c484
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_discovery_event.py
@@ -0,0 +1,32 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuDiscoveryEvent(DeviceEventBase):
+    def __init__(self, event_mgr, pon_id, serial_number, raised_ts):
+        super(OnuDiscoveryEvent, self).__init__(event_mgr, raised_ts, object_type='ONU Discovery',
+                                                event='ONU_DISCOVERY',
+                                                resource_id=pon_id,
+                                                category=EventCategory.EQUIPMENT,
+                                                sub_category=EventSubCategory.ONU)
+        self._pon_id = pon_id
+        self._serial_number = serial_number
+
+    def get_context_data(self):
+        return {
+            'pon-id': self._pon_id,
+            'serial-number': self._serial_number,
+            'device-type': 'onu'
+        }
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_dying_gasp_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_dying_gasp_event.py
new file mode 100644
index 0000000..e8efc0a
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_dying_gasp_event.py
@@ -0,0 +1,32 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuDyingGaspEvent(DeviceEventBase):
+    def __init__(self, event_mgr, onu_id, intf_id, serial_number, raised_ts):
+        super(OnuDyingGaspEvent, self).__init__(event_mgr, raised_ts, object_type='onu DYING_GASP',
+                                                event='ONU_DYING_GASP',
+                                                category=EventCategory.EQUIPMENT,
+                                                sub_category=EventSubCategory.ONU)
+        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-serial-number': self._serial_number
+        }
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_equipment_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_equipment_event.py
new file mode 100644
index 0000000..cdc2e21
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_equipment_event.py
@@ -0,0 +1,44 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+
+class OnuEquipmentEvent(DeviceEventBase):
+    """
+    The ONU Equipment Event 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 events, the intf_id reported is that of the
+    UNI's logical port number
+
+    For ONT-G equipment events, the intf_id reported is that of the PON/ANI
+    physical port number
+
+    Note: Some ONUs may use this event to report a self-test failure or may
+          may report it with a different event number specifically for a
+          self-test failure.
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuEquipmentEvent, self).__init__(event_mgr, raised_ts, object_type='onu equipment',
+                                                event='ONU_EQUIPMENT',
+                                                category=EventCategory.EQUIPMENT,
+                                                sub_category=EventSubCategory.ONU,
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_high_rx_optical_power_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_high_rx_optical_power_event.py
new file mode 100644
index 0000000..da72b33
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_high_rx_optical_power_event.py
@@ -0,0 +1,35 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuHighRxOpticalEvent(DeviceEventBase):
+    """
+    The ONU High Tx Optical Power Event is reported by the ANI-G (ME # 263) to
+    indicate that the received downstream optical power above threshold..
+
+    For ANI-G equipment events, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuHighRxOpticalEvent, self).__init__(event_mgr, raised_ts, object_type='onu high rx optical power',
+                                                    event='ONU_HIGH_RX_OPTICAL',
+                                                    category=EventCategory.COMMUNICATION,
+                                                    sub_category=EventSubCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_high_tx_optical_power_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_high_tx_optical_power_event.py
new file mode 100644
index 0000000..05ede7b
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_high_tx_optical_power_event.py
@@ -0,0 +1,35 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuHighTxOpticalEvent(DeviceEventBase):
+    """
+    The ONU High Tx Optical Power Event is reported by the ANI-G (ME # 263) to
+    indicate that the received downstream optical power above upper threshold.
+
+    For ANI-G equipment events, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuHighTxOpticalEvent, self).__init__(event_mgr, raised_ts, object_type='onu high tx optical power',
+                                                    event='ONU_HIGH_TX_OPTICAL',
+                                                    category=EventCategory.COMMUNICATION,
+                                                    sub_category=EventSubCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_laser_bias_current_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_laser_bias_current_event.py
new file mode 100644
index 0000000..c7971d2
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_laser_bias_current_event.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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuLaserBiasEvent(DeviceEventBase):
+    """
+    The ONU Laser Bias Current Event 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 events, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuLaserBiasEvent, self).__init__(event_mgr, raised_ts, object_type='onu laser bias current',
+                                                event='ONU_LASER_BIAS_CURRENT',
+                                                category=EventCategory.EQUIPMENT,
+                                                sub_category=EventSubCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_laser_eol_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_laser_eol_event.py
new file mode 100644
index 0000000..4cc17e2
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_laser_eol_event.py
@@ -0,0 +1,35 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuLaserEolEvent(DeviceEventBase):
+    """
+    The ONU Laser End-of-Lifer Event 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, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuLaserEolEvent, self).__init__(event_mgr, raised_ts, object_type='onu laser EOL',
+                                               event='ONU_LASER_EOL',
+                                               category=EventCategory.EQUIPMENT,
+                                               sub_category=EventSubCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_lob_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_lob_event.py
new file mode 100644
index 0000000..da22c0f
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_lob_event.py
@@ -0,0 +1,32 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuLobEvent(DeviceEventBase):
+    def __init__(self, event_mgr, onu_id, intf_id, serial_number, raised_ts):
+        super(OnuLobEvent, self).__init__(event_mgr, raised_ts, object_type='onu LOB',
+                                          event='ONU_LOB',
+                                          category=EventCategory.COMMUNICATION,
+                                          sub_category=EventSubCategory.ONU)
+
+        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-serial-number': self._serial_number
+        }
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_lopc_mic_error_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_lopc_mic_error_event.py
new file mode 100644
index 0000000..7605bef
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_lopc_mic_error_event.py
@@ -0,0 +1,34 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuLopcMicErrorEvent(DeviceEventBase):
+    def __init__(self, evemt_mgr, onu_id, intf_id, serial_number, raised_ts):
+        super(OnuLopcMicErrorEvent, self).__init__(event_mgr, raised_ts, object_type='onu LOPC_MIC_ERROR',
+                                                   event='ONU_LOPC_MIC_ERROR',
+                                                   category=EventCategory.COMMUNICATION,
+                                                   sub_category=EventSubCategory.ONU)
+
+        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-serial-number': self._serial_number
+        }
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_lopc_miss_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_lopc_miss_event.py
new file mode 100644
index 0000000..58e949c
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_lopc_miss_event.py
@@ -0,0 +1,33 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuLopcMissEvent(DeviceEventBase):
+    def __init__(self, event_mgr, onu_id, intf_id, serial_number, raised_ts):
+        super(OnuLopcMissEvent, self).__init__(event_mgr, raised_ts, object_type='onu LOPC_MISS',
+                                               event='ONU_LOPC_MISS',
+                                               category=EventCategory.EQUIPMENT,
+                                               sub_category=EventSubCategory.ONU)
+        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-serial-number': self._serial_number
+        }
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_los_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_los_event.py
new file mode 100644
index 0000000..f9bbccd
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_los_event.py
@@ -0,0 +1,32 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+
+class OnuLosEvent(DeviceEventBase):
+    def __init__(self, event_mgr, onu_id, intf_id, serial_number, raised_ts):
+        super(OnuLosEvent, self).__init__(event_mgr, raised_ts, object_type='onu LOS',
+                                          event='ONU_LOS',
+                                          category=EventCategory.EQUIPMENT,
+                                          sub_category=EventSubCategory.ONU)
+        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-serial-number': self._serial_number
+        }
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_low_rx_optical_power_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_low_rx_optical_power_event.py
new file mode 100644
index 0000000..45603d5
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_low_rx_optical_power_event.py
@@ -0,0 +1,36 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuLowRxOpticalEvent(DeviceEventBase):
+    """
+    The ONU Low Rx Optical Power Event is reported by the ANI-G (ME # 263) to
+    indicate that the received downstream optical power below threshold.
+
+    For ANI-G equipment events, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuLowRxOpticalEvent, self).__init__(event_mgr, raised_ts, object_type='onu low rx optical power',
+                                                   event='ONU_LOW_RX_OPTICAL',
+                                                   category=EventCategory.COMMUNICATION,
+                                                   sub_category=EventSubCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_low_tx_optical_power_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_low_tx_optical_power_event.py
new file mode 100644
index 0000000..8a073c2
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_low_tx_optical_power_event.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 EventCategory, EventSubCategory, EventType
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+
+class OnuLowTxOpticalEvent(DeviceEventBase):
+    """
+    The ONU Low Tx Optical Power Event is reported by the ANI-G (ME # 263) to
+    indicate that the transmit optical power below lower threshold
+
+    For ANI-G equipment events, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuLowTxOpticalEvent, self).__init__(event_mgr, raised_ts, object_type='onu low tx optical power',
+                                                   event='ONU_LOW_TX_OPTICAL',
+                                                   category=EventCategory.COMMUNICATION,
+                                                   sub_category=EventCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_selftest_failure_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_selftest_failure_event.py
new file mode 100644
index 0000000..72ff144
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_selftest_failure_event.py
@@ -0,0 +1,42 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuSelfTestFailureEvent(DeviceEventBase):
+    """
+    The ONU Self Test Failure Event 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 events, the intf_id reported is that of the
+    UNI's logical port number
+
+    For ONT-G equipment events, the intf_id reported is that of the PON/ANI
+    physical port number
+
+    Note: Some ONUs may use this events to report a self-test failure or may
+          may report it with the ONU Equipment Event which can also cover a
+          self-test failure.
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuSelfTestFailureEvent, self).__init__(event_mgr, raised_ts, object_type='onu self-test failure',
+                                                      event='ONU_SELF_TEST_FAIL',
+                                                      category=EventCategory.EQUIPMENT,
+                                                      sub_category=EventSubCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_signal_degrade_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_signal_degrade_event.py
new file mode 100644
index 0000000..840a72b
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_signal_degrade_event.py
@@ -0,0 +1,34 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuSignalDegradeEvent(DeviceEventBase):
+    def __init__(self, event_mgr, onu_id, intf_id,
+                 inverse_bit_error_rate, serial_number, raised_ts):
+        super(OnuSignalDegradeEvent, self).__init__(event_mgr, raised_ts, object_type='onu SIGNAL DEGRADE',
+                                          event='ONU_SIGNAL_DEGRADE',
+                                          category=EventCategory.COMMUNICATION
+                                          sub_category=EventSubCategory.ONU)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+        self._inverse_bit_error_rate=inverse_bit_error_rate
+        self._serial_number = serial_number
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id,
+                'onu-serial-number': self._serial_number,
+                'inverse-bit-error-rate': self._inverse_bit_error_rate}
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_signal_fail_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_signal_fail_event.py
new file mode 100644
index 0000000..17f4bc5
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_signal_fail_event.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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+"""
+    OnuSignalsFailureIndication {
+                fixed32 intf_id = 1;
+                fixed32 onu_id = 2;
+                string status = 3;
+                fixed32 inverse_bit_error_rate = 4;
+"""
+
+class OnuSignalFailEvent(DeviceEventBase):
+    def __init__(self, event_mgr, onu_id, intf_id, inverse_bit_error_rate, serial_number, raised_ts):
+        super(OnuSignalFailEvent, self).__init__(event_mgr, raised_ts, object_type='onu SIGNAL FAIL',
+                                          alarm='ONU_SIGNAL_FAIL',
+                                          category=EventCategory.COMMUNICATION,
+                                          sub_category=EventSubCategory.ONU)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+        self._inverse_bit_error_rate = inverse_bit_error_rate
+        self._serial_number = serial_number
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id,
+                'inverse-bit-error-rate': self._inverse_bit_error_rate,
+                 'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_startup_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_startup_event.py
new file mode 100644
index 0000000..a621a20
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_startup_event.py
@@ -0,0 +1,43 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+"""
+    message OnuStartupFailureIndication {
+    fixed32 intf_id = 1;
+    fixed32 onu_id = 2;
+    string status = 3;
+}
+
+"""
+
+class OnuStartupEvent(DeviceEventBase):
+
+    def __init__(self, event_mgr, onu_id, intf_id, serial_number, raised_ts):
+        super(OnuStartupEvent, self).__init__(event_mgr, raised_ts, object_type='onu STARTUP FAIL',
+                                              event='ONU_STARTUP_FAIL',
+                                              category=EventCategory.COMMUNICATION,
+                                              sub_category=EventSubCategory.ONU)
+
+        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-serial-number': self._serial_number
+        }
diff --git a/pyvoltha/adapters/extensions/events/device_events/onu/onu_temp_red_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_temp_red_event.py
new file mode 100644
index 0000000..8b01796
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_temp_red_event.py
@@ -0,0 +1,40 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuTempRedEvent(DeviceEventBase):
+    """
+    The ONU Temperature Yellow Event 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 events, the intf_id reported is that of the
+    UNI's logical port number
+
+    For ONT-G equipment events, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuTempRedEvent, self).__init__(event_mgr, raised_ts, object_type='onu temperature red',
+                                              event='ONU_TEMP_RED',
+                                              category=EventCategory.ENVIRONMENT,
+                                              sub_category=EventSubCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_temp_yellow_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_temp_yellow_event.py
new file mode 100644
index 0000000..5531b2a
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_temp_yellow_event.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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuTempYellowEvent(DeviceEventBase):
+    """
+    The ONU Temperature Yellow Event 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 events, the intf_id reported is that of the
+    UNI's logical port number
+
+    For ONT-G equipment events, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuTempYellowEvent, self).__init__(event_mgr, raised_ts, object_type='onu temperature yellow',
+                                                 event='ONU_TEMP_YELLOW',
+                                                 category=EventCategory.ENVIRONMENT,
+                                                 sub_category=EventSubCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_voltage_red_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_voltage_red_event.py
new file mode 100644
index 0000000..438e79f
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_voltage_red_event.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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuVoltageRedEvent(DeviceEventBase):
+    """
+    The ONU Voltage Red Event 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 events, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuVoltageRedEvent, self).__init__(event_mgr, raised_ts, object_type='onu voltage red',
+                                                 event='ONU_VOLTAGE_RED',
+                                                 category=EventCategory.ENVIRONMENT,
+                                                 sub_category=EventSubCategory.ONU)
+
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_voltage_yellow_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_voltage_yellow_event.py
new file mode 100644
index 0000000..2758949
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_voltage_yellow_event.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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuVoltageYellowEvent(DeviceEventBase):
+    """
+    The ONU Voltage Red Event 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 events, the intf_id reported is that of the PON/ANI
+    physical port number
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, raised_ts):
+        super(OnuVoltageYellowEvent, self).__init__(event_mgr, raised_ts, object_type='onu voltage yellow',
+                                                    event='ONU_VOLTAGE_YELLOW',
+                                                    category=EventCategory.EQUIPMENT,
+                                                    sub_category=EventSubCategory.ONU)
+        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/pyvoltha/adapters/extensions/events/device_events/onu/onu_window_drift_event.py b/pyvoltha/adapters/extensions/events/device_events/onu/onu_window_drift_event.py
new file mode 100644
index 0000000..175ce10
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/device_events/onu/onu_window_drift_event.py
@@ -0,0 +1,44 @@
+# 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 EventType, EventCategory, EventSubCategory
+from pyvoltha.adapters.extensions.events.adapter_events import DeviceEventBase
+
+class OnuWindowDriftEvent(DeviceEventBase):
+    """
+    OnuDriftOfWindowIndication {
+            fixed32 intf_id = 1;
+            fixed32 onu_id = 2;
+            string status = 3;
+            fixed32 drift = 4;
+            fixed32 new_eqd = 5;
+        }
+    """
+    def __init__(self, event_mgr, onu_id, intf_id, drift, new_eqd, serial_number, raised_ts):
+        super(OnuWindowDriftEvent, self).__init__(event_mgr, raised_ts, object_type='onu WINDOW DRIFT',
+                                          event='ONU_WINDOW_DRIFT',
+                                          category=EventCategory.COMMUNICATION,
+                                          sub_category=EventSubCategory.ONU)
+        self._onu_id = onu_id
+        self._intf_id = intf_id
+        self._drift = drift
+        self._new_eqd = new_eqd
+        self._serial_number = serial_number
+        
+
+    def get_context_data(self):
+        return {'onu-id': self._onu_id,
+                'onu-intf-id': self._intf_id,
+                'drift': self._drift,
+                'new-eqd': self._new_eqd,
+                'onu-serial-number': self._serial_number}
diff --git a/pyvoltha/adapters/extensions/alarms/heartbeat_alarm.py b/pyvoltha/adapters/extensions/events/heartbeat_event.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/heartbeat_alarm.py
rename to pyvoltha/adapters/extensions/events/heartbeat_event.py
diff --git a/pyvoltha/adapters/extensions/kpi/README.md b/pyvoltha/adapters/extensions/events/kpi/README.md
similarity index 100%
rename from pyvoltha/adapters/extensions/kpi/README.md
rename to pyvoltha/adapters/extensions/events/kpi/README.md
diff --git a/pyvoltha/adapters/extensions/kpi/__init__.py b/pyvoltha/adapters/extensions/events/kpi/__init__.py
similarity index 100%
rename from pyvoltha/adapters/extensions/kpi/__init__.py
rename to pyvoltha/adapters/extensions/events/kpi/__init__.py
diff --git a/pyvoltha/adapters/extensions/kpi/adapter_pm_metrics.py b/pyvoltha/adapters/extensions/events/kpi/adapter_pm_metrics.py
similarity index 88%
rename from pyvoltha/adapters/extensions/kpi/adapter_pm_metrics.py
rename to pyvoltha/adapters/extensions/events/kpi/adapter_pm_metrics.py
index 1ee6e7e..3a3a95f 100644
--- a/pyvoltha/adapters/extensions/kpi/adapter_pm_metrics.py
+++ b/pyvoltha/adapters/extensions/events/kpi/adapter_pm_metrics.py
@@ -16,6 +16,7 @@
 import arrow
 from twisted.internet.task import LoopingCall
 from voltha_protos.events_pb2 import KpiEvent2, KpiEventType, MetricInformation, MetricMetaData
+from voltha_protos.events_pb2 import Event, EventType, EventCategory, EventSubCategory
 from voltha_protos.device_pb2 import PmConfig
 
 
@@ -37,7 +38,7 @@
     # for collection.
     TIMESTAMP_ATTRIBUTE = 'timestamp'
 
-    def __init__(self, core_proxy, device_id, logical_device_id, serial_number,
+    def __init__(self, event_mgr, core_proxy, device_id, logical_device_id, serial_number,
                  grouped=False, freq_override=False, **kwargs):
         """
         Initializer for shared Device Adapter PM metrics manager
@@ -51,6 +52,7 @@
         :param kwargs: (dict) Device Adapter specific values
         """
         self.log = structlog.get_logger(device_id=device_id)
+        self.event_mgr = event_mgr
         self.device_id = device_id
         self.core_proxy = core_proxy
         self.name = core_proxy.listening_topic
@@ -58,6 +60,9 @@
         self.serial_number = serial_number
         self.default_freq = kwargs.get(AdapterPmMetrics.DEFAULT_FREQUENCY_KEY,
                                        AdapterPmMetrics.DEFAULT_COLLECTION_FREQUENCY)
+        self._event = "KPI_EVENT"
+        self._category = EventCategory.EQUIPMENT
+        self._sub_category = EventSubCategory.ONU
         self.grouped = grouped
         self.freq_override = grouped and freq_override
         self.lc = None
@@ -175,12 +180,13 @@
         """ Request collection of all enabled metrics and publish them """
         try:
             data = self.collect_metrics()
-            self.publish_metrics(data)
+            raised_ts = arrow.utcnow().timestamp
+            self.publish_metrics(data, raised_ts)
 
         except Exception as e:
             self.log.exception('failed-to-collect-kpis', e=e)
 
-    def publish_metrics(self, data):
+    def publish_metrics(self, data, raised_ts):
         """
         Publish the metrics during a collection.
 
@@ -192,18 +198,22 @@
                             to convert to a KPIEvent and publish
         """
         self.log.debug('publish-metrics', data=data)
-
+        event_header = self.event_mgr.get_event_header(EventType.KPI_EVENT2,
+                                                       self._category,
+                                                       self._sub_category,
+                                                       self._event,
+                                                       raised_ts)
         if len(data):
             try:
                 # TODO: Existing adapters use the KpiEvent, if/when all existing
                 #       adapters use the shared KPI library, we may want to
                 #       deprecate the KPIEvent
-                kpi_event = KpiEvent2(
-                    type=KpiEventType.slice,
-                    ts=arrow.utcnow().float_timestamp,
-                    slice_data=data
-                )
-                self.core_proxy.submit_kpis(kpi_event)
+                event_body = KpiEvent2(
+                             type=KpiEventType.slice,
+                             ts=arrow.utcnow().float_timestamp,
+                             slice_data=data
+                             )
+                self.event_mgr.send_event(event_header, event_body)
 
             except Exception as e:
                 self.log.exception('failed-to-submit-kpis', e=e)
diff --git a/pyvoltha/adapters/extensions/kpi/olt/README.md b/pyvoltha/adapters/extensions/events/kpi/olt/README.md
similarity index 100%
rename from pyvoltha/adapters/extensions/kpi/olt/README.md
rename to pyvoltha/adapters/extensions/events/kpi/olt/README.md
diff --git a/pyvoltha/adapters/extensions/kpi/olt/__init__.py b/pyvoltha/adapters/extensions/events/kpi/olt/__init__.py
similarity index 100%
rename from pyvoltha/adapters/extensions/kpi/olt/__init__.py
rename to pyvoltha/adapters/extensions/events/kpi/olt/__init__.py
diff --git a/pyvoltha/adapters/extensions/kpi/olt/olt_pm_metrics.py b/pyvoltha/adapters/extensions/events/kpi/olt/olt_pm_metrics.py
similarity index 100%
rename from pyvoltha/adapters/extensions/kpi/olt/olt_pm_metrics.py
rename to pyvoltha/adapters/extensions/events/kpi/olt/olt_pm_metrics.py
diff --git a/pyvoltha/adapters/extensions/kpi/onu/IntervalMetrics.md b/pyvoltha/adapters/extensions/events/kpi/onu/IntervalMetrics.md
similarity index 100%
rename from pyvoltha/adapters/extensions/kpi/onu/IntervalMetrics.md
rename to pyvoltha/adapters/extensions/events/kpi/onu/IntervalMetrics.md
diff --git a/pyvoltha/adapters/extensions/kpi/onu/README.md b/pyvoltha/adapters/extensions/events/kpi/onu/README.md
similarity index 100%
rename from pyvoltha/adapters/extensions/kpi/onu/README.md
rename to pyvoltha/adapters/extensions/events/kpi/onu/README.md
diff --git a/pyvoltha/adapters/extensions/kpi/onu/__init__.py b/pyvoltha/adapters/extensions/events/kpi/onu/__init__.py
similarity index 100%
rename from pyvoltha/adapters/extensions/kpi/onu/__init__.py
rename to pyvoltha/adapters/extensions/events/kpi/onu/__init__.py
diff --git a/pyvoltha/adapters/extensions/kpi/onu/onu_omci_pm.py b/pyvoltha/adapters/extensions/events/kpi/onu/onu_omci_pm.py
similarity index 96%
rename from pyvoltha/adapters/extensions/kpi/onu/onu_omci_pm.py
rename to pyvoltha/adapters/extensions/events/kpi/onu/onu_omci_pm.py
index d627ca4..0e2af4f 100644
--- a/pyvoltha/adapters/extensions/kpi/onu/onu_omci_pm.py
+++ b/pyvoltha/adapters/extensions/events/kpi/onu/onu_omci_pm.py
@@ -15,8 +15,8 @@
 import arrow
 from voltha_protos.device_pb2 import PmConfig, PmGroupConfig
 from voltha_protos.events_pb2 import MetricInformation, MetricMetaData
-from pyvoltha.adapters.extensions.kpi.adapter_pm_metrics import AdapterPmMetrics
-from pyvoltha.adapters.extensions.kpi.onu.onu_pm_interval_metrics import OnuPmIntervalMetrics
+from pyvoltha.adapters.extensions.events.kpi.adapter_pm_metrics import AdapterPmMetrics
+from pyvoltha.adapters.extensions.events.kpi.onu.onu_pm_interval_metrics import OnuPmIntervalMetrics
 from pyvoltha.adapters.extensions.omci.omci_entities import UniG
 from pyvoltha.adapters.extensions.omci.omci_entities import PptpEthernetUni
 
@@ -41,7 +41,7 @@
     DEFAULT_UNI_STATUS_ENABLED = True
     DEFAULT_UNI_STATUS_FREQUENCY = (15 * 60 * 10)
 
-    def __init__(self, core_proxy, device_id, logical_device_id, serial_number,
+    def __init__(self, event_mgr, core_proxy, device_id, logical_device_id, serial_number,
                  grouped=False, freq_override=False, **kwargs):
         """
         Initializer for shared ONU Device Adapter OMCI CC PM metrics
@@ -60,7 +60,7 @@
                                          retrieval of OpenOMCI Communications channel statistics
                                          and retrieval of polled statistics.
         """
-        super(OnuOmciPmMetrics, self).__init__(core_proxy, device_id, logical_device_id, serial_number,
+        super(OnuOmciPmMetrics, self).__init__(event_mgr, core_proxy, device_id, logical_device_id, serial_number,
                                                grouped=grouped, freq_override=freq_override,
                                                **kwargs)
 
@@ -108,7 +108,7 @@
         self.omci_uni_metrics_config = {m: PmConfig(name=m, type=t, enabled=True)
                                         for (m, t) in self.omci_uni_pm_names}
 
-        self.openomci_interval_pm = OnuPmIntervalMetrics(core_proxy, device_id, logical_device_id,
+        self.openomci_interval_pm = OnuPmIntervalMetrics(event_mgr, core_proxy, device_id, logical_device_id,
                                                          serial_number)
 
     def update(self, pm_config):
diff --git a/pyvoltha/adapters/extensions/kpi/onu/onu_pm_interval_metrics.py b/pyvoltha/adapters/extensions/events/kpi/onu/onu_pm_interval_metrics.py
similarity index 94%
rename from pyvoltha/adapters/extensions/kpi/onu/onu_pm_interval_metrics.py
rename to pyvoltha/adapters/extensions/events/kpi/onu/onu_pm_interval_metrics.py
index 45b9ca2..2a3337f 100644
--- a/pyvoltha/adapters/extensions/kpi/onu/onu_pm_interval_metrics.py
+++ b/pyvoltha/adapters/extensions/events/kpi/onu/onu_pm_interval_metrics.py
@@ -16,7 +16,8 @@
 from twisted.internet.defer import inlineCallbacks, returnValue 
 from voltha_protos.device_pb2 import PmConfig, PmGroupConfig
 from voltha_protos.events_pb2 import KpiEvent2, MetricInformation, MetricMetaData, KpiEventType
-from pyvoltha.adapters.extensions.kpi.adapter_pm_metrics import AdapterPmMetrics
+from voltha_protos.events_pb2 import Event, EventType
+from pyvoltha.adapters.extensions.events.kpi.adapter_pm_metrics import AdapterPmMetrics
 from pyvoltha.adapters.extensions.omci.omci_entities import \
     EthernetFrameUpstreamPerformanceMonitoringHistoryData, \
     EthernetFrameDownstreamPerformanceMonitoringHistoryData, \
@@ -56,8 +57,8 @@
     XGPON_DOWNSTREAM_HISTORY = False
     XGPON_UPSTREAM_HISTORY = False
 
-    def __init__(self, core_proxy, device_id, logical_device_id, serial_number, **kwargs):
-        super(OnuPmIntervalMetrics, self).__init__(core_proxy, device_id, logical_device_id, serial_number,
+    def __init__(self, event_mgr, core_proxy, device_id, logical_device_id, serial_number, **kwargs):
+        super(OnuPmIntervalMetrics, self).__init__(event_mgr, core_proxy, device_id, logical_device_id, serial_number,
                                                    grouped=True, freq_override=False,
                                                    **kwargs)
         ethernet_bridge_history = {
@@ -375,11 +376,19 @@
                                               device_id=self.device_id,
                                               context=context)
                     slice_data = [MetricInformation(metadata=metadata, metrics=metrics)]
+                    raised_ts = arrow.utcnow().timestamp
+                    event_header = self.event_mgr.get_event_header(EventType.KPI_EVENT2, 
+                                                                   self._category,
+                                                                   self._sub_category,
+                                                                   self._event, 
+                                                                   raised_ts)
 
-                    kpi_event = KpiEvent2(type=KpiEventType.slice,
+                    event_body = KpiEvent2(type=KpiEventType.slice,
                                           ts=now.float_timestamp,
                                           slice_data=slice_data)
-                    yield self.core_proxy.submit_kpis(kpi_event)
+
+                    self.log.debug('Sending-onu-metrics-to-kafka')
+                    yield self.event_mgr.send_event(event_header, event_body)
 
         except Exception as e:
             self.log.exception('failed-to-submit-kpis', e=e)
diff --git a/pyvoltha/adapters/extensions/kpi/onu/onu_pm_metrics.py b/pyvoltha/adapters/extensions/events/kpi/onu/onu_pm_metrics.py
similarity index 93%
rename from pyvoltha/adapters/extensions/kpi/onu/onu_pm_metrics.py
rename to pyvoltha/adapters/extensions/events/kpi/onu/onu_pm_metrics.py
index 3d6fd42..61f1c98 100644
--- a/pyvoltha/adapters/extensions/kpi/onu/onu_pm_metrics.py
+++ b/pyvoltha/adapters/extensions/events/kpi/onu/onu_pm_metrics.py
@@ -13,8 +13,8 @@
 # limitations under the License.
 
 from voltha_protos.device_pb2 import PmConfig, PmConfigs, PmGroupConfig
-from pyvoltha.adapters.extensions.kpi.adapter_pm_metrics import AdapterPmMetrics
-from pyvoltha.adapters.extensions.kpi.onu.onu_omci_pm import OnuOmciPmMetrics
+from pyvoltha.adapters.extensions.events.kpi.adapter_pm_metrics import AdapterPmMetrics
+from pyvoltha.adapters.extensions.events.kpi.onu.onu_omci_pm import OnuOmciPmMetrics
 
 
 class OnuPmMetrics(AdapterPmMetrics):
@@ -35,7 +35,7 @@
     # the KPI shared library supports individual collection.
     DEFAULT_ONU_COLLECTION_FREQUENCY = 60 * 10      # 1 minute
 
-    def __init__(self, core_proxy, device_id, logical_device_id, serial_number,
+    def __init__(self, event_mgr, core_proxy, device_id, logical_device_id, serial_number,
                  grouped=False, freq_override=False, **kwargs):
         """
         Initializer for shared ONU Device Adapter PM metrics
@@ -53,7 +53,7 @@
                               'heartbeat': Reference to the a class that provides an ONU heartbeat
                                            statistics.   TODO: This should be standardized across adapters
         """
-        super(OnuPmMetrics, self).__init__(core_proxy, device_id, logical_device_id, serial_number,
+        super(OnuPmMetrics, self).__init__(event_mgr, core_proxy, device_id, logical_device_id, serial_number,
                                            grouped=grouped, freq_override=freq_override,
                                            **kwargs)
 
@@ -77,7 +77,7 @@
         self.health_metrics_config = {m: PmConfig(name=m, type=t, enabled=True)
                                       for (m, t) in self.health_pm_names}
 
-        self.omci_pm = OnuOmciPmMetrics(core_proxy, device_id, logical_device_id, serial_number,
+        self.omci_pm = OnuOmciPmMetrics(event_mgr, core_proxy, device_id, logical_device_id, serial_number,
                                         grouped=grouped, freq_override=freq_override,
                                         **kwargs)
 
diff --git a/pyvoltha/adapters/extensions/alarms/olt/__init__.py b/pyvoltha/adapters/extensions/events/olt/__init__.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/olt/__init__.py
rename to pyvoltha/adapters/extensions/events/olt/__init__.py
diff --git a/pyvoltha/adapters/extensions/alarms/olt/olt_los_alarm.py b/pyvoltha/adapters/extensions/events/olt/olt_los_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/olt/olt_los_alarm.py
rename to pyvoltha/adapters/extensions/events/olt/olt_los_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/__init__.py b/pyvoltha/adapters/extensions/events/onu/__init__.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/__init__.py
rename to pyvoltha/adapters/extensions/events/onu/__init__.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_activation_fail_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_activation_fail_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_activation_fail_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_activation_fail_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_active_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_active_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_active_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_active_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_discovery_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_discovery_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_discovery_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_discovery_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_dying_gasp_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_dying_gasp_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_dying_gasp_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_dying_gasp_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_equipment_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_equipment_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_equipment_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_equipment_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_high_rx_optical_power_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_high_rx_optical_power_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_high_rx_optical_power_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_high_rx_optical_power_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_high_tx_optical_power_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_high_tx_optical_power_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_high_tx_optical_power_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_high_tx_optical_power_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_laser_bias_current_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_laser_bias_current_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_laser_bias_current_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_laser_bias_current_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_laser_eol_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_laser_eol_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_laser_eol_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_laser_eol_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_lob_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_lob_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_lob_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_lob_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_lopc_mic_error_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_lopc_mic_error_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_lopc_mic_error_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_lopc_mic_error_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_lopc_miss_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_lopc_miss_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_lopc_miss_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_lopc_miss_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_los_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_los_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_los_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_los_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_low_rx_optical_power_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_low_rx_optical_power_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_low_rx_optical_power_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_low_rx_optical_power_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_low_tx_optical_power_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_low_tx_optical_power_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_low_tx_optical_power_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_low_tx_optical_power_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_selftest_failure_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_selftest_failure_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_selftest_failure_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_selftest_failure_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_signal_degrade_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_signal_degrade_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_signal_degrade_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_signal_degrade_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_signal_fail_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_signal_fail_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_signal_fail_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_signal_fail_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_startup_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_startup_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_startup_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_startup_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_temp_red_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_temp_red_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_temp_red_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_temp_red_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_temp_yellow_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_temp_yellow_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_temp_yellow_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_temp_yellow_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_red_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_voltage_red_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_voltage_red_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_voltage_red_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_voltage_yellow_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_voltage_yellow_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_voltage_yellow_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_voltage_yellow_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/onu/onu_window_drift_alarm.py b/pyvoltha/adapters/extensions/events/onu/onu_window_drift_alarm.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/onu/onu_window_drift_alarm.py
rename to pyvoltha/adapters/extensions/events/onu/onu_window_drift_alarm.py
diff --git a/pyvoltha/adapters/extensions/alarms/simulator/README.md b/pyvoltha/adapters/extensions/events/simulator/README.md
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/simulator/README.md
rename to pyvoltha/adapters/extensions/events/simulator/README.md
diff --git a/pyvoltha/adapters/extensions/alarms/simulator/__init__.py b/pyvoltha/adapters/extensions/events/simulator/__init__.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/simulator/__init__.py
rename to pyvoltha/adapters/extensions/events/simulator/__init__.py
diff --git a/pyvoltha/adapters/extensions/alarms/simulator/simulate_alarms.py b/pyvoltha/adapters/extensions/events/simulator/simulate_alarms.py
similarity index 100%
rename from pyvoltha/adapters/extensions/alarms/simulator/simulate_alarms.py
rename to pyvoltha/adapters/extensions/events/simulator/simulate_alarms.py
diff --git a/pyvoltha/adapters/extensions/events/simulator/simulate_events.py b/pyvoltha/adapters/extensions/events/simulator/simulate_events.py
new file mode 100644
index 0000000..06c327e
--- /dev/null
+++ b/pyvoltha/adapters/extensions/events/simulator/simulate_events.py
@@ -0,0 +1,77 @@
+#
+# Copyright 2017 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.
+
+import arrow
+from pyvoltha.adapters.extensions.events.device_events.olt.olt_los_event import OltLosEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_dying_gasp_event import OnuDyingGaspEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_los_event import OnuLosEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_lopc_miss_event import OnuLopcMissEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_lopc_mic_error_event import OnuLopcMicErrorEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_lob_event import OnuLobEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_startup_event import OnuStartupEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_signal_degrade_event import OnuSignalDegradeEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_signal_fail_event import OnuSignalFailEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_window_drift_event import OnuWindowDriftEvent
+from pyvoltha.adapters.extensions.events.device_events.device_events.onu.onu_activation_fail_event import OnuActivationFailEvent
+from pyvoltha.adapters.extensions.events.device_events.onu.device_events.onu.onu_discovery_event import OnuDiscoveryEvent
+
+class AdapterEventSimulator(object):
+    def __init__(self, adapter_events):
+        self.adapter_events = adapter_events
+
+    def simulate_device_events(self, event):
+        raised_ts = arrow.utcnow().timestamp 
+        if event.indicator == "los":
+            event_obj = OltLosEvent(self.adapter_events, intf_id=event.intf_id, port_type_name=event.port_type_name, raised_ts)
+        elif event.indicator == "dying_gasp":
+            event_obj = OnuDyingGaspEvent(self.adapter_events, onu_id=event.onu_device_id, intf_id=event.intf_id, raised_ts)
+        elif event.indicator == "onu_los":
+            event_obj = OnuLosEvent(self.adapter_events, onu_id=event.onu_device_id, intf_id=event.intf_idraised_ts, raised_ts)
+        elif event.indicator == "onu_lopc_miss":
+            event_obj = OnuLopcMissEvent(self.adapter_events, onu_id=event.onu_device_id, intf_id=event.intf_id, raised_ts)
+        elif event.indicator == "onu_lopc_mic":
+            event_obj = OnuLopcMicErrorEvent(self.adapter_events, onu_id=event.onu_device_id, intf_id=event.intf_id, raised_ts)
+        elif event.indicator == "onu_lob":
+            event_obj = OnuLobEvent(self.adapter_events, onu_id=event.onu_device_id, intf_id=event.intf_id, raised_ts)
+        elif event.indicator == "onu_startup":
+            event_obj = OnuStartupEvent(self.adapter_events, intf_id=event.intf_id, onu_id=event.onu_device_id, raised_ts)
+        elif event.indicator == "onu_signal_degrade":
+            event_obj = OnuSignalDegradeEvent(self.adapter_events, intf_id=event.intf_id, onu_id=event.onu_device_id,
+                                  inverse_bit_error_rate=event.inverse_bit_error_rate, raised_ts)
+        elif event.indicator == "onu_drift_of_window":
+            event_obj = OnuWindowDriftEvent(self.adapter_events, intf_id=event.intf_id,
+                                onu_id=event.onu_device_id,
+                                drift=event.drift,
+                                new_eqd=event.new_eqd, raised_ts)
+        elif event.indicator == "onu_signal_fail":
+            event_obj = OnuSignalFailEvent(self.adapter_events, intf_id=event.intf_id,
+                               onu_id=event.onu_device_id,
+                               inverse_bit_error_rate=event.inverse_bit_error_rate, raised_ts)
+        elif event.indicator == "onu_activation":
+            event_obj = OnuActivationFailEvent(self.adapter_events, intf_id=event.intf_id,
+                                   onu_id=event.onu_device_id, raised_ts)
+        elif event.indicator == "onu_discovery":
+            event_obj = OnuDiscoveryEvent(self.adapter_events, pon_id=event.intf_id,
+                                   serial_number=event.onu_serial_number, raised_ts)
+        else:
+            raise Exception("Unknown event indicator %s" % event.indicator)
+
+        if event.operation == event.RAISE:
+            event_obj.send(True)
+        elif event.operation == event.CLEAR:
+            event_obj.send(False)
+        else:
+            # This shouldn't happen
+            raise Exception("Unknown event operation")
diff --git a/pyvoltha/adapters/extensions/omci/state_machines/alarm_sync.py b/pyvoltha/adapters/extensions/omci/state_machines/alarm_sync.py
index 1f1377e..976d1d0 100644
--- a/pyvoltha/adapters/extensions/omci/state_machines/alarm_sync.py
+++ b/pyvoltha/adapters/extensions/omci/state_machines/alarm_sync.py
@@ -579,20 +579,20 @@
         :param alarm_number: (int) Alarm Number
         :return: (AlarmBase) Alarm library alarm or None if not supported/found
         """
-        from pyvoltha.adapters.extensions.alarms.onu.onu_dying_gasp_alarm import OnuDyingGaspAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_los_alarm import OnuLosAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_equipment_alarm import OnuEquipmentAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_selftest_failure_alarm import OnuSelfTestFailureAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_laser_eol_alarm import OnuLaserEolAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_laser_bias_current_alarm import OnuLaserBiasAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_temp_yellow_alarm import OnuTempYellowAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_temp_red_alarm import OnuTempRedAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_voltage_yellow_alarm import OnuVoltageYellowAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_voltage_red_alarm import OnuVoltageRedAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_low_rx_optical_power_alarm import OnuLowRxOpticalAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_high_rx_optical_power_alarm import OnuHighRxOpticalAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_low_tx_optical_power_alarm import OnuLowTxOpticalAlarm
-        from pyvoltha.adapters.extensions.alarms.onu.onu_high_tx_optical_power_alarm import OnuHighTxOpticalAlarm
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_dying_gasp_event import OnuDyingGaspEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_los_event import OnuLosEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_equipment_event import OnuEquipmentEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_selftest_failure_event import OnuSelfTestFailureEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_laser_eol_event import OnuLaserEolEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_laser_bias_current_event import OnuLaserBiasEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_temp_yellow_event import OnuTempYellowEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_temp_red_event import OnuTempRedEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_voltage_yellow_event import OnuVoltageYellowEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_voltage_red_event import OnuVoltageRedEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_low_rx_optical_power_event import OnuLowRxOpticalEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_high_rx_optical_power_event import OnuHighRxOpticalEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_low_tx_optical_power_event import OnuLowTxOpticalEvent
+        from pyvoltha.adapters.extensions.events.device_events.onu.onu_high_tx_optical_power_event import OnuHighTxOpticalEvent
 
         mgr = self._alarm_manager
         if class_id in (CircuitPack.class_id, PptpEthernetUni.class_id):
@@ -606,27 +606,27 @@
             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,
+            (CircuitPack.class_id, 0): OnuEquipmentEvent,
+            (CircuitPack.class_id, 2): OnuSelfTestFailureEvent,
+            (CircuitPack.class_id, 3): OnuLaserEolEvent,
+            (CircuitPack.class_id, 4): OnuTempYellowEvent,
+            (CircuitPack.class_id, 5): OnuTempRedEvent,
 
-            (PptpEthernetUni.class_id, 0): OnuLosAlarm,
+            (PptpEthernetUni.class_id, 0): OnuLosEvent,
 
-            (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,
+            (OntG.class_id, 0): OnuEquipmentEvent,
+            (OntG.class_id, 6): OnuSelfTestFailureEvent,
+            (OntG.class_id, 7): OnuDyingGaspEvent,
+            (OntG.class_id, 8): OnuTempYellowEvent,
+            (OntG.class_id, 9): OnuTempRedEvent,
+            (OntG.class_id, 10): OnuVoltageYellowEvent,
+            (OntG.class_id, 11): OnuVoltageRedEvent,
 
-            (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,
+            (AniG.class_id, 0): OnuLowRxOpticalEvent,
+            (AniG.class_id, 1): OnuHighRxOpticalEvent,
+            (AniG.class_id, 4): OnuLowTxOpticalEvent,
+            (AniG.class_id, 5): OnuHighTxOpticalEvent,
+            (AniG.class_id, 6): OnuLaserBiasEvent,
         }
         alarm_cls = alarm_map.get((class_id, alarm_number))
 
diff --git a/pyvoltha/adapters/kafka/core_proxy.py b/pyvoltha/adapters/kafka/core_proxy.py
index 88cf278..01ea362 100644
--- a/pyvoltha/adapters/kafka/core_proxy.py
+++ b/pyvoltha/adapters/kafka/core_proxy.py
@@ -28,8 +28,7 @@
 from voltha_protos.inter_container_pb2 import StrType, BoolType, IntType, Packet
 from voltha_protos.device_pb2 import Device, Ports, Devices
 from voltha_protos.voltha_pb2 import CoreInstance, AlarmFilterRuleKey
-from voltha_protos.events_pb2 import AlarmEvent, AlarmEventType, \
-    AlarmEventState, AlarmEventCategory, AlarmEventSeverity
+from voltha_protos.events_pb2 import Event
 from voltha_protos.events_pb2 import KpiEvent2, KpiEventType, MetricInformation, MetricMetaData
 
 log = structlog.get_logger()
@@ -40,10 +39,11 @@
 
 class CoreProxy(ContainerProxy):
 
-    def __init__(self, kafka_proxy, default_core_topic, my_listening_topic):
+    def __init__(self, kafka_proxy, default_core_topic, default_event_topic, my_listening_topic):
         super(CoreProxy, self).__init__(kafka_proxy, default_core_topic,
                                         my_listening_topic)
         self.core_default_topic = default_core_topic
+        self.event_default_topic = default_event_topic
         self.deviceId_to_core_map = dict()
 
     def update_device_core_reference(self, device_id, core_topic):
@@ -455,48 +455,7 @@
                                 packet=pac)
         returnValue(res)
         
-    # ~~~~~~~~~~~~~~~~~~~ Handle alarm submissions ~~~~~~~~~~~~~~~~~~~~~
-
-    def create_alarm(self, id=None, resource_id=None, description=None,
-                     raised_ts=0, changed_ts=0,
-                     type=AlarmEventType.EQUIPMENT,
-                     category=AlarmEventCategory.PON,
-                     severity=AlarmEventSeverity.MINOR,
-                     state=AlarmEventState.RAISED,
-                     context=None,
-                     logical_device_id=None,
-                     alarm_type_name=None):
-        # Construct the ID if it is not provided
-        if id is None:
-            id = 'voltha.{}.{}'.format(self.adapter_name, resource_id)
-        log.debug('create alarmevent', id=id,
-            resource_id=resource_id,
-            type=type,
-            category=category,
-            severity=severity,
-            state=state,
-            description=description,
-            reported_ts=arrow.utcnow().timestamp,
-            raised_ts=raised_ts,
-            changed_ts=changed_ts,
-            context=context,
-            logical_device_id=logical_device_id,
-            alarm_type_name=alarm_type_name)
-        return AlarmEvent(
-            id=id,
-            resource_id=resource_id,
-            type=type,
-            category=category,
-            severity=severity,
-            state=state,
-            description=description,
-            reported_ts=arrow.utcnow().timestamp,
-            raised_ts=raised_ts,
-            changed_ts=changed_ts,
-            context=context,
-            logical_device_id=logical_device_id,
-            alarm_type_name=alarm_type_name
-        )
+    # ~~~~~~~~~~~~~~~~~~~ Handle event submissions ~~~~~~~~~~~~~~~~~~~~~
 
     def filter_alarm(self, device_id, alarm_event):
         '''
@@ -544,22 +503,11 @@
         return False
 
     @inlineCallbacks
-    def submit_alarm(self, device_id, alarm_event_msg):
+    def submit_event(self, event_msg):
         try:
-            assert isinstance(alarm_event_msg, AlarmEvent)
-            if not self.filter_alarm(device_id, alarm_event_msg):
-                res = yield self.kafka_proxy._send_kafka_message('alarms', alarm_event_msg)
-                returnValue(res)
-        except Exception as e:
-            log.exception('failed-alarm-submission',
-                        type=type(alarm_event_msg), e=e)
-
-    @inlineCallbacks
-    def submit_kpis(self, kpi_event_msg):
-        try:
-            assert isinstance(kpi_event_msg, KpiEvent2)
-            res = yield self.kafka_proxy._send_kafka_message('kpis', kpi_event_msg)
+            assert isinstance(event_msg, Event)
+            res = yield self.kafka_proxy._send_kafka_message(self.event_default_topic, event_msg)
             returnValue(res)
         except Exception as e:
-            log.exception('failed-kpis-submission',
-                        type=type(kpi_event_msg), e=e)
+            log.exception('failed-event-submission',
+                        type=type(event_msg), e=e)