VOL-4277 onu-adapter should change device's operational-state to FAILED if EnableDevice fails in adapter.

Change-Id: I71e34e1f3efd322ab2e06073dab9fe60e445dbd7
diff --git a/internal/pkg/common/defines.go b/internal/pkg/common/defines.go
index 0662465..d7ca0f5 100755
--- a/internal/pkg/common/defines.go
+++ b/internal/pkg/common/defines.go
@@ -161,6 +161,8 @@
 	UniDisableStateDone
 	// UniEnableStateDone - Uni ports admin set to unlock based on device re-enable
 	UniEnableStateDone
+	// UniEnableStateFailed - Uni ports admin set to unlock failure based on device re-enable
+	UniEnableStateFailed
 	// PortLinkUp - Port link state change
 	PortLinkUp
 	// PortLinkDw - Port link state change
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 09b04ee..a6bba99 100755
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -2356,6 +2356,17 @@
 	}
 }
 
+func (dh *deviceHandler) processUniEnableStateFailedEvent(ctx context.Context, devEvent cmn.OnuDeviceEvent) {
+	logger.Debugw(ctx, "DeviceStateUpdate upon re-enable failure. ", log.Fields{
+		"OperStatus": voltha.OperStatus_FAILED, "device-id": dh.DeviceID})
+	if err := dh.updateDeviceStateInCore(ctx, &ic.DeviceStateFilter{
+		DeviceId:   dh.DeviceID,
+		OperStatus: voltha.OperStatus_FAILED,
+	}); err != nil {
+		logger.Errorw(ctx, "error-updating-device-state", log.Fields{"device-id": dh.DeviceID, "error": err})
+	}
+}
+
 func (dh *deviceHandler) processOmciAniConfigDoneEvent(ctx context.Context, devEvent cmn.OnuDeviceEvent) {
 	if devEvent == cmn.OmciAniConfigDone {
 		logger.Debugw(ctx, "OmciAniConfigDone event received", log.Fields{"device-id": dh.DeviceID})
@@ -2436,6 +2447,10 @@
 		{
 			dh.processUniEnableStateDoneEvent(ctx, devEvent)
 		}
+	case cmn.UniEnableStateFailed:
+		{
+			dh.processUniEnableStateFailedEvent(ctx, devEvent)
+		}
 	case cmn.UniDisableStateDone:
 		{
 			dh.processUniDisableStateDoneEvent(ctx, devEvent)
diff --git a/internal/pkg/uniprt/uniportadmin.go b/internal/pkg/uniprt/uniportadmin.go
index a9de1dd..60f210e 100755
--- a/internal/pkg/uniprt/uniportadmin.go
+++ b/internal/pkg/uniprt/uniportadmin.go
@@ -218,6 +218,10 @@
 	meInstance, err := oFsm.pOmciCC.SendSetOnuGLS(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.GetOmciTimeout(), true,
 		requestedAttributes, oFsm.PAdaptFsm.CommChan)
 	if err != nil {
+		//Indicate the failure in UnLock case
+		if omciAdminState == 0 {
+			oFsm.SetSuccessEvent(cmn.UniEnableStateFailed)
+		}
 		oFsm.mutexPLastTxMeInstance.Unlock()
 		logger.Errorw(ctx, "OnuGLS set failed, aborting LockStateFSM", log.Fields{"device-id": oFsm.deviceID})
 		pLockStateAFsm := oFsm.PAdaptFsm
@@ -234,6 +238,10 @@
 	//  - this avoids misinterpretation of new received OMCI messages
 	oFsm.pLastTxMeInstance = meInstance
 	if oFsm.pLastTxMeInstance == nil {
+		//Indicate the failure in UnLock case
+		if omciAdminState == 0 {
+			oFsm.SetSuccessEvent(cmn.UniEnableStateFailed)
+		}
 		oFsm.mutexPLastTxMeInstance.Unlock()
 		logger.Errorw(ctx, "could not send OMCI message from LockStateFsm", log.Fields{
 			"device-id": oFsm.deviceID})
@@ -280,6 +288,13 @@
 
 func (oFsm *LockStateFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
 	logger.Debugw(ctx, "LockStateFSM resetting", log.Fields{"device-id": oFsm.deviceID})
+	//If the fsm is reseted because of a failure during reenable, then issue the fail event.
+	if oFsm.requestEvent == cmn.UniEnableStateFailed {
+		logger.Debugw(ctx, "LockStateFSM send notification to core", log.Fields{"state": e.FSM.Current(), "device-id": oFsm.deviceID})
+		//use DeviceHandler event notification directly, no need/support to update DeviceEntryState for lock/unlock
+		oFsm.pDeviceHandler.DeviceProcStatusUpdate(ctx, oFsm.requestEvent)
+	}
+
 	pLockStateAFsm := oFsm.PAdaptFsm
 	if pLockStateAFsm != nil {
 		// abort running message processing
@@ -434,6 +449,10 @@
 					oFsm.mutexPLastTxMeInstance.Unlock()
 					logger.Errorw(ctx, "SetPptpEthUniLS set failed, aborting LockStateFsm!",
 						log.Fields{"device-id": oFsm.deviceID})
+					//Indicate the failure in UnLock case
+					if omciAdminState == 0 {
+						oFsm.SetSuccessEvent(cmn.UniEnableStateFailed)
+					}
 					_ = oFsm.PAdaptFsm.PFsm.Event(UniEvReset)
 					return
 				}
@@ -450,12 +469,17 @@
 					oFsm.mutexPLastTxMeInstance.Unlock()
 					logger.Errorw(ctx, "SetVeipLS set failed, aborting LockStateFsm!",
 						log.Fields{"device-id": oFsm.deviceID})
+					//Indicate the failure in UnLock case
+					if omciAdminState == 0 {
+						oFsm.SetSuccessEvent(cmn.UniEnableStateFailed)
+					}
 					_ = oFsm.PAdaptFsm.PFsm.Event(UniEvReset)
 					return
 				}
 				oFsm.pLastTxMeInstance = meInstance
 				oFsm.mutexPLastTxMeInstance.Unlock()
 			} else {
+				//TODO: Discuss on the uni port type POTS .
 				logger.Warnw(ctx, "Unsupported UniTP type - skip",
 					log.Fields{"device-id": oFsm.deviceID, "Port": uniNo})
 				continue
@@ -465,6 +489,10 @@
 				oFsm.mutexPLastTxMeInstance.RUnlock()
 				logger.Errorw(ctx, "could not send PortAdmin OMCI message from LockStateFsm", log.Fields{
 					"device-id": oFsm.deviceID, "Port": uniNo})
+				//Indicate the failure in UnLock case
+				if omciAdminState == 0 {
+					oFsm.SetSuccessEvent(cmn.UniEnableStateFailed)
+				}
 				//some more sophisticated approach is possible, e.g. repeating once, by now let's reset the state machine in order to release all resources now
 				_ = oFsm.PAdaptFsm.PFsm.Event(UniEvReset)
 				return
@@ -476,6 +504,10 @@
 			if err != nil {
 				logger.Errorw(ctx, "UniTP Admin State set failed, aborting LockState set!",
 					log.Fields{"device-id": oFsm.deviceID, "Port": uniNo})
+				//Indicate the failure in UnLock case
+				if omciAdminState == 0 {
+					oFsm.SetSuccessEvent(cmn.UniEnableStateFailed)
+				}
 				_ = oFsm.PAdaptFsm.PFsm.Event(UniEvReset)
 				return
 			}