VOL-3052 Onu Software upgrade extensions with http download

Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: Iebcbdc0fc01c83d8293862486acb12fd9f7f8f61
diff --git a/VERSION b/VERSION
index 3c43790..909897b 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.6
+1.2.7-dev177
diff --git a/internal/pkg/onuadaptercore/adapter_download_manager.go b/internal/pkg/onuadaptercore/adapter_download_manager.go
index 3db9cc7..a49698f 100644
--- a/internal/pkg/onuadaptercore/adapter_download_manager.go
+++ b/internal/pkg/onuadaptercore/adapter_download_manager.go
@@ -21,10 +21,12 @@
 	"bufio"
 	"context"
 	"errors"
+	"io"
+	"net/http"
+	"net/url"
 	"os"
 	"sync"
-
-	//"time"
+	"time"
 
 	"github.com/opencord/voltha-protos/v4/go/voltha"
 
@@ -97,12 +99,23 @@
 //startDownload returns true if the download of the requested image could be started
 func (dm *adapterDownloadManager) startDownload(ctx context.Context, apImageDsc *voltha.ImageDownload) error {
 	if apImageDsc.LocalDir != "" {
-		logger.Infow(ctx, "image download-to-adapter requested", log.Fields{"image-name": apImageDsc.Name})
+		logger.Infow(ctx, "image download-to-adapter requested", log.Fields{
+			"image-path": apImageDsc.LocalDir, "image-name": apImageDsc.Name})
 		newImageDscPos := len(dm.downloadImageDscSlice)
 		dm.downloadImageDscSlice = append(dm.downloadImageDscSlice, apImageDsc)
 		dm.downloadImageDscSlice[newImageDscPos].DownloadState = voltha.ImageDownload_DOWNLOAD_STARTED
-		//just some basic test file simulation
-		go dm.writeFileToLFS(ctx, apImageDsc.Name, apImageDsc.LocalDir)
+		if apImageDsc.LocalDir == "/intern" {
+			//just for initial 'internal' test verification
+			//just some basic test file simulation
+			dm.downloadImageDscSlice[newImageDscPos].LocalDir = "/tmp"
+			go dm.writeFileToLFS(ctx, "/tmp", apImageDsc.Name)
+			return nil
+		} else if apImageDsc.LocalDir == "/reboot" {
+			dm.downloadImageDscSlice[newImageDscPos].LocalDir = "/tmp"
+		}
+		//try to download from http
+		urlName := apImageDsc.Url + "/" + apImageDsc.Name
+		go dm.downloadFile(ctx, urlName, apImageDsc.LocalDir, apImageDsc.Name)
 		//return success to comfort the core processing during integration
 		return nil
 	}
@@ -112,8 +125,77 @@
 	return errors.New("could not start download: no valid local directory to write to")
 }
 
+//downloadFile downloads the specified file from the given http location
+func (dm *adapterDownloadManager) downloadFile(ctx context.Context, aURLName string, aFilePath string, aFileName string) {
+	// Get the data
+	logger.Infow(ctx, "downloading from http", log.Fields{"url": aURLName, "localPath": aFilePath})
+	// http command is already part of the aURLName argument
+	urlBase, err1 := url.Parse(aURLName)
+	if err1 != nil {
+		logger.Errorw(ctx, "could not set base url command", log.Fields{"url": aURLName, "error": err1})
+	}
+	urlParams := url.Values{}
+	urlBase.RawQuery = urlParams.Encode()
+	req, err2 := http.NewRequest("GET", urlBase.String(), nil)
+	if err2 != nil {
+		logger.Errorw(ctx, "could not generate http request", log.Fields{"url": urlBase.String(), "error": err2})
+		return
+	}
+	ctx, cancel := context.WithDeadline(ctx, time.Now().Add(10*time.Second)) //timeout to be discussed
+	defer cancel()
+	_ = req.WithContext(ctx)
+
+	resp, err3 := http.DefaultClient.Do(req)
+	if err3 != nil {
+		logger.Errorw(ctx, "could not http get from url", log.Fields{"url": urlBase.String(), "error": err3})
+		return
+	}
+	defer func() {
+		deferredErr := resp.Body.Close()
+		if deferredErr != nil {
+			logger.Errorw(ctx, "error at closing http response body", log.Fields{"url": urlBase.String(), "error": deferredErr})
+		}
+	}()
+
+	// Create the file
+	aLocalPathName := aFilePath + "/" + aFileName
+	file, err := os.Create(aLocalPathName)
+	if err != nil {
+		logger.Errorw(ctx, "could not create local file", log.Fields{"path_file": aLocalPathName, "error": err})
+		return
+	}
+	defer func() {
+		deferredErr := file.Close()
+		if deferredErr != nil {
+			logger.Errorw(ctx, "error at closing new file", log.Fields{"path_file": aLocalPathName, "error": deferredErr})
+		}
+	}()
+
+	// Write the body to file
+	_, err = io.Copy(file, resp.Body)
+	if err != nil {
+		logger.Errorw(ctx, "could not copy file content", log.Fields{"url": urlBase.String(), "file": aLocalPathName, "error": err})
+		return
+	}
+
+	fileStats, statsErr := file.Stat()
+	if err != nil {
+		logger.Errorw(ctx, "created file can't be accessed", log.Fields{"file": aLocalPathName, "stat-error": statsErr})
+	}
+	logger.Infow(ctx, "written file size is", log.Fields{"file": aLocalPathName, "length": fileStats.Size()})
+
+	for _, pDnldImgDsc := range dm.downloadImageDscSlice {
+		if (*pDnldImgDsc).Name == aFileName {
+			//image found (by name)
+			(*pDnldImgDsc).DownloadState = voltha.ImageDownload_DOWNLOAD_SUCCEEDED
+			return //can leave directly
+		}
+	}
+}
+
 //writeFileToLFS writes the downloaded file to the local file system
