Openolt data model - cache onu info

Change-Id: I62840f1f8bd2668041b587b7845d78fefdd72060
diff --git a/voltha/adapters/openolt/openolt_data_model.py b/voltha/adapters/openolt/openolt_data_model.py
index 33b5a77..b32ca28 100644
--- a/voltha/adapters/openolt/openolt_data_model.py
+++ b/voltha/adapters/openolt/openolt_data_model.py
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+import collections
 import structlog
 import socket
 from scapy.layers.l2 import Ether
@@ -30,6 +31,13 @@
 from voltha.registry import registry
 
 
+# Onu info cache is hashed on both (intf_id, onu_id) and onu serial number
+OnuId = collections.namedtuple('OnuId', ['intf_id', 'onu_id'])
+OnuInfo = collections.namedtuple('OnuInfo', ['intf_id',
+                                             'onu_id',
+                                             'serial_number'])
+
+
 class OpenOltDataModel(object):
 
     def __init__(self, device, adapter_agent, platform):
@@ -50,6 +58,9 @@
 
         self.proxy = registry('core').get_proxy('/')
 
+        self._onu_ids = {}
+        self._onu_serial_numbers = {}
+
     def reconcile(self):
         assert self.logical_device_id is not None
         self.adapter_agent.reconcile_logical_device(
@@ -187,6 +198,13 @@
             connect_status=ConnectStatus.REACHABLE
         )
 
+        # Add onu info to cache
+        onu_info = OnuInfo(intf_id=intf_id,
+                           onu_id=onu_id,
+                           serial_number=serial_number)
+        self._onu_ids[OnuId(intf_id=intf_id, onu_id=onu_id)] = onu_info
+        self._onu_serial_numbers[serial_number] = onu_info
+
     def onu_delete(self, serial_number):
         onu_device = self.adapter_agent.get_child_device(
             self.device.id,
@@ -211,15 +229,36 @@
         except Exception as e:
             self.log.error('port delete error', error=e)
 
-    def onu_id(self, serial_number):
-        onu_device = self.adapter_agent.get_child_device(
-            self.device.id,
-            serial_number=serial_number)
+        # Delete onu info from cache
+        onu_info = self._onu_ids[serial_number]
+        del self._onu_ids[OnuId(intf_id=onu_info.intf_id,
+                                onu_id=onu_info.onu_id)]
+        del self._onu_serial_numbers[serial_number]
 
-        if onu_device:
-            return onu_device.proxy_address.onu_id
-        else:
-            return 0  # Invalid onu id
+    def onu_id(self, serial_number):
+        """ Get onu_id from serial_number
+        Returns: onu_id
+        Raises:
+            ValueError: no onu_id found for serial_number
+        """
+        try:
+            return self._onu_serial_numbers[serial_number].onu_id
+        except KeyError:
+            raise ValueError('onu_id not found, serial_number=%s'
+                             % serial_number)
+
+    def serial_number(self, intf_id, onu_id):
+        """ Get serial_number from intf_id, onu_id
+        Returns: onu_id
+        Raises:
+            ValueError: no serial_number found for intf_id, onu_id
+        """
+        try:
+            return self._onu_ids[OnuId(intf_id=intf_id,
+                                       onu_id=onu_id)].serial_number
+        except KeyError:
+            raise ValueError('serial_number not found, intf_id=%s, onu_id=%s'
+                             % (intf_id, onu_id))
 
     def onu_oper_down(self, intf_id, onu_id):
 
diff --git a/voltha/adapters/openolt/openolt_device.py b/voltha/adapters/openolt/openolt_device.py
index e4b6e64..f6f07d5 100644
--- a/voltha/adapters/openolt/openolt_device.py
+++ b/voltha/adapters/openolt/openolt_device.py
@@ -300,9 +300,10 @@
                                errmsg=disc_alarm_error.message)
             # continue for now.
 
-        onu_id = self.data_model.onu_id(serial_number_str)
-
-        if onu_id == 0:
+        try:
+            onu_id = self.data_model.onu_id(serial_number_str)
+        except ValueError:
+            # FIXME - resource_mgr.get_onu_id() should raise exception
             onu_id = self.resource_mgr.get_onu_id(intf_id)
             if onu_id is None:
                 raise Exception("onu-id-unavailable")