VOL-812: If fiber is pulled at ONU side, ONU LOS alarm will not get clear from kafka bus.
         ONU state is changed to active. (Refer to VOL-483)
         - When pon cable pulled out from OLT end, LoS event raised for Onu's connected to it
         - When pon cable connected back to OLT, Onu LoS Clear event raised for Onu's if
           Onu Discovery is received and Onu LoS already raised
         - When pon disconnection or connection from Onu end respective Onu LoS Raise/Clear
           Event raised
         - Included Onu serial number while formating onuAlarmIndication event context

Change-Id: Ic1e965da62fb3876ea896788c87d04f376af9e53
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 0e8d460..625ab63 100644
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -90,6 +90,7 @@
 	intfID        uint32
 	proxyDeviceID string
 	uniPorts      map[uint32]struct{}
+	losRaised     bool
 }
 
 var pmNames = []string{
@@ -104,7 +105,7 @@
 }
 
 //NewOnuDevice creates a new Onu Device
-func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string) *OnuDevice {
+func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
 	var device OnuDevice
 	device.deviceID = devID
 	device.deviceType = deviceTp
@@ -113,6 +114,7 @@
 	device.intfID = intfID
 	device.proxyDeviceID = proxyDevID
 	device.uniPorts = make(map[uint32]struct{})
+	device.losRaised = losRaised
 	return &device
 }
 
@@ -769,7 +771,7 @@
 		deviceID = onuDevice.Id
 		proxyDeviceID = onuDevice.ProxyAddress.DeviceId
 		//if not exist in cache, then add to cache.
-		dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID))
+		dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
 	} else {
 		//found in cache
 		log.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
@@ -922,7 +924,31 @@
 		return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
 	}
 
+	var alarmInd oop.OnuAlarmIndication
+	raisedTs := time.Now().UnixNano()
 	if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
+
+		/* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
+		   with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
+		   OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
+		   OnuLosRaise event sent for it */
+		dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
+			if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
+				if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
+					log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
+						"previousIntfId": onuInCache.(*OnuDevice).intfID,
+						"currentIntfId":  onuDiscInd.GetIntfId()})
+					// TODO:: Should we need to ignore raising OnuLosClear event
+					// when onu connected to different PON?
+				}
+				alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
+				alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
+				alarmInd.LosStatus = statusCheckOff
+				go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
+			}
+			return true
+		})
+
 		log.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
 		return nil
 	}
@@ -989,7 +1015,7 @@
 		"intfId": onuDiscInd.GetIntfId(), "sn": sn})
 	onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
 
-	onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId)
+	onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
 	dh.onus.Store(onuKey, onuDev)
 	log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
 
@@ -1059,7 +1085,7 @@
 	if !foundInCache {
 		onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
 
-		dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
+		dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false))
 
 	}
 	if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {