VOL-5209 VOL-5210 VOL-5208, race condition and crashes during onu delete fix

Change-Id: I5a5073ce6d968c2c91178fab8b4aa614dd979868
diff --git a/VERSION b/VERSION
index 7cd5929..497a78c 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.11.4
+2.11.5
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index c14008e..33ba76e 100755
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -4737,6 +4737,7 @@
 		v.PrepareForGarbageCollection(ctx, aDeviceID)
 		delete(dh.UniVlanConfigFsmMap, k)
 	}
+	dh.pOnuIndication = nil
 	dh.pOnuOmciDevice = nil
 	dh.pOnuTP = nil
 	dh.pOnuMetricsMgr = nil
diff --git a/internal/pkg/core/openonu.go b/internal/pkg/core/openonu.go
index 6831237..365ed92 100755
--- a/internal/pkg/core/openonu.go
+++ b/internal/pkg/core/openonu.go
@@ -335,8 +335,9 @@
 		handler.mutexDeletionInProgressFlag.Unlock()
 
 		// Setting the device deletion progress flag will cause the PM FSM to cleanup for GC after FSM moves to NULL state
-		handler.pOnuMetricsMgr.SetdeviceDeletionInProgress(true)
-
+		if handler.pOnuMetricsMgr != nil {
+			handler.pOnuMetricsMgr.SetdeviceDeletionInProgress(true)
+		}
 		if err := handler.resetFsms(ctx, true); err != nil {
 			errorsList = append(errorsList, err)
 		}
