VOL-1400: TP Instance and PON resources are not cleared from KV store
          when ONU devices is DISABLED and DELETEd from Voltha

Change-Id: I923dbac6a4c7023e1786d41715bb7c2240bd7053
diff --git a/voltha/adapters/openolt/openolt_device.py b/voltha/adapters/openolt/openolt_device.py
index cba09c3..ed3dc06 100644
--- a/voltha/adapters/openolt/openolt_device.py
+++ b/voltha/adapters/openolt/openolt_device.py
@@ -744,6 +744,15 @@
 
         return port_no, label
 
+    def get_uni_ofp_port_name(self, child_device):
+        logical_ports = self.proxy.get('/logical_devices/{}/ports'.format(
+            self.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))
@@ -870,6 +879,12 @@
                                                    child_device)
         except Exception as e:
             self.log.error('adapter_agent error', error=e)
+
+        ofp_port_name = self.get_uni_ofp_port_name(child_device)
+        if ofp_port_name is None:
+            self.log.exception("uni-ofp-port-not-found")
+            return
+
         try:
             self.delete_logical_port(child_device)
         except Exception as e:
@@ -883,21 +898,32 @@
         # TODO FIXME - For each uni.
         # TODO FIXME - Flows are not deleted
         uni_id = 0  # FIXME
-        self.flow_mgr.delete_tech_profile_instance(
-                    child_device.proxy_address.channel_id,
-                    child_device.proxy_address.onu_id,
-                    uni_id
-        )
-        pon_intf_id_onu_id = (child_device.proxy_address.channel_id,
-                              child_device.proxy_address.onu_id,
-                              uni_id)
-        # Free any PON resources that were reserved for the ONU
-        self.resource_mgr.free_pon_resources_for_onu(pon_intf_id_onu_id)
+        try:
+            self.flow_mgr.delete_tech_profile_instance(
+                        child_device.proxy_address.channel_id,
+                        child_device.proxy_address.onu_id,
+                        uni_id,
+                        ofp_port_name
+            )
+        except Exception as e:
+            self.log.exception("error-removing-tp-instance")
 
-        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)
+        try:
+            pon_intf_id_onu_id = (child_device.proxy_address.channel_id,
+                                  child_device.proxy_address.onu_id,
+                                  uni_id)
+            # Free any PON resources that were reserved for the ONU
+            self.resource_mgr.free_pon_resources_for_onu(pon_intf_id_onu_id)
+        except Exception as e:
+            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)
+            self.stub.DeleteOnu(onu)
+        except Exception as e:
+            self.log.exception("error-deleting-the-onu-on-olt-device")
 
     def reboot(self):
         self.log.debug('rebooting openolt device', device_id=self.device_id)
diff --git a/voltha/adapters/openolt/openolt_flow_mgr.py b/voltha/adapters/openolt/openolt_flow_mgr.py
index 99d387c..410c86a 100644
--- a/voltha/adapters/openolt/openolt_flow_mgr.py
+++ b/voltha/adapters/openolt/openolt_flow_mgr.py
@@ -327,20 +327,18 @@
         ofp_port_name = (logical_port.ofp_port.name, logical_port.ofp_port.port_no)
         return ofp_port_name
 
-    def get_tp_path(self, intf_id, ofp_port_name):
-        # FIXME Should get Table id form the flow, as of now hardcoded to
-        # DEFAULT_TECH_PROFILE_TABLE_ID (64)
-        # 'tp_path' contains the suffix part of the tech_profile_instance path.
-        # The prefix to the 'tp_path' should be set to \
-        # TechProfile.KV_STORE_TECH_PROFILE_PATH_PREFIX by the ONU adapter.
+    def get_tp_path(self, intf_id, ofp_port_name, techprofile_id):
         return self.tech_profile[intf_id]. \
