[VOL-3041] - Configuration of port admin state
[VOL-3036] - Read MIB Templates from ETCD

Change-Id: I55b9553104701bf9ecd873a218c9aeffca782cd1
Signed-off-by: Holger Hildebrandt <holger.hildebrandt@adtran.com>
diff --git a/VERSION b/VERSION
index 0844a16..4b88d86 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.11-dev
+0.1.11-dev115
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index e5946f4..b67ceab 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -92,9 +92,9 @@
 	exitChannel     chan int
 	lockDevice      sync.RWMutex
 	pOnuIndication  *oop.OnuIndication
+	pLockStateFsm   *LockStateFsm
+	pUnlockStateFsm *LockStateFsm
 
-	//Client        oop.OpenoltClient
-	//clientCon     *grpc.ClientConn
 	//flowMgr       *OpenOltFlowMgr
 	//eventMgr      *OpenOltEventMgr
 	//resourceMgr   *rsrcMgr.OpenOltResourceMgr
@@ -174,12 +174,12 @@
 func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
 	logger.Debugw("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
 
-	logger.Debug("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
+	logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
 	if dh.pDeviceStateFsm.Is("null") {
 		if err := dh.pDeviceStateFsm.Event("DeviceInit"); err != nil {
 			logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
 		}
-		logger.Debug("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
+		logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
 	} else {
 		logger.Debug("AdoptDevice: Agent/device init already done")
 	}
@@ -287,32 +287,52 @@
 	return nil
 }
 
+//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
 func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
-	logger.Debug("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
-	// and disable port
-	// yield self.disable_ports(lock_ports=True, device_disabled=True)
-	if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "OmciAdminLock"); err != nil {
-		logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
+	logger.Debugw("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
+
+	// disable UNI ports/ONU
+	// *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
+	//     here the result of the processing is not checked (trusted in background) *****
+	if dh.pLockStateFsm == nil {
+		dh.createUniLockFsm(true, UniAdminStateDone)
+	} else { //LockStateFSM already init
+		dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
+		dh.runUniLockFsm(true)
 	}
 
+	if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
+		logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
+	}
+	// TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...
 	if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
 		voltha.OperStatus_UNKNOWN); err != nil {
 		logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
 	}
 }
 
+//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
 func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
-	logger.Debug("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
+	logger.Debugw("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
+	// TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...
 	if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
 		voltha.OperStatus_ACTIVE); err != nil {
 		logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
 	}
 
-	if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "InitialMibDownloaded"); err != nil {
+	if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
 		logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
 	}
-	// and enable port
-	// yield self.enable_ports(device)
+
+	// enable ONU/UNI ports
+	// *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
+	//     here the result of the processing is not checked (trusted in background) *****
+	if dh.pUnlockStateFsm == nil {
+		dh.createUniLockFsm(false, UniAdminStateDone)
+	} else { //UnlockStateFSM already init
+		dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
+		dh.runUniLockFsm(false)
+	}
 }
 
 func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device,
@@ -627,7 +647,8 @@
 		   we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
 		/* also no 'clock' argument - usage open ...*/
 		/* and no alarm_db yet (oo.alarm_db)  */
-		deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh, dh.coreProxy, dh.AdapterProxy,
+		deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost, dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
+			dh, dh.coreProxy, dh.AdapterProxy,
 			dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
 		//error treatment possible //TODO!!!
 		dh.SetOnuDeviceEntry(deviceEntry)
@@ -767,36 +788,17 @@
 				logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
 				return errors.New("Can't go to state starting")
 			} else {
-				logger.Debug("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
+				logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
 				//Determine ONU status and start/re-start MIB Synchronization tasks
 				//Determine if this ONU has ever synchronized
 				if true { //TODO: insert valid check
 					if err := pMibUlFsm.Event("load_mib_template"); err != nil {
 						logger.Errorw("MibSyncFsm: Can't go to state loading_mib_template", log.Fields{"err": err})
 						return errors.New("Can't go to state loading_mib_template")
-					} else {
-						logger.Debug("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
-						//Find and load a mib template. If not found proceed with mib_upload
-						// callbacks to be handled:
-						// Event("success")
-						// Event("timeout")
-						//no mib template found
-						if true { //TODO: insert valid check
-							if err := pMibUlFsm.Event("upload_mib"); err != nil {
-								logger.Errorw("MibSyncFsm: Can't go to state uploading", log.Fields{"err": err})
-								return errors.New("Can't go to state uploading")
-							} else {
-								logger.Debug("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
-								//Begin full MIB data upload, starting with a MIB RESET
-								// callbacks to be handled:
-								// success: e.Event("success")
-								// failure: e.Event("timeout")
-							}
-						}
 					}
 				} else {
 					pMibUlFsm.Event("examine_mds")
-					logger.Debug("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
+					logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
 					//Examine the MIB Data Sync
 					// callbacks to be handled:
 					// Event("success")
@@ -819,75 +821,122 @@
 	return nil
 }
 
-func (dh *DeviceHandler) DeviceStateUpdate(dev_Event OnuDeviceEvent) {
-	if dev_Event == MibDatabaseSync {
-		logger.Debugw("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
-		//initiate DevStateUpdate
-		if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
-			logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{"deviceID": dh.deviceID, "error": err})
-		}
-
-		unigMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.UniGClassID]
-		unigInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(unigMap)
-		if ok {
-			i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
-			for _, mgmtEntityId := range unigInstKeys {
-				logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{"deviceId": dh.GetOnuDeviceEntry().deviceID, "UnigMe EntityID": mgmtEntityId})
-				dh.addUniPort(mgmtEntityId, i, UniPPTP)
-				i++
+func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
+	switch dev_Event {
+	case MibDatabaseSync:
+		{
+			logger.Infow("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
+			//initiate DevStateUpdate
+			if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
+				logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
+					"deviceID": dh.deviceID, "error": err})
 			}
-		} else {
-			logger.Warnw("No UniG instances found!", log.Fields{"deviceId": dh.GetOnuDeviceEntry().deviceID})
-		}
 
-		/*  real Mib download procedure could look somthing like this:
-		 ***** but for the moment the FSM is still limited (sending no OMCI)  *****
-		 ***** thus never reaches 'downloaded' state                          *****
-		 */
-		pMibDlFsm := dh.GetOnuDeviceEntry().pMibDownloadFsm.pFsm
-		if pMibDlFsm != nil {
-			if pMibDlFsm.Is("disabled") {
-				if err := pMibDlFsm.Event("start"); err != nil {
-					logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
-					// maybe try a FSM reset and then again ... - TODO!!!
-				} else {
-					logger.Debug("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
-					// maybe use more specific states here for the specific download steps ...
-					if err := pMibDlFsm.Event("create_gal"); err != nil {
-						logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
-					} else {
-						logger.Debug("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
-						//Begin MIB data download (running autonomously)
-					}
+			unigMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.UniGClassID]
+			unigInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(unigMap)
+			i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
+			if ok {
+				for _, mgmtEntityId := range unigInstKeys {
+					logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
+						"deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
+					dh.addUniPort(mgmtEntityId, i, UniPPTP)
+					i++
 				}
 			} else {
-				logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
-				// maybe try a FSM reset and then again ... - TODO!!!
+				logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
 			}
-			/***** Mib download started */
-		} else {
-			logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
-		}
-	} else if dev_Event == MibDownloadDone {
-		logger.Debugw("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
-		//initiate DevStateUpdate
-		if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
-			voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
-			logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
-		}
-		logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
-		if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
-			logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
-				log.Fields{"deviceID": dh.deviceID, "error": err})
-		}
+			veipMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.VirtualEthernetInterfacePointClassID]
+			veipInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(veipMap)
+			if ok {
+				for _, mgmtEntityId := range veipInstKeys {
+					logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
+						"deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
+					dh.addUniPort(mgmtEntityId, i, UniVEIP)
+					i++
+				}
+			} else {
+				logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
+			}
+			if i == 0 {
+				logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
+			}
 
-		go dh.enableUniPortStateUpdate(dh.deviceID) //cmp python yield self.enable_ports()
+			// Init Uni Ports to Admin locked state
+			// maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
+			// *** should generate UniLockStateDone event *****
+			if dh.pLockStateFsm == nil {
+				dh.createUniLockFsm(true, UniLockStateDone)
+			} else { //LockStateFSM already init
+				dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
+				dh.runUniLockFsm(true)
+			}
+		}
+	case UniLockStateDone:
+		{
+			logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
+			/*  Mib download procedure -
+			***** should run over 'downloaded' state and generate MibDownloadDone event *****
+			 */
+			pMibDlFsm := dh.GetOnuDeviceEntry().pMibDownloadFsm.pFsm
+			if pMibDlFsm != nil {
+				if pMibDlFsm.Is("disabled") {
+					if err := pMibDlFsm.Event("start"); err != nil {
+						logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
+						// maybe try a FSM reset and then again ... - TODO!!!
+					} else {
+						logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
+						// maybe use more specific states here for the specific download steps ...
+						if err := pMibDlFsm.Event("create_gal"); err != nil {
+							logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
+						} else {
+							logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
+							//Begin MIB data download (running autonomously)
+						}
+					}
+				} else {
+					logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
+					// maybe try a FSM reset and then again ... - TODO!!!
+				}
+				/***** Mib download started */
+			} else {
+				logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
+			}
+		}
+	case MibDownloadDone:
+		{
+			logger.Infow("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
+			//initiate DevStateUpdate
+			if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
+				voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
+				logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
+			}
+			logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
+			if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
+				logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
+					log.Fields{"deviceID": dh.deviceID, "error": err})
+			}
 
-		raisedTs := time.Now().UnixNano()
-		go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
-	} else {
-		logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
-	}
+			// *** should generate UniUnlockStateDone event *****
+			if dh.pUnlockStateFsm == nil {
+				dh.createUniLockFsm(false, UniUnlockStateDone)
+			} else { //UnlockStateFSM already init
+				dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
+				dh.runUniLockFsm(false)
+			}
+		}
+	case UniUnlockStateDone:
+		{
+			go dh.enableUniPortStateUpdate(dh.deviceID) //cmp python yield self.enable_ports()
+
+			logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
+			raisedTs := time.Now().UnixNano()
+			go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
+		}
+	default:
+		{
+			logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
+		}
+	} //switch
 }
 
 func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
@@ -920,7 +969,7 @@
 	//       # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
 	//       #  load on the core
 
-	// dh.lock_ports(false) ONU port activation via OMCI //TODO!!! not yet supported
+	// lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
 
 	for uniNo, uniPort := range dh.uniEntityMap {
 		// only if this port is validated for operState transfer}
@@ -977,6 +1026,73 @@
 		log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
 }
 
+// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
+func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
+	chLSFsm := make(chan Message, 2048)
+	var sFsmName string
+	if aAdminState == true {
+		logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
+		sFsmName = "LockStateFSM"
+	} else {
+		logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
+		sFsmName = "UnLockStateFSM"
+	}
+	pLSFsm := NewLockStateFsm(dh.GetOnuDeviceEntry().PDevOmciCC, aAdminState, devEvent,
+		sFsmName, dh.deviceID, chLSFsm)
+	if pLSFsm != nil {
+		if aAdminState == true {
+			dh.pLockStateFsm = pLSFsm
+		} else {
+			dh.pUnlockStateFsm = pLSFsm
+		}
+		dh.runUniLockFsm(aAdminState)
+	} else {
+		logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
+	}
+}
+
+// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
+func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
+	/*  Uni Port lock/unlock procedure -
+	 ***** should run via 'adminDone' state and generate the argument requested event *****
+	 */
+	var pLSStatemachine *fsm.FSM
+	if aAdminState == true {
+		pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
+		//make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
+		if (dh.pUnlockStateFsm != nil) &&
+			(dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
+			dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
+		}
+	} else {
+		pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
+		//make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
+		if (dh.pLockStateFsm != nil) &&
+			(dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
+			dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
+		}
+	}
+	if pLSStatemachine != nil {
+		if pLSStatemachine.Is("disabled") {
+			if err := pLSStatemachine.Event("start"); err != nil {
+				logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
+				// maybe try a FSM reset and then again ... - TODO!!!
+			} else {
+				/***** LockStateFSM started */
+				logger.Debugw("LockStateFSM started", log.Fields{
+					"state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
+			}
+		} else {
+			logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
+				"have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
+			// maybe try a FSM reset and then again ... - TODO!!!
+		}
+	} else {
+		logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
+		// maybe try a FSM reset and then again ... - TODO!!!
+	}
+}
+
 /* *********************************************************** */
 
 func genMacFromOctets(a_octets [6]uint8) string {
diff --git a/internal/pkg/onuadaptercore/messageTypes.go b/internal/pkg/onuadaptercore/messageTypes.go
index b3e9191..a5d5aff 100644
--- a/internal/pkg/onuadaptercore/messageTypes.go
+++ b/internal/pkg/onuadaptercore/messageTypes.go
@@ -22,11 +22,11 @@
 	"github.com/opencord/omci-lib-go"
 )
 
-type MessageType int
+type MessageType uint8
 
 const (
-	TestMsg MessageType = 0
-	OMCI    MessageType = 1
+	TestMsg MessageType = iota
+	OMCI
 )
 
 func (m MessageType) String() string {
@@ -42,14 +42,19 @@
 	Data interface{}
 }
 
+type TestMessageType uint8
+
 const (
-	AnyTriggerForMibSyncUploadMib = 0
-	AbortMessageProcessing        = 1
+	noOperation TestMessageType = iota
+	LoadMibTemplateOk
+	LoadMibTemplateFailed
+	TimeOutOccurred
+	AbortMessageProcessing
 )
 
 //TODO: place holder to have a second interface variant - to be replaced by real variant later on
 type TestMessage struct {
-	TestMessageVal uint32
+	TestMessageVal TestMessageType
 }
 
 type OmciMessage struct {
diff --git a/internal/pkg/onuadaptercore/mib_download.go b/internal/pkg/onuadaptercore/mib_download.go
index 03c328d..8d00188 100644
--- a/internal/pkg/onuadaptercore/mib_download.go
+++ b/internal/pkg/onuadaptercore/mib_download.go
@@ -41,7 +41,6 @@
 	}
 	// start go routine for processing of MibDownload messages
 	go onuDeviceEntry.ProcessMibDownloadMessages()
-	//possibly include a further MibReset here in order to enforce reset of incomplete set data ...(TODO?)
 }
 
 func (onuDeviceEntry *OnuDeviceEntry) enterCreatingGalState(e *fsm.Event) {
@@ -61,7 +60,7 @@
 }
 
 func (onuDeviceEntry *OnuDeviceEntry) enterBridgeInitState(e *fsm.Event) {
-	logger.Debugw("MibDownload FSM - starting bridge config loop", log.Fields{
+	logger.Infow("MibDownload FSM - starting bridge config port loop", log.Fields{
 		"in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
 	go onuDeviceEntry.performInitialBridgeSetup()
 }
@@ -86,13 +85,13 @@
 	pMibDlFsm := onuDeviceEntry.pMibDownloadFsm
 	if pMibDlFsm != nil {
 		// abort running message processing
-		mibSyncMsg := Message{
+		fsmAbortMsg := Message{
 			Type: TestMsg,
 			Data: TestMessage{
 				TestMessageVal: AbortMessageProcessing,
 			},
 		}
-		pMibDlFsm.commChan <- mibSyncMsg
+		pMibDlFsm.commChan <- fsmAbortMsg
 
 		//try to restart the FSM to 'disabled'
 		// see DownloadedState: decouple event transfer
@@ -206,12 +205,6 @@
 				logger.Error("Omci Msg layer could not be assigned for SetResponse")
 				return
 			}
-			logger.Debugw("SetResponse Data for:", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
-			if msgObj.Result != me.Success {
-				logger.Errorw("Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
-				// possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
-				return
-			}
 			logger.Debugw("SetResponse Data", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
 			if msgObj.Result != me.Success {
 				logger.Errorw("Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
@@ -233,9 +226,6 @@
 					//so far that was the only MibDownlad Set Element ...
 				}
 			}
-
-			// TODO!!!: further needed processing here ....
-
 		} //SetResponseType
 	default:
 		{
@@ -247,7 +237,7 @@
 
 func (onuDeviceEntry *OnuDeviceEntry) performInitialBridgeSetup() {
 	for uniNo, uniPort := range onuDeviceEntry.baseDeviceHandler.uniEntityMap {
-		logger.Infow("Starting IntialBridgeSetup", log.Fields{
+		logger.Debugw("Starting IntialBridgeSetup", log.Fields{
 			"deviceId": onuDeviceEntry.deviceID, "for PortNo": uniNo})
 
 		//create MBSP
diff --git a/internal/pkg/onuadaptercore/mib_sync.go b/internal/pkg/onuadaptercore/mib_sync.go
index d15ae03..d5f2696 100644
--- a/internal/pkg/onuadaptercore/mib_sync.go
+++ b/internal/pkg/onuadaptercore/mib_sync.go
@@ -19,7 +19,10 @@
 
 import (
 	"context"
+	"encoding/json"
 	"errors"
+	"fmt"
+	"strconv"
 
 	"github.com/looplab/fsm"
 
@@ -29,12 +32,37 @@
 	//"github.com/opencord/voltha-lib-go/v3/pkg/kafka"
 	"github.com/opencord/omci-lib-go"
 	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/voltha-lib-go/v3/pkg/db"
+	"github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
 	"github.com/opencord/voltha-lib-go/v3/pkg/log"
 	//ic "github.com/opencord/voltha-protos/v3/go/inter_container"
 	//"github.com/opencord/voltha-protos/v3/go/openflow_13"
 	//"github.com/opencord/voltha-protos/v3/go/voltha"
 )
 
+var supportedClassIds = []me.ClassID{
+	me.CardholderClassID,                              // 5
+	me.CircuitPackClassID,                             // 6
+	me.SoftwareImageClassID,                           // 7
+	me.PhysicalPathTerminationPointEthernetUniClassID, // 11
+	me.OltGClassID,                                    // 131
+	me.OnuPowerSheddingClassID,                        // 133
+	me.IpHostConfigDataClassID,                        // 134
+	me.OnuGClassID,                                    // 256
+	me.Onu2GClassID,                                   // 257
+	me.TContClassID,                                   // 262
+	me.AniGClassID,                                    // 263
+	me.UniGClassID,                                    // 264
+	me.PriorityQueueClassID,                           // 277
+	me.TrafficSchedulerClassID,                        // 278
+	me.VirtualEthernetInterfacePointClassID,           // 329
+	me.EnhancedSecurityControlClassID,                 // 332
+	me.OnuDynamicPowerManagementControlClassID,        // 336
+	// 347 // definitions for ME "IPv6 host config data" are currently missing in omci-lib-go!
+}
+
+var fsmMsg TestMessageType
+
 func (onuDeviceEntry *OnuDeviceEntry) enterStartingState(e *fsm.Event) {
 	logger.Debugw("MibSync FSM", log.Fields{"Start processing MibSync-msgs in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
 
@@ -45,7 +73,85 @@
 
 func (onuDeviceEntry *OnuDeviceEntry) enterLoadingMibTemplateState(e *fsm.Event) {
 	logger.Debugw("MibSync FSM", log.Fields{"Start MibTemplate processing in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
-	logger.Debug("function not implemented yet")
+
+	meStoredFromTemplate := false
+
+	//TODO: perform MIB-reset
+	//TODO: needs to handle timeouts
+
+	//TODO: etrieve these values via OMCI GetRequests
+	//OltGClassID
+	onuDeviceEntry.vendorID = "BBSM"
+	onuDeviceEntry.serialNumber = "BBSM00000001"
+	//Onu2GClassID
+	onuDeviceEntry.equipmentID = "12345123451234512345"
+	//SoftwareImageClassID
+	onuDeviceEntry.activeSwVersion = "00000000000001"
+	//IpHostConfigDataClassID
+	onuDeviceEntry.macAddress = "00:00:00:00:00:00"
+
+	Path := fmt.Sprintf(SuffixMibTemplateKvStore, onuDeviceEntry.vendorID, onuDeviceEntry.equipmentID, onuDeviceEntry.activeSwVersion)
+	Value, err := onuDeviceEntry.mibTemplateKVStore.Get(context.TODO(), Path)
+	if err == nil {
+		if Value != nil {
+			logger.Debugf("MibSync FSM - MibTemplate read: Key: %s, Value: %s  %s", Value.Key, Value.Value)
+			mibTmpBytes, _ := kvstore.ToByte(Value.Value)
+
+			var fistLevelMap map[string]interface{}
+			if err = json.Unmarshal(mibTmpBytes, &fistLevelMap); err != nil {
+				logger.Error("MibSync FSM - Failed to unmarshal template", log.Fields{"error": err, "device-id": onuDeviceEntry.deviceID})
+			} else {
+				for fistLevelKey, firstLevelValue := range fistLevelMap {
+					logger.Debugw("MibSync FSM - fistLevelKey", log.Fields{"fistLevelKey": fistLevelKey})
+					if uint16ValidNumber, err := strconv.ParseUint(fistLevelKey, 10, 16); err == nil {
+						meClassId := me.ClassID(uint16ValidNumber)
+						logger.Debugw("MibSync FSM - fistLevelKey is a number in uint16-range", log.Fields{"uint16ValidNumber": uint16ValidNumber})
+						if IsSupportedClassId(meClassId) {
+							logger.Debugw("MibSync FSM - fistLevelKey is a supported classId", log.Fields{"meClassId": meClassId})
+							secondLevelMap := firstLevelValue.(map[string]interface{})
+							for secondLevelKey, secondLevelValue := range secondLevelMap {
+								logger.Debugw("MibSync FSM - secondLevelKey", log.Fields{"secondLevelKey": secondLevelKey})
+								if uint16ValidNumber, err := strconv.ParseUint(secondLevelKey, 10, 16); err == nil {
+									meEntityId := uint16(uint16ValidNumber)
+									logger.Debugw("MibSync FSM - secondLevelKey is a numberand a valid EntityId", log.Fields{"meEntityId": meEntityId})
+									thirdLevelMap := secondLevelValue.(map[string]interface{})
+									for thirdLevelKey, thirdLevelValue := range thirdLevelMap {
+										if thirdLevelKey == "attributes" {
+											logger.Debugw("MibSync FSM - thirdLevelKey refers to attributes", log.Fields{"thirdLevelKey": thirdLevelKey})
+											attributesMap := thirdLevelValue.(map[string]interface{})
+											logger.Debugw("MibSync FSM - attributesMap", log.Fields{"attributesMap": attributesMap})
+											onuDeviceEntry.pOnuDB.StoreMe(meClassId, meEntityId, attributesMap)
+											meStoredFromTemplate = true
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		} else {
+			logger.Debugw("No MIB template found", log.Fields{"device-id": onuDeviceEntry.deviceID})
+		}
+	} else {
+		logger.Errorf("Get from kvstore operation failed for path %s", Path)
+	}
+	if meStoredFromTemplate {
+		logger.Debug("MibSync FSM - valid MEs stored from template")
+		onuDeviceEntry.pOnuDB.LogMeDb()
+		fsmMsg = LoadMibTemplateOk
+	} else {
+		logger.Debug("MibSync FSM - no valid MEs stored from template - perform MIB-upload!")
+		fsmMsg = LoadMibTemplateFailed
+	}
+
+	mibSyncMsg := Message{
+		Type: TestMsg,
+		Data: TestMessage{
+			TestMessageVal: fsmMsg,
+		},
+	}
+	onuDeviceEntry.pMibUploadFsm.commChan <- mibSyncMsg
 }
 
 func (onuDeviceEntry *OnuDeviceEntry) enterUploadingState(e *fsm.Event) {
@@ -115,9 +221,12 @@
 	logger.Debugw("MibSync Msg", log.Fields{"TestMessage received for device-id": onuDeviceEntry.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
 
 	switch msg.TestMessageVal {
-	case AnyTriggerForMibSyncUploadMib:
+	case LoadMibTemplateFailed:
 		onuDeviceEntry.pMibUploadFsm.pFsm.Event("upload_mib")
 		logger.Debugw("MibSync Msg", log.Fields{"state": string(onuDeviceEntry.pMibUploadFsm.pFsm.Current())})
+	case LoadMibTemplateOk:
+		onuDeviceEntry.pMibUploadFsm.pFsm.Event("success")
+		logger.Debugw("MibSync Msg", log.Fields{"state": string(onuDeviceEntry.pMibUploadFsm.pFsm.Current())})
 	default:
 		logger.Warn("MibSync Msg", log.Fields{"Unknown message type received for device-id": onuDeviceEntry.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
 	}
@@ -181,7 +290,11 @@
 		}
 		logger.Debugw("MibUploadNextResponse Data for:", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
 
-		onuDeviceEntry.pOnuDB.StoreMe(msgObj)
+		meClassId := msgObj.ReportedME.GetClassID()
+		meEntityId := msgObj.ReportedME.GetEntityID()
+		meAttributes := msgObj.ReportedME.GetAttributeValueMap()
+
+		onuDeviceEntry.pOnuDB.StoreMe(meClassId, meEntityId, meAttributes)
 
 		if onuDeviceEntry.PDevOmciCC.uploadSequNo < onuDeviceEntry.PDevOmciCC.uploadNoOfCmds {
 			onuDeviceEntry.PDevOmciCC.sendMibUploadNext(context.TODO(), ConstDefaultOmciTimeout, true)
@@ -193,6 +306,50 @@
 	}
 }
 
+func (onuDeviceEntry *OnuDeviceEntry) newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
+	logger.Infow("kv-store-type", log.Fields{"store": storeType})
+	switch storeType {
+	case "consul":
+		return kvstore.NewConsulClient(address, timeout)
+	case "etcd":
+		return kvstore.NewEtcdClient(address, timeout, log.FatalLevel)
+	}
+	return nil, errors.New("unsupported-kv-store")
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) SetKVClient(backend string, Host string, Port int, BasePathKvStore string) *db.Backend {
+	logger.Debugw("SetKVClient with params:", log.Fields{"backend": backend, "Host": Host, "Port": Port,
+		"BasePathKvStore": BasePathKvStore, "deviceId": onuDeviceEntry.deviceID})
+
+	addr := Host + ":" + strconv.Itoa(Port)
+	// TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
+	// issue between kv store and backend , core is not calling NewBackend directly
+	kvClient, err := onuDeviceEntry.newKVClient(backend, addr, KvstoreTimeout)
+	if err != nil {
+		logger.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
+		return nil
+	}
+
+	kvbackend := &db.Backend{
+		Client:     kvClient,
+		StoreType:  backend,
+		Host:       Host,
+		Port:       Port,
+		Timeout:    KvstoreTimeout,
+		PathPrefix: BasePathKvStore}
+
+	return kvbackend
+}
+
+func IsSupportedClassId(meClassId me.ClassID) bool {
+	for _, v := range supportedClassIds {
+		if v == meClassId {
+			return true
+		}
+	}
+	return false
+}
+
 func (onuDeviceEntry *OnuDeviceEntry) MibDbVolatileDict() error {
 	logger.Debug("MibVolatileDict- running from default Entry code")
 	return errors.New("not_implemented")
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index 972670f..9074fc8 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -57,10 +57,16 @@
 
 // ### OMCI related definitions - end
 
+//CallbackPairEntry to be used for OMCI send/receive correlation
+type CallbackPairEntry struct {
+	cbRespChannel chan Message
+	cbFunction    func(*omci.OMCI, *gp.Packet, chan Message) error
+}
+
 //CallbackPair to be used for ReceiveCallback init
 type CallbackPair struct {
-	cbKey      uint16
-	cbFunction func(*omci.OMCI, *gp.Packet) error
+	cbKey   uint16
+	cbEntry CallbackPairEntry
 }
 
 type omciTransferStructure struct {
@@ -96,7 +102,7 @@
 	mutexTxQueue      sync.Mutex
 	txQueue           *list.List
 	mutexRxSchedMap   sync.Mutex
-	rxSchedulerMap    map[uint16]func(*omci.OMCI, *gp.Packet) error
+	rxSchedulerMap    map[uint16]CallbackPairEntry
 	pLastTxMeInstance *me.ManagedEntity
 }
 
@@ -125,7 +131,7 @@
 	omciCC.uploadNoOfCmds = 0
 
 	omciCC.txQueue = list.New()
-	omciCC.rxSchedulerMap = make(map[uint16]func(*omci.OMCI, *gp.Packet) error)
+	omciCC.rxSchedulerMap = make(map[uint16]CallbackPairEntry)
 
 	return &omciCC
 }
@@ -229,11 +235,11 @@
 	} else {
 		logger.Debug("RxMsg is a Omci Response Message: try to schedule it to the requester")
 		oo.mutexRxSchedMap.Lock()
-		rxCallback, ok := oo.rxSchedulerMap[omciMsg.TransactionID]
-		if ok && rxCallback != nil {
+		rxCallbackEntry, ok := oo.rxSchedulerMap[omciMsg.TransactionID]
+		if ok && rxCallbackEntry.cbFunction != nil {
 			//disadvantage of decoupling: error verification made difficult, but anyway the question is
 			// how to react on erroneous frame reception, maybe can simply be ignored
-			go rxCallback(omciMsg, &packet)
+			go rxCallbackEntry.cbFunction(omciMsg, &packet, rxCallbackEntry.cbRespChannel)
 			// having posted the response the request is regarded as 'done'
 			delete(oo.rxSchedulerMap, omciMsg.TransactionID)
 			oo.mutexRxSchedMap.Unlock()
@@ -362,7 +368,7 @@
 	logger.Debugw("register-response-callback:", log.Fields{"for TansCorrId": receiveCallbackPair.cbKey})
 	// it could be checked, if the callback keay is already registered - but simply overwrite may be acceptable ...
 	oo.mutexRxSchedMap.Lock()
-	oo.rxSchedulerMap[receiveCallbackPair.cbKey] = receiveCallbackPair.cbFunction
+	oo.rxSchedulerMap[receiveCallbackPair.cbKey] = receiveCallbackPair.cbEntry
 	oo.mutexRxSchedMap.Unlock()
 
 	//just use a simple list for starting - might need some more effort, especially for multi source write access
@@ -526,20 +532,21 @@
 	return dst, nil
 }
 
-//supply a response handler for the MibSync omci response messages
-func (oo *OmciCC) receiveMibSyncResponse(omciMsg *omci.OMCI, packet *gp.Packet) error {
+//supply a response handler for omci response messages to be transferred to the requested FSM
+func (oo *OmciCC) receiveOmciResponse(omciMsg *omci.OMCI, packet *gp.Packet, respChan chan Message) error {
 
-	logger.Debugw("mib-sync-omci-message-response received:", log.Fields{"omciMsgType": omciMsg.MessageType,
+	logger.Debugw("omci-message-response received:", log.Fields{"omciMsgType": omciMsg.MessageType,
 		"transCorrId": omciMsg.TransactionID, "deviceId": oo.deviceID})
 
 	if oo.pOnuDeviceEntry == nil {
-		logger.Error("Abort Receive MibSync OMCI, DeviceEntryPointer is nil")
+		logger.Errorw("Abort receiving OMCI response, DeviceEntryPointer is nil", log.Fields{
+			"deviceId": oo.deviceID})
 		return errors.New("DeviceEntryPointer is nil")
 	}
 
 	// no further test on SeqNo is done here, assignment from rxScheduler is trusted
 	// MibSync responses are simply transferred via deviceEntry to MibSync, no specific analysis here
-	mibSyncMsg := Message{
+	omciRespMsg := Message{
 		Type: OMCI,
 		Data: OmciMessage{
 			OmciMsg:    omciMsg,
@@ -547,32 +554,7 @@
 		},
 	}
 	//logger.Debugw("Message to be sent into channel:", log.Fields{"mibSyncMsg": mibSyncMsg})
-	(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan <- mibSyncMsg
-
-	return nil
-}
-
-//supply a response handler for the MibDownload omci response messages
-func (oo *OmciCC) ReceiveMibDownloadResponse(omciMsg *omci.OMCI, packet *gp.Packet) error {
-
-	logger.Debugw("mib-download-omci-message-response received:", log.Fields{"omciMsgType": omciMsg.MessageType,
-		"transCorrId": omciMsg.TransactionID, "deviceId": oo.deviceID})
-
-	if oo.pOnuDeviceEntry == nil {
-		logger.Error("Abort Receive MibDownload OMCI response, DeviceEntryPointer is nil")
-		return errors.New("DeviceEntryPointer is nil")
-	}
-
-	// no further test on SeqNo is done here, assignment from rxScheduler is trusted
-	// MibDownload responses are simply transferred via deviceEntry to MibDownload, no specific analysis here
-	mibDlMsg := Message{
-		Type: OMCI,
-		Data: OmciMessage{
-			OmciMsg:    omciMsg,
-			OmciPacket: packet,
-		},
-	}
-	(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan <- mibDlMsg
+	respChan <- omciRespMsg
 
 	return nil
 }
@@ -588,10 +570,14 @@
 	tid := oo.GetNextTid(highPrio)
 	pkt, err := serialize(omci.MibResetRequestType, request, tid)
 	if err != nil {
-		logger.Errorw("Cannot serialize MibResetRequest", log.Fields{"Err": err})
+		logger.Errorw("Cannot serialize MibResetRequest", log.Fields{
+			"Err": err, "deviceId": oo.deviceID})
 		return err
 	}
-	omciRxCallbackPair := CallbackPair{tid, oo.receiveMibSyncResponse}
+	omciRxCallbackPair := CallbackPair{
+		cbKey:   tid,
+		cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+	}
 	return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 }
 
@@ -605,13 +591,17 @@
 	tid := oo.GetNextTid(highPrio)
 	pkt, err := serialize(omci.MibUploadRequestType, request, tid)
 	if err != nil {
-		logger.Errorw("Cannot serialize MibUploadRequest", log.Fields{"Err": err})
+		logger.Errorw("Cannot serialize MibUploadRequest", log.Fields{
+			"Err": err, "deviceId": oo.deviceID})
 		return err
 	}
 	oo.uploadSequNo = 0
 	oo.uploadNoOfCmds = 0
 
-	omciRxCallbackPair := CallbackPair{tid, oo.receiveMibSyncResponse}
+	omciRxCallbackPair := CallbackPair{
+		cbKey:   tid,
+		cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+	}
 	return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 }
 
@@ -626,12 +616,16 @@
 	tid := oo.GetNextTid(highPrio)
 	pkt, err := serialize(omci.MibUploadNextRequestType, request, tid)
 	if err != nil {
-		logger.Errorw("Cannot serialize MibUploadNextRequest", log.Fields{"Err": err})
+		logger.Errorw("Cannot serialize MibUploadNextRequest", log.Fields{
+			"Err": err, "deviceId": oo.deviceID})
 		return err
 	}
 	oo.uploadSequNo++
 
-	omciRxCallbackPair := CallbackPair{tid, oo.receiveMibSyncResponse}
+	omciRxCallbackPair := CallbackPair{
+		cbKey:   tid,
+		cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+	}
 	return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 }
 
@@ -648,38 +642,45 @@
 		//all setByCreate parameters already set, no default option required ...
 		omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.CreateRequestType, omci.TransactionID(tid))
 		if err != nil {
-			logger.Errorw("Cannot encode GalEnetProfileInstance for create", log.Fields{"Err": err})
+			logger.Errorw("Cannot encode GalEnetProfileInstance for create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
 		pkt, err := serializeOmciLayer(omciLayer, msgLayer)
 		if err != nil {
-			logger.Errorw("Cannot serialize GalEnetProfile create", log.Fields{"Err": err})
+			logger.Errorw("Cannot serialize GalEnetProfile create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
-		omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+		omciRxCallbackPair := CallbackPair{
+			cbKey:   tid,
+			cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+		}
 		err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
-			logger.Errorw("Cannot send GalEnetProfile create", log.Fields{"Err": err})
+			logger.Errorw("Cannot send GalEnetProfile create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		} else {
 			logger.Debug("send GalEnetProfile-Create-msg done")
 			return meInstance
 		}
 	} else {
-		logger.Errorw("Cannot generate GalEnetProfileInstance", log.Fields{"Err": omciErr.GetError()})
+		logger.Errorw("Cannot generate GalEnetProfileInstance", log.Fields{
+			"Err": omciErr.GetError(), "deviceId": oo.deviceID})
 		return nil
 	}
 }
 
-// might be needed to extend for parameter arguments, here just for setting the VonnectivityMode!!
+// might be needed to extend for parameter arguments, here just for setting the ConnectivityMode!!
 func (oo *OmciCC) sendSetOnu2g(ctx context.Context, timeout int, highPrio bool) *me.ManagedEntity {
 	tid := oo.GetNextTid(highPrio)
 	logger.Debugw("send ONU2-G-Set-msg:", log.Fields{"deviceId": oo.deviceID, "SequNo": strconv.FormatInt(int64(tid), 16)})
 
-	// here we should better use the MibUpload stored ONU2-G data to re-use the given InstanceNumber
-	//   and to verify, if the ONU really supports the desired connectivity mode 5 (in ConnCap)
+	// ONU-G ME-ID is defined to be 0, but we could verify, if the ONU really supports the desired
+	//   connectivity mode 5 (in ConnCap)
 	// By now we just use fix values to fire - this is anyway what the python adapter does
 	// read ONU-2G from DB ???? //TODO!!!
 	meParams := me.ParamData{
@@ -690,27 +691,34 @@
 	if omciErr.GetError() == nil {
 		omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.SetRequestType, omci.TransactionID(tid))
 		if err != nil {
-			logger.Errorw("Cannot encode ONU2-G instance for set", log.Fields{"Err": err})
+			logger.Errorw("Cannot encode ONU2-G instance for set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
 		pkt, err := serializeOmciLayer(omciLayer, msgLayer)
 		if err != nil {
-			logger.Errorw("Cannot serialize ONU2-G set", log.Fields{"Err": err})
+			logger.Errorw("Cannot serialize ONU2-G set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
-		omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+		omciRxCallbackPair := CallbackPair{
+			cbKey:   tid,
+			cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+		}
 		err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
-			logger.Errorw("Cannot send ONU2-G set", log.Fields{"Err": err})
+			logger.Errorw("Cannot send ONU2-G set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		} else {
 			logger.Debug("send ONU2-G-Set-msg done")
 			return meInstance
 		}
 	} else {
-		logger.Errorw("Cannot generate ONU2-G", log.Fields{"Err": omciErr.GetError()})
+		logger.Errorw("Cannot generate ONU2-G", log.Fields{
+			"Err": omciErr.GetError(), "deviceId": oo.deviceID})
 		return nil
 	}
 }
@@ -741,27 +749,34 @@
 		omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.CreateRequestType,
 			omci.TransactionID(tid), omci.AddDefaults(true))
 		if err != nil {
-			logger.Errorw("Cannot encode MBSP for create", log.Fields{"Err": err})
+			logger.Errorw("Cannot encode MBSP for create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
 		pkt, err := serializeOmciLayer(omciLayer, msgLayer)
 		if err != nil {
-			logger.Errorw("Cannot serialize MBSP create", log.Fields{"Err": err})
+			logger.Errorw("Cannot serialize MBSP create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
-		omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+		omciRxCallbackPair := CallbackPair{
+			cbKey:   tid,
+			cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+		}
 		err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
-			logger.Errorw("Cannot send MBSP create", log.Fields{"Err": err})
+			logger.Errorw("Cannot send MBSP create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		} else {
 			logger.Debug("send MBSP-Create-msg done")
 			return meInstance
 		}
 	} else {
-		logger.Errorw("Cannot generate MBSP Instance", log.Fields{"Err": omciErr.GetError()})
+		logger.Errorw("Cannot generate MBSP Instance", log.Fields{
+			"Err": omciErr.GetError(), "deviceId": oo.deviceID})
 		return nil
 	}
 }
@@ -788,27 +803,34 @@
 		omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.CreateRequestType,
 			omci.TransactionID(tid), omci.AddDefaults(true))
 		if err != nil {
-			logger.Errorw("Cannot encode MBPCD for create", log.Fields{"Err": err})
+			logger.Errorw("Cannot encode MBPCD for create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
 		pkt, err := serializeOmciLayer(omciLayer, msgLayer)
 		if err != nil {
-			logger.Errorw("Cannot serialize MBPCD create", log.Fields{"Err": err})
+			logger.Errorw("Cannot serialize MBPCD create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
-		omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+		omciRxCallbackPair := CallbackPair{
+			cbKey:   tid,
+			cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+		}
 		err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
-			logger.Errorw("Cannot send MBPCD create", log.Fields{"Err": err})
+			logger.Errorw("Cannot send MBPCD create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		} else {
 			logger.Debug("send MBPCD-Create-msg done")
 			return meInstance
 		}
 	} else {
-		logger.Errorw("Cannot generate MBPCD Instance", log.Fields{"Err": omciErr.GetError()})
+		logger.Errorw("Cannot generate MBPCD Instance", log.Fields{
+			"Err": omciErr.GetError(), "deviceId": oo.deviceID})
 		return nil
 	}
 }
@@ -840,27 +862,172 @@
 		//all setByCreate parameters already set, no default option required ...
 		omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.CreateRequestType, omci.TransactionID(tid))
 		if err != nil {
-			logger.Errorw("Cannot encode EVTOCD for create", log.Fields{"Err": err})
+			logger.Errorw("Cannot encode EVTOCD for create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
 		pkt, err := serializeOmciLayer(omciLayer, msgLayer)
 		if err != nil {
-			logger.Errorw("Cannot serialize EVTOCD create", log.Fields{"Err": err})
+			logger.Errorw("Cannot serialize EVTOCD create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		}
 
-		omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+		omciRxCallbackPair := CallbackPair{
+			cbKey:   tid,
+			cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+		}
 		err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
 		if err != nil {
-			logger.Errorw("Cannot send EVTOCD create", log.Fields{"Err": err})
+			logger.Errorw("Cannot send EVTOCD create", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
 			return nil
 		} else {
 			logger.Debug("send EVTOCD-Create-msg done")
 			return meInstance
 		}
 	} else {
-		logger.Errorw("Cannot generate EVTOCD Instance", log.Fields{"Err": omciErr.GetError()})
+		logger.Errorw("Cannot generate EVTOCD Instance", log.Fields{
+			"Err": omciErr.GetError(), "deviceId": oo.deviceID})
+		return nil
+	}
+}
+
+func (oo *OmciCC) sendSetOnuGLS(ctx context.Context, timeout int,
+	highPrio bool, requestedAttributes me.AttributeValueMap, rxChan chan Message) *me.ManagedEntity {
+	tid := oo.GetNextTid(highPrio)
+	logger.Debugw("send ONU-G-Set-msg:", log.Fields{"deviceId": oo.deviceID, "SequNo": strconv.FormatInt(int64(tid), 16)})
+
+	// ONU-G ME-ID is defined to be 0, no need to perform a DB lookup
+	meParams := me.ParamData{
+		EntityID:   0,
+		Attributes: requestedAttributes,
+	}
+	meInstance, omciErr := me.NewOnuG(meParams)
+	if omciErr.GetError() == nil {
+		omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.SetRequestType, omci.TransactionID(tid))
+		if err != nil {
+			logger.Errorw("Cannot encode ONU-G instance for set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
+			return nil
+		}
+
+		pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+		if err != nil {
+			logger.Errorw("Cannot serialize ONU-G set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
+			return nil
+		}
+
+		omciRxCallbackPair := CallbackPair{
+			cbKey:   tid,
+			cbEntry: CallbackPairEntry{rxChan, oo.receiveOmciResponse},
+		}
+		err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+		if err != nil {
+			logger.Errorw("Cannot send ONU-G set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
+			return nil
+		} else {
+			logger.Debug("send ONU-G-Set-msg done")
+			return meInstance
+		}
+	} else {
+		logger.Errorw("Cannot generate ONU-G", log.Fields{
+			"Err": omciErr.GetError(), "deviceId": oo.deviceID})
+		return nil
+	}
+}
+
+func (oo *OmciCC) sendSetUniGLS(ctx context.Context, aInstNo uint16, timeout int,
+	highPrio bool, requestedAttributes me.AttributeValueMap, rxChan chan Message) *me.ManagedEntity {
+	tid := oo.GetNextTid(highPrio)
+	logger.Debugw("send UNI-G-Set-msg:", log.Fields{"deviceId": oo.deviceID, "SequNo": strconv.FormatInt(int64(tid), 16)})
+
+	// UNI-G ME-ID is taken from Mib Upload stored OnuUniPort instance (argument)
+	meParams := me.ParamData{
+		EntityID:   aInstNo,
+		Attributes: requestedAttributes,
+	}
+	meInstance, omciErr := me.NewUniG(meParams)
+	if omciErr.GetError() == nil {
+		omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.SetRequestType, omci.TransactionID(tid))
+		if err != nil {
+			logger.Errorw("Cannot encode UNI-G instance for set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
+			return nil
+		}
+
+		pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+		if err != nil {
+			logger.Errorw("Cannot serialize UNI-G-Set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
+			return nil
+		}
+
+		omciRxCallbackPair := CallbackPair{
+			cbKey:   tid,
+			cbEntry: CallbackPairEntry{rxChan, oo.receiveOmciResponse},
+		}
+		err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+		if err != nil {
+			logger.Errorw("Cannot send UNIG-G-Set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
+			return nil
+		} else {
+			logger.Debug("send UNI-G-Set-msg done")
+			return meInstance
+		}
+	} else {
+		logger.Errorw("Cannot generate UNI-G", log.Fields{
+			"Err": omciErr.GetError(), "deviceId": oo.deviceID})
+		return nil
+	}
+}
+
+func (oo *OmciCC) sendSetVeipLS(ctx context.Context, aInstNo uint16, timeout int,
+	highPrio bool, requestedAttributes me.AttributeValueMap, rxChan chan Message) *me.ManagedEntity {
+	tid := oo.GetNextTid(highPrio)
+	logger.Debugw("send VEIP-Set-msg:", log.Fields{"deviceId": oo.deviceID, "SequNo": strconv.FormatInt(int64(tid), 16)})
+
+	// ONU-G ME-ID is defined to be 0, no need to perform a DB lookup
+	meParams := me.ParamData{
+		EntityID:   aInstNo,
+		Attributes: requestedAttributes,
+	}
+	meInstance, omciErr := me.NewVirtualEthernetInterfacePoint(meParams)
+	if omciErr.GetError() == nil {
+		omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.SetRequestType, omci.TransactionID(tid))
+		if err != nil {
+			logger.Errorw("Cannot encode VEIP instance for set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
+			return nil
+		}
+
+		pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+		if err != nil {
+			logger.Errorw("Cannot serialize VEIP-Set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
+			return nil
+		}
+
+		omciRxCallbackPair := CallbackPair{
+			cbKey:   tid,
+			cbEntry: CallbackPairEntry{rxChan, oo.receiveOmciResponse},
+		}
+		err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+		if err != nil {
+			logger.Errorw("Cannot send VEIP-Set", log.Fields{
+				"Err": err, "deviceId": oo.deviceID})
+			return nil
+		} else {
+			logger.Debug("send VEIP-Set-msg done")
+			return meInstance
+		}
+	} else {
+		logger.Errorw("Cannot generate VEIP", log.Fields{
+			"Err": omciErr.GetError(), "deviceId": oo.deviceID})
 		return nil
 	}
 }
diff --git a/internal/pkg/onuadaptercore/omci_test_request.go b/internal/pkg/onuadaptercore/omci_test_request.go
index a79ad21..cfb3096 100644
--- a/internal/pkg/onuadaptercore/omci_test_request.go
+++ b/internal/pkg/onuadaptercore/omci_test_request.go
@@ -73,7 +73,10 @@
 		// without yet checking the received response automatically here (might be improved ??)
 		tid := oo.pDevOmciCC.GetNextTid(false)
 		onu2gBaseGet, _ := oo.CreateOnu2gBaseGet(tid)
-		omciRxCallbackPair := CallbackPair{tid, oo.ReceiveOmciVerifyResponse}
+		omciRxCallbackPair := CallbackPair{
+			cbKey:   tid,
+			cbEntry: CallbackPairEntry{nil, oo.ReceiveOmciVerifyResponse},
+		}
 
 		logger.Debugw("performOmciTest-start sending frame", log.Fields{"for deviceId": oo.deviceID})
 		// send with default timeout and normal prio
@@ -109,8 +112,8 @@
 	return pkt, nil
 }
 
-//supply a response handler
-func (oo *OmciTestRequest) ReceiveOmciVerifyResponse(omciMsg *omci.OMCI, packet *gp.Packet) error {
+//supply a response handler - in this testobject the message is evaluated directly, no response channel used
+func (oo *OmciTestRequest) ReceiveOmciVerifyResponse(omciMsg *omci.OMCI, packet *gp.Packet, respChan chan Message) error {
 
 	logger.Debugw("verify-omci-message-response received:", log.Fields{"omciMsgType": omciMsg.MessageType,
 		"transCorrId": omciMsg.TransactionID, "DeviceIdent": omciMsg.DeviceIdentifier})
diff --git a/internal/pkg/onuadaptercore/onu_device_db.go b/internal/pkg/onuadaptercore/onu_device_db.go
index 0b985d6..7f779b2 100644
--- a/internal/pkg/onuadaptercore/onu_device_db.go
+++ b/internal/pkg/onuadaptercore/onu_device_db.go
@@ -21,7 +21,6 @@
 	"context"
 	"sort"
 
-	"github.com/opencord/omci-lib-go"
 	me "github.com/opencord/omci-lib-go/generated"
 	"github.com/opencord/voltha-lib-go/v3/pkg/log"
 )
@@ -46,11 +45,7 @@
 	return &onuDeviceDB
 }
 
-func (onuDeviceDB *OnuDeviceDB) StoreMe(a_pMibUpResp *omci.MibUploadNextResponse) {
-
-	meClassId := a_pMibUpResp.ReportedME.GetClassID()
-	meEntityId := a_pMibUpResp.ReportedME.GetEntityID()
-	meAttributes := a_pMibUpResp.ReportedME.GetAttributeValueMap()
+func (onuDeviceDB *OnuDeviceDB) StoreMe(meClassId me.ClassID, meEntityId uint16, meAttributes me.AttributeValueMap) {
 
 	//filter out the OnuData
 	if me.OnuDataClassID == meClassId {
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index 2d7caa6..2a7c29e 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -19,12 +19,14 @@
 
 import (
 	"context"
-	//"errors"
+	"errors"
+
 	//"sync"
 	//"time"
 
 	"github.com/looplab/fsm"
 	"github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
+	"github.com/opencord/voltha-lib-go/v3/pkg/db"
 
 	//"github.com/opencord/voltha-lib-go/v3/pkg/kafka"
 	"github.com/opencord/voltha-lib-go/v3/pkg/log"
@@ -33,6 +35,12 @@
 	//"github.com/opencord/voltha-protos/v3/go/voltha"
 )
 
+const (
+	KvstoreTimeout             = 5 //in seconds
+	BasePathMibTemplateKvStore = "service/voltha/omci_mibs/templates"
+	SuffixMibTemplateKvStore   = "%s/%s/%s"
+)
+
 type OnuDeviceEvent int
 
 const (
@@ -41,8 +49,11 @@
 	MibDatabaseSync      OnuDeviceEvent = 1 // MIB database sync (upload done)
 	OmciCapabilitiesDone OnuDeviceEvent = 2 // OMCI ME and message type capabilities known
 	MibDownloadDone      OnuDeviceEvent = 3 // MIB database sync (upload done)
-	PortLinkUp           OnuDeviceEvent = 4 // Port link state change
-	PortLinkDw           OnuDeviceEvent = 5 // Port link state change
+	UniLockStateDone     OnuDeviceEvent = 4 // Uni ports admin set to lock
+	UniUnlockStateDone   OnuDeviceEvent = 5 // Uni ports admin set to unlock
+	UniAdminStateDone    OnuDeviceEvent = 6 // Uni ports admin set done - general
+	PortLinkUp           OnuDeviceEvent = 7 // Port link state change
+	PortLinkDw           OnuDeviceEvent = 8 // Port link state change
 	// Add other events here as needed (alarms separate???)
 )
 
@@ -78,25 +89,29 @@
 
 //OntDeviceEntry structure holds information about the attached FSM'as and their communication
 type OnuDeviceEntry struct {
-	deviceID          string
-	baseDeviceHandler *DeviceHandler
-	coreProxy         adapterif.CoreProxy
-	adapterProxy      adapterif.AdapterProxy
-	started           bool
-	PDevOmciCC        *OmciCC
-	pOnuDB            *OnuDeviceDB
+	deviceID           string
+	baseDeviceHandler  *DeviceHandler
+	coreProxy          adapterif.CoreProxy
+	adapterProxy       adapterif.AdapterProxy
+	started            bool
+	PDevOmciCC         *OmciCC
+	pOnuDB             *OnuDeviceDB
+	mibTemplateKVStore *db.Backend
+	vendorID           string
+	serialNumber       string
+	equipmentID        string
+	activeSwVersion    string
+	macAddress         string
 	//lockDeviceEntries           sync.RWMutex
 	mibDbClass    func() error
 	supportedFsms OmciDeviceFsms
 	devState      OnuDeviceEvent
 	// for mibUpload
 	mibAuditDelay uint16
-	//MibSyncFsm    *fsm.FSM
-	//MibSyncChan   chan Message
+
+	// for mibUpload
 	pMibUploadFsm *AdapterFsm //could be handled dynamically and more general as pAdapterFsm - perhaps later
 	// for mibDownload
-	//MibDownloadFsm  *fsm.FSM
-	//MibDownloadChan chan Message
 	pMibDownloadFsm *AdapterFsm //could be handled dynamically and more general as pAdapterFsm - perhaps later
 	//remark: general usage of pAdapterFsm would require generalization of commChan  usage and internal event setting
 	//  within the FSM event procedures
@@ -105,8 +120,7 @@
 
 //OnuDeviceEntry returns a new instance of a OnuDeviceEntry
 //mib_db (as well as not inluded alarm_db not really used in this code? VERIFY!!)
-func NewOnuDeviceEntry(ctx context.Context,
-	device_id string, device_Handler *DeviceHandler,
+func NewOnuDeviceEntry(ctx context.Context, device_id string, kVStoreHost string, kVStorePort int, kvStoreType string, device_Handler *DeviceHandler,
 	core_proxy adapterif.CoreProxy, adapter_proxy adapterif.AdapterProxy,
 	supported_Fsms_Ptr *OmciDeviceFsms) *OnuDeviceEntry {
 	logger.Infow("init-onuDeviceEntry", log.Fields{"deviceId": device_id})
@@ -240,6 +254,11 @@
 		// some specifc error treatment - or waiting for crash ???
 	}
 
+	onuDeviceEntry.mibTemplateKVStore = onuDeviceEntry.SetKVClient(kvStoreType, kVStoreHost, kVStorePort, BasePathMibTemplateKvStore)
+	if onuDeviceEntry.mibTemplateKVStore == nil {
+		logger.Error("Failed to setup mibTemplateKVStore")
+	}
+
 	// Alarm Synchronization Database
 	//self._alarm_db = None
 	//self._alarm_database_cls = support_classes['alarm-synchronizer']['database']
@@ -252,11 +271,13 @@
 
 	oo.PDevOmciCC = NewOmciCC(ctx, oo, oo.deviceID, oo.baseDeviceHandler,
 		oo.coreProxy, oo.adapterProxy)
+	if oo.PDevOmciCC == nil {
+		logger.Errorw("Could not create devOmciCc - abort", log.Fields{"for device": oo.deviceID})
+		return errors.New("Could not create devOmciCc")
+	}
 
-	//TODO .....
-	//mib_db.start()
 	oo.started = true
-	logger.Info("OnuDeviceEntry-started, but not yet mib_db!!!")
+	logger.Info("OnuDeviceEntry-started")
 	return nil
 }
 
@@ -277,7 +298,7 @@
 	if dev_Event == MibDatabaseSync {
 		if oo.devState < MibDatabaseSync { //devState has not been synced yet
 			oo.devState = MibDatabaseSync
-			go oo.baseDeviceHandler.DeviceStateUpdate(dev_Event)
+			go oo.baseDeviceHandler.DeviceProcStatusUpdate(dev_Event)
 			//TODO!!! device control: next step: start MIB capability verification from here ?!!!
 		} else {
 			logger.Debugw("mibinsync-event in some already synced state - ignored", log.Fields{"state": oo.devState})
@@ -285,7 +306,7 @@
 	} else if dev_Event == MibDownloadDone {
 		if oo.devState < MibDownloadDone { //devState has not been synced yet
 			oo.devState = MibDownloadDone
-			go oo.baseDeviceHandler.DeviceStateUpdate(dev_Event)
+			go oo.baseDeviceHandler.DeviceProcStatusUpdate(dev_Event)
 		} else {
 			logger.Debugw("mibdownloaddone-event was already seen - ignored", log.Fields{"state": oo.devState})
 		}
diff --git a/internal/pkg/onuadaptercore/openonu.go b/internal/pkg/onuadaptercore/openonu.go
index 255af1d..253f901 100644
--- a/internal/pkg/onuadaptercore/openonu.go
+++ b/internal/pkg/onuadaptercore/openonu.go
@@ -195,7 +195,8 @@
 		//   and are by now not reported to the calling party (to force what reaction there?)
 		return nil
 	}
-	logger.Warn("no handler found for received Inter-Proxy-message 'ToDeviceId'")
+	logger.Warnw("no handler found for received Inter-Proxy-message", log.Fields{
+		"msgToDeviceId": targetDevice})
 	return fmt.Errorf(fmt.Sprintf("handler-not-found-%s", targetDevice))
 }
 
@@ -226,23 +227,23 @@
 
 //Disable_device disables the given device
 func (oo *OpenONUAC) Disable_device(device *voltha.Device) error {
-	logger.Debug("Disable_device", device.Id)
+	logger.Debugw("Disable_device", log.Fields{"deviceId": device.Id})
 	if handler := oo.getDeviceHandler(device.Id); handler != nil {
 		go handler.DisableDevice(device)
 		return nil
 	}
-	logger.Warn("no handler found for reenable device 'device.Id'")
+	logger.Warnw("no handler found for device-disable", log.Fields{"deviceId": device.Id})
 	return fmt.Errorf(fmt.Sprintf("handler-not-found-%s", device.Id))
 }
 
-//Reenable_device enables the olt device after disable
+//Reenable_device enables the onu device after disable
 func (oo *OpenONUAC) Reenable_device(device *voltha.Device) error {
-	logger.Debug("Reenable_device", device.Id)
+	logger.Debugw("Reenable_device", log.Fields{"deviceId": device.Id})
 	if handler := oo.getDeviceHandler(device.Id); handler != nil {
 		go handler.ReenableDevice(device)
 		return nil
 	}
-	logger.Warn("no handler found for reenable device 'device.Id'")
+	logger.Warnw("no handler found for device-reenable", log.Fields{"deviceId": device.Id})
 	return fmt.Errorf(fmt.Sprintf("handler-not-found-%s", device.Id))
 }
 
@@ -251,7 +252,7 @@
 	return errors.New("unImplemented")
 }
 
-//Self_test_device unimplented
+//Self_test_device unimplemented
 func (oo *OpenONUAC) Self_test_device(device *voltha.Device) error {
 	return errors.New("unImplemented")
 }
@@ -321,21 +322,16 @@
 	return nil, errors.New("unImplemented")
 }
 
-// Enable_port to Enable PON/NNI interface
+// Enable_port to Enable PON/NNI interface - seems not to be used/required according to python code
 func (oo *OpenONUAC) Enable_port(deviceID string, port *voltha.Port) error {
 	return errors.New("unImplemented")
 }
 
-// Disable_port to Disable pon/nni interface
+// Disable_port to Disable pon/nni interface  - seems not to be used/required according to python code
 func (oo *OpenONUAC) Disable_port(deviceID string, port *voltha.Port) error {
 	return errors.New("unImplemented")
 }
 
-// enableDisablePort to Disable pon or Enable PON interface
-func (oo *OpenONUAC) enableDisablePort(deviceID string, port *voltha.Port, enablePort bool) error {
-	return errors.New("unImplemented")
-}
-
 //needed for if update >= 3.1.x
 func (oo *OpenONUAC) Child_device_lost(deviceID string, pPortNo uint32, onuID uint32) error {
 	return errors.New("unImplemented")
diff --git a/internal/pkg/onuadaptercore/uniportadmin.go b/internal/pkg/onuadaptercore/uniportadmin.go
new file mode 100644
index 0000000..f7b98da
--- /dev/null
+++ b/internal/pkg/onuadaptercore/uniportadmin.go
@@ -0,0 +1,375 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//Package adaptercoreonu provides the utility for onu devices, flows and statistics
+package adaptercoreonu
+
+import (
+	"context"
+	"errors"
+	"time"
+
+	"github.com/looplab/fsm"
+
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/voltha-lib-go/v3/pkg/log"
+	//ic "github.com/opencord/voltha-protos/v3/go/inter_container"
+	//"github.com/opencord/voltha-protos/v3/go/openflow_13"
+	//"github.com/opencord/voltha-protos/v3/go/voltha"
+)
+
+//LockStateFsm defines the structure for the state machine to lock/unlock the ONU UNI ports via OMCI
+type LockStateFsm struct {
+	pOmciCC                  *OmciCC
+	adminState               bool
+	requestEvent             OnuDeviceEvent
+	omciLockResponseReceived chan bool //seperate channel needed for checking UNI port OMCi message responses
+	pAdaptFsm                *AdapterFsm
+}
+
+//NewLockStateFsm is the 'constructor' for the state machine to lock/unlock the ONU UNI ports via OMCI
+func NewLockStateFsm(apDevOmciCC *OmciCC, aAdminState bool, aRequestEvent OnuDeviceEvent,
+	aName string, aDeviceID string, aCommChannel chan Message) *LockStateFsm {
+	instFsm := &LockStateFsm{
+		pOmciCC:      apDevOmciCC,
+		adminState:   aAdminState,
+		requestEvent: aRequestEvent,
+	}
+	instFsm.pAdaptFsm = NewAdapterFsm(aName, aDeviceID, aCommChannel)
+	if instFsm.pAdaptFsm == nil {
+		logger.Errorw("LockStateFsm's AdapterFsm could not be instantiated!!", log.Fields{
+			"device-id": aDeviceID})
+		return nil
+	}
+	if aAdminState == true { //port locking requested
+		instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
+			"disabled",
+			fsm.Events{
+
+				{Name: "start", Src: []string{"disabled"}, Dst: "starting"},
+
+				{Name: "start_admin", Src: []string{"starting"}, Dst: "settingUnis"},
+				// the settingUnis state is used for multi ME config for alle UNI related ports
+				// maybe such could be reflected in the state machine as well (port number parametrized)
+				// but that looks not straightforward here - so we keep it simple here for the beginning(?)
+				{Name: "rx_unis_resp", Src: []string{"settingUnis"}, Dst: "settingOnuG"},
+				{Name: "rx_onug_resp", Src: []string{"settingOnuG"}, Dst: "adminDone"},
+
+				{Name: "timeout_simple", Src: []string{"settingOnuG"}, Dst: "starting"},
+				{Name: "timeout_unis", Src: []string{"settingUnis"}, Dst: "starting"},
+
+				{Name: "reset", Src: []string{"starting", "settingOnuG", "settingUnis",
+					"adminDone"}, Dst: "resetting"},
+				// exceptional treatment for all states except "resetting"
+				{Name: "restart", Src: []string{"starting", "settingOnuG", "settingUnis",
+					"adminDone", "resetting"}, Dst: "disabled"},
+			},
+
+			fsm.Callbacks{
+				"enter_state":       func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
+				"enter_starting":    func(e *fsm.Event) { instFsm.enterAdminStartingState(e) },
+				"enter_settingOnuG": func(e *fsm.Event) { instFsm.enterSettingOnuGState(e) },
+				"enter_settingUnis": func(e *fsm.Event) { instFsm.enterSettingUnisState(e) },
+				"enter_adminDone":   func(e *fsm.Event) { instFsm.enterAdminDoneState(e) },
+				"enter_resetting":   func(e *fsm.Event) { instFsm.enterResettingState(e) },
+			},
+		)
+	} else { //port unlocking requested
+		instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
+			"disabled",
+			fsm.Events{
+
+				{Name: "start", Src: []string{"disabled"}, Dst: "starting"},
+
+				{Name: "start_admin", Src: []string{"starting"}, Dst: "settingOnuG"},
+				{Name: "rx_onug_resp", Src: []string{"settingOnuG"}, Dst: "settingUnis"},
+				// the settingUnis state is used for multi ME config for alle UNI related ports
+				// maybe such could be reflected in the state machine as well (port number parametrized)
+				// but that looks not straightforward here - so we keep it simple here for the beginning(?)
+				{Name: "rx_unis_resp", Src: []string{"settingUnis"}, Dst: "adminDone"},
+
+				{Name: "timeout_simple", Src: []string{"settingOnuG"}, Dst: "starting"},
+				{Name: "timeout_unis", Src: []string{"settingUnis"}, Dst: "starting"},
+
+				{Name: "reset", Src: []string{"starting", "settingOnuG", "settingUnis",
+					"adminDone"}, Dst: "resetting"},
+				// exceptional treatment for all states except "resetting"
+				{Name: "restart", Src: []string{"starting", "settingOnuG", "settingUnis",
+					"adminDone", "resetting"}, Dst: "disabled"},
+			},
+
+			fsm.Callbacks{
+				"enter_state":       func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
+				"enter_starting":    func(e *fsm.Event) { instFsm.enterAdminStartingState(e) },
+				"enter_settingOnuG": func(e *fsm.Event) { instFsm.enterSettingOnuGState(e) },
+				"enter_settingUnis": func(e *fsm.Event) { instFsm.enterSettingUnisState(e) },
+				"enter_adminDone":   func(e *fsm.Event) { instFsm.enterAdminDoneState(e) },
+				"enter_resetting":   func(e *fsm.Event) { instFsm.enterResettingState(e) },
+			},
+		)
+	}
+	if instFsm.pAdaptFsm.pFsm == nil {
+		logger.Errorw("LockStateFsm's Base FSM could not be instantiated!!", log.Fields{
+			"device-id": aDeviceID})
+		return nil
+	}
+
+	logger.Infow("LockStateFsm created", log.Fields{"device-id": aDeviceID})
+	return instFsm
+}
+
+//SetSuccessEvent modifies the requested event notified on success
+//assumption is that this is only called in the disabled (idle) state of the FSM, hence no sem protection required
+func (oFsm *LockStateFsm) SetSuccessEvent(aEvent OnuDeviceEvent) {
+	oFsm.requestEvent = aEvent
+}
+
+func (oFsm *LockStateFsm) enterAdminStartingState(e *fsm.Event) {
+	logger.Debugw("LockStateFSM start", log.Fields{"in state": e.FSM.Current(),
+		"device-id": oFsm.pAdaptFsm.deviceID})
+	// in case the used channel is not yet defined (can be re-used after restarts)
+	if oFsm.omciLockResponseReceived == nil {
+		oFsm.omciLockResponseReceived = make(chan bool)
+		logger.Debug("LockStateFSM - OMCI UniLock RxChannel defined")
+	} else {
+		// as we may 're-use' this instance of FSM and the connected channel
+		// make sure there is no 'lingering' request in the already existing channel:
+		// (simple loop sufficient as we are the only receiver)
+		for len(oFsm.omciLockResponseReceived) > 0 {
+			<-oFsm.omciLockResponseReceived
+		}
+	}
+	// start go routine for processing of LockState messages
+	go oFsm.ProcessOmciLockMessages()
+
+	//let the state machine run forward from here directly
+	pLockStateAFsm := oFsm.pAdaptFsm
+	if pLockStateAFsm != nil {
+		// obviously calling some FSM event here directly does not work - so trying to decouple it ...
+		go func(a_pAFsm *AdapterFsm) {
+			if a_pAFsm != nil && a_pAFsm.pFsm != nil {
+				a_pAFsm.pFsm.Event("start_admin")
+			}
+		}(pLockStateAFsm)
+	}
+}
+
+func (oFsm *LockStateFsm) enterSettingOnuGState(e *fsm.Event) {
+	var omciAdminState uint8 = 1 //default locked
+	if oFsm.adminState == false {
+		omciAdminState = 0
+	}
+	logger.Debugw("LockStateFSM Tx Set::ONU-G:admin", log.Fields{
+		"omciAdmin": omciAdminState, "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
+	requestedAttributes := me.AttributeValueMap{"AdministrativeState": omciAdminState}
+	meInstance := oFsm.pOmciCC.sendSetOnuGLS(context.TODO(), ConstDefaultOmciTimeout, true,
+		requestedAttributes, oFsm.pAdaptFsm.commChan)
+	//accept also nil as (error) return value for writing to LastTx
+	//  - this avoids misinterpretation of new received OMCI messages
+	//  we might already abort the processing with nil here, but maybe some auto-recovery may be tried
+	//  - may be improved later, for now we just handle it with the Rx timeout or missing next event (stick in state)
+	oFsm.pOmciCC.pLastTxMeInstance = meInstance
+}
+
+func (oFsm *LockStateFsm) enterSettingUnisState(e *fsm.Event) {
+	logger.Infow("LockStateFSM - starting PPTP config loop", log.Fields{
+		"in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID, "LockState": oFsm.adminState})
+	go oFsm.performUniPortAdminSet()
+}
+
+func (oFsm *LockStateFsm) enterAdminDoneState(e *fsm.Event) {
+	logger.Debugw("LockStateFSM", log.Fields{"send notification to core in State": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
+	//use DeviceHandler event notification directly, no need/support to update DeviceEntryState for lock/unlock
+	oFsm.pOmciCC.pBaseDeviceHandler.DeviceProcStatusUpdate(oFsm.requestEvent)
+	//let's reset the state machine in order to release all resources now
+	pLockStateAFsm := oFsm.pAdaptFsm
+	if pLockStateAFsm != nil {
+		// obviously calling some FSM event here directly does not work - so trying to decouple it ...
+		go func(a_pAFsm *AdapterFsm) {
+			if a_pAFsm != nil && a_pAFsm.pFsm != nil {
+				a_pAFsm.pFsm.Event("reset")
+			}
+		}(pLockStateAFsm)
+	}
+}
+
+func (oFsm *LockStateFsm) enterResettingState(e *fsm.Event) {
+	logger.Debugw("LockStateFSM resetting", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
+	pLockStateAFsm := oFsm.pAdaptFsm
+	if pLockStateAFsm != nil {
+		// abort running message processing
+		fsmAbortMsg := Message{
+			Type: TestMsg,
+			Data: TestMessage{
+				TestMessageVal: AbortMessageProcessing,
+			},
+		}
+		pLockStateAFsm.commChan <- fsmAbortMsg
+
+		//try to restart the FSM to 'disabled'
+		// see DownloadedState: decouple event transfer
+		go func(a_pAFsm *AdapterFsm) {
+			if a_pAFsm != nil && a_pAFsm.pFsm != nil {
+				a_pAFsm.pFsm.Event("restart")
+			}
+		}(pLockStateAFsm)
+	}
+}
+
+func (oFsm *LockStateFsm) ProcessOmciLockMessages( /*ctx context.Context*/ ) {
+	logger.Debugw("Start LockStateFsm Msg processing", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+loop:
+	for {
+		select {
+		// case <-ctx.Done():
+		// 	logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.pAdaptFsm.deviceID})
+		// 	break loop
+		case message, ok := <-oFsm.pAdaptFsm.commChan:
+			if !ok {
+				logger.Info("LockStateFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
+				// but then we have to ensure a restart of the FSM as well - as exceptional procedure
+				oFsm.pAdaptFsm.pFsm.Event("restart")
+				break loop
+			}
+			logger.Debugw("LockStateFsm Rx Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
+
+			switch message.Type {
+			case TestMsg:
+				msg, _ := message.Data.(TestMessage)
+				if msg.TestMessageVal == AbortMessageProcessing {
+					logger.Infow("LockStateFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+					break loop
+				}
+				logger.Warnw("LockStateFsm unknown TestMessage", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "MessageVal": msg.TestMessageVal})
+			case OMCI:
+				msg, _ := message.Data.(OmciMessage)
+				oFsm.handleOmciLockStateMessage(msg)
+			default:
+				logger.Warn("LockStateFsm Rx unknown message", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
+					"message.Type": message.Type})
+			}
+		}
+	}
+	logger.Infow("End LockStateFsm Msg processing", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
+}
+
+func (oFsm *LockStateFsm) handleOmciLockStateMessage(msg OmciMessage) {
+	logger.Debugw("Rx OMCI LockStateFsm Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
+		"msgType": msg.OmciMsg.MessageType})
+
+	if msg.OmciMsg.MessageType == omci.SetResponseType {
+		msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
+		if msgLayer == nil {
+			logger.Error("LockStateFsm - Omci Msg layer could not be detected for SetResponse")
+			return
+		}
+		msgObj, msgOk := msgLayer.(*omci.SetResponse)
+		if !msgOk {
+			logger.Error("LockStateFsm - Omci Msg layer could not be assigned for SetResponse")
+			return
+		}
+		logger.Debugw("LockStateFsm SetResponse Data", log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "data-fields": msgObj})
+		if msgObj.Result != me.Success {
+			logger.Errorw("LockStateFsm - Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
+			// possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+			return
+		}
+		// compare comments above for CreateResponse (apply also here ...)
+		if msgObj.EntityClass == oFsm.pOmciCC.pLastTxMeInstance.GetClassID() &&
+			msgObj.EntityInstance == oFsm.pOmciCC.pLastTxMeInstance.GetEntityID() {
+			//store the created ME into DB //TODO??? obviously the Python code does not store the config ...
+			// if, then something like:
+			//oFsm.pOnuDB.StoreMe(msgObj)
+
+			switch oFsm.pOmciCC.pLastTxMeInstance.GetName() {
+			case "OnuG":
+				{ // let the FSM proceed ...
+					oFsm.pAdaptFsm.pFsm.Event("rx_onug_resp")
+				}
+			case "UniG", "VEIP":
+				{ // let the PPTP init proceed by stopping the wait function
+					oFsm.omciLockResponseReceived <- true
+				}
+			}
+		}
+	} else {
+		logger.Errorw("LockStateFsm - Rx OMCI unhandled MsgType", log.Fields{"omciMsgType": msg.OmciMsg.MessageType})
+		return
+	}
+}
+
+func (oFsm *LockStateFsm) performUniPortAdminSet() {
+	var omciAdminState uint8 = 1 //default locked
+	if oFsm.adminState == false {
+		omciAdminState = 0
+	}
+	//set UNI-G or VEIP AdminState
+	requestedAttributes := me.AttributeValueMap{"AdministrativeState": omciAdminState}
+
+	for uniNo, uniPort := range oFsm.pOmciCC.pBaseDeviceHandler.uniEntityMap {
+		logger.Debugw("Setting PPTP admin state", log.Fields{
+			"deviceId": oFsm.pAdaptFsm.deviceID, "for PortNo": uniNo})
+
+		var meInstance *me.ManagedEntity
+		if uniPort.portType == UniPPTP {
+			meInstance = oFsm.pOmciCC.sendSetUniGLS(context.TODO(), uniPort.entityId, ConstDefaultOmciTimeout,
+				true, requestedAttributes, oFsm.pAdaptFsm.commChan)
+			oFsm.pOmciCC.pLastTxMeInstance = meInstance
+		} else if uniPort.portType == UniVEIP {
+			meInstance = oFsm.pOmciCC.sendSetVeipLS(context.TODO(), uniPort.entityId, ConstDefaultOmciTimeout,
+				true, requestedAttributes, oFsm.pAdaptFsm.commChan)
+			oFsm.pOmciCC.pLastTxMeInstance = meInstance
+		} else {
+			logger.Warnw("Unsupported PPTP type - skip",
+				log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "Port": uniNo})
+			continue
+		}
+
+		//verify response
+		err := oFsm.WaitforOmciResponse(meInstance)
+		if err != nil {
+			logger.Errorw("PPTP Admin State set failed, aborting LockState set!",
+				log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "Port": uniNo})
+			oFsm.pAdaptFsm.pFsm.Event("reset")
+			return
+		}
+	} //for all UNI ports
+	// if Config has been done for all UNI related instances let the FSM proceed
+	// while we did not check here, if there is some port at all - !?
+	logger.Infow("PPTP config loop finished", log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID})
+	oFsm.pAdaptFsm.pFsm.Event("rx_unis_resp")
+	return
+}
+
+func (oFsm *LockStateFsm) WaitforOmciResponse(a_pMeInstance *me.ManagedEntity) error {
+	select {
+	// maybe be also some outside cancel (but no context modelled for the moment ...)
+	// case <-ctx.Done():
+	// 		logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+	case <-time.After(3 * time.Second):
+		logger.Warnw("LockStateFSM uni-set timeout", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+		return errors.New("LockStateFsm uni-set timeout")
+	case success := <-oFsm.omciLockResponseReceived:
+		if success == true {
+			logger.Debug("LockStateFSM uni-set response received")
+			return nil
+		}
+		// should not happen so far
+		logger.Warnw("LockStateFSM uni-set response error", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+		return errors.New("LockStateFsm uni-set responseError")
+	}
+}