-func (dm *adapterDownloadManager) writeFileToLFS(ctx context.Context, aFileName string, aLocalPath string) {
+//  this is just an internal test function and can be removed if other download capabilities exist
+func (dm *adapterDownloadManager) writeFileToLFS(ctx context.Context, aLocalPath string, aFileName string) {
 	// by now just a simulation to write a file with predefined 'variable' content
 	totalFileLength := 0
 	logger.Debugw(ctx, "writing fixed size simulation file locally", log.Fields{
@@ -138,8 +220,13 @@
 		logger.Errorw(ctx, "created file can't be accessed", log.Fields{"stat-error": statsErr})
 	}
 	logger.Infow(ctx, "written file size is", log.Fields{"file": aLocalPath + "/" + aFileName, "length": fileStats.Size()})
-	//nolint:gosec,errcheck
-	file.Close()
+
+	defer func() {
+		deferredErr := file.Close()
+		if deferredErr != nil {
+			logger.Errorw(ctx, "error at closing test file", log.Fields{"file": aLocalPath + "/" + aFileName, "error": deferredErr})
+		}
+	}()
 
 	for _, pDnldImgDsc := range dm.downloadImageDscSlice {
 		if (*pDnldImgDsc).Name == aFileName {
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index b720f4f..cadd230 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -2300,8 +2300,8 @@
 			// commit is only processed in case out upgrade FSM indicates the according state (for automatic commit)
 			//  (some manual forced commit could do without)
 			if pUpgradeStatemachine.Is(upgradeStWaitForCommit) {
-				forcedTest := true //TODO!!: needed as long as BBSIM does not fully support SW upgrade simulation
-				if forcedTest || pDevEntry.IsImageToBeCommitted(ctx, dh.pOnuUpradeFsm.inactiveImageMeID) {
+				//TODO!!: needed as long as BBSIM does not fully support SW upgrade simulation (re-use SoftReboot flag for simplicity)
+				if dh.pOnuUpradeFsm.useSoftReboot || pDevEntry.IsImageToBeCommitted(ctx, dh.pOnuUpradeFsm.inactiveImageMeID) {
 					if err := pUpgradeStatemachine.Event(upgradeEvCommitSw); err != nil {
 						logger.Errorw(ctx, "OnuSwUpgradeFSM: can't call commit event", log.Fields{"err": err})
 						return
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index 1f32be0..24d6ea1 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -42,6 +42,9 @@
 	//"github.com/opencord/voltha-protos/v4/go/voltha"
 )
 
+// ### global test related tag #####
+const cbSwUpgradeRespSim = false
+
 // ### OMCI related definitions - retrieved from Python adapter code/trace ####
 
 const galEthernetEID = uint16(1)
@@ -2673,44 +2676,46 @@
 	}
 	logger.Debug(ctx, "send StartSwDlRequest done")
 
-	go func() {
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
-		time.Sleep(time.Millisecond * 50) //give some response time
-		respOmciLayer := &omci.OMCI{
-			TransactionID: tid,
-			MessageType:   omci.StartSoftwareDownloadResponseType,
-			// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-			// Length:           0x28,						// Optional, defaults to 40 octets
-		}
-		response := &omci.StartSoftwareDownloadResponse{
-			MeBasePacket: omci.MeBasePacket{
-				EntityClass:    me.SoftwareImageClassID,
-				EntityInstance: aImageMeID, //inactive image
-			},
-			Result:            0,
-			WindowSize:        aDownloadWindowSize,
-			NumberOfInstances: 0, //seems at the moment I can only generate 0 instances, using 1 here panics as MeResult can not be set below
-			//MeResults: cannot set here: downloadResults type not exported from omci-lib!
-		}
-		var respOptions gopacket.SerializeOptions
-		respOptions.FixLengths = true
-		respBuffer := gopacket.NewSerializeBuffer()
-		respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
-		if respErr != nil {
-			logger.Errorw(ctx, "Cannot serialize StartSwDlResponse", log.Fields{"Err": respErr,
-				"device-id": oo.deviceID})
-			return
-		}
-		respPacket := respBuffer.Bytes()
-		logger.Debugw(ctx, "simulate StartSwDlResponse", log.Fields{"device-id": oo.deviceID,
-			"SequNo":     strconv.FormatInt(int64(tid), 16),
-			"InstId":     strconv.FormatInt(int64(aImageMeID), 16),
-			"windowSize": aDownloadWindowSize})
-		go func(oo *omciCC) {
-			_ = oo.receiveMessage(ctx, respPacket)
-		}(oo)
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
-	}()
+	if cbSwUpgradeRespSim == true {
+		go func() {
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+			time.Sleep(time.Millisecond * 50) //give some response time
+			respOmciLayer := &omci.OMCI{
+				TransactionID: tid,
+				MessageType:   omci.StartSoftwareDownloadResponseType,
+				// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+				// Length:           0x28,						// Optional, defaults to 40 octets
+			}
+			response := &omci.StartSoftwareDownloadResponse{
+				MeBasePacket: omci.MeBasePacket{
+					EntityClass:    me.SoftwareImageClassID,
+					EntityInstance: aImageMeID, //inactive image
+				},
+				Result:            0,
+				WindowSize:        aDownloadWindowSize,
+				NumberOfInstances: 0, //seems at the moment I can only generate 0 instances, using 1 here panics as MeResult can not be set below
+				//MeResults: cannot set here: downloadResults type not exported from omci-lib!
+			}
+			var respOptions gopacket.SerializeOptions
+			respOptions.FixLengths = true
+			respBuffer := gopacket.NewSerializeBuffer()
+			respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+			if respErr != nil {
+				logger.Errorw(ctx, "Cannot serialize StartSwDlResponse", log.Fields{"Err": respErr,
+					"device-id": oo.deviceID})
+				return
+			}
+			respPacket := respBuffer.Bytes()
+			logger.Debugw(ctx, "simulate StartSwDlResponse", log.Fields{"device-id": oo.deviceID,
+				"SequNo":     strconv.FormatInt(int64(tid), 16),
+				"InstId":     strconv.FormatInt(int64(aImageMeID), 16),
+				"windowSize": aDownloadWindowSize})
+			go func(oo *omciCC) {
+				_ = oo.receiveMessage(ctx, respPacket)
+			}(oo)
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+		}()
+	}
 	return nil
 }
 
@@ -2772,50 +2777,52 @@
 	}
 	logger.Debug(ctx, "send DlSectionRequest done")
 
-	go func() {
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
-		if aAckRequest > 0 {
-			time.Sleep(time.Millisecond * 50) //give some response time
-			respOmciLayer := &omci.OMCI{
-				TransactionID: tid,
-				MessageType:   omci.DownloadSectionResponseType,
-				// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-				// Length:           0x28,						// Optional, defaults to 40 octets
+	if cbSwUpgradeRespSim == true {
+		go func() {
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+			if aAckRequest > 0 {
+				time.Sleep(time.Millisecond * 50) //give some response time
+				respOmciLayer := &omci.OMCI{
+					TransactionID: tid,
+					MessageType:   omci.DownloadSectionResponseType,
+					// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+					// Length:           0x28,						// Optional, defaults to 40 octets
+				}
+				response := &omci.DownloadSectionResponse{
+					MeBasePacket: omci.MeBasePacket{
+						EntityClass:    me.SoftwareImageClassID,
+						EntityInstance: aImageMeID, //inactive image
+					},
+					Result:        0,
+					SectionNumber: aDownloadSectionNo,
+				}
+				var respOptions gopacket.SerializeOptions
+				respOptions.FixLengths = true
+				respBuffer := gopacket.NewSerializeBuffer()
+				respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+				if respErr != nil {
+					logger.Errorw(ctx, "Cannot serialize DlSectionResponse", log.Fields{"Err": respErr,
+						"device-id": oo.deviceID})
+					return
+				}
+				respPacket := respBuffer.Bytes()
+				if aPrint {
+					logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
+						"SequNo": strconv.FormatInt(int64(tid), 16),
+						"InstId": strconv.FormatInt(int64(aImageMeID), 16),
+						"packet": hex.EncodeToString(respPacket)})
+				} else {
+					logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
+						"SequNo": strconv.FormatInt(int64(tid), 16),
+						"InstId": strconv.FormatInt(int64(aImageMeID), 16)})
+				}
+				go func(oo *omciCC) {
+					_ = oo.receiveMessage(ctx, respPacket)
+				}(oo)
 			}
-			response := &omci.DownloadSectionResponse{
-				MeBasePacket: omci.MeBasePacket{
-					EntityClass:    me.SoftwareImageClassID,
-					EntityInstance: aImageMeID, //inactive image
-				},
-				Result:        0,
-				SectionNumber: aDownloadSectionNo,
-			}
-			var respOptions gopacket.SerializeOptions
-			respOptions.FixLengths = true
-			respBuffer := gopacket.NewSerializeBuffer()
-			respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
-			if respErr != nil {
-				logger.Errorw(ctx, "Cannot serialize DlSectionResponse", log.Fields{"Err": respErr,
-					"device-id": oo.deviceID})
-				return
-			}
-			respPacket := respBuffer.Bytes()
-			if aPrint {
-				logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
-					"SequNo": strconv.FormatInt(int64(tid), 16),
-					"InstId": strconv.FormatInt(int64(aImageMeID), 16),
-					"packet": hex.EncodeToString(respPacket)})
-			} else {
-				logger.Debugw(ctx, "simulate DlSectionResponse", log.Fields{"device-id": oo.deviceID,
-					"SequNo": strconv.FormatInt(int64(tid), 16),
-					"InstId": strconv.FormatInt(int64(aImageMeID), 16)})
-			}
-			go func(oo *omciCC) {
-				_ = oo.receiveMessage(ctx, respPacket)
-			}(oo)
-		}
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
-	}()
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+		}()
+	}
 	return nil
 }
 