@@ -952,8 +953,11 @@
 // DeleteGemPort is part of the ONU Inter-adapter service API.
 func (oo *OpenONUAC) DeleteGemPort(ctx context.Context, gPort *ia.DeleteGemPortMessage) (*empty.Empty, error) {
 	logger.Debugw(ctx, "delete-gem-port", log.Fields{"device-id": gPort.DeviceId, "uni-id": gPort.UniId})
-
 	if handler := oo.getDeviceHandler(ctx, gPort.DeviceId, false); handler != nil {
+		if handler.GetDeletionInProgress() {
+			logger.Error(ctx, "device deletion in progres", log.Fields{"device-id": gPort.DeviceId})
+			return nil, fmt.Errorf("device deletion in progress for device-id: %s", gPort.DeviceId)
+		}
 		if err := handler.handleDeleteGemPortRequest(log.WithSpanFromContext(context.Background(), ctx), gPort); err != nil {
 			return nil, err
 		}
@@ -967,8 +971,11 @@
 // DeleteTCont is part of the ONU Inter-adapter service API.
 func (oo *OpenONUAC) DeleteTCont(ctx context.Context, tConf *ia.DeleteTcontMessage) (*empty.Empty, error) {
 	logger.Debugw(ctx, "delete-tcont", log.Fields{"device-id": tConf.DeviceId, "tconf": tConf})
-
 	if handler := oo.getDeviceHandler(ctx, tConf.DeviceId, false); handler != nil {
+		if handler.GetDeletionInProgress() {
+			logger.Error(ctx, "device deletion in progres", log.Fields{"device-id": tConf.DeviceId})
+			return nil, fmt.Errorf("device deletion in progress for device-id: %s", tConf.DeviceId)
+		}
 		if err := handler.handleDeleteTcontRequest(log.WithSpanFromContext(context.Background(), ctx), tConf); err != nil {
 			return nil, err
 		}
diff --git a/internal/pkg/mib/onu_device_entry.go b/internal/pkg/mib/onu_device_entry.go
index b97a209..36b24db 100755
--- a/internal/pkg/mib/onu_device_entry.go
+++ b/internal/pkg/mib/onu_device_entry.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-//Package mib provides the utilities for managing the onu mib
+// Package mib provides the utilities for managing the onu mib
 package mib
 
 import (
@@ -220,8 +220,8 @@
 	omciRebootMessageReceivedChannel chan cmn.Message // channel needed by reboot request
 }
 
-//NewOnuDeviceEntry returns a new instance of a OnuDeviceEntry
-//mib_db (as well as not inluded alarm_db not really used in this code? VERIFY!!)
+// NewOnuDeviceEntry 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, cc *vgrpc.Client, dh cmn.IdeviceHandler,
 	openonu cmn.IopenONUAC) *OnuDeviceEntry {
 	var onuDeviceEntry OnuDeviceEntry
@@ -438,7 +438,7 @@
 	return &onuDeviceEntry
 }
 
-//Start starts (logs) the omci agent
+// Start starts (logs) the omci agent
 func (oo *OnuDeviceEntry) Start(ctx context.Context) error {
 	logger.Debugw(ctx, "OnuDeviceEntry-starting", log.Fields{"for device-id": oo.deviceID})
 	if oo.PDevOmciCC == nil {
@@ -451,7 +451,7 @@
 	return nil
 }
 
-//Stop stops/resets the omciCC
+// Stop stops/resets the omciCC
 func (oo *OnuDeviceEntry) Stop(ctx context.Context, abResetOmciCC bool) error {
 	logger.Debugw(ctx, "OnuDeviceEntry-stopping", log.Fields{"for device-id": oo.deviceID})
 	if abResetOmciCC && (oo.PDevOmciCC != nil) {
@@ -507,7 +507,7 @@
 	}
 }
 
-//Relay the InSync message via Handler to Rw core - Status update
+// Relay the InSync message via Handler to Rw core - Status update
 func (oo *OnuDeviceEntry) transferSystemEvent(ctx context.Context, devEvent cmn.OnuDeviceEvent) {
 	logger.Debugw(ctx, "relaying system-event", log.Fields{"device-id": oo.deviceID, "Event": devEvent})
 	// decouple the handler transfer from further processing here
@@ -637,23 +637,7 @@
 
 	oo.MutexPersOnuConfig.Lock()
 	defer oo.MutexPersOnuConfig.Unlock()
-	//assign values which are not already present when NewOnuDeviceEntry() is called
-	onuIndication := oo.baseDeviceHandler.GetOnuIndication()
-	oo.SOnuPersistentData.PersOnuID = onuIndication.OnuId
-	oo.SOnuPersistentData.PersIntfID = onuIndication.IntfId
-	//TODO: verify usage of these values during restart UC
-	oo.SOnuPersistentData.PersAdminState = onuIndication.AdminState
-	oo.SOnuPersistentData.PersOperState = onuIndication.OperState
 
-	logger.Debugw(ctx, "Update ONU-data in KVStore", log.Fields{"device-id": oo.deviceID, "SOnuPersistentData": oo.SOnuPersistentData})
-
-	Value, err := json.Marshal(oo.SOnuPersistentData)
-	if err != nil {
-		logger.Errorw(ctx, "unable to marshal ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
-			"device-id": oo.deviceID, "err": err})
-		oo.chOnuKvProcessingStep <- 0 //error indication
-		return
-	}
 	oo.pOpenOnuAc.RLockMutexDeviceHandlersMap()
 	if _, exist := oo.pOpenOnuAc.GetDeviceHandler(oo.deviceID); !exist {
 		logger.Debugw(ctx, "delete_device in progress - skip write request", log.Fields{"device-id": oo.deviceID})
@@ -672,6 +656,30 @@
 	oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
 	oo.baseDeviceHandler.RUnlockMutexDeletionInProgressFlag()
 
+	//assign values which are not already present when NewOnuDeviceEntry() is called
+	onuIndication := oo.baseDeviceHandler.GetOnuIndication()
+	if onuIndication != nil {
+		oo.SOnuPersistentData.PersOnuID = onuIndication.OnuId
+		oo.SOnuPersistentData.PersIntfID = onuIndication.IntfId
+		//TODO: verify usage of these values during restart UC
+		oo.SOnuPersistentData.PersAdminState = onuIndication.AdminState
+		oo.SOnuPersistentData.PersOperState = onuIndication.OperState
+	} else {
+		logger.Errorw(ctx, "onuIndication not set, unable to load ONU-data", log.Fields{"device-id": oo.deviceID})
+		oo.chOnuKvProcessingStep <- 0 //error indication
+		return
+	}
+
+	logger.Debugw(ctx, "Update ONU-data in KVStore", log.Fields{"device-id": oo.deviceID, "SOnuPersistentData": oo.SOnuPersistentData})
+
+	Value, err := json.Marshal(oo.SOnuPersistentData)
+	if err != nil {
+		logger.Errorw(ctx, "unable to marshal ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
+			"device-id": oo.deviceID, "err": err})
+		oo.chOnuKvProcessingStep <- 0 //error indication
+		return
+	}
+
 	oo.mutexOnuKVStore.Lock()
 	err = oo.onuKVStore.Put(ctx, oo.onuKVStorePath, Value)
 	oo.mutexOnuKVStore.Unlock()
@@ -1041,7 +1049,7 @@
 	oo.PDevOmciCC = nil
 }
 
-//SendOnuDeviceEvent sends an ONU DeviceEvent via eventProxy
+// SendOnuDeviceEvent sends an ONU DeviceEvent via eventProxy
 func (oo *OnuDeviceEntry) SendOnuDeviceEvent(ctx context.Context, aDeviceEventName string, aDescription string) {
 
 	oo.MutexPersOnuConfig.RLock()