[VOL-4385] ONU Software upgrade download start improvements

Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I53ed3406a57d5cc9064e41da57d57aaa4caedc4e
diff --git a/internal/pkg/core/openonu.go b/internal/pkg/core/openonu.go
index a7ad35c..c14655e 100755
--- a/internal/pkg/core/openonu.go
+++ b/internal/pkg/core/openonu.go
@@ -416,7 +416,7 @@
 	return nil, errors.New("invalid image definition")
 }
 
-//ActivateImageUpdate requests downloading some Onu Software image to the INU via OMCI
+//ActivateImageUpdate requests downloading some Onu Software image to the ONU via OMCI
 //  according to indications as given in request and on success activate the image on the ONU
 //The ImageDownload needs to be called `request`due to library reflection requirements
 func (oo *OpenONUAC) ActivateImageUpdate(ctx context.Context, imageInfo *ic.ImageDownloadMessage) (*voltha.ImageDownload, error) {
@@ -488,6 +488,8 @@
 		downloadedToAdapter := false
 		firstDevice := true
 		var vendorID string
+		var onuVolthaDevice *voltha.Device
+		var devErr error
 		for _, pCommonID := range (*request).DeviceId {
 			vendorIDMatch := true
 			loDeviceID := (*pCommonID).Id
@@ -497,21 +499,17 @@
 			loDeviceImageState.ImageState = &loImageState
 			loDeviceImageState.ImageState.Version = (*request).Image.Version
 
+			onuVolthaDevice = nil
 			handler := oo.getDeviceHandler(ctx, loDeviceID, false)
-			if handler == nil {
-				//cannot start ONU download for requested device
-				logger.Warnw(ctx, "no handler found for image activation", log.Fields{"device-id": loDeviceID})
-				loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_FAILED
-				loDeviceImageState.ImageState.Reason = voltha.ImageState_UNKNOWN_ERROR
-				loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
-				loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, &loDeviceImageState)
-				continue
+			if handler != nil {
+				onuVolthaDevice, devErr = handler.getDeviceFromCore(ctx, loDeviceID)
+			} else {
+				// assumption here is, that the concerned device was already created (automatic start after device creation not supported)
+				devErr = errors.New("no handler found for device-id")
 			}
-
-			onuVolthaDevice, err := handler.getDeviceFromCore(ctx, loDeviceID)
-			if err != nil || onuVolthaDevice == nil {
-				logger.Warnw(ctx, "Failed to fetch Onu device for image download",
-					log.Fields{"device-id": loDeviceID, "err": err})
+			if devErr != nil || onuVolthaDevice == nil {
+				logger.Warnw(ctx, "Failed to fetch ONU device for image download",
+					log.Fields{"device-id": loDeviceID, "err": devErr})
 				loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_FAILED
 				loDeviceImageState.ImageState.Reason = voltha.ImageState_UNKNOWN_ERROR //proto restriction, better option: 'INVALID_DEVICE'
 				loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
@@ -552,24 +550,15 @@
 				}
 				if downloadedToAdapter && vendorIDMatch {
 					// start the ONU download activity for each possible device
-					// assumption here is, that the concerned device was already created (automatic start after device creation not supported)
-					if handler := oo.getDeviceHandler(ctx, loDeviceID, false); handler != nil {
-						logger.Debugw(ctx, "image download on omci requested", log.Fields{
-							"image-id": imageIdentifier, "device-id": loDeviceID})
-						//onu upgrade handling called in background without immediate error evaluation here
-						//  as the processing can be done for multiple ONU's and an error on one ONU should not stop processing for others
-						//  state/progress/success of the request has to be verified using the Get_onu_image_status() API
-						go handler.onuSwUpgradeAfterDownload(ctx, request, oo.pFileManager, imageIdentifier)
-						loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_STARTED
-						loDeviceImageState.ImageState.Reason = voltha.ImageState_NO_ERROR
-						loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
-					} else {
-						//cannot start ONU download for requested device
-						logger.Warnw(ctx, "no handler found for image activation", log.Fields{"device-id": loDeviceID})
-						loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_FAILED
-						loDeviceImageState.ImageState.Reason = voltha.ImageState_UNKNOWN_ERROR //proto restriction, better option: 'INVALID_DEVICE'
-						loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
-					}
+					logger.Debugw(ctx, "image download on omci requested", log.Fields{
+						"image-id": imageIdentifier, "device-id": loDeviceID})
+					//onu upgrade handling called in background without immediate error evaluation here
+					//  as the processing can be done for multiple ONU's and an error on one ONU should not stop processing for others
+					//  state/progress/success of the request has to be verified using the Get_onu_image_status() API
+					go handler.onuSwUpgradeAfterDownload(ctx, request, oo.pFileManager, imageIdentifier)
+					loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_STARTED
+					loDeviceImageState.ImageState.Reason = voltha.ImageState_NO_ERROR
+					loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
 				} else {
 					loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_FAILED
 					if !downloadedToAdapter {
@@ -580,19 +569,8 @@
 					loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
 				}
 			}
-
-			// start the ONU download activity for each possible device
-			logger.Debugw(ctx, "image download on omci requested", log.Fields{
-				"image-id": imageIdentifier, "device-id": loDeviceID})
-			//onu upgrade handling called in background without immediate error evaluation here
-			//  as the processing can be done for multiple ONU's and an error on one ONU should not stop processing for others
-			//  state/progress/success of the request has to be verified using the Get_onu_image_status() API
-			go handler.onuSwUpgradeAfterDownload(ctx, request, oo.pFileManager, imageIdentifier)
-			loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_STARTED
-			loDeviceImageState.ImageState.Reason = voltha.ImageState_NO_ERROR
-			loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
 			loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, &loDeviceImageState)
-		}
+		} //for all requested devices
 		pImageResp := &loResponse
 		return pImageResp, nil
 	}
@@ -608,25 +586,23 @@
 		var vendorIDSet bool
 		firstDevice := true
 		var vendorID string
+		var onuVolthaDevice *voltha.Device
+		var devErr error
 		for _, pCommonID := range (*in).DeviceId {
 			loDeviceID := (*pCommonID).Id
 			pDeviceImageState := &voltha.DeviceImageState{DeviceId: loDeviceID}
+			vendorIDSet = false
+			onuVolthaDevice = nil
 			handler := oo.getDeviceHandler(ctx, loDeviceID, false)
-			if handler == nil {
-				//cannot get the handler
-				logger.Warnw(ctx, "no handler found for image status request ", log.Fields{"device-id": loDeviceID})
-				pDeviceImageState.DeviceId = loDeviceID
-				pDeviceImageState.ImageState.Version = (*in).Version
-				pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_FAILED
-				pDeviceImageState.ImageState.Reason = voltha.ImageState_UNKNOWN_ERROR
-				pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
-				loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, pDeviceImageState)
-				continue
+			if handler != nil {
+				onuVolthaDevice, devErr = handler.getDeviceFromCore(ctx, loDeviceID)
+			} else {
+				// assumption here is, that the concerned device was already created (automatic start after device creation not supported)
+				devErr = errors.New("no handler found for device-id")
 			}
-			onuVolthaDevice, err := handler.getDeviceFromCore(ctx, loDeviceID)
-			if err != nil || onuVolthaDevice == nil {
+			if devErr != nil || onuVolthaDevice == nil {
 				logger.Warnw(ctx, "Failed to fetch Onu device to get image status",
-					log.Fields{"device-id": loDeviceID, "err": err})
+					log.Fields{"device-id": loDeviceID, "err": devErr})
 				pImageState := &voltha.ImageState{
 					Version:       (*in).Version,
 					DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN, //no statement about last activity possible
@@ -668,7 +644,7 @@
 				}
 			}
 			loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, pDeviceImageState)
-		}
+		} //for all requested devices
 		pImageResp := &loResponse
 		return pImageResp, nil
 	}
@@ -682,56 +658,64 @@
 		imageIdentifier := (*in).Version
 		firstDevice := true
 		var vendorID string