-            get_tp_path(DEFAULT_TECH_PROFILE_TABLE_ID,
+            get_tp_path(techprofile_id,
                         ofp_port_name)
 
-    def delete_tech_profile_instance(self, intf_id, onu_id, uni_id):
+    def delete_tech_profile_instance(self, intf_id, onu_id, uni_id, ofp_port_name):
         # Remove the TP instance associated with the ONU
-        ofp_port_name = self._get_ofp_port_name(intf_id, onu_id, uni_id)
-        tp_path = self.get_tp_path(intf_id, ofp_port_name)
+        if ofp_port_name is None:
+            ofp_port_name, ofp_port_no = self._get_ofp_port_name(intf_id, onu_id, uni_id)
+        tp_id = self.resource_mgr.get_tech_profile_id_for_onu(intf_id, onu_id, uni_id)
+        tp_path = self.get_tp_path(intf_id, ofp_port_name, tp_id)
+        self.log.debug(" tp-path-in-delete",tp_path=tp_path)
         return self.tech_profile[intf_id].delete_tech_profile_instance(tp_path)
 
     def divide_and_add_flow(self, intf_id, onu_id, uni_id, port_no, classifier,
@@ -391,8 +389,8 @@
                     if ofp_port_name is None:
                         self.log.error("port-name-not-found")
                         return
-
-                    tp_path = self.get_tp_path(intf_id, ofp_port_name)
+                    tp_id = self.resource_mgr.get_tech_profile_id_for_onu(intf_id, onu_id, uni_id)
+                    tp_path = self.get_tp_path(intf_id, ofp_port_name, tp_id)
 
                     self.log.debug('Load-tech-profile-request-to-brcm-handler',
                                    tp_path=tp_path)
@@ -980,16 +978,17 @@
         port_no = logical_port.ofp_port.port_no
         pon_port = child_device.proxy_address.channel_id
         onu_id = child_device.proxy_address.onu_id
-        uni_id = self.platform.uni_id_from_port_num(logical_port)
+        uni_id = self.platform.uni_id_from_port_num(port_no)
 
         # TODO: The DEFAULT_TECH_PROFILE_ID is assumed. Right way to do,
         # is probably to maintain a list of Tech-profile table IDs associated
         # with the UNI logical_port. This way, when the logical port is deleted,
         # all the associated tech-profile configuration with the UNI logical_port
         # can be cleared.
+        tp_id = self.resource_mgr.get_tech_profile_id_for_onu(pon_port, onu_id, uni_id)
         tech_profile_instance = self.tech_profile[pon_port]. \
             get_tech_profile_instance(
-            DEFAULT_TECH_PROFILE_TABLE_ID,
+            tp_id,
             ofp_port_name)
         flow_ids = self.resource_mgr.get_current_flow_ids(pon_port, onu_id, uni_id)
         self.log.debug("outstanding-flows-to-be-cleared", flow_ids=flow_ids)
diff --git a/voltha/adapters/openolt/openolt_resource_manager.py b/voltha/adapters/openolt/openolt_resource_manager.py
index ae94343..bda822c 100644
--- a/voltha/adapters/openolt/openolt_resource_manager.py
+++ b/voltha/adapters/openolt/openolt_resource_manager.py
@@ -28,6 +28,7 @@
 
 class OpenOltResourceMgr(object):
     BASE_PATH_KV_STORE = "service/voltha/openolt/{}"  # service/voltha/openolt/<device_id>
+    TP_ID_PATH_SUFFIX = 'tp_id/{}'
 
     def __init__(self, device_id, host_and_port, extra_args, device_info):
         self.log = structlog.get_logger(id=device_id,
@@ -133,11 +134,6 @@
         onu_id = self.resource_mgrs[pon_intf_id].get_resource_id(
             pon_intf_id, PONResourceManager.ONU_ID, 1)
 
-        if onu_id is not None:
-            pon_intf_onu_id = (pon_intf_id, onu_id)
-            self.resource_mgrs[pon_intf_id].init_resource_map(
-                pon_intf_onu_id)
-
         return onu_id
 
     def get_flow_id(self, intf_id, onu_id, uni_id, flow_store_cookie,
@@ -466,3 +462,12 @@
             self.log.error("error-retrieving-flow-info", e=e)
 
         return False
+
+    def get_tech_profile_id_for_onu(self, intf_id, onu_id, uni_id):
+        intf_id_onu_id_uni_id = (intf_id, onu_id, uni_id)
+        try:
+            kv_path = OpenOltResourceMgr.TP_ID_PATH_SUFFIX.format(str(intf_id_onu_id_uni_id))
+            return int(self.kv_store[kv_path])
+        except Exception as e:
+            self.log.warn("tp-id-not-found-on-kv-store", e=e)
+            return DEFAULT_TECH_PROFILE_TABLE_ID