[VOL-1825] Implemetation of the reconcile feature in the Core

This commit implements the reconcile feature in the Core as
well as the necessary changes in the GO libraries.  Changes were
also made in the simulated OLT and ONU adapters to react to a
reconcile request following an adapter restart. These changes
were tested in a 1-node deployment (1 core pair) and 3-nodes
deployment (3 core-pairs but single adapter instances).  Test
was also done using the openolt to ensure the reconcile request
does not cause panic in the Core or Openolt since the reconcile
feature is not implemented in Openolt.

Change-Id: I178d619fbcfcc6caa0ee3abfd70fc03c384c5fea
diff --git a/rw_core/core/logical_device_agent.go b/rw_core/core/logical_device_agent.go
index 70349d8..941cb3b 100644
--- a/rw_core/core/logical_device_agent.go
+++ b/rw_core/core/logical_device_agent.go
@@ -80,13 +80,8 @@
 	log.Infow("starting-logical_device-agent", log.Fields{"logicaldeviceId": agent.logicalDeviceId, "loadFromdB": loadFromdB})
 	var ld *voltha.LogicalDevice
 	if !loadFromdB {
-		//Build the logical device based on information retrieved from the device adapter
-		var switchCap *ic.SwitchCapability
 		var err error
-		if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceId); err != nil {
-			log.Errorw("error-creating-logical-device", log.Fields{"error": err})
-			return err
-		}
+		// First create and store the logical device
 		ld = &voltha.LogicalDevice{Id: agent.logicalDeviceId, RootDeviceId: agent.rootDeviceId}
 
 		// Create the datapath ID (uint64) using the logical device ID (based on the MAC Address)
@@ -96,9 +91,6 @@
 			return err
 		}
 		ld.DatapathId = datapathID
-		ld.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
-		log.Debugw("Switch-capability", log.Fields{"Desc": ld.Desc, "fromAd": switchCap.Desc})
-		ld.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
 		ld.Flows = &ofp.Flows{Items: nil}
 		ld.FlowGroups = &ofp.FlowGroups{Items: nil}
 
@@ -111,6 +103,25 @@
 		}
 		agent.lockLogicalDevice.Unlock()
 
+		//Retrieve the switch capability from the device adapter
+		var switchCap *ic.SwitchCapability
+		if switchCap, err = agent.deviceMgr.getSwitchCapability(ctx, agent.rootDeviceId); err != nil {
+			log.Errorw("error-creating-logical-device", log.Fields{"error": err})
+			return err
+		}
+
+		// Save the data
+		agent.lockLogicalDevice.Lock()
+		if ld, err = agent.getLogicalDeviceWithoutLock(); err != nil {
+			log.Warnw("failed-to-load-logical-device", log.Fields{"logicaldeviceId": agent.logicalDeviceId})
+			return err
+		}
+		clonedLd := (proto.Clone(ld)).(*voltha.LogicalDevice)
+		clonedLd.Desc = (proto.Clone(switchCap.Desc)).(*ofp.OfpDesc)
+		log.Debugw("Switch-capability", log.Fields{"Desc": clonedLd.Desc})
+		clonedLd.SwitchFeatures = (proto.Clone(switchCap.SwitchFeatures)).(*ofp.OfpSwitchFeatures)
+		agent.lockLogicalDevice.Unlock()
+
 		// TODO:  Set the logical ports in a separate call once the port update issue is fixed.
 		go agent.setupLogicalPorts(ctx)