+		var vendorIDSet bool
+		var onuVolthaDevice *voltha.Device
+		var devErr error
 		for _, pCommonID := range (*in).DeviceId {
 			loDeviceID := (*pCommonID).Id
 			pDeviceImageState := &voltha.DeviceImageState{}
 			loImageState := voltha.ImageState{}
 			pDeviceImageState.ImageState = &loImageState
-
+			vendorIDSet = false
+			onuVolthaDevice = nil
 			handler := oo.getDeviceHandler(ctx, loDeviceID, false)
-			if handler == nil {
-				//cannot start ONU download for requested device
-				logger.Warnw(ctx, "no handler found for aborting upgrade ", log.Fields{"device-id": loDeviceID})
+			if handler != nil {
+				onuVolthaDevice, devErr = handler.getDeviceFromCore(ctx, loDeviceID)
+			} else {
+				// assumption here is, that the concerned device was already created (automatic start after device creation not supported)
+				devErr = errors.New("no handler found for device-id")
+			}
+			if devErr != nil || onuVolthaDevice == nil {
+				logger.Warnw(ctx, "Failed to fetch Onu device to abort its download",
+					log.Fields{"device-id": loDeviceID, "err": devErr})
 				pDeviceImageState.DeviceId = loDeviceID
 				pDeviceImageState.ImageState.Version = (*in).Version
-				//nolint:misspell
-				pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
-				//nolint:misspell
-				pDeviceImageState.ImageState.Reason = voltha.ImageState_CANCELLED_ON_REQUEST
+				pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
+				pDeviceImageState.ImageState.Reason = voltha.ImageState_CANCELLED_ON_REQUEST //something better could be considered (MissingHandler) - proto
 				pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
-				loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, pDeviceImageState)
-				continue
-			}
-			onuVolthaDevice, err := handler.getDeviceFromCore(ctx, loDeviceID)
-			if err != nil || onuVolthaDevice == nil {
-				logger.Warnw(ctx, "Failed to fetch Onu device to abort its download",
-					log.Fields{"device-id": loDeviceID, "err": err})
-				continue //try the work with next deviceId
-			}
-
-			if firstDevice {
-				//start/verify download of the image to the adapter based on first found device only
-				//  use the OnuVendor identification from first given device
-				firstDevice = false
-				vendorID = onuVolthaDevice.VendorId
-				imageIdentifier = vendorID + imageIdentifier //head on vendor ID of the ONU
-				logger.Debugw(ctx, "abort request for file", log.Fields{"image-id": imageIdentifier})
 			} else {
-				//for all following devices verify the matching vendorID
-				if onuVolthaDevice.VendorId != vendorID {
-					logger.Warnw(ctx, "onu vendor id does not match image vendor id, device ignored",
-						log.Fields{"onu-vendor-id": onuVolthaDevice.VendorId, "image-vendor-id": vendorID})
-					continue //try the work with next deviceId
+				if firstDevice {
+					//start/verify download of the image to the adapter based on first found device only
+					//  use the OnuVendor identification from first given device
+					firstDevice = false
+					vendorID = onuVolthaDevice.VendorId
+					vendorIDSet = true
+					imageIdentifier = vendorID + imageIdentifier //head on vendor ID of the ONU
+					logger.Debugw(ctx, "abort request for file", log.Fields{"image-id": imageIdentifier})
+				} else {
+					//for all following devices verify the matching vendorID
+					if onuVolthaDevice.VendorId != vendorID {
+						logger.Warnw(ctx, "onu vendor id does not match image vendor id, device ignored",
+							log.Fields{"onu-vendor-id": onuVolthaDevice.VendorId, "image-vendor-id": vendorID})
+						pDeviceImageState.DeviceId = loDeviceID
+						pDeviceImageState.ImageState.Version = (*in).Version
+						pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
+						pDeviceImageState.ImageState.Reason = voltha.ImageState_VENDOR_DEVICE_MISMATCH
+						pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
+					} else {
+						vendorIDSet = true
+					}
+				}
+				if vendorIDSet {
+					// cancel the ONU upgrade activity for each possible device
+					logger.Debugw(ctx, "image upgrade abort requested", log.Fields{
+						"image-id": imageIdentifier, "device-id": loDeviceID})
+					//upgrade cancel is called synchronously to collect the imageResponse indications for all concerned devices
+					handler.cancelOnuSwUpgrade(ctx, imageIdentifier, (*in).Version, pDeviceImageState)
 				}
 			}
-
-			// cancel the ONU upgrade activity for each possible device
-			logger.Debugw(ctx, "image upgrade abort requested", log.Fields{
-				"image-id": imageIdentifier, "device-id": loDeviceID})
-			//upgrade cancel is called synchronously to collect the imageResponse indications for all concerned devices
-			handler.cancelOnuSwUpgrade(ctx, imageIdentifier, (*in).Version, pDeviceImageState)
 			loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, pDeviceImageState)
-		}
+		} //for all requested devices
 		if !firstDevice {
 			//if at least one valid device was found cancel also a possibly running download to adapter and remove the image
 			//  this is to be done after the upgradeOnu cancel activities in order to not subduct the file for still running processes