@@ -2865,42 +2872,44 @@
 	}
 	logger.Debug(ctx, "send EndSwDlRequest done")
 
-	go func() {
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
-		time.Sleep(time.Millisecond * 50) //give some response time
-		respOmciLayer := &omci.OMCI{
-			TransactionID: tid,
-			MessageType:   omci.EndSoftwareDownloadResponseType,
-			// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-			// Length:           0x28,						// Optional, defaults to 40 octets
-		}
-		response := &omci.EndSoftwareDownloadResponse{
-			MeBasePacket: omci.MeBasePacket{
-				EntityClass:    me.SoftwareImageClassID,
-				EntityInstance: aImageMeID, //inactive image
-			},
-			Result:            0, //simulate done, option would be busy
-			NumberOfInstances: 0, //basic ONU-G instance
-		}
-		var respOptions gopacket.SerializeOptions
-		respOptions.FixLengths = true
-		respBuffer := gopacket.NewSerializeBuffer()
-		respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
-		if respErr != nil {
-			logger.Errorw(ctx, "Cannot serialize EndSwDlResponse", log.Fields{"Err": respErr,
-				"device-id": oo.deviceID})
-			return
-		}
-		respPacket := respBuffer.Bytes()
-		logger.Debugw(ctx, "simulate EndSwDlResponse", log.Fields{"device-id": oo.deviceID,
-			"SequNo": strconv.FormatInt(int64(tid), 16),
-			"InstId": strconv.FormatInt(int64(aImageMeID), 16),
-			"result": 0})
-		go func(oo *omciCC) {
-			_ = oo.receiveMessage(ctx, respPacket)
-		}(oo)
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
-	}()
+	if cbSwUpgradeRespSim == true {
+		go func() {
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+			time.Sleep(time.Millisecond * 50) //give some response time
+			respOmciLayer := &omci.OMCI{
+				TransactionID: tid,
+				MessageType:   omci.EndSoftwareDownloadResponseType,
+				// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+				// Length:           0x28,						// Optional, defaults to 40 octets
+			}
+			response := &omci.EndSoftwareDownloadResponse{
+				MeBasePacket: omci.MeBasePacket{
+					EntityClass:    me.SoftwareImageClassID,
+					EntityInstance: aImageMeID, //inactive image
+				},
+				Result:            0, //simulate done, option would be busy
+				NumberOfInstances: 0, //basic ONU-G instance
+			}
+			var respOptions gopacket.SerializeOptions
+			respOptions.FixLengths = true
+			respBuffer := gopacket.NewSerializeBuffer()
+			respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+			if respErr != nil {
+				logger.Errorw(ctx, "Cannot serialize EndSwDlResponse", log.Fields{"Err": respErr,
+					"device-id": oo.deviceID})
+				return
+			}
+			respPacket := respBuffer.Bytes()
+			logger.Debugw(ctx, "simulate EndSwDlResponse", log.Fields{"device-id": oo.deviceID,
+				"SequNo": strconv.FormatInt(int64(tid), 16),
+				"InstId": strconv.FormatInt(int64(aImageMeID), 16),
+				"result": 0})
+			go func(oo *omciCC) {
+				_ = oo.receiveMessage(ctx, respPacket)
+			}(oo)
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+		}()
+	}
 	return nil
 }
 
