[VOL-4487] openonuAdapterGo - reconciling not working after ONU device disable

Change-Id: Ie816790f688b8bd4f2fd65454ec68ab32e7d85e7
diff --git a/VERSION b/VERSION
index 209873d..7a1a884 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.2-dev252
+2.1.2-dev253
diff --git a/internal/pkg/common/interfaces.go b/internal/pkg/common/interfaces.go
index d842350..a4612f7 100755
--- a/internal/pkg/common/interfaces.go
+++ b/internal/pkg/common/interfaces.go
@@ -92,7 +92,7 @@
 	IsReconciling() bool
 	IsSkipOnuConfigReconciling() bool
 	PrepareReconcilingWithActiveAdapter(context.Context)
-	ReconcileDeviceTechProf(context.Context)
+	ReconcileDeviceTechProf(context.Context) bool
 	ReconcileDeviceFlowConfig(context.Context)
 	GetReconcileExpiryVlanConfigAbort() time.Duration
 	SendChUniVlanConfigFinished(value uint16)
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 4274e90..27c0f52 100755
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -843,16 +843,16 @@
 	_ = dh.createInterface(ctx, &onuIndication)
 }
 
-func (dh *deviceHandler) ReconcileDeviceTechProf(ctx context.Context) {
+func (dh *deviceHandler) ReconcileDeviceTechProf(ctx context.Context) bool {
 	logger.Debugw(ctx, "reconciling - trigger tech profile config", log.Fields{"device-id": dh.DeviceID})
 
+	continueWithFlowConfig := false
+
 	pDevEntry := dh.GetOnuDeviceEntry(ctx, true)
 	if pDevEntry == nil {
 		logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.DeviceID})
-		if !dh.IsSkipOnuConfigReconciling() {
-			dh.stopReconciling(ctx, false, cWaitReconcileFlowNoActivity)
-		}
-		return
+		dh.stopReconciling(ctx, false, cWaitReconcileFlowNoActivity)
+		return continueWithFlowConfig
 	}
 	dh.pOnuTP.LockTpProcMutex()
 	defer dh.pOnuTP.UnlockTpProcMutex()
@@ -863,10 +863,8 @@
 		pDevEntry.MutexPersOnuConfig.RUnlock()
 		logger.Debugw(ctx, "reconciling - no uni-configs have been stored before adapter restart - terminate reconcilement",
 			log.Fields{"device-id": dh.DeviceID})
-		if !dh.IsSkipOnuConfigReconciling() {
-			dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
-		}
-		return
+		dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
+		return continueWithFlowConfig
 	}
 	flowsFound := false
 	techProfsFound := false
@@ -874,7 +872,7 @@
 outerLoop:
 	for _, uniData := range pDevEntry.SOnuPersistentData.PersUniConfig {
 		//TODO: check for uni-port specific reconcilement in case of multi-uni-port-per-onu-support
-		if len(uniData.PersTpPathMap) == 0 {
+		if !dh.anyTpPathExists(uniData.PersTpPathMap) {
 			logger.Debugw(ctx, "reconciling - no TPs stored for uniID",
 				log.Fields{"uni-id": uniData.PersUniID, "device-id": dh.DeviceID})
 			continue
@@ -898,11 +896,16 @@
 					UniId:          uint32(uniData.PersUniID),
 				})
 			if err != nil || iaTechTpInst == nil {
+				// TODO: During the absence of the ONU adapter there seem to have been TP specific configurations!
+				// The no longer available TPs and the associated flows must be deleted from the ONU KV store
+				// and after a MIB reset a new reconciling attempt with OMCI configuration must be started.
 				logger.Errorw(ctx, "error fetching tp instance",
-					log.Fields{"tp-id": tpID, "tpPath": uniData.PersTpPathMap[tpID], "uni-id": uniData.PersUniID, "device-id": dh.DeviceID, "err": err})
+					log.Fields{"tp-id": tpID, "tpPath": uniData.PersTpPathMap[tpID], "uni-id": uniData.PersUniID,
+						"device-id": dh.DeviceID, "err": err})
 				techProfInstLoadFailed = true // stop loading tp instance as soon as we hit failure
 				break outerLoop
 			}
