Openolt data model changes

- store device and logical_device_id in data model
- add new data_model interfaces:
    olt_oper_up()
    olt_oper_down()
    onu_create()
    onu_id()
- pep8 cleanup to openolt_statistics

Change-Id: Ic953d93873f86e0a6370b31b05320a5bbec09518
diff --git a/voltha/adapters/openolt/openolt.py b/voltha/adapters/openolt/openolt.py
index 814c26a..196fb97 100644
--- a/voltha/adapters/openolt/openolt.py
+++ b/voltha/adapters/openolt/openolt.py
@@ -44,6 +44,7 @@
 OpenOltDefaults = {
     'support_classes': {
         'platform': OpenOltPlatform,
+        'data_model': OpenOltDataModel,
         'resource_mgr': OpenOltResourceMgr,
         'flow_mgr': OpenOltFlowMgr,
         'alarm_mgr': OpenOltAlarmMgr,
@@ -80,7 +81,6 @@
         self.interface = registry('main').get_args().interface
         self.logical_device_id_to_root_device_id = dict()
         self.num_devices = 0
-        self.data_model = OpenOltDataModel(adapter_agent)
 
     def start(self):
         log.info('started', interface=self.interface)
@@ -111,7 +111,6 @@
 
         kwargs = {
             'support_classes': OpenOltDefaults['support_classes'],
-            'data_model': self.data_model,
             'adapter_agent': self.adapter_agent,
             'device': device,
             'device_num': self.num_devices + 1
diff --git a/voltha/adapters/openolt/openolt_data_model.py b/voltha/adapters/openolt/openolt_data_model.py
index 14903ae..77c21e0 100644
--- a/voltha/adapters/openolt/openolt_data_model.py
+++ b/voltha/adapters/openolt/openolt_data_model.py
@@ -16,34 +16,48 @@
 import structlog
 import socket
 from voltha.adapters.openolt.openolt_utils import OpenoltUtils
-from voltha.protos.device_pb2 import Port
+from voltha.protos.device_pb2 import Port, Device
 from voltha.protos.openflow_13_pb2 import OFPPS_LIVE, OFPPF_FIBER, \
     OFPPS_LINK_DOWN, OFPPF_1GB_FD, OFPC_PORT_STATS, OFPC_TABLE_STATS, \
     OFPC_FLOW_STATS, OFPC_GROUP_STATS, ofp_port, ofp_port_stats, ofp_desc, \
     ofp_switch_features
 from voltha.core.logical_device_agent import mac_str_to_tuple
 from voltha.protos.logical_device_pb2 import LogicalPort
-from voltha.protos.common_pb2 import OperStatus, ConnectStatus
+from voltha.protos.common_pb2 import OperStatus, AdminState, ConnectStatus
 from voltha.protos.logical_device_pb2 import LogicalDevice
 from voltha.registry import registry
 
 
 class OpenOltDataModel(object):
-    log = structlog.get_logger()
 
-    def __init__(self, adapter_agent):
-        self.adapter_agent = adapter_agent
+    def __init__(self, device, adapter_agent, platform):
         self.log = structlog.get_logger()
 
-    def create_logical_device(self, device_id, device_info):
+        self.device = device
+        self.adapter_agent = adapter_agent
+        self.platform = platform
+        self.logical_device_id = None
+
+        self.device.root = True
+        self.device.connect_status = ConnectStatus.UNREACHABLE
+        self.device.oper_status = OperStatus.ACTIVATING
+
+        self.adapter_agent.update_device(device)
+
+    def reconcile(self):
+        assert self.logical_device_id is not None
+        self.adapter_agent.reconcile_logical_device(
+            self.logical_device_id)
+
+    def olt_create(self, device_info):
+        if self.logical_device_id is not None:
+            return
+
         dpid = device_info.device_id
         serial_number = device_info.device_serial_number
 
-        device = self.adapter_agent.get_device(device_id)
-        host_and_port = device.host_and_port
-
         if dpid is None or dpid == '':
-            uri = host_and_port.split(":")[0]
+            uri = self.device.host_and_port.split(":")[0]
             try:
                 socket.inet_pton(socket.AF_INET, uri)
                 dpid = '00:00:' + OpenoltUtils.ip_hex(uri)
@@ -60,7 +74,7 @@
 
         # Create logical OF device
         ld = LogicalDevice(
-            root_device_id=device_id,
+            root_device_id=self.device.id,
             switch_features=ofp_switch_features(
                 n_buffers=256,  # TODO fake for now
                 n_tables=2,  # TODO ditto
@@ -75,28 +89,29 @@
                 serial_num=serial_number
             )
         )
-        ld_init = self.adapter_agent.create_logical_device(ld,
-                                                           dpid=dpid)
+        self.logical_device_id = \
+            self.adapter_agent.create_logical_device(ld, dpid=dpid).id
 
-        device = self.adapter_agent.get_device(device_id)
-        device.serial_number = serial_number
-        self.adapter_agent.update_device(device)
+        self.device.vendor = device_info.vendor
+        self.device.model = device_info.model
+        self.device.hardware_version = device_info.hardware_version
+        self.device.firmware_version = device_info.firmware_version
+        self.device.connect_status = ConnectStatus.REACHABLE
+        self.device.serial_number = serial_number
+
+        self.adapter_agent.update_device(self.device)
 
         self.log.info('created-openolt-logical-device',
-                      logical_device_id=ld_init.id)
+                      logical_device_id=self.logical_device_id)
 
-        return ld_init.id
+        return self.logical_device_id
 
-    def disable_logical_device(self, device_id):
+    def disable_logical_device(self):
 
         oper_state = OperStatus.UNKNOWN
         connect_state = ConnectStatus.UNREACHABLE
 
-        device = self.adapter_agent.get_device(device_id)
-
-        logical_device_id = device.parent_id
-
-        child_devices = self.adapter_agent.get_child_devices(device_id)
+        child_devices = self.adapter_agent.get_child_devices(self.device.id)
         for onu_device in child_devices:
             onu_adapter_agent = \
                 registry('adapter_loader').get_agent(onu_device.adapter)
@@ -106,32 +121,31 @@
 
         # Children devices
         self.adapter_agent.update_child_devices_state(
-            device_id, oper_status=oper_state,
+            self.device.id, oper_status=oper_state,
             connect_status=connect_state)
         # Device Ports
-        device_ports = self.adapter_agent.get_ports(device_id,
+        device_ports = self.adapter_agent.get_ports(self.device.id,
                                                     Port.ETHERNET_NNI)
         logical_ports_ids = [port.label for port in device_ports]
-        device_ports += self.adapter_agent.get_ports(device_id,
+        device_ports += self.adapter_agent.get_ports(self.device.id,
                                                      Port.PON_OLT)
 
         for port in device_ports:
             port.oper_status = oper_state
-            self.adapter_agent.add_port(device_id, port)
+            self.adapter_agent.add_port(self.device.id, port)
 
         # Device logical port
         for logical_port_id in logical_ports_ids:
             logical_port = self.adapter_agent.get_logical_port(
-                logical_device_id, logical_port_id)
+                self.logical_device_id, logical_port_id)
             logical_port.ofp_port.state = OFPPS_LINK_DOWN
             self.adapter_agent.update_logical_port(self.logical_device_id,
                                                    logical_port)
-        device.oper_status = oper_state
-        device.connect_status = connect_state
-        self.adapter_agent.update_device(device)
+        self.device.oper_status = oper_state
+        self.device.connect_status = connect_state
+        self.adapter_agent.update_device(self.device)
 
-    def add_logical_port(self, logical_device_id, device_id, port_no, intf_id,
-                         oper_state):
+    def add_logical_port(self, port_no, intf_id, oper_state):
         self.log.info('adding-logical-port', port_no=port_no)
 
         label = OpenoltUtils.port_name(port_no, Port.ETHERNET_NNI)
@@ -156,8 +170,58 @@
         ofp_stats = ofp_port_stats(port_no=port_no)
 
         logical_port = LogicalPort(
-            id=label, ofp_port=ofp, device_id=device_id,
+            id=label, ofp_port=ofp, device_id=self.device.id,
             device_port_no=port_no, root_port=True,
             ofp_port_stats=ofp_stats)
 
-        self.adapter_agent.add_logical_port(logical_device_id, logical_port)
+        self.adapter_agent.add_logical_port(self.logical_device_id,
+                                            logical_port)
+
+    def olt_oper_up(self):
+        self.device.parent_id = self.logical_device_id
+        self.device.oper_status = OperStatus.ACTIVE
+        self.adapter_agent.update_device(self.device)
+
+    def olt_oper_down(self):
+        self.disable_logical_device()
+
+    def onu_create(self, intf_id, onu_id, serial_number):
+
+        onu_device = self.adapter_agent.get_child_device(
+            self.device.id,
+            serial_number=serial_number)
+
+        if onu_device:
+            self.log.debug("data_model onu update", intf_id=intf_id,
+                           onu_id=onu_id, serial_number=serial_number)
+            onu_device.oper_status = OperStatus.DISCOVERED
+            onu_device.connect_status = ConnectStatus.REACHABLE
+            self.adapter_agent.update_device(onu_device)
+            return
+
+        self.log.debug("data_model onu create", intf_id=intf_id,
+                       onu_id=onu_id, serial_number=serial_number)
+
+        # NOTE - channel_id of onu is set to intf_id
+        proxy_address = Device.ProxyAddress(device_id=self.device.id,
+                                            channel_id=intf_id, onu_id=onu_id,
+                                            onu_session_id=onu_id)
+        port_no = self.platform.intf_id_to_port_no(intf_id, Port.PON_OLT)
+        vendor_id = serial_number[:4]
+        self.adapter_agent.add_onu_device(
+            parent_device_id=self.device.id, parent_port_no=port_no,
+            vendor_id=vendor_id, proxy_address=proxy_address,
+            root=False, serial_number=serial_number,
+            admin_state=AdminState.ENABLED,
+            connect_status=ConnectStatus.REACHABLE
+        )
+
+    def onu_id(self, serial_number):
+        onu_device = self.adapter_agent.get_child_device(
+            self.device.id,
+            serial_number=serial_number)
+
+        if onu_device:
+            return onu_device.proxy_address.onu_id
+        else:
+            return 0  # Invalid onu id
diff --git a/voltha/adapters/openolt/openolt_device.py b/voltha/adapters/openolt/openolt_device.py
index ed3dc06..1793a43 100644
--- a/voltha/adapters/openolt/openolt_device.py
+++ b/voltha/adapters/openolt/openolt_device.py
@@ -22,7 +22,7 @@
 from scapy.layers.l2 import Ether, Dot1Q
 from transitions import Machine
 
-from voltha.protos.device_pb2 import Port, Device
+from voltha.protos.device_pb2 import Port
 from voltha.protos.common_pb2 import OperStatus, AdminState, ConnectStatus
 from voltha.protos.openflow_13_pb2 import OFPPS_LINK_DOWN
 from voltha.registry import registry
@@ -76,12 +76,13 @@
 
         self.admin_state = "up"
 
-        self.data_model = kwargs['data_model']
         self.adapter_agent = kwargs['adapter_agent']
         self.device_num = kwargs['device_num']
         device = kwargs['device']
 
+        self.data_model_class = kwargs['support_classes']['data_model']
         self.platform_class = kwargs['support_classes']['platform']
+        self.platform = self.platform_class()
         self.resource_mgr_class = kwargs['support_classes']['resource_mgr']
         self.flow_mgr_class = kwargs['support_classes']['flow_mgr']
         self.alarm_mgr_class = kwargs['support_classes']['alarm_mgr']
@@ -98,26 +99,16 @@
 
         self.log.info('openolt-device-init')
 
-        # Device already set in the event of reconciliation
         if not is_reconciliation:
-            self.log.info('updating-device')
-            # It is a new device
-            # Update device
-            device.root = True
-            device.connect_status = ConnectStatus.UNREACHABLE
-            device.oper_status = OperStatus.ACTIVATING
-            self.adapter_agent.update_device(device)
-
-        # If logical device does exist use it, else create one after connecting
-        # to device
-        if device.parent_id:
-            # logical device already exists
-            self.logical_device_id = device.parent_id
-            if is_reconciliation:
-                self.adapter_agent.reconcile_logical_device(
-                    self.logical_device_id)
+            self.log.info('create data model')
+            self.data_model = self.data_model_class(device,
+                                                    self.adapter_agent,
+                                                    self.platform)
         else:
-            self.logical_device_id = None
+            self.log.info('reconcile data model')
+            assert device.parent_id is not None
+            assert self.data_model is not None
+            self.data_model.reconcile()
 
         # Initialize the OLT state machine
         self.machine = Machine(model=self, states=OpenoltDevice.states,
@@ -162,60 +153,30 @@
                and self.device_info.device_serial_number is not None
                and self.device_info.device_serial_number != '')
 
-        device = self.adapter_agent.get_device(self.device_id)
-
-        if self.logical_device_id is None:
-            # first time connect to olt
-            self.logical_device_id = self.data_model.create_logical_device(
-                self.device_id, self.device_info)
-        else:
-            # reconnect to olt (e.g. olt reboot)
-            # TODO - Update logical device with new device_info
-            pass
-
-        device.serial_number = self.device_info.device_serial_number
+        self.data_model.olt_create(self.device_info)
 
         self.resource_mgr = self.resource_mgr_class(self.device_id,
                                                     self.host_and_port,
                                                     self.extra_args,
                                                     self.device_info)
-        self.platform = self.platform_class()
         self.flow_mgr = self.flow_mgr_class(self.adapter_agent, self.log,
                                             self.stub, self.device_id,
-                                            self.logical_device_id,
+                                            self.data_model.logical_device_id,
                                             self.platform, self.resource_mgr)
 
-        self.alarm_mgr = self.alarm_mgr_class(self.log, self.adapter_agent,
-                                              self.device_id,
-                                              self.logical_device_id,
-                                              self.platform)
+        self.alarm_mgr = self.alarm_mgr_class(
+            self.log, self.adapter_agent, self.device_id,
+            self.data_model.logical_device_id, self.platform)
         self.stats_mgr = self.stats_mgr_class(self, self.log, self.platform)
         self.bw_mgr = self.bw_mgr_class(self.log, self.proxy)
 
-        device.vendor = self.device_info.vendor
-        device.model = self.device_info.model
-        device.hardware_version = self.device_info.hardware_version
-        device.firmware_version = self.device_info.firmware_version
-
-        # TODO: check for uptime and reboot if too long (VOL-1192)
-
-        device.connect_status = ConnectStatus.REACHABLE
-        self.adapter_agent.update_device(device)
-
     def do_state_up(self, event):
         self.log.debug("do_state_up")
-
-        device = self.adapter_agent.get_device(self.device_id)
-
-        # Update phys OF device
-        device.parent_id = self.logical_device_id
-        device.oper_status = OperStatus.ACTIVE
-        self.adapter_agent.update_device(device)
+        self.data_model.olt_oper_up()
 
     def do_state_down(self, event):
         self.log.debug("do_state_down")
-
-        self.data_model.disable_logical_device(self.device_id)
+        self.data_model.olt_oper_down()
 
     def post_down(self, event):
         self.log.debug('post_down')
@@ -343,8 +304,7 @@
             port_no, label = self.add_port(intf_oper_indication.intf_id,
                                            Port.ETHERNET_NNI, oper_state)
             self.log.debug("int_oper_indication", port_no=port_no, label=label)
-            self.data_model.add_logical_port(self.logical_device_id,
-                                             self.device_id, port_no,
+            self.data_model.add_logical_port(port_no,
                                              intf_oper_indication.intf_id,
                                              oper_state)
 
@@ -355,7 +315,6 @@
     def onu_discovery_indication(self, onu_disc_indication):
         intf_id = onu_disc_indication.intf_id
         serial_number = onu_disc_indication.serial_number
-
         serial_number_str = OpenoltUtils.stringify_serial_number(serial_number)
 
         self.log.debug("onu discovery indication", intf_id=intf_id,
@@ -370,58 +329,16 @@
                                errmsg=disc_alarm_error.message)
             # continue for now.
 
-        onu_device = self.adapter_agent.get_child_device(
-            self.device_id,
-            serial_number=serial_number_str)
+        onu_id = self.data_model.onu_id(serial_number_str)
 
-        if onu_device is None:
-            try:
-                onu_id = self.resource_mgr.get_onu_id(intf_id)
-                if onu_id is None:
-                    raise Exception("onu-id-unavailable")
+        if onu_id == 0:
+            onu_id = self.resource_mgr.get_onu_id(intf_id)
+            if onu_id is None:
+                raise Exception("onu-id-unavailable")
 
-                self.add_onu_device(
-                    intf_id,
-                    self.platform.intf_id_to_port_no(intf_id, Port.PON_OLT),
-                    onu_id, serial_number)
-                self.activate_onu(intf_id, onu_id, serial_number,
-                                  serial_number_str)
-            except Exception as e:
-                self.log.exception('onu-activation-failed', e=e)
+        self.data_model.onu_create(intf_id, onu_id, serial_number_str)
 
-        else:
-            if onu_device.connect_status != ConnectStatus.REACHABLE:
-                onu_device.connect_status = ConnectStatus.REACHABLE
-                self.adapter_agent.update_device(onu_device)
-
-            onu_id = onu_device.proxy_address.onu_id
-            if onu_device.oper_status == OperStatus.DISCOVERED \
-                    or onu_device.oper_status == OperStatus.ACTIVATING:
-                self.log.debug("ignore onu discovery indication, \
-                               the onu has been discovered and should be \
-                               activating shorlty", intf_id=intf_id,
-                               onu_id=onu_id, state=onu_device.oper_status)
-            elif onu_device.oper_status == OperStatus.ACTIVE:
-                self.log.warn("onu discovery indication whereas onu is \
-                              supposed to be active",
-                              intf_id=intf_id, onu_id=onu_id,
-                              state=onu_device.oper_status)
-            elif onu_device.oper_status == OperStatus.UNKNOWN:
-                self.log.info("onu in unknown state, recovering from olt \
-                              reboot probably, activate onu", intf_id=intf_id,
-                              onu_id=onu_id, serial_number=serial_number_str)
-
-                onu_device.oper_status = OperStatus.DISCOVERED
-                self.adapter_agent.update_device(onu_device)
-                try:
-                    self.activate_onu(intf_id, onu_id, serial_number,
-                                      serial_number_str)
-                except Exception as e:
-                    self.log.error('onu-activation-error',
-                                   serial_number=serial_number_str, error=e)
-            else:
-                self.log.warn('unexpected state', onu_id=onu_id,
-                              onu_device_oper_state=onu_device.oper_status)
+        self.activate_onu(intf_id, onu_id, serial_number, serial_number_str)
 
     def onu_indication(self, onu_indication):
         self.log.debug("onu indication", intf_id=onu_indication.intf_id,
@@ -429,22 +346,12 @@
                        serial_number=onu_indication.serial_number,
                        oper_state=onu_indication.oper_state,
                        admin_state=onu_indication.admin_state)
-        try:
-            serial_number_str = OpenoltUtils.stringify_serial_number(
-                onu_indication.serial_number)
-        except:  # noqa: E722
-            serial_number_str = None
 
-        if serial_number_str is not None:
-            onu_device = self.adapter_agent.get_child_device(
-                self.device_id,
-                serial_number=serial_number_str)
-        else:
-            onu_device = self.adapter_agent.get_child_device(
-                self.device_id,
-                parent_port_no=self.platform.intf_id_to_port_no(
-                    onu_indication.intf_id, Port.PON_OLT),
-                onu_id=onu_indication.onu_id)
+        onu_device = self.adapter_agent.get_child_device(
+            self.device_id,
+            parent_port_no=self.platform.intf_id_to_port_no(
+                onu_indication.intf_id, Port.PON_OLT),
+            onu_id=onu_indication.onu_id)
 
         if onu_device is None:
             self.log.error('onu not found', intf_id=onu_indication.intf_id,
@@ -556,11 +463,11 @@
             onu_port_id = onu_port.label
             try:
                 onu_logical_port = self.adapter_agent.get_logical_port(
-                    logical_device_id=self.logical_device_id,
+                    logical_device_id=self.data_model.logical_device_id,
                     port_id=onu_port_id)
                 onu_logical_port.ofp_port.state = OFPPS_LINK_DOWN
                 self.adapter_agent.update_logical_port(
-                    logical_device_id=self.logical_device_id,
+                    logical_device_id=self.data_model.logical_device_id,
                     port=onu_logical_port)
                 self.log.debug('cascading-oper-state-to-port-and-logical-port')
             except KeyError as e:
@@ -625,11 +532,11 @@
         pkt = Ether(pkt_indication.pkt)
 
         self.log.debug("packet indication",
-                       logical_device_id=self.logical_device_id,
+                       logical_device_id=self.data_model.logical_device_id,
                        logical_port_no=logical_port_num)
 
         self.adapter_agent.send_packet_in(
-            logical_device_id=self.logical_device_id,
+            logical_device_id=self.data_model.logical_device_id,
             logical_port_no=logical_port_num,
             packet=str(pkt))
 
@@ -637,7 +544,7 @@
         pkt = Ether(msg)
         self.log.debug('packet out', egress_port=egress_port,
                        device_id=self.device_id,
-                       logical_device_id=self.logical_device_id,
+                       logical_device_id=self.data_model.logical_device_id,
                        packet=str(pkt).encode("HEX"))
 
         # Find port type
@@ -709,26 +616,6 @@
                                    onu_id=proxy_address.onu_id, pkt=str(msg))
         self.stub.OmciMsgOut(omci)
 
-    def add_onu_device(self, intf_id, port_no, onu_id, serial_number):
-        self.log.info("Adding ONU", port_no=port_no, onu_id=onu_id,
-                      serial_number=serial_number)
-
-        # NOTE - channel_id of onu is set to intf_id
-        proxy_address = Device.ProxyAddress(device_id=self.device_id,
-                                            channel_id=intf_id, onu_id=onu_id,
-                                            onu_session_id=onu_id)
-
-        self.log.debug("Adding ONU", proxy_address=proxy_address)
-
-        serial_number_str = OpenoltUtils.stringify_serial_number(serial_number)
-
-        self.adapter_agent.add_onu_device(
-            parent_device_id=self.device_id, parent_port_no=port_no,
-            vendor_id=serial_number.vendor_id, proxy_address=proxy_address,
-            root=False, serial_number=serial_number_str,
-            admin_state=AdminState.ENABLED
-        )
-
     def add_port(self, intf_id, port_type, oper_status):
         port_no = self.platform.intf_id_to_port_no(intf_id, port_type)
 
@@ -746,16 +633,15 @@
 
     def get_uni_ofp_port_name(self, child_device):
         logical_ports = self.proxy.get('/logical_devices/{}/ports'.format(
-            self.logical_device_id))
+            self.data_model.logical_device_id))
         for logical_port in logical_ports:
             if logical_port.device_id == child_device.id:
                 return logical_port.ofp_port.name
         return None
 
-
     def delete_logical_port(self, child_device):
         logical_ports = self.proxy.get('/logical_devices/{}/ports'.format(
-            self.logical_device_id))
+            self.data_model.logical_device_id))
         for logical_port in logical_ports:
             if logical_port.device_id == child_device.id:
                 self.log.debug('delete-logical-port',
@@ -764,7 +650,7 @@
                 self.flow_mgr.clear_flows_and_scheduler_for_logical_port(
                     child_device, logical_port)
                 self.adapter_agent.delete_logical_port(
-                    self.logical_device_id, logical_port)
+                    self.data_model.logical_device_id, logical_port)
                 return
 
     def delete_port(self, child_serial_number):
@@ -828,7 +714,7 @@
 
     def delete(self):
         self.log.info('deleting-olt', device_id=self.device_id,
-                      logical_device_id=self.logical_device_id)
+                      logical_device_id=self.data_model.logical_device_id)
 
         # Clears up the data from the resource manager KV store
         # for the device
@@ -838,7 +724,8 @@
             # Rebooting to reset the state
             self.reboot()
             # Removing logical device
-            ld = self.adapter_agent.get_logical_device(self.logical_device_id)
+            ld = self.adapter_agent.get_logical_device(
+                self.data_model.logical_device_id)
             self.adapter_agent.delete_logical_device(ld)
         except Exception as e:
             self.log.error('Failure to delete openolt device', error=e)
@@ -918,9 +805,10 @@
             self.log.exception("error-removing-pon-resources-for-onu")
 
         try:
-            onu = openolt_pb2.Onu(intf_id=child_device.proxy_address.channel_id,
-                                  onu_id=child_device.proxy_address.onu_id,
-                                  serial_number=serial_number)
+            onu = openolt_pb2.Onu(
+                intf_id=child_device.proxy_address.channel_id,
+                onu_id=child_device.proxy_address.onu_id,
+                serial_number=serial_number)
             self.stub.DeleteOnu(onu)
         except Exception as e:
             self.log.exception("error-deleting-the-onu-on-olt-device")