@@ -2947,42 +2956,44 @@
 	}
 	logger.Debug(ctx, "send ActivateSwRequest done")
 
-	go func() {
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
-		time.Sleep(time.Millisecond * 50) //give some response time
+	if cbSwUpgradeRespSim == true {
+		go func() {
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+			time.Sleep(time.Millisecond * 50) //give some response time
 
-		respOmciLayer := &omci.OMCI{
-			TransactionID: tid,
-			MessageType:   omci.ActivateSoftwareResponseType,
-			// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-			// Length:           0x28,						// Optional, defaults to 40 octets
-		}
-		response := &omci.ActivateSoftwareResponse{
-			MeBasePacket: omci.MeBasePacket{
-				EntityClass:    me.SoftwareImageClassID,
-				EntityInstance: aImageMeID, //inactive image
-			},
-			Result: 0, //simulate done, option would be busy
-		}
-		var respOptions gopacket.SerializeOptions
-		respOptions.FixLengths = true
-		respBuffer := gopacket.NewSerializeBuffer()
-		respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
-		if respErr != nil {
-			logger.Errorw(ctx, "Cannot serialize ActivateSwResponse", log.Fields{"Err": respErr,
-				"device-id": oo.deviceID})
-			return
-		}
-		respPacket := respBuffer.Bytes()
-		logger.Debugw(ctx, "simulate ActivateSwResponse", log.Fields{"device-id": oo.deviceID,
-			"SequNo": strconv.FormatInt(int64(tid), 16),
-			"InstId": strconv.FormatInt(int64(aImageMeID), 16),
-			"result": 0})
-		go func(oo *omciCC) {
-			_ = oo.receiveMessage(ctx, respPacket)
-		}(oo)
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
-	}()
+			respOmciLayer := &omci.OMCI{
+				TransactionID: tid,
+				MessageType:   omci.ActivateSoftwareResponseType,
+				// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+				// Length:           0x28,						// Optional, defaults to 40 octets
+			}
+			response := &omci.ActivateSoftwareResponse{
+				MeBasePacket: omci.MeBasePacket{
+					EntityClass:    me.SoftwareImageClassID,
+					EntityInstance: aImageMeID, //inactive image
+				},
+				Result: 0, //simulate done, option would be busy
+			}
+			var respOptions gopacket.SerializeOptions
+			respOptions.FixLengths = true
+			respBuffer := gopacket.NewSerializeBuffer()
+			respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+			if respErr != nil {
+				logger.Errorw(ctx, "Cannot serialize ActivateSwResponse", log.Fields{"Err": respErr,
+					"device-id": oo.deviceID})
+				return
+			}
+			respPacket := respBuffer.Bytes()
+			logger.Debugw(ctx, "simulate ActivateSwResponse", log.Fields{"device-id": oo.deviceID,
+				"SequNo": strconv.FormatInt(int64(tid), 16),
+				"InstId": strconv.FormatInt(int64(aImageMeID), 16),
+				"result": 0})
+			go func(oo *omciCC) {
+				_ = oo.receiveMessage(ctx, respPacket)
+			}(oo)
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+		}()
+	}
 	return nil
 }
 
@@ -3028,41 +3039,43 @@
 	}
 	logger.Debug(ctx, "send CommitSwRequest done")
 
-	go func() {
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
-		time.Sleep(time.Millisecond * 50) //give some response time
-		respOmciLayer := &omci.OMCI{
-			TransactionID: tid,
-			MessageType:   omci.CommitSoftwareResponseType,
-			// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-			// Length:           0x28,						// Optional, defaults to 40 octets
-		}
-		response := &omci.CommitSoftwareResponse{
-			MeBasePacket: omci.MeBasePacket{
-				EntityClass:    me.SoftwareImageClassID,
-				EntityInstance: aImageMeID, //inactive image
-			},
-			//TODO: Not yet supported by omci-lib Result: 0, //simulate done
-		}
-		var respOptions gopacket.SerializeOptions
-		respOptions.FixLengths = true
-		respBuffer := gopacket.NewSerializeBuffer()
-		respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
-		if respErr != nil {
-			logger.Errorw(ctx, "Cannot serialize CommitSwResponse", log.Fields{"Err": respErr,
-				"device-id": oo.deviceID})
-			return
-		}
-		respPacket := respBuffer.Bytes()
-		logger.Debugw(ctx, "simulate CommitSwResponse", log.Fields{"device-id": oo.deviceID,
-			"SequNo": strconv.FormatInt(int64(tid), 16),
-			"InstId": strconv.FormatInt(int64(aImageMeID), 16),
-			"result": 0})
-		go func(oo *omciCC) {
-			_ = oo.receiveMessage(ctx, respPacket)
-		}(oo)
-		//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
-	}()
+	if cbSwUpgradeRespSim == true {
+		go func() {
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** start *****
+			time.Sleep(time.Millisecond * 50) //give some response time
+			respOmciLayer := &omci.OMCI{
+				TransactionID: tid,
+				MessageType:   omci.CommitSoftwareResponseType,
+				// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+				// Length:           0x28,						// Optional, defaults to 40 octets
+			}
+			response := &omci.CommitSoftwareResponse{
+				MeBasePacket: omci.MeBasePacket{
+					EntityClass:    me.SoftwareImageClassID,
+					EntityInstance: aImageMeID, //inactive image
+				},
+				//TODO: Not yet supported by omci-lib Result: 0, //simulate done
+			}
+			var respOptions gopacket.SerializeOptions
+			respOptions.FixLengths = true
+			respBuffer := gopacket.NewSerializeBuffer()
+			respErr := gopacket.SerializeLayers(respBuffer, respOptions, respOmciLayer, response)
+			if respErr != nil {
+				logger.Errorw(ctx, "Cannot serialize CommitSwResponse", log.Fields{"Err": respErr,
+					"device-id": oo.deviceID})
+				return
+			}
+			respPacket := respBuffer.Bytes()
+			logger.Debugw(ctx, "simulate CommitSwResponse", log.Fields{"device-id": oo.deviceID,
+				"SequNo": strconv.FormatInt(int64(tid), 16),
+				"InstId": strconv.FormatInt(int64(aImageMeID), 16),
+				"result": 0})
+			go func(oo *omciCC) {
+				_ = oo.receiveMessage(ctx, respPacket)
+			}(oo)
+			//**** test simulation - as long as BBSIM does not support ONU SW upgrade *** stop *****
+		}()
+	}
 	return nil
 }
 
diff --git a/internal/pkg/onuadaptercore/omci_onu_upgrade.go b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
index 4150cc5..c8c2c96 100644
--- a/internal/pkg/onuadaptercore/omci_onu_upgrade.go
+++ b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
@@ -107,6 +107,7 @@
 	omciSectionInterleaveMilliseconds time.Duration //DownloadSectionInterleave delay in milliseconds
 	delayEndSwDl                      bool          //flag to provide a delay between last section and EndSwDl
 	pLastTxMeInstance                 *me.ManagedEntity
+	useSoftReboot                     bool
 }
 
 //NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
@@ -196,6 +197,14 @@
 			"device-id": oFsm.deviceID, "image-description": apImageDsc})
 		oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
 		oFsm.pImageDsc = apImageDsc
+		//path overwrite for internal test file usage
+		oFsm.useSoftReboot = false
+		if apImageDsc.LocalDir == "/intern" {
+			oFsm.pImageDsc.LocalDir = "/tmp"
+		} else if apImageDsc.LocalDir == "/reboot" {
+			oFsm.useSoftReboot = true
+			oFsm.pImageDsc.LocalDir = "/tmp"
+		}
 		oFsm.pDownloadManager = apDownloadManager
 
 		go func(aPBaseFsm *fsm.FSM) {
@@ -621,7 +630,7 @@
 				oFsm.nextDownloadWindow++
 				if oFsm.nextDownloadWindow >= oFsm.noOfWindows {
 					if sectionNumber != oFsm.omciDownloadWindowSizeLast {
-						logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
+						logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error last window - later: repeat window once?", //TODO!!!
 							log.Fields{"device-id": oFsm.deviceID, "actual section": sectionNumber,
 								"expected section": oFsm.omciDownloadWindowSizeLast})
 						//TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
@@ -634,7 +643,8 @@
 				}
 				if sectionNumber != oFsm.omciDownloadWindowSizeLimit {
 					logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
-						log.Fields{"device-id": oFsm.deviceID, "window-section-limit": oFsm.omciDownloadWindowSizeLimit})
+						log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
+							"expected section": oFsm.omciDownloadWindowSizeLimit})
 					//TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
 					_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
 					return
@@ -720,10 +730,12 @@
 				return
 			}
 			if msgObj.EntityInstance == oFsm.inactiveImageMeID {
-				logger.Debugw(ctx, "Expected ActivateSwResponse received", log.Fields{"device-id": oFsm.deviceID})
+				logger.Infow(ctx, "Expected ActivateSwResponse received", log.Fields{"device-id": oFsm.deviceID})
 				_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
-				//TODO:  as long as BBSIM does not fully support upgrade: simulate restart by calling the BBSIM (ONU) reboot
-				go oFsm.pDeviceHandler.rebootDevice(ctx, false, oFsm.pDeviceHandler.device)
+				if oFsm.useSoftReboot {
+					//TODO:  as long as BBSIM does not fully support upgrade: simulate restart by calling the BBSIM (ONU) reboot
+					go oFsm.pDeviceHandler.rebootDevice(ctx, false, oFsm.pDeviceHandler.device)
+				}
 				return
 			}
 			logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
@@ -811,15 +823,16 @@
 			imageIsCommitted := meAttributes["IsCommitted"].(uint8)
 			imageIsActive := meAttributes["IsActive"].(uint8)
 			imageVersion := trimStringFromInterface(meAttributes["Version"])
-			logger.Infow(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
+			logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
 				log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
 					"version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
 
 			//a check on the delivered image version is not done, the ONU delivered version might be different from what might have been
 			//  indicated in the download image version string (version must be part of the image content itself)
 			//  so checking that might be quite unreliable
-			if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive &&
-				imageIsCommitted == swIsCommitted {
+			// TODO!! workaround for still not valid bbsim load indications (re-use SoftReboot flag for simplicity)
+			if oFsm.useSoftReboot || (msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive &&
+				imageIsCommitted == swIsCommitted) {
 				logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
 				//releasing the upgrade FSM
 				_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvReset)