VOL-287 : Disabling and reenabling ponsim after a Voltha restart fails
          Introducing ONU Vendor ID from ONU serial number for identifying
          onu device type and associated adapter

Change-Id: I81e59a60b7805249d76d47d0965d17951d79b86e
diff --git a/voltha/adapters/iadapter.py b/voltha/adapters/iadapter.py
index 5b916ed..dcb373b 100644
--- a/voltha/adapters/iadapter.py
+++ b/voltha/adapters/iadapter.py
@@ -34,7 +34,7 @@
 
 @implementer(IAdapterInterface)
 class IAdapter(object):
-    def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type):
+    def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type, vendor_id):
         log.debug('Initializing adapter: {} {} {}'.format(vendor, name, version))
         self.adapter_agent = adapter_agent
         self.config = config
@@ -42,6 +42,7 @@
         self.supported_device_types = [
             DeviceType(
                 id=device_type,
+                vendor_id=vendor_id,
                 adapter=name,
                 accepts_bulk_flow_update=True
             )
@@ -170,7 +171,8 @@
                                          name,
                                          vendor,
                                          version,
-                                         device_type)
+                                         device_type,
+                                         None)
         self.logical_device_id_to_root_device_id = dict()
 
     def reconcile_device(self, device):
@@ -211,14 +213,15 @@
 ONU Adapter base class
 """
 class OnuAdapter(IAdapter):
-    def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type):
+    def __init__(self, adapter_agent, config, device_handler_class, name, vendor, version, device_type, vendor_id):
         super(OnuAdapter, self).__init__(adapter_agent,
                                          config,
                                          device_handler_class,
                                          name,
                                          vendor,
                                          version,
-                                         device_type)
+                                         device_type,
+                                         vendor_id)
 
     def reconcile_device(self, device):
         self.devices_handlers[device.id] = self.device_handler_class(self, device.id)
diff --git a/voltha/adapters/ponsim_olt/ponsim_olt.py b/voltha/adapters/ponsim_olt/ponsim_olt.py
index f1940bf..aca7fc2 100644
--- a/voltha/adapters/ponsim_olt/ponsim_olt.py
+++ b/voltha/adapters/ponsim_olt/ponsim_olt.py
@@ -361,7 +361,7 @@
             self.adapter_agent.child_device_detected(
                 parent_device_id=device.id,
                 parent_port_no=1,
-                child_device_type='PSMO', #''ponsim_onu', # refers notes from ponsim_onu
+                child_device_type='ponsim_onu',
                 proxy_address=Device.ProxyAddress(
                     device_id=device.id,
                     channel_id=vlan_id
diff --git a/voltha/adapters/ponsim_onu/ponsim_onu.py b/voltha/adapters/ponsim_onu/ponsim_onu.py
index 04ae976..499b825 100644
--- a/voltha/adapters/ponsim_onu/ponsim_onu.py
+++ b/voltha/adapters/ponsim_onu/ponsim_onu.py
@@ -47,7 +47,8 @@
                                                name='ponsim_onu',
                                                vendor='Voltha project',
                                                version='0.4',
-                                               device_type='PSMO')
+                                               device_type='ponsim_onu',
+                                               vendor_id='PSMO')
 
 class PonSimOnuHandler(object):
     def __init__(self, adapter, device_id):
diff --git a/voltha/core/adapter_agent.py b/voltha/core/adapter_agent.py
index d966c3b..07b9510 100644
--- a/voltha/core/adapter_agent.py
+++ b/voltha/core/adapter_agent.py
@@ -528,6 +528,8 @@
             device_agent.reconcile_existing_device(child)
 
 
+    #Obselete API - discouraged to be decommissioned after
+    #adapters are align to new APIs
     def child_device_detected(self,
                               parent_device_id,
                               parent_port_no,
@@ -553,6 +555,34 @@
         self._tx_event_subscriptions[topic] = self.event_bus.subscribe(
             topic, lambda t, m: self._send_proxied_message(proxy_address, m))
 
+    def add_onu_device(self,
+                       parent_device_id,
+                       parent_port_no,
+                       vendor_id,
+                       proxy_address,
+                       admin_state,
+                       **kw):
+        device_type = next((dt for dt in self.root_proxy.get('/device_types')
+                            if dt.vendor_id == vendor_id), None)
+        # we create new ONU device objects and insert them into the config
+        device = Device(
+            id=create_cluster_device_id(self.core.core_store_id),
+            # id=uuid4().hex[:12],
+            type=device_type.id,
+            vendor_id=vendor_id,
+            parent_id=parent_device_id,
+            parent_port_no=parent_port_no,
+            proxy_address=proxy_address,
+            admin_state=admin_state,
+            adapter=device_type.adapter,
+            **kw
+        )
+        self._make_up_to_date('/devices', device.id, device)
+
+        topic = self._gen_tx_proxy_address_topic(proxy_address)
+        self._tx_event_subscriptions[topic] = self.event_bus.subscribe(
+            topic, lambda t, m: self._send_proxied_message(proxy_address, m))
+
     def get_child_device_with_proxy_address(self, proxy_address):
         # Proxy address is defined as {parent id, channel_id}
         devices = self.root_proxy.get('/devices')
diff --git a/voltha/core/xpon_agent.py b/voltha/core/xpon_agent.py
index 4dd6a87..024008a 100644
--- a/voltha/core/xpon_agent.py
+++ b/voltha/core/xpon_agent.py
@@ -480,16 +480,16 @@
         parent_chnl_pair_id = self.get_port_num(
             device.id, v_ont_ani.data.preferred_chanpair)
         log.info('create-onu-device:', parent_chnl_pair_id=parent_chnl_pair_id)
-        onu_type = v_ont_ani.data.expected_serial_number[:4]
+        vendor_id = v_ont_ani.data.expected_serial_number[:4]
         proxy_address = Device.ProxyAddress(
             device_id=device.id, channel_id=parent_chnl_pair_id,
             onu_id=v_ont_ani.data.onu_id, onu_session_id=v_ont_ani.data.onu_id)
-        adapter_agent.child_device_detected(
+        adapter_agent.add_onu_device(
             parent_device_id=device.id, parent_port_no=parent_chnl_pair_id,
-            child_device_type=onu_type, proxy_address=proxy_address, root=True,
-            serial_number=v_ont_ani.data.expected_serial_number,
-            admin_state=AdminState.ENABLED if v_ont_ani.interface.enabled else
-            AdminState.DISABLED)
+            vendor_id=vendor_id, proxy_address=proxy_address,
+            root=True, serial_number=v_ont_ani.data.expected_serial_number,
+            admin_state=AdminState.ENABLED if v_ont_ani.interface.enabled
+                                           else AdminState.DISABLED)
         return
 
     def delete_onu_device(self, device_id, v_ont_ani):
diff --git a/voltha/protos/device.proto b/voltha/protos/device.proto
index f7828e6..1cafdd8 100644
--- a/voltha/protos/device.proto
+++ b/voltha/protos/device.proto
@@ -15,6 +15,10 @@
     // Unique name for the device type
     string id = 1;
 
+    // Unique venor id for the device type applicable to ONU
+    // 4 bytes of vendor id from ONU serial number
+    string vendor_id = 5;
+
     // Name of the adapter that handles device type
     string adapter = 2;
 
@@ -153,6 +157,7 @@
     // List of software on the device
     Images images = 9 [(access) = READ_ONLY];
     string serial_number = 10 [(access) = READ_ONLY];
+    string vendor_id = 24 [(access) = READ_ONLY];
 
     // Addapter that takes care of device
     string adapter = 11 [(access) = READ_ONLY];