diff --git a/voltha/adapters/openolt/openolt_statistics.py b/voltha/adapters/openolt/openolt_statistics.py
index bfdb61c..7f3aad5 100644
--- a/voltha/adapters/openolt/openolt_statistics.py
+++ b/voltha/adapters/openolt/openolt_statistics.py
@@ -20,9 +20,9 @@
 # from voltha.adapters.openolt.pon_port import PonPort
 # from voltha.protos.device_pb2 import Port
 
-from twisted.internet import reactor, defer
+from twisted.internet import reactor
 from voltha.extensions.kpi.olt.olt_pm_metrics import OltPmMetrics
-from voltha.protos.device_pb2 import PmConfig, PmConfigs, PmGroupConfig, Port
+from voltha.protos.device_pb2 import PmConfig, Port
 
 
 class OpenOltStatisticsMgr(object):
@@ -46,37 +46,44 @@
         # The following can be used to allow a standalone test routine to start
         # the metrics independently
         self.metrics_init = kargs.pop("metrics_init", True)
-        if self.metrics_init == True:
+        if self.metrics_init is True:
             self.init_pm_metrics()
 
     def init_pm_metrics(self):
         # Setup PM configuration for this device
         if self.pm_metrics is None:
             try:
-                self.device.reason = 'setting up Performance Monitoring configuration'
+                self.device.reason = \
+                    'setting up Performance Monitoring configuration'
                 kwargs = {
                     'nni-ports': self.northbound_ports.values(),
                     'pon-ports': self.southbound_ports.values()
                 }
-                self.pm_metrics = OltPmMetrics(self.device.adapter_agent, self.device.device_id,
-                                               self.device.logical_device_id,
-                                               grouped=True, freq_override=False,
-                                               **kwargs)
+                self.pm_metrics = OltPmMetrics(
+                    self.device.adapter_agent, self.device.device_id,
+                    self.device.data_model.logical_device_id,
+                    grouped=True, freq_override=False, **kwargs)
                 """
-                    override the default naming structures in the OltPmMetrics class.
-                    This is being done until the protos can be modified in the BAL driver
+                override the default naming structures in the OltPmMetrics
+                class. This is being done until the protos can be modified in
+                the BAL driver
 
                 """
-                self.pm_metrics.nni_pm_names = (self.get_openolt_port_pm_names())['nni_pm_names']
-                self.pm_metrics.nni_metrics_config = {m: PmConfig(name=m, type=t, enabled=True)
-                                                 for (m, t) in self.pm_metrics.nni_pm_names}
+                self.pm_metrics.nni_pm_names = \
+                    (self.get_openolt_port_pm_names())['nni_pm_names']
+                self.pm_metrics.nni_metrics_config = \
+                    {m: PmConfig(name=m, type=t, enabled=True)
+                     for (m, t) in self.pm_metrics.nni_pm_names}
 
-                self.pm_metrics.pon_pm_names = (self.get_openolt_port_pm_names())['pon_pm_names']
-                self.pm_metrics.pon_metrics_config = {m: PmConfig(name=m, type=t, enabled=True)
-                                                 for (m, t) in self.pm_metrics.pon_pm_names}
+                self.pm_metrics.pon_pm_names = \
+                    (self.get_openolt_port_pm_names())['pon_pm_names']
+                self.pm_metrics.pon_metrics_config = \
+                    {m: PmConfig(name=m, type=t, enabled=True)
+                     for (m, t) in self.pm_metrics.pon_pm_names}
                 pm_config = self.pm_metrics.make_proto()
                 self.log.info("initial-pm-config", pm_config=pm_config)
-                self.device.adapter_agent.update_device_pm_config(pm_config, init=True)
+                self.device.adapter_agent.update_device_pm_config(pm_config,
+                                                                  init=True)
                 # Start collecting stats from the device after a brief pause
                 reactor.callLater(10, self.pm_metrics.start_collector)
             except Exception as e:
@@ -85,7 +92,7 @@
     def port_statistics_indication(self, port_stats):
         # self.log.info('port-stats-collected', stats=port_stats)
         self.ports_statistics_kpis(port_stats)
-        #FIXME: etcd problem, do not update objects for now
+        # FIXME: etcd problem, do not update objects for now
 
         #
         #
@@ -118,7 +125,7 @@
         # FIXME: etcd problem, do not update objects for now
         # # UNTESTED : the openolt driver does not yet provide flow stats
         # self.device.adapter_agent.update_flow_stats(
-        #       self.device.logical_device_id,
+        #       self.device.data_model.logical_device_id,
         #       flow_id=flow_stats.flow_id, packet_count=flow_stats.tx_packets,
         #       byte_count=flow_stats.tx_bytes)
 
@@ -134,8 +141,9 @@
         try:
             intf_id = port_stats.intf_id
 
-            if self.platform.intf_id_to_port_no(0, Port.ETHERNET_NNI) < intf_id < \
-                    self.platform.intf_id_to_port_no(4, Port.ETHERNET_NNI) :
+            if self.platform.intf_id_to_port_no(0, Port.ETHERNET_NNI) \
+                    < intf_id \
+                    < self.platform.intf_id_to_port_no(4, Port.ETHERNET_NNI):
                 """
                 for this release we are only interested in the first NNI for
                 Northbound.
@@ -163,42 +171,47 @@
                 pm_data["intf_id"] = intf_id
 
                 """
-                   Based upon the intf_id map to an nni port or a pon port
-                    the intf_id is the key to the north or south bound collections
+                Based upon the intf_id map to an nni port or a pon port the
+                intf_id is the key to the north or south bound collections
 
-                    Based upon the intf_id the port object (nni_port or pon_port) will
-                    have its data attr. updated by the current dataset collected.
+                Based upon the intf_id the port object (nni_port or pon_port)
+                will have its data attr. updated by the current dataset
+                collected.
 