+			continueWithFlowConfig = true // valid TP found - try flow configuration later
 			var tpInst tech_profile.TechProfileInstance
 			switch techTpInst := iaTechTpInst.TechTpInstance.(type) {
 			case *ia.TechProfileDownloadMessage_TpInstance: // supports only GPON, XGPON, XGS-PON
@@ -944,6 +947,8 @@
 
 	//had to move techProf/flow result evaluation into separate function due to SCA complexity limit
 	dh.updateReconcileStates(ctx, techProfsFound, techProfInstLoadFailed, flowsFound)
+
+	return continueWithFlowConfig
 }
 
 func (dh *deviceHandler) updateReconcileStates(ctx context.Context,
@@ -951,9 +956,7 @@
 	if !abTechProfsFound {
 		logger.Debugw(ctx, "reconciling - no TPs have been stored before adapter restart - terminate reconcilement",
 			log.Fields{"device-id": dh.DeviceID})
-		if !dh.IsSkipOnuConfigReconciling() {
-			dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
-		}
+		dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
 		return
 	}
 	if abTechProfInstLoadFailed {
@@ -966,9 +969,7 @@
 	if !abFlowsFound {
 		logger.Debugw(ctx, "reconciling - no flows have been stored before adapter restart - terminate reconcilement",
 			log.Fields{"device-id": dh.DeviceID})
-		if !dh.IsSkipOnuConfigReconciling() {
-			dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
-		}
+		dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
 	}
 }
 
@@ -978,14 +979,7 @@
 	pDevEntry := dh.GetOnuDeviceEntry(ctx, true)
 	if pDevEntry == nil {
 		logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.DeviceID})
-		if !dh.IsSkipOnuConfigReconciling() {
-			dh.stopReconciling(ctx, false, cWaitReconcileFlowNoActivity)
-		}
-		//else we don't stop the device handler reconciling in constellation with omci configuration
-		//  to avoid unintented state update to rwCore due to still running background processes
-		//  such is e.g. possible in TT scenarios with multiple techProfiles as currently the end of processing
-		//  of all techProfiles is not awaited (ready on first TP done event)
-		//  (applicable to all according code points below)
+		dh.stopReconciling(ctx, false, cWaitReconcileFlowNoActivity)
 		return
 	}
 
@@ -994,9 +988,7 @@
 		pDevEntry.MutexPersOnuConfig.RUnlock()
 		logger.Debugw(ctx, "reconciling - no uni-configs have been stored before adapter restart - terminate reconcilement",
 			log.Fields{"device-id": dh.DeviceID})
-		if !dh.IsSkipOnuConfigReconciling() {
-			dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
-		}
+		dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
 		return
 	}
 	flowsFound := false
@@ -1010,7 +1002,7 @@
 				log.Fields{"uni-id": uniData.PersUniID, "device-id": dh.DeviceID})
 			continue
 		}
-		if len(uniData.PersTpPathMap) == 0 {
+		if !dh.anyTpPathExists(uniData.PersTpPathMap) {
 			logger.Warnw(ctx, "reconciling flows - but no TPs stored for uniID, abort",
 				log.Fields{"uni-id": uniData.PersUniID, "device-id": dh.DeviceID})
 			// It doesn't make sense to configure any flows if no TPs are available
@@ -1027,9 +1019,7 @@
 		if uniPort, exist = dh.uniEntityMap[uniNo]; !exist {
 			logger.Errorw(ctx, "reconciling - OnuUniPort data not found  - terminate reconcilement",
 				log.Fields{"uniNo": uniNo, "device-id": dh.DeviceID})
-			if !dh.IsSkipOnuConfigReconciling() {
-				dh.stopReconciling(ctx, false, cWaitReconcileFlowNoActivity)
-			}
+			dh.stopReconciling(ctx, false, cWaitReconcileFlowNoActivity)
 			return
 		}
 		//needed to split up function due to sca complexity
@@ -1049,9 +1039,7 @@
 	if !flowsFound {
 		logger.Debugw(ctx, "reconciling - no flows have been stored before adapter restart - terminate reconcilement",
 			log.Fields{"device-id": dh.DeviceID})
-		if !dh.IsSkipOnuConfigReconciling() {
-			dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
-		}
+		dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
 		return
 	}
 
@@ -4418,3 +4406,13 @@
 func (dh *deviceHandler) GetUniPortMask() int {
 	return dh.pOpenOnuAc.config.UniPortMask
 }
+
+func (dh *deviceHandler) anyTpPathExists(aTpPathMap map[uint8]string) bool {
+	tpPathFound := false
+	for _, tpPath := range aTpPathMap {
+		if tpPath != "" {
+			tpPathFound = true
+		}
+	}
+	return tpPathFound
+}
diff --git a/internal/pkg/mib/mib_sync.go b/internal/pkg/mib/mib_sync.go
index 5c15ea7..6e2378e 100755
--- a/internal/pkg/mib/mib_sync.go
+++ b/internal/pkg/mib/mib_sync.go
@@ -324,38 +324,6 @@
 				}
 			}
 		}
-
-		// no need to reconcile additional data for MibDownloadFsm, LockStateFsm, or UnlockStateFsm
-		oo.baseDeviceHandler.ReconcileDeviceTechProf(ctx)
-
-		// start go routine with select() on reconciling flow channel before
-		// starting flow reconciling process to prevent loss of any signal
-		go func() {
-			// In multi-ONU/multi-flow environment stopping reconcilement has to be delayed until
-			// we get a signal that the processing of the last step to rebuild the adapter internal
-			// flow data is finished.
-			expiry := oo.baseDeviceHandler.GetReconcileExpiryVlanConfigAbort()
-			oo.setReconcilingFlows(true)
-			select {
-			case success := <-oo.chReconcilingFlowsFinished:
-				if success {
-					logger.Debugw(ctx, "reconciling flows has been finished in time",
-						log.Fields{"device-id": oo.deviceID})
-					_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
-
-				} else {
-					logger.Debugw(ctx, "wait for reconciling flows aborted",
-						log.Fields{"device-id": oo.deviceID})
-				}
-			case <-time.After(expiry):
-				logger.Errorw(ctx, "timeout waiting for reconciling flows to be finished!",
-					log.Fields{"device-id": oo.deviceID, "expiry": expiry})
-				_ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
-			}
-			oo.setReconcilingFlows(false)
-		}()
-		oo.baseDeviceHandler.ReconcileDeviceFlowConfig(ctx)
-
 		oo.MutexPersOnuConfig.RLock()
 		if oo.SOnuPersistentData.PersUniDisableDone {
 			oo.MutexPersOnuConfig.RUnlock()
@@ -365,6 +333,38 @@
 			oo.MutexPersOnuConfig.RUnlock()
 			oo.baseDeviceHandler.EnableUniPortStateUpdate(ctx)
 		}
+
+		// no need to reconcile additional data for MibDownloadFsm, LockStateFsm, or UnlockStateFsm
+
+		if oo.baseDeviceHandler.ReconcileDeviceTechProf(ctx) {
+			// start go routine with select() on reconciling flow channel before
+			// starting flow reconciling process to prevent loss of any signal
+			go func() {
+				// In multi-ONU/multi-flow environment stopping reconcilement has to be delayed until
+				// we get a signal that the processing of the last step to rebuild the adapter internal
+				// flow data is finished.
+				expiry := oo.baseDeviceHandler.GetReconcileExpiryVlanConfigAbort()
+				oo.setReconcilingFlows(true)
+				select {
+				case success := <-oo.chReconcilingFlowsFinished:
+					if success {
+						logger.Debugw(ctx, "reconciling flows has been finished in time",
+							log.Fields{"device-id": oo.deviceID})
+						_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+
+					} else {
+						logger.Debugw(ctx, "wait for reconciling flows aborted",
+							log.Fields{"device-id": oo.deviceID})
+					}
+				case <-time.After(expiry):
+					logger.Errorw(ctx, "timeout waiting for reconciling flows to be finished!",
+						log.Fields{"device-id": oo.deviceID, "expiry": expiry})
+					_ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+				}
+				oo.setReconcilingFlows(false)
+			}()
+			oo.baseDeviceHandler.ReconcileDeviceFlowConfig(ctx)
+		}
 	} else {
 		logger.Debugw(ctx, "MibSync FSM",
 			log.Fields{"Getting MIB from template not successful": e.FSM.Current(), "device-id": oo.deviceID})