-                    For prefixing the rule is currently to use the port number and not the intf_id
-
+                For prefixing the rule is currently to use the port number and
+                not the intf_id
                 """
-                #FIXME : Just use first NNI for now
-                if intf_id == self.platform.intf_id_to_port_no(0,
-                                                          Port.ETHERNET_NNI):
-                    #NNI port (just the first one)
+                # FIXME : Just use first NNI for now
+                if intf_id == self.platform.intf_id_to_port_no(
+                        0, Port.ETHERNET_NNI):
+                    # NNI port (just the first one)
                     self.update_port_object_kpi_data(
-                        port_object=self.northbound_ports[port_stats.intf_id], datadict=pm_data)
+                        port_object=self.northbound_ports[port_stats.intf_id],
+                        datadict=pm_data)
                 else:
-                    #PON ports
+                    # PON ports
                     self.update_port_object_kpi_data(
-                        port_object=self.southbound_ports[port_stats.intf_id],datadict=pm_data)
+                        port_object=self.southbound_ports[port_stats.intf_id],
+                        datadict=pm_data)
         except Exception as err:
-            self.log.exception("Error publishing kpi statistics. ", errmessage=err)
+            self.log.exception("Error publishing kpi statistics. ",
+                               errmessage=err)
 
     def update_logical_port_stats(self, port_stats):
         try:
             label = 'nni-{}'.format(port_stats.intf_id)
             logical_port = self.device.adapter_agent.get_logical_port(
-                self.device.logical_device_id, label)
+                self.device.data_model.logical_device_id, label)
         except KeyError as e:
             self.log.warn('logical port was not found, it may not have been '
                           'created yet', exception=e)
             return
 
         if logical_port is None:
-            self.log.error('logical-port-is-None',
-                logical_device_id=self.device.logical_device_id, label=label,
-                port_stats=port_stats)
+            self.log.error(
+                'logical-port-is-None',
+                logical_device_id=self.device.data_model.logical_device_id,
+                label=label, port_stats=port_stats)
             return
 
         logical_port.ofp_port_stats.rx_packets = port_stats.rx_packets
@@ -212,13 +225,14 @@
         self.log.debug('after-stats-update', port=logical_port)
 
         self.device.adapter_agent.update_logical_port(
-            self.device.logical_device_id, logical_port)
+            self.device.data_model.logical_device_id, logical_port)
 
     """
-    The following 4 methods customer naming, the generation of the port objects, building of those
-    objects and populating new data.   The pm metrics operate on the value that are contained in the Port objects.
-    This class updates those port objects with the current data from the grpc indication and
-    post the data on a fixed interval.
+    The following 4 methods customer naming, the generation of the port
+    objects, building of those objects and populating new data.
+    The pm metrics operate on the value that are contained in the Port objects.
+    This class updates those port objects with the current data from the grpc
+    indication and post the data on a fixed interval.
 
     """
     def get_openolt_port_pm_names(self):
@@ -226,15 +240,16 @@
         This collects a dictionary of the custom port names
         used by the openolt.
 
-        Some of these are the same as the pm names used by the olt_pm_metrics class
-        if the set is the same then there is no need to call this method.   However, when
-        custom names are used in the protos then the specific names should be pushed into
-        the olt_pm_metrics class.
+        Some of these are the same as the pm names used by the olt_pm_metrics
+        class if the set is the same then there is no need to call this
+        method. However, when custom names are used in the protos then the
+        specific names should be pushed into the olt_pm_metrics class.
 
         :return:
         """
         nni_pm_names = {
-            ('intf_id', PmConfig.CONTEXT),  # Physical device interface ID/Port number
+            # Physical device interface ID/Port number
+            ('intf_id', PmConfig.CONTEXT),
 
             ('admin_state', PmConfig.STATE),
             ('oper_status', PmConfig.STATE),
@@ -252,8 +267,10 @@
             ('tx_bcast_packets', PmConfig.COUNTER),
             ('tx_error_packets', PmConfig.COUNTER)
         }
+        '''
         nni_pm_names_from_kpi_extension = {
-            ('intf_id', PmConfig.CONTEXT),  # Physical device interface ID/Port number
+            # Physical device interface ID/Port number
+            ('intf_id', PmConfig.CONTEXT),
 
             ('admin_state', PmConfig.STATE),
             ('oper_status', PmConfig.STATE),
@@ -274,8 +291,10 @@
             ('rx_crc_errors', PmConfig.COUNTER),
             ('bip_errors', PmConfig.COUNTER),
         }
+        '''
 
-        # pon_names uses same structure as nmi_names with the addition of pon_id to context
+        # pon_names uses same structure as nmi_names with the addition of
+        # pon_id to context
         pon_pm_names = {
             ('pon_id', PmConfig.CONTEXT),  # PON ID (0..n)
             ('port_no', PmConfig.CONTEXT),
@@ -296,8 +315,8 @@
             ('tx_error_packets', PmConfig.COUNTER)
         }
         pon_pm_names_from_kpi_extension = {
-            ('intf_id', PmConfig.CONTEXT),        # Physical device port number (PON)
-            ('pon_id', PmConfig.CONTEXT),         # PON ID (0..n)
+            ('intf_id', PmConfig.CONTEXT),  # Physical device port number (PON)
+            ('pon_id', PmConfig.CONTEXT),   # PON ID (0..n)
 
             ('admin_state', PmConfig.STATE),
             ('oper_status', PmConfig.STATE),
@@ -310,7 +329,7 @@
             ('closest_onu_distance', PmConfig.GAUGE)
         }
         onu_pm_names = {
-            ('intf_id', PmConfig.CONTEXT),        # Physical device port number (PON)
+            ('intf_id', PmConfig.CONTEXT),  # Physical device port number (PON)
             ('pon_id', PmConfig.CONTEXT),
             ('onu_id', PmConfig.CONTEXT),
 
@@ -319,7 +338,7 @@
             ('rssi', PmConfig.GAUGE),
         }
         gem_pm_names = {
-            ('intf_id', PmConfig.CONTEXT),        # Physical device port number (PON)
+            ('intf_id', PmConfig.CONTEXT),  # Physical device port number (PON)
             ('pon_id', PmConfig.CONTEXT),
             ('onu_id', PmConfig.CONTEXT),
             ('gem_id', PmConfig.CONTEXT),
@@ -330,7 +349,8 @@
             ('tx_packets', PmConfig.COUNTER),
             ('tx_bytes', PmConfig.COUNTER),
         }
-        # Build a dict for the names.  The caller will index to the correct values
+        # Build a dict for the names. The caller will index to the correct
+        # values
         names_dict = {"nni_pm_names": nni_pm_names,
                       "pon_pm_names": pon_pm_names,
                       "pon_pm_names_orig": pon_pm_names_from_kpi_extension,
@@ -343,12 +363,12 @@
 
     def init_ports(self,  device_id=12345, type="nni", log=None):
         """
-        This method collects the port objects:  nni and pon that are updated with the
-        current data from the OLT
+        This method collects the port objects:  nni and pon that are updated
+        with the current data from the OLT
 
-        Both the northbound (nni) and southbound ports are indexed by the interface id (intf_id)
-        and NOT the port number. When the port object is instantiated it will contain the intf_id and
-        port_no values
+        Both the northbound (nni) and southbound ports are indexed by the
+        interface id (intf_id) and NOT the port number. When the port object
+        is instantiated it will contain the intf_id and port_no values
 
         :param type:
         :param device_id:
@@ -369,7 +389,8 @@
                     pon_ports[pon_port.intf_id] = pon_port
                 return pon_ports
             else:
-                self.log.exception("Unmapped port type requested = " , type=type)
+                self.log.exception("Unmapped port type requested = ",
+                                   type=type)
                 raise Exception("Unmapped port type requested = " + type)
 
         except Exception as err:
@@ -392,12 +413,12 @@
             if type == "nni":
                 kwargs = {
                     'port_no': port_num,
-                    'intf_id': self.platform.intf_id_to_port_no(port_num,
-                                                           Port.ETHERNET_NNI),
+                    'intf_id': self.platform.intf_id_to_port_no(
+                        port_num, Port.ETHERNET_NNI),
                     "device_id": self.device.device_id
                 }
                 nni_port = NniPort
-                port = nni_port( **kwargs)
+                port = nni_port(**kwargs)
                 return port
             elif type == "pon":
                 # PON ports require a different configuration
@@ -405,9 +426,9 @@
                 kwargs = {
                     'port_no': port_num,
                     'intf_id':  self.platform.intf_id_to_port_no(port_num,
-                                                           Port.PON_OLT),
+                                                                 Port.PON_OLT),
                     'pon-id':  self.platform.intf_id_to_port_no(port_num,
-                                                           Port.PON_OLT),
+                                                                Port.PON_OLT),
                     "device_id": self.device.device_id
                 }
                 pon_port = PonPort
@@ -449,7 +470,8 @@
                 raise Exception("Must be either PON or NNI port.")
             return
         except Exception as err:
-            self.log.exception("Caught error updating port data: ", cur_attr=cur_attr, errormsg=err.message)
+            self.log.exception("Caught error updating port data: ",
+                               cur_attr=cur_attr, errormsg=err.message)
             raise Exception(err)
 
 
@@ -488,10 +510,11 @@
         self.port_no = 0  #handled by getter
         self.port_id = 0  #handled by getter
 
-        Note:  In the current implementation of the kpis coming from the BAL the stats are the
-        samne model for NNI and PON.
+        Note:  In the current implementation of the kpis coming from the BAL
+        the stats are the same model for NNI and PON.
 
-        TODO:   Integrate additional kpis for the PON and other southbound port objecgts.
+        TODO: Integrate additional kpis for the PON and other southbound port
+        objects.
 
         """
 
@@ -509,10 +532,8 @@
         return
 
     def __str__(self):
-        return "PonPort-{}: Admin: {}, Oper: {}, OLT: {}".format(self._label,
-                                                                 self._admin_state,
-                                                                 self._oper_status,
-                                                                 self.olt)
+        return "PonPort-{}: Admin: {}, Oper: {}, OLT: {}".format(
+            self._label, self._admin_state, self._oper_status, self.olt)
 
     @property
     def intf_id(self):
@@ -549,12 +570,13 @@
     @property
     def onus(self):
         """
-        Get a set of all ONUs.  While the set is immutable, do not use this method
-        to get a collection that you will iterate through that my yield the CPU
-        such as inline callback.  ONUs may be deleted at any time and they will
-        set some references to other objects to NULL during the 'delete' call.
-        Instead, get a list of ONU-IDs and iterate on these and call the 'onu'
-        method below (which will return 'None' if the ONU has been deleted.
+        Get a set of all ONUs.  While the set is immutable, do not use this
+        method to get a collection that you will iterate through that my yield
+        the CPU such as inline callback.  ONUs may be deleted at any time and
+        they will set some references to other objects to NULL during the
+        'delete' call. Instead, get a list of ONU-IDs and iterate on these and
+        call the 'onu' method below (which will return 'None' if the ONU has
+        been deleted.
 
         :return: (frozenset) collection of ONU objects on this PON
         """
@@ -600,7 +622,5 @@
         return
 
     def __str__(self):
-        return "NniPort-{}: Admin: {}, Oper: {}, parent: {}".format(self._port_no,
-                                                                    self._admin_state,
-                                                                    self._oper_status,
-                                                                    self._parent)
+        return "NniPort-{}: Admin: {}, Oper: {}, parent: {}".format(
+            self._port_no, self._admin_state, self._oper_status, self._parent)