[VOL-4239] openonu-go-adapter: wrong indication of download failure,
[VOL-4258] openonu-go-adapter: wrong indication of download from wrong url
Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I5f03085e4c7268c2370c92c081f31b9e7fb178c1
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index edb44ce..75e6213 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -46,13 +46,10 @@
"github.com/opencord/voltha-protos/v4/go/voltha"
)
-/*
-// Constants for number of retries and for timeout
+// Constants for timeouts
const (
- MaxRetry = 10
- MaxTimeOutInMs = 500
+ cTimeOutRemoveUpgrade = 1 //for usage in seconds
)
-*/
const (
// events of Device FSM
@@ -234,7 +231,8 @@
readyForOmciConfig bool
deletionInProgress bool
mutexDeletionInProgressFlag sync.RWMutex
- upgradeSuccess bool
+ pLastUpgradeImageState *voltha.ImageState
+ upgradeFsmChan chan struct{}
}
//newDeviceHandler creates a new device handler
@@ -269,6 +267,12 @@
dh.chReconcilingFlowsFinished = make(chan bool)
dh.readyForOmciConfig = false
dh.deletionInProgress = false
+ dh.pLastUpgradeImageState = &voltha.ImageState{
+ DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
+ Reason: voltha.ImageState_UNKNOWN_ERROR,
+ ImageState: voltha.ImageState_IMAGE_UNKNOWN,
+ }
+ dh.upgradeFsmChan = make(chan struct{})
if dh.device.PmConfigs != nil { // can happen after onu adapter restart
dh.pmConfigs = cloned.PmConfigs
@@ -1163,6 +1167,7 @@
}
//doOnuSwUpgrade initiates the SW download transfer to the ONU and on success activates the (inactive) image
+// used only for old - R2.7 style - upgrade API
func (dh *deviceHandler) doOnuSwUpgrade(ctx context.Context, apImageDsc *voltha.ImageDownload,
apDownloadManager *adapterDownloadManager) error {
logger.Debugw(ctx, "onuSwUpgrade requested", log.Fields{
@@ -1193,20 +1198,9 @@
}
} else { //OnuSw upgrade already running - restart (with possible abort of running)
logger.Debugw(ctx, "Onu SW upgrade already running - abort", log.Fields{"device-id": dh.deviceID})
- pUpgradeStatemachine := dh.pOnuUpradeFsm.pAdaptFsm.pFsm
- if pUpgradeStatemachine != nil {
- if err = pUpgradeStatemachine.Event(upgradeEvAbort); err != nil {
- logger.Errorw(ctx, "onu upgrade fsm could not abort a running processing", log.Fields{
- "device-id": dh.deviceID, "error": err})
- }
- err = fmt.Errorf("aborted Onu SW upgrade but not automatically started, try again, device-id: %s", dh.deviceID)
- //TODO!!!: wait for 'ready' to start and configure - see above SetDownloadParams()
- // for now a second start of download should work again
- } else { //should never occur
- logger.Errorw(ctx, "onu upgrade fsm inconsistent setup", log.Fields{
- "device-id": dh.deviceID})
- err = fmt.Errorf("onu upgrade fsm inconsistent setup, baseFsm invalid for device-id: %s", dh.deviceID)
- }
+ dh.pOnuUpradeFsm.CancelProcessing(ctx, true, voltha.ImageState_CANCELLED_ON_REQUEST) //complete abort
+ //no effort spent anymore for the old API to automatically cancel and restart the download
+ // like done for the new API
}
} else {
logger.Errorw(ctx, "start Onu SW upgrade rejected: no inactive image", log.Fields{
@@ -1235,39 +1229,46 @@
if inactiveImageID, err = pDevEntry.GetInactiveImageMeID(ctx); err == nil {
logger.Debugw(ctx, "onuSwUpgrade requested", log.Fields{
"device-id": dh.deviceID, "image-version": apImageRequest.Image.Version, "to onu-image": inactiveImageID})
- dh.lockUpgradeFsm.Lock()
- defer dh.lockUpgradeFsm.Unlock()
- if dh.pOnuUpradeFsm == nil {
- //OmciOnuSwUpgradeDone could be used to create some Kafka event with information on upgrade completion,
- // but none yet defined
- err = dh.createOnuUpgradeFsm(ctx, pDevEntry, OmciOnuSwUpgradeDone)
- if err == nil {
- if err = dh.pOnuUpradeFsm.SetDownloadParamsAfterDownload(ctx, inactiveImageID,
- apImageRequest, apDownloadManager, aImageIdentifier); err != nil {
- logger.Errorw(ctx, "onu upgrade fsm could not set parameters", log.Fields{
- "device-id": dh.deviceID, "error": err})
- return
- }
- } else {
- logger.Errorw(ctx, "onu upgrade fsm could not be created", log.Fields{
- "device-id": dh.deviceID, "error": err})
+
+ dh.lockUpgradeFsm.RLock()
+ lopOnuUpradeFsm := dh.pOnuUpradeFsm
+ //lockUpgradeFsm must be release before cancellation as this may implicitly request removeOnuUpgradeFsm()
+ dh.lockUpgradeFsm.RUnlock()
+ if lopOnuUpradeFsm != nil {
+ //OnuSw upgrade already running on this device (e.g. with activate/commit not yet set)
+ // abort the current processing, running upgrades are always aborted by newer request
+ logger.Debugw(ctx, "Onu SW upgrade already running - abort previous activity", log.Fields{"device-id": dh.deviceID})
+ //flush the remove upgradeFsmChan channel
+ select {
+ case <-dh.upgradeFsmChan:
+ logger.Debug(ctx, "flushed-upgrade-fsm-channel")
+ default:
}
- return
+ lopOnuUpradeFsm.CancelProcessing(ctx, true, voltha.ImageState_CANCELLED_ON_REQUEST) //complete abort
+ select {
+ case <-time.After(cTimeOutRemoveUpgrade * time.Second):
+ logger.Errorw(ctx, "could not remove Upgrade FSM in time, aborting", log.Fields{"device-id": dh.deviceID})
+ //should not appear, can't proceed with new upgrade, perhaps operator can retry manually later
+ return
+ case <-dh.upgradeFsmChan:
+ logger.Debugw(ctx, "recent Upgrade FSM removed, proceed with new request", log.Fields{"device-id": dh.deviceID})
+ }
}
- //OnuSw upgrade already running - restart (with possible abort of running)
- logger.Debugw(ctx, "Onu SW upgrade already running - abort", log.Fields{"device-id": dh.deviceID})
- pUpgradeStatemachine := dh.pOnuUpradeFsm.pAdaptFsm.pFsm
- if pUpgradeStatemachine != nil {
- if err = pUpgradeStatemachine.Event(upgradeEvAbort); err != nil {
- logger.Errorw(ctx, "onu upgrade fsm could not abort a running processing", log.Fields{
+
+ //here it can be assumed that no running upgrade processing exists (anymore)
+ //OmciOnuSwUpgradeDone could be used to create some Kafka event with information on upgrade completion,
+ // but none yet defined
+ err = dh.createOnuUpgradeFsm(ctx, pDevEntry, OmciOnuSwUpgradeDone)
+ if err == nil {
+ if err = dh.pOnuUpradeFsm.SetDownloadParamsAfterDownload(ctx, inactiveImageID,
+ apImageRequest, apDownloadManager, aImageIdentifier); err != nil {
+ logger.Errorw(ctx, "onu upgrade fsm could not set parameters", log.Fields{
"device-id": dh.deviceID, "error": err})
return
}
- //TODO!!!: wait for 'ready' to start and configure - see above SetDownloadParams()
- // for now a second start of download should work again - must still be initiated by user
- } else { //should never occur
- logger.Errorw(ctx, "onu upgrade fsm inconsistent setup", log.Fields{
- "device-id": dh.deviceID})
+ } else {
+ logger.Errorw(ctx, "onu upgrade fsm could not be created", log.Fields{
+ "device-id": dh.deviceID, "error": err})
}
return
}
@@ -1299,7 +1300,7 @@
}
// use the OnuVendor identification from this device for the internal unique name
imageIdentifier := onuVolthaDevice.VendorId + aVersion //head on vendor ID of the ONU
- // 1.) check a started upgrade process and rely the activation request to it
+ // 1.) check a started upgrade process and relay the activation request to it
if err = dh.pOnuUpradeFsm.SetActivationParamsRunning(ctx, imageIdentifier, aCommitRequest); err != nil {
//if some ONU upgrade is ongoing we do not accept some explicit ONU image-version related activation
logger.Errorw(ctx, "onu upgrade fsm did not accept activation while running", log.Fields{
@@ -1308,13 +1309,7 @@
}
logger.Debugw(ctx, "image activation acknowledged by onu upgrade processing", log.Fields{
"device-id": dh.deviceID, "image-id": imageIdentifier})
- var pImageStates *voltha.ImageState
- if pImageStates, err = dh.pOnuUpradeFsm.GetImageStates(ctx, "", aVersion); err != nil {
- pImageStates = &voltha.ImageState{}
- pImageStates.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
- pImageStates.Reason = voltha.ImageState_UNKNOWN_ERROR
- pImageStates.ImageState = voltha.ImageState_IMAGE_UNKNOWN
- }
+ pImageStates := dh.pOnuUpradeFsm.GetImageStates(ctx, "", aVersion)
return pImageStates, nil
} //else
dh.lockUpgradeFsm.RUnlock()
@@ -1337,13 +1332,7 @@
}
logger.Debugw(ctx, "inactive image activation acknowledged by onu upgrade", log.Fields{
"device-id": dh.deviceID, "image-version": aVersion})
- var pImageStates *voltha.ImageState
- if pImageStates, err = dh.pOnuUpradeFsm.GetImageStates(ctx, "", aVersion); err != nil {
- pImageStates := &voltha.ImageState{}
- pImageStates.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
- pImageStates.Reason = voltha.ImageState_UNKNOWN_ERROR
- pImageStates.ImageState = voltha.ImageState_IMAGE_UNKNOWN
- }
+ pImageStates := dh.pOnuUpradeFsm.GetImageStates(ctx, "", aVersion)
return pImageStates, nil
} //else
logger.Errorw(ctx, "onu upgrade fsm could not be created", log.Fields{
@@ -1375,22 +1364,18 @@
}
// use the OnuVendor identification from this device for the internal unique name
imageIdentifier := onuVolthaDevice.VendorId + aVersion //head on vendor ID of the ONU
- // 1.) check a started upgrade process and rely the commitment request to it
- if err = dh.pOnuUpradeFsm.SetCommitmentParamsRunning(ctx, imageIdentifier); err != nil {
- //if some ONU upgrade is ongoing we do not accept some explicit ONU image-version related commitment
+ // 1.) check a started upgrade process and relay the commitment request to it
+ // the running upgrade may be based either on the imageIdentifier (started from download)
+ // or on the imageVersion (started from pure activation)
+ if err = dh.pOnuUpradeFsm.SetCommitmentParamsRunning(ctx, imageIdentifier, aVersion); err != nil {
+ //if some ONU upgrade is ongoing we do not accept some explicit different ONU image-version related commitment
logger.Errorw(ctx, "onu upgrade fsm did not accept commitment while running", log.Fields{
"device-id": dh.deviceID, "error": err})
return nil, fmt.Errorf("commitment not accepted for this version for device-id: %s", dh.deviceID)
}
logger.Debugw(ctx, "image commitment acknowledged by onu upgrade processing", log.Fields{
"device-id": dh.deviceID, "image-id": imageIdentifier})
- var pImageStates *voltha.ImageState
- if pImageStates, err = dh.pOnuUpradeFsm.GetImageStates(ctx, "", aVersion); err != nil {
- pImageStates := &voltha.ImageState{}
- pImageStates.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
- pImageStates.Reason = voltha.ImageState_UNKNOWN_ERROR
- pImageStates.ImageState = voltha.ImageState_IMAGE_UNKNOWN
- }
+ pImageStates := dh.pOnuUpradeFsm.GetImageStates(ctx, "", aVersion)
return pImageStates, nil
} //else
dh.lockUpgradeFsm.RUnlock()
@@ -1411,13 +1396,7 @@
}
logger.Debugw(ctx, "active image commitment acknowledged by onu upgrade", log.Fields{
"device-id": dh.deviceID, "image-version": aVersion})
- var pImageStates *voltha.ImageState
- if pImageStates, err = dh.pOnuUpradeFsm.GetImageStates(ctx, "", aVersion); err != nil {
- pImageStates := &voltha.ImageState{}
- pImageStates.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
- pImageStates.Reason = voltha.ImageState_UNKNOWN_ERROR
- pImageStates.ImageState = voltha.ImageState_IMAGE_UNKNOWN
- }
+ pImageStates := dh.pOnuUpradeFsm.GetImageStates(ctx, "", aVersion)
return pImageStates, nil
} //else
logger.Errorw(ctx, "onu upgrade fsm could not be created", log.Fields{
@@ -1426,53 +1405,60 @@
}
func (dh *deviceHandler) requestOnuSwUpgradeState(ctx context.Context, aImageIdentifier string,
- aVersion string, pDeviceImageState *voltha.DeviceImageState) {
- pDeviceImageState.DeviceId = dh.deviceID
- pDeviceImageState.ImageState.Version = aVersion
+ aVersion string) *voltha.ImageState {
+ var pImageState *voltha.ImageState
dh.lockUpgradeFsm.RLock()
+ defer dh.lockUpgradeFsm.RUnlock()
if dh.pOnuUpradeFsm != nil {
- dh.lockUpgradeFsm.RUnlock()
- if pImageStates, err := dh.pOnuUpradeFsm.GetImageStates(ctx, aImageIdentifier, aVersion); err == nil {
- pDeviceImageState.ImageState.DownloadState = pImageStates.DownloadState
- pDeviceImageState.ImageState.Reason = pImageStates.Reason
- pDeviceImageState.ImageState.ImageState = pImageStates.ImageState
- } else {
- pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
- pDeviceImageState.ImageState.Reason = voltha.ImageState_NO_ERROR
- pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
- }
- } else {
- dh.lockUpgradeFsm.RUnlock()
- pDeviceImageState.ImageState.Reason = voltha.ImageState_NO_ERROR
- if dh.upgradeSuccess {
- pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
- pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_COMMITTED
- } else {
- pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
- pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
+ pImageState = dh.pOnuUpradeFsm.GetImageStates(ctx, aImageIdentifier, aVersion)
+ } else { //use the last stored ImageState (if the requested Imageversion coincides)
+ if aVersion == dh.pLastUpgradeImageState.Version {
+ pImageState = dh.pLastUpgradeImageState
+ } else { //state request for an image version different from last processed image version
+ pImageState = &voltha.ImageState{
+ Version: aVersion,
+ //we cannot state something concerning this version
+ DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN,
+ Reason: voltha.ImageState_NO_ERROR,
+ ImageState: voltha.ImageState_IMAGE_UNKNOWN,
+ }
}
}
+ return pImageState
}
func (dh *deviceHandler) cancelOnuSwUpgrade(ctx context.Context, aImageIdentifier string,
aVersion string, pDeviceImageState *voltha.DeviceImageState) {
pDeviceImageState.DeviceId = dh.deviceID
pDeviceImageState.ImageState.Version = aVersion
- pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
dh.lockUpgradeFsm.RLock()
if dh.pOnuUpradeFsm != nil {
- dh.lockUpgradeFsm.RUnlock()
- //option: it could be also checked if the upgrade FSM is running on the given imageIdentifier or version
- // by now just straightforward assume this to be true
- dh.pOnuUpradeFsm.CancelProcessing(ctx)
- //nolint:misspell
- pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
- //nolint:misspell
- pDeviceImageState.ImageState.Reason = voltha.ImageState_CANCELLED_ON_REQUEST
+ if aVersion == dh.pOnuUpradeFsm.GetImageVersion(ctx) {
+ // so then we cancel the upgrade operation
+ // but before we still request the actual ImageState (which should not change with the cancellation)
+ pDeviceImageState.ImageState.ImageState = dh.pOnuUpradeFsm.GetSpecificImageState(ctx)
+ dh.lockUpgradeFsm.RUnlock()
+ pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
+ pDeviceImageState.ImageState.Reason = voltha.ImageState_CANCELLED_ON_REQUEST
+ dh.pOnuUpradeFsm.CancelProcessing(ctx, true, voltha.ImageState_CANCELLED_ON_REQUEST) //complete abort
+ } else { //nothing to cancel, states unknown
+ dh.lockUpgradeFsm.RUnlock()
+ pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
+ pDeviceImageState.ImageState.Reason = voltha.ImageState_NO_ERROR
+ pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
+ }
} else {
+ // if no upgrade is ongoing, nothing is canceled and accordingly the states of the requested image are unknown
+ // reset also the dh handler LastUpgradeImageState (not relevant anymore/cleared)
+ (*dh.pLastUpgradeImageState).DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
+ (*dh.pLastUpgradeImageState).Reason = voltha.ImageState_NO_ERROR
+ (*dh.pLastUpgradeImageState).ImageState = voltha.ImageState_IMAGE_UNKNOWN
+ (*dh.pLastUpgradeImageState).Version = "" //reset to 'no (relevant) upgrade done' (like initial state)
dh.lockUpgradeFsm.RUnlock()
pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
pDeviceImageState.ImageState.Reason = voltha.ImageState_NO_ERROR
+ pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
+ //an abort request to a not active upgrade processing can be used to reset the device upgrade states completely
}
}
@@ -2128,10 +2114,12 @@
//reset a possibly running upgrade FSM
// (note the Upgrade FSM may stay alive e.g. in state upgradeStWaitForCommit to endure the ONU reboot)
dh.lockUpgradeFsm.RLock()
- if dh.pOnuUpradeFsm != nil {
- dh.pOnuUpradeFsm.CancelProcessing(ctx)
- }
+ lopOnuUpradeFsm := dh.pOnuUpradeFsm
+ //lockUpgradeFsm must be release before cancellation as this may implicitly request removeOnuUpgradeFsm()
dh.lockUpgradeFsm.RUnlock()
+ if lopOnuUpradeFsm != nil {
+ lopOnuUpradeFsm.CancelProcessing(ctx, false, voltha.ImageState_CANCELLED_ON_ONU_STATE) //conditional cancel
+ }
logger.Infow(ctx, "resetFsms done", log.Fields{"device-id": dh.deviceID})
return nil
@@ -2449,10 +2437,6 @@
{
dh.processOmciVlanFilterDoneEvent(ctx, devEvent)
}
- case OmciOnuSwUpgradeDone:
- {
- dh.upgradeSuccess = true
- }
default:
{
logger.Debugw(ctx, "unhandled-device-event", log.Fields{"device-id": dh.deviceID, "event": devEvent})
@@ -2715,13 +2699,16 @@
pUpgradeStatemachine := dh.pOnuUpradeFsm.pAdaptFsm.pFsm
if pUpgradeStatemachine != nil {
if pUpgradeStatemachine.Is(upgradeStDisabled) {
- dh.upgradeSuccess = false //for start of upgrade processing reset the last indication
if err := pUpgradeStatemachine.Event(upgradeEvStart); err != nil {
logger.Errorw(ctx, "OnuSwUpgradeFSM: can't start", log.Fields{"err": err})
// maybe try a FSM reset and then again ... - TODO!!!
return fmt.Errorf(fmt.Sprintf("OnuSwUpgradeFSM could not be started for device-id: %s", dh.device.Id))
}
/***** LockStateFSM started */
+ //reset the last stored upgrade states
+ (*dh.pLastUpgradeImageState).DownloadState = voltha.ImageState_DOWNLOAD_STARTED //already with updated state
+ (*dh.pLastUpgradeImageState).Reason = voltha.ImageState_NO_ERROR
+ (*dh.pLastUpgradeImageState).ImageState = voltha.ImageState_IMAGE_UNKNOWN
logger.Debugw(ctx, "OnuSwUpgradeFSM started", log.Fields{
"state": pUpgradeStatemachine.Current(), "device-id": dh.deviceID})
} else {
@@ -2743,12 +2730,20 @@
}
// removeOnuUpgradeFsm clears the Onu Software upgrade FSM
-func (dh *deviceHandler) removeOnuUpgradeFsm(ctx context.Context) {
+func (dh *deviceHandler) removeOnuUpgradeFsm(ctx context.Context, apImageState *voltha.ImageState) {
logger.Debugw(ctx, "remove OnuSwUpgradeFSM StateMachine", log.Fields{
"device-id": dh.deviceID})
dh.lockUpgradeFsm.Lock()
- defer dh.lockUpgradeFsm.Unlock()
dh.pOnuUpradeFsm = nil //resource clearing is left to garbage collector
+ dh.pLastUpgradeImageState = apImageState
+ dh.lockUpgradeFsm.Unlock()
+ //signal upgradeFsm removed using non-blocking channel send
+ select {
+ case dh.upgradeFsmChan <- struct{}{}:
+ default:
+ logger.Debugw(ctx, "removed-UpgradeFsm signal not send on upgradeFsmChan (no receiver)", log.Fields{
+ "device-id": dh.deviceID})
+ }
}
// checkOnOnuImageCommit verifies if the ONU is in some upgrade state that allows for image commit and if tries to commit
@@ -2776,7 +2771,7 @@
if errImg != nil {
logger.Errorw(ctx, "OnuSwUpgradeFSM abort - could not get active image after reboot",
log.Fields{"device-id": dh.deviceID})
- _ = pUpgradeStatemachine.Event(upgradeEvAbort)
+ dh.pOnuUpradeFsm.CancelProcessing(ctx, true, voltha.ImageState_CANCELLED_ON_ONU_STATE) //complete abort
return
}
if activeImageID == dh.pOnuUpradeFsm.inactiveImageMeID {
@@ -2800,13 +2795,13 @@
} else {
logger.Errorw(ctx, "OnuSwUpgradeFSM waiting to commit/on ActivateResponse, but load did not start with expected image Id",
log.Fields{"device-id": dh.deviceID})
- _ = pUpgradeStatemachine.Event(upgradeEvAbort)
+ dh.pOnuUpradeFsm.CancelProcessing(ctx, true, voltha.ImageState_CANCELLED_ON_ONU_STATE) //complete abort
return
}
} else {
logger.Errorw(ctx, "OnuSwUpgradeFSM waiting to commit, but nothing to commit on ONU - abort upgrade",
log.Fields{"device-id": dh.deviceID})
- _ = pUpgradeStatemachine.Event(upgradeEvAbort)
+ dh.pOnuUpradeFsm.CancelProcessing(ctx, true, voltha.ImageState_CANCELLED_ON_ONU_STATE) //complete abort
return
}
} else {
@@ -2816,7 +2811,7 @@
if dh.pOnuUpradeFsm.inactiveImageMeID == activeImageID {
logger.Debugw(ctx, "OnuSwUpgradeFSM image state set to activated", log.Fields{
"state": pUpgradeStatemachine.Current(), "device-id": dh.deviceID})
- dh.pOnuUpradeFsm.SetImageState(ctx, voltha.ImageState_IMAGE_ACTIVE)
+ dh.pOnuUpradeFsm.SetImageStateActive(ctx)
}
}
}
diff --git a/internal/pkg/onuadaptercore/file_download_manager.go b/internal/pkg/onuadaptercore/file_download_manager.go
index d283606..3767df2 100644
--- a/internal/pkg/onuadaptercore/file_download_manager.go
+++ b/internal/pkg/onuadaptercore/file_download_manager.go
@@ -30,7 +30,6 @@
"time"
"github.com/opencord/voltha-lib-go/v5/pkg/log"
- "github.com/opencord/voltha-protos/v4/go/voltha"
)
const cDefaultLocalDir = "/tmp" //this is the default local dir to download to
@@ -113,11 +112,13 @@
loDownloadImageParams := downloadImageParams{
downloadImageName: aImageName, downloadImageState: cFileStateDlStarted,
downloadImageLen: 0, downloadImageCrc: 0}
- dm.mutexDownloadImageDsc.Lock()
- dm.downloadImageDscSlice = append(dm.downloadImageDscSlice, loDownloadImageParams)
- dm.mutexDownloadImageDsc.Unlock()
//try to download from http
- err := dm.downloadFile(ctx, aURLCommand, cDefaultLocalDir, aImageName)
+ var err error
+ if err = dm.downloadFile(ctx, aURLCommand, cDefaultLocalDir, aImageName); err == nil {
+ dm.mutexDownloadImageDsc.Lock()
+ dm.downloadImageDscSlice = append(dm.downloadImageDscSlice, loDownloadImageParams)
+ dm.mutexDownloadImageDsc.Unlock()
+ }
//return the result of the start-request to comfort the core processing even though the complete download may go on in background
return err
}
@@ -282,6 +283,7 @@
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})
+ dm.removeImage(ctx, aFileName, false) //wo FileSystem access
return
}
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(dm.dlToAdapterTimeout)) //timeout as given from SetDownloadTimeout()
@@ -291,6 +293,7 @@
if err3 != nil || respExist.StatusCode != http.StatusOK {
logger.Errorw(ctx, "could not http get from url", log.Fields{"url": urlBase.String(),
"error": err3, "status": respExist.StatusCode})
+ dm.removeImage(ctx, aFileName, false) //wo FileSystem access
return
}
defer func() {
@@ -305,6 +308,7 @@
file, err := os.Create(aLocalPathName)
if err != nil {
logger.Errorw(ctx, "could not create local file", log.Fields{"path_file": aLocalPathName, "error": err})
+ dm.removeImage(ctx, aFileName, false) //wo FileSystem access
return
}
defer func() {
@@ -318,6 +322,7 @@
_, 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})
+ dm.removeImage(ctx, aFileName, true)
return
}
@@ -354,43 +359,27 @@
return nil
}
-func (dm *fileDownloadManager) RequestDownloadState(ctx context.Context, aImageName string,
- apDlToAdapterImageState *voltha.ImageState) {
- logger.Debugw(ctx, "request download state for image to Adapter", log.Fields{"image-name": aImageName})
- dm.mutexDownloadImageDsc.RLock()
- defer dm.mutexDownloadImageDsc.RUnlock()
-
- for _, dnldImgDsc := range dm.downloadImageDscSlice {
- if dnldImgDsc.downloadImageName == aImageName {
- //image found (by name)
- apDlToAdapterImageState.DownloadState = voltha.ImageState_DOWNLOAD_REQUESTED
- apDlToAdapterImageState.Reason = voltha.ImageState_NO_ERROR
- return
- }
- }
- //image not found (by name)
- apDlToAdapterImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
- apDlToAdapterImageState.Reason = voltha.ImageState_NO_ERROR
-}
-
-func (dm *fileDownloadManager) CancelDownload(ctx context.Context, aImageName string) {
- logger.Debugw(ctx, "Cancel the download to Adapter", log.Fields{"image-name": aImageName})
- // for the moment that would only support to wait for the download end and remove the image then
- // further reactions while still downloading can be considered with some effort, but does it make sense (synchronous load here!)
+//removeImage deletes the given image according to the Image name from filesystem and downloadImageDscSlice
+func (dm *fileDownloadManager) removeImage(ctx context.Context, aImageName string, aDelFs bool) {
+ logger.Debugw(ctx, "remove the image from Adapter", log.Fields{"image-name": aImageName})
dm.mutexDownloadImageDsc.RLock()
defer dm.mutexDownloadImageDsc.RUnlock()
tmpSlice := dm.downloadImageDscSlice[:0]
for _, dnldImgDsc := range dm.downloadImageDscSlice {
if dnldImgDsc.downloadImageName == aImageName {
- //image found (by name) - remove the image from filesystem
+ //image found (by name)
logger.Debugw(ctx, "removing image", log.Fields{"image-name": aImageName})
- aLocalPathName := cDefaultLocalDir + "/" + aImageName
- if err := os.Remove(aLocalPathName); err != nil {
- logger.Debugw(ctx, "image not removed from filesystem", log.Fields{
- "image-name": aImageName, "error": err})
+ if aDelFs {
+ //remove the image from filesystem
+ aLocalPathName := cDefaultLocalDir + "/" + aImageName
+ if err := os.Remove(aLocalPathName); err != nil {
+ // might be a temporary situation, when the file was not yet (completely) written
+ logger.Debugw(ctx, "image not removed from filesystem", log.Fields{
+ "image-name": aImageName, "error": err})
+ }
}
- // and in the imageDsc slice by just not appending
+ // and remove from the imageDsc slice by just not appending
} else {
tmpSlice = append(tmpSlice, dnldImgDsc)
}
@@ -398,3 +387,10 @@
dm.downloadImageDscSlice = tmpSlice
//image not found (by name)
}
+
+//CancelDownload just wraps removeImage (for possible extensions to e.g. really stop a ongoing download)
+func (dm *fileDownloadManager) CancelDownload(ctx context.Context, aImageName string) {
+ // for the moment that would only support to wait for the download end and remove the image then
+ // further reactions while still downloading can be considered with some effort, but does it make sense (synchronous load here!)
+ dm.removeImage(ctx, aImageName, true)
+}
diff --git a/internal/pkg/onuadaptercore/omci_onu_upgrade.go b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
index 88101b3..b4c4d35 100644
--- a/internal/pkg/onuadaptercore/omci_onu_upgrade.go
+++ b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
@@ -58,6 +58,7 @@
upgradeEvEndSwDownload = "upgradeEvEndSwDownload"
upgradeEvWaitEndDownload = "upgradeEvWaitEndDownload"
upgradeEvContinueFinalize = "upgradeEvContinueFinalize"
+ upgradeEvCheckImageName = "upgradeEvCheckImageName"
upgradeEvWaitForActivate = "upgradeEvWaitForActivate"
upgradeEvRequestActivate = "upgradeEvRequestActivate"
upgradeEvActivationDone = "upgradeEvActivationDone"
@@ -82,6 +83,7 @@
upgradeStVerifyWindow = "upgradeStVerifyWindow"
upgradeStFinalizeDL = "upgradeStFinalizeDL"
upgradeStWaitEndDL = "upgradeStWaitEndDL"
+ upgradeStCheckImageName = "upgradeStCheckImageName"
upgradeStWaitForActivate = "upgradeStWaitForActivate"
upgradeStRequestingActivate = "upgradeStRequestingActivate"
upgradeStActivated = "upgradeStActivated"
@@ -100,7 +102,7 @@
pDownloadManager *adapterDownloadManager
pFileManager *fileDownloadManager //used from R2.8 with new API version
deviceID string
- pOnuOmciDevice *OnuDeviceEntry
+ pDevEntry *OnuDeviceEntry
pOmciCC *omciCC
pOnuDB *onuDeviceDB
requestEvent OnuDeviceEvent
@@ -138,6 +140,9 @@
isWaitingForOnuDlResponse bool
activateImage bool
commitImage bool
+ mutexAbortRequest sync.RWMutex
+ abortRequested voltha.ImageState_ImageFailureReason
+ conditionalCancelRequested bool
volthaDownloadState voltha.ImageState_ImageDownloadState
volthaDownloadReason voltha.ImageState_ImageFailureReason
volthaImageState voltha.ImageState_ImageActivationState
@@ -151,7 +156,7 @@
instFsm := &OnuUpgradeFsm{
pDeviceHandler: apDeviceHandler,
deviceID: apDeviceHandler.deviceID,
- pOnuOmciDevice: apDevEntry,
+ pDevEntry: apDevEntry,
pOmciCC: apDevEntry.PDevOmciCC,
pOnuDB: apOnuDB,
requestEvent: aRequestEvent,
@@ -163,6 +168,7 @@
volthaDownloadState: voltha.ImageState_DOWNLOAD_STARTED, //if FSM created we can assume that the download (to adapter) really started
volthaDownloadReason: voltha.ImageState_NO_ERROR,
volthaImageState: voltha.ImageState_IMAGE_UNKNOWN,
+ abortRequested: voltha.ImageState_NO_ERROR,
}
instFsm.chReceiveExpectedResponse = make(chan bool)
instFsm.chAdapterDlReady = make(chan bool)
@@ -186,9 +192,13 @@
{Name: upgradeEvEndSwDownload, Src: []string{upgradeStVerifyWindow}, Dst: upgradeStFinalizeDL},
{Name: upgradeEvWaitEndDownload, Src: []string{upgradeStFinalizeDL}, Dst: upgradeStWaitEndDL},
{Name: upgradeEvContinueFinalize, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStFinalizeDL},
- {Name: upgradeEvWaitForActivate, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStWaitForActivate},
- {Name: upgradeEvRequestActivate, Src: []string{upgradeStStarting, upgradeStWaitEndDL, upgradeStWaitForActivate},
- Dst: upgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
+ //upgradeStCheckImageName only used with useAPIVersion43
+ {Name: upgradeEvCheckImageName, Src: []string{upgradeStWaitEndDL}, Dst: upgradeStCheckImageName},
+ //upgradeEvWaitForActivate state transitions depend on useAPIVersion43
+ {Name: upgradeEvWaitForActivate, Src: []string{upgradeStWaitEndDL, upgradeStCheckImageName}, Dst: upgradeStWaitForActivate},
+ //upgradeEvRequestActivate state transitions depend on useAPIVersion43
+ {Name: upgradeEvRequestActivate, Src: []string{upgradeStStarting, upgradeStWaitEndDL, upgradeStCheckImageName,
+ upgradeStWaitForActivate}, Dst: upgradeStRequestingActivate}, //allows also for direct activation (without download) [TODO!!!]
{Name: upgradeEvActivationDone, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStActivated},
{Name: upgradeEvWaitForCommit, Src: []string{upgradeStRequestingActivate}, Dst: upgradeStWaitForCommit},
{Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStRequestingActivate, upgradeStWaitForCommit,
@@ -205,12 +215,15 @@
//on upgradeEvReset: upgradeStRequestingActivate, upgradeStWaitForCommit and upgradeStActivated are not reset
// (to let the FSM survive the expected OnuDown indication)
{Name: upgradeEvReset, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
- upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStWaitForActivate,
+ upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
+ upgradeStWaitForActivate,
upgradeStCommitSw, upgradeStCheckCommitted},
Dst: upgradeStResetting},
{Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
- upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStWaitForActivate,
- upgradeStRequestingActivate, upgradeStActivated, upgradeStWaitForCommit, upgradeStCommitSw, upgradeStCheckCommitted},
+ upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStCheckImageName,
+ upgradeStWaitForActivate,
+ upgradeStRequestingActivate, upgradeStActivated, upgradeStWaitForCommit,
+ upgradeStCommitSw, upgradeStCheckCommitted},
Dst: upgradeStResetting},
{Name: upgradeEvRestart, Src: []string{upgradeStResetting}, Dst: upgradeStDisabled},
},
@@ -223,6 +236,7 @@
"enter_" + upgradeStVerifyWindow: func(e *fsm.Event) { instFsm.enterVerifyWindow(ctx, e) },
"enter_" + upgradeStFinalizeDL: func(e *fsm.Event) { instFsm.enterFinalizeDL(ctx, e) },
"enter_" + upgradeStWaitEndDL: func(e *fsm.Event) { instFsm.enterWaitEndDL(ctx, e) },
+ "enter_" + upgradeStCheckImageName: func(e *fsm.Event) { instFsm.enterCheckImageName(ctx, e) },
"enter_" + upgradeStRequestingActivate: func(e *fsm.Event) { instFsm.enterActivateSw(ctx, e) },
"enter_" + upgradeStCommitSw: func(e *fsm.Event) { instFsm.enterCommitSw(ctx, e) },
"enter_" + upgradeStCheckCommitted: func(e *fsm.Event) { instFsm.enterCheckCommitted(ctx, e) },
@@ -318,15 +332,20 @@
}
oFsm.activateImage = true
oFsm.commitImage = aCommit
- oFsm.mutexUpgradeParams.Unlock()
var pBaseFsm *fsm.FSM = nil
if oFsm.pAdaptFsm != nil {
pBaseFsm = oFsm.pAdaptFsm.pFsm
}
if pBaseFsm != nil {
if pBaseFsm.Is(upgradeStWaitForActivate) {
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
+ oFsm.mutexUpgradeParams.Unlock()
logger.Debugw(ctx, "OnuUpgradeFsm finish waiting for activate", log.Fields{"device-id": oFsm.deviceID})
_ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
+ } else {
+ oFsm.mutexUpgradeParams.Unlock()
+ logger.Debugw(ctx, "OnuUpgradeFsm not (yet?) waiting for activate", log.Fields{
+ "device-id": oFsm.deviceID, "current FsmState": pBaseFsm.Current()})
}
return nil
}
@@ -351,7 +370,9 @@
oFsm.imageVersion = aImageVersion
oFsm.activateImage = true
oFsm.commitImage = aCommit
- oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN // this is just an activate request without prior download
+ // indicate start of the upgrade activity
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE //as simply applied for inactive image
oFsm.mutexUpgradeParams.Unlock()
//directly request the FSM to activate the image
_ = pBaseFsm.Event(upgradeEvRequestActivate) //no need to call the FSM event in background here
@@ -365,20 +386,23 @@
//SetCommitmentParamsRunning sets the commit flag for a running download to the ONU according to adapters rpc call
// called from 'new' API Commit_onu_image
-func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context, aImageIdentifier string) error {
+func (oFsm *OnuUpgradeFsm) SetCommitmentParamsRunning(ctx context.Context,
+ aImageIdentifier string, aImageVersion string) error {
oFsm.mutexUpgradeParams.Lock()
//set commit independent from state, if FSM is already beyond commit state (just ready), then it does not matter anyway
// (as long as the Imageidentifier is correct)
logger.Debugw(ctx, "OnuUpgradeFsm commit parameter setting", log.Fields{
"device-id": oFsm.deviceID, "image-id": aImageIdentifier})
- if aImageIdentifier != oFsm.imageIdentifier {
+ if (aImageIdentifier != oFsm.imageIdentifier) && (aImageVersion != oFsm.imageVersion) {
logger.Errorw(ctx, "OnuUpgradeFsm abort: mismatching upgrade image", log.Fields{
- "device-id": oFsm.deviceID, "request-image": aImageIdentifier, "fsm-image": oFsm.imageIdentifier})
+ "device-id": oFsm.deviceID, "request-identifier": aImageIdentifier, "fsm-identifier": oFsm.imageIdentifier,
+ "request-version": aImageVersion, "fsm-version": oFsm.imageVersion})
oFsm.mutexUpgradeParams.Unlock()
return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm params ignored: requested image-name not used in current upgrade for device-id: %s",
oFsm.deviceID))
}
oFsm.commitImage = true
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
oFsm.mutexUpgradeParams.Unlock()
var pBaseFsm *fsm.FSM = nil
if oFsm.pAdaptFsm != nil {
@@ -391,6 +415,7 @@
_ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
return nil
}
+ //should never occur
logger.Errorw(ctx, "OnuUpgradeFsm abort: invalid FSM base pointer", log.Fields{
"device-id": oFsm.deviceID})
return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer for device-id: %s", oFsm.deviceID))
@@ -411,9 +436,10 @@
oFsm.inactiveImageMeID = aActiveImageID //upgrade state machines inactive ImageId is the new active ImageId
oFsm.imageVersion = aImageVersion
oFsm.commitImage = true
- oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN // this is just a commit request without prior download
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_STARTED //better choice would be 'UpgradeState=Started'
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE //as simply applied for active image
oFsm.mutexUpgradeParams.Unlock()
- //directly request the FSM to activate the image
+ //directly request the FSM to commit the image
_ = pBaseFsm.Event(upgradeEvCommitSw) //no need to call the FSM event in background here
return nil
}
@@ -430,10 +456,11 @@
return oFsm.commitImage
}
-//GetImageStates delivers the download states as per device proto buf or error indication
+//GetImageStates delivers the download/image states as per device proto buf definition
func (oFsm *OnuUpgradeFsm) GetImageStates(ctx context.Context,
- aImageIdentifier string, aVersion string) (*voltha.ImageState, error) {
+ aImageIdentifier string, aVersion string) *voltha.ImageState {
pImageState := &voltha.ImageState{}
+ pImageState.Version = aVersion //version as requested
// check if the request refers to some active image/version of the processing
oFsm.mutexUpgradeParams.RLock()
if (aImageIdentifier == oFsm.imageIdentifier) || (aVersion == oFsm.imageVersion) {
@@ -446,18 +473,42 @@
pImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
}
oFsm.mutexUpgradeParams.RUnlock()
- return pImageState, nil
+ return pImageState
}
-//SetImageState sets the FSM internal volthaImageState
-func (oFsm *OnuUpgradeFsm) SetImageState(ctx context.Context, aImageState voltha.ImageState_ImageActivationState) {
+//GetSpecificImageState delivers ImageState of the download/image states as per device proto buf definition
+func (oFsm *OnuUpgradeFsm) GetSpecificImageState(ctx context.Context) voltha.ImageState_ImageActivationState {
+ oFsm.mutexUpgradeParams.RLock()
+ imageState := oFsm.volthaImageState
+ oFsm.mutexUpgradeParams.RUnlock()
+ return imageState
+}
+
+//SetImageStateActive sets the FSM internal volthaImageState to ImageState_IMAGE_ACTIVE
+func (oFsm *OnuUpgradeFsm) SetImageStateActive(ctx context.Context) {
oFsm.mutexUpgradeParams.Lock()
defer oFsm.mutexUpgradeParams.Unlock()
- oFsm.volthaImageState = aImageState
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE
+ if !oFsm.commitImage {
+ //if commit is not additionally set, regard the upgrade activity as successful
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED //better choice would be 'UpgradeState=Succeeded'
+ }
+}
+
+//GetImageVersion delivers image-version of the running upgrade
+func (oFsm *OnuUpgradeFsm) GetImageVersion(ctx context.Context) string {
+ oFsm.mutexUpgradeParams.RLock()
+ imageVersion := oFsm.imageVersion
+ oFsm.mutexUpgradeParams.RUnlock()
+ return imageVersion
}
//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
-func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context) {
+func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context, abCompleteAbort bool,
+ aReason voltha.ImageState_ImageFailureReason) {
+ oFsm.mutexAbortRequest.Lock()
+ oFsm.abortRequested = aReason //possibly abort the sectionDownload loop
+ oFsm.mutexAbortRequest.Unlock()
//mutex protection is required for possible concurrent access to FSM members
//attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
// accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
@@ -479,9 +530,33 @@
go func(aPAFsm *AdapterFsm) {
if aPAFsm.pFsm != nil {
if aPAFsm.pFsm.Is(upgradeStWaitEndDL) {
- oFsm.chReceiveExpectedResponse <- false //which aborts the FSM (activate was not yet sent)
+ oFsm.chReceiveExpectedResponse <- false //which aborts the FSM in WaitEndDL state
}
- _ = aPAFsm.pFsm.Event(upgradeEvReset) //anyway and for all other states
+ // in case of state-conditional request the
+
+ var err error
+ if abCompleteAbort {
+ oFsm.mutexUpgradeParams.Lock()
+ //any previous lingering conditional cancelRequest is superseded by this abortion
+ oFsm.conditionalCancelRequested = false
+ if aReason == voltha.ImageState_CANCELLED_ON_REQUEST {
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
+ } else {
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ }
+ oFsm.volthaDownloadReason = aReason
+ oFsm.mutexUpgradeParams.Unlock()
+ err = aPAFsm.pFsm.Event(upgradeEvAbort) //as unconditional default FSM cancellation
+ } else {
+ //at conditional request the image states are set when reaching the reset state
+ oFsm.conditionalCancelRequested = true
+ err = aPAFsm.pFsm.Event(upgradeEvReset) //as state-conditional default FSM cleanup
+ }
+ if err != nil {
+ //error return is expected in case of conditional request and no state transition
+ logger.Debugw(ctx, "onu upgrade fsm could not cancel with abort/reset event", log.Fields{
+ "device-id": oFsm.deviceID, "error": err})
+ }
} //else the FSM seems already to be in some released state
}(pAdaptFsm)
}
@@ -499,7 +574,10 @@
func (oFsm *OnuUpgradeFsm) enterWaitingAdapterDL(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "OnuUpgradeFsm waiting for adapter download", log.Fields{"in state": e.FSM.Current(),
"device-id": oFsm.deviceID})
- go oFsm.waitOnDownloadToAdapterReady(ctx, oFsm.chAdapterDlReady)
+ syncChannel := make(chan struct{})
+ go oFsm.waitOnDownloadToAdapterReady(ctx, syncChannel, oFsm.chAdapterDlReady)
+ //block until the wait routine is really blocked on chAdapterDlReady
+ <-syncChannel
go oFsm.pFileManager.RequestDownloadReady(ctx, oFsm.imageIdentifier, oFsm.chAdapterDlReady)
}
@@ -517,6 +595,9 @@
fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
}
if err != nil || fileLen > int64(cMaxUint32) {
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //Something like 'LOCAL_FILE_ERROR' would be better (proto)
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN
oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
"device-id": oFsm.deviceID, "error": err, "length": fileLen})
@@ -536,6 +617,9 @@
oFsm.imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
}
if err != nil {
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //Something like 'LOCAL_FILE_ERROR' would be better (proto)
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN
oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
"device-id": oFsm.deviceID, "error": err})
@@ -569,12 +653,7 @@
if err != nil {
logger.Errorw(ctx, "StartSwDl abort: can't send section", log.Fields{
"device-id": oFsm.deviceID, "error": err})
- //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
- pBaseFsm := oFsm.pAdaptFsm
- // Can't call FSM Event directly, decoupling it
- go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
- }(pBaseFsm)
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
return
}
}
@@ -596,6 +675,26 @@
}
for {
+ oFsm.mutexAbortRequest.RLock()
+ // this way out of the section download loop on abort request
+ if oFsm.abortRequested != voltha.ImageState_NO_ERROR {
+ if oFsm.abortRequested == voltha.ImageState_CANCELLED_ON_REQUEST {
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_CANCELLED
+ } else {
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ }
+ oFsm.volthaDownloadReason = oFsm.abortRequested
+ oFsm.mutexAbortRequest.RUnlock()
+ oFsm.mutexUpgradeParams.Unlock()
+ pBaseFsm := oFsm.pAdaptFsm
+ // Can't call FSM Event directly, decoupling it
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
+ }(pBaseFsm)
+ return
+ }
+ oFsm.mutexAbortRequest.RUnlock()
+
bufferStartOffset = oFsm.nextDownloadSectionsAbsolute * cOmciDownloadSectionSize
bufferEndOffset = bufferStartOffset + cOmciDownloadSectionSize - 1 //for representing cOmciDownloadSectionSizeLimit values
logger.Debugw(ctx, "DlSection values are", log.Fields{
@@ -606,6 +705,8 @@
logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
"device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
"bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR //Something like 'LOCAL_FILE_ERROR' would be better (proto)
oFsm.mutexUpgradeParams.Unlock()
//logical error -- reset the FSM
pBaseFsm := oFsm.pAdaptFsm
@@ -634,12 +735,7 @@
if err != nil {
logger.Errorw(ctx, "DlSection abort: can't send section", log.Fields{
"device-id": oFsm.deviceID, "section absolute": oFsm.nextDownloadSectionsAbsolute, "error": err})
- //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
- pBaseFsm := oFsm.pAdaptFsm
- // Can't call FSM Event directly, decoupling it
- go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
- }(pBaseFsm)
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
return
}
oFsm.mutexUpgradeParams.Lock()
@@ -685,9 +781,11 @@
pBaseFsm := oFsm.pAdaptFsm
if pBaseFsm == nil {
- logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{
- "device-id": oFsm.deviceID})
- //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
+ logger.Errorw(ctx, "EndSwDl abort: BaseFsm invalid", log.Fields{"device-id": oFsm.deviceID})
+ oFsm.mutexUpgradeParams.Lock()
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_UNKNOWN_ERROR
+ oFsm.mutexUpgradeParams.Unlock()
// Can't call FSM Event directly, decoupling it
go func(a_pAFsm *AdapterFsm) {
_ = a_pAFsm.pFsm.Event(upgradeEvAbort)
@@ -699,11 +797,7 @@
if err != nil {
logger.Errorw(ctx, "EndSwDl abort: can't send section", log.Fields{
"device-id": oFsm.deviceID, "error": err})
- //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
- // Can't call FSM Event directly, decoupling it
- go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
- }(pBaseFsm)
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
return
}
// go waiting for the EndSwDLResponse and check, if the ONU is ready for activation
@@ -725,6 +819,10 @@
"device-id": oFsm.deviceID})
return
}
+ oFsm.mutexUpgradeParams.Lock()
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_IMAGE_REFUSED_BY_ONU //Something like 'END_DOWNLOAD_TIMEOUT' would be better (proto)
+ oFsm.mutexUpgradeParams.Unlock()
go func(a_pAFsm *AdapterFsm) {
_ = a_pAFsm.pFsm.Event(upgradeEvAbort)
}(pBaseFsm)
@@ -760,56 +858,74 @@
}
if success {
//answer received with ready indication
- if oFsm.activateImage {
- //immediate activation requested
+ //useAPIVersion43 may not conflict in concurrency in this state function
+ if oFsm.useAPIVersion43 { // newer API usage requires verification of downloaded image version
go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvRequestActivate)
+ _ = a_pAFsm.pFsm.Event(upgradeEvCheckImageName)
}(pBaseFsm)
- } else {
- //have to wait on explicit activation request
- go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvWaitForActivate)
- }(pBaseFsm)
+ } else { // elder API usage does not support image version check -immediately consider download as successful
+ if oFsm.activateImage {
+ //immediate activation requested
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(upgradeEvRequestActivate)
+ }(pBaseFsm)
+ } else {
+ //have to wait on explicit activation request
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(upgradeEvWaitForActivate)
+ }(pBaseFsm)
+ }
}
return
}
//timer was aborted
- go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
- }(pBaseFsm)
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
return
}
}
+func (oFsm *OnuUpgradeFsm) enterCheckImageName(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "OnuUpgradeFsm checking downloaded image name", log.Fields{
+ "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
+ requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
+ meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
+ me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
+ false, oFsm.pAdaptFsm.commChan)
+ if err != nil {
+ logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
+ log.Fields{"device-id": oFsm.deviceID, "Error": err})
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
+ return
+ }
+ oFsm.pLastTxMeInstance = meInstance
+}
+
func (oFsm *OnuUpgradeFsm) enterActivateSw(ctx context.Context, e *fsm.Event) {
logger.Infow(ctx, "OnuUpgradeFsm activate SW", log.Fields{
"device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
- oFsm.mutexUpgradeParams.Lock()
- oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
- oFsm.mutexUpgradeParams.Unlock()
-
err := oFsm.pOmciCC.sendActivateSoftware(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID)
if err != nil {
logger.Errorw(ctx, "ActivateSw abort: can't send activate frame", log.Fields{
"device-id": oFsm.deviceID, "error": err})
- //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
- pBaseFsm := oFsm.pAdaptFsm
- // Can't call FSM Event directly, decoupling it
- go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
- }(pBaseFsm)
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
return
}
+ oFsm.mutexUpgradeParams.Lock()
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVATING
+ oFsm.mutexUpgradeParams.Unlock()
}
func (oFsm *OnuUpgradeFsm) enterCommitSw(ctx context.Context, e *fsm.Event) {
- if activeImageID, err := oFsm.pOnuOmciDevice.GetActiveImageMeID(ctx); err == nil {
- //TODO!!: as long as testing with BBSIM and BBSIM not support upgrade tests following check needs to be deactivated
- imageFit := true //TODO!!: test workaround as long as BBSIM does not fully support upgrade
+ logger.Debugw(ctx, "OnuUpgradeFsm start commit SW", log.Fields{
+ "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
+ //any abort request (also conditional) is still regarded as valid as the commit indication might not be possible to verify
+ // (which is a bit problematic as the ONU might already be in committed state,
+ // in this case (committing failed) always 'onuimage list' should be used to verify the real state (if ONU is reachable))
+ if activeImageID, err := oFsm.pDevEntry.GetActiveImageMeID(ctx); err == nil {
oFsm.mutexUpgradeParams.Lock()
- if imageFit || activeImageID == oFsm.inactiveImageMeID {
+ if activeImageID == oFsm.inactiveImageMeID {
inactiveImageID := oFsm.inactiveImageMeID
logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
"device-id": oFsm.deviceID, "me-id": inactiveImageID}) //more efficient activeImageID with above check
@@ -820,31 +936,24 @@
if err != nil {
logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
"device-id": oFsm.deviceID, "error": err})
- //TODO!!!: define some more sophisticated error treatment with some repetition, for now just reset the FSM
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- pBaseFsm := oFsm.pAdaptFsm
- // Can't call FSM Event directly, decoupling it
- go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
- }(pBaseFsm)
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_COMMIT_ABORTED)
return
}
return
}
+ oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm active ImageId <> IdToCommit", log.Fields{
"device-id": oFsm.deviceID, "active ID": activeImageID, "to commit ID": oFsm.inactiveImageMeID})
- oFsm.mutexUpgradeParams.Unlock()
-
- //TODO!!!: possibly send event information for aborted upgrade (not activated)??
- pBaseFsm := oFsm.pAdaptFsm
- // Can't call FSM Event directly, decoupling it
- go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
- }(pBaseFsm)
- return
+ } else {
+ logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
+ "device-id": oFsm.deviceID})
}
- logger.Errorw(ctx, "OnuUpgradeFsm can't commit, no valid active image", log.Fields{
- "device-id": oFsm.deviceID})
+ oFsm.mutexUpgradeParams.Lock()
+ oFsm.conditionalCancelRequested = false //any lingering conditional cancelRequest is superseded by this error
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
+ oFsm.mutexUpgradeParams.Unlock()
//TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
@@ -854,22 +963,15 @@
}
func (oFsm *OnuUpgradeFsm) enterCheckCommitted(ctx context.Context, e *fsm.Event) {
- logger.Infow(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
+ logger.Debugw(ctx, "OnuUpgradeFsm checking committed SW", log.Fields{
"device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID})
requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
meInstance, err := oFsm.pOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
me.SoftwareImageClassID, oFsm.inactiveImageMeID, requestedAttributes, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false, oFsm.pAdaptFsm.commChan)
- //accept also nil as (error) return value for writing to LastTx
- // - this avoids misinterpretation of new received OMCI messages
if err != nil {
logger.Errorw(ctx, "OnuUpgradeFsm get Software Image ME result error",
log.Fields{"device-id": oFsm.deviceID, "Error": err})
- pOnuUpgradeFsm := oFsm.pAdaptFsm
- if pOnuUpgradeFsm != nil {
- go func(a_pAFsm *AdapterFsm) {
- _ = a_pAFsm.pFsm.Event(upgradeEvAbort)
- }(pOnuUpgradeFsm)
- }
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_COMMIT_ABORTED)
return
}
oFsm.pLastTxMeInstance = meInstance
@@ -878,6 +980,14 @@
func (oFsm *OnuUpgradeFsm) enterResetting(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "OnuUpgradeFsm resetting", log.Fields{"device-id": oFsm.deviceID})
+ // if the reset was conditionally requested
+ if oFsm.conditionalCancelRequested {
+ oFsm.mutexUpgradeParams.Lock()
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
+ oFsm.mutexUpgradeParams.Unlock()
+ }
+
// in case the download-to-ONU timer is still running - cancel it
oFsm.mutexIsAwaitingOnuDlResponse.RLock()
if oFsm.isWaitingForOnuDlResponse {
@@ -914,7 +1024,13 @@
// no need to flush possible channels here, Upgrade FSM will be completely removed, garbage collector should find its way
if oFsm.pDeviceHandler != nil {
//request removal of 'reference' in the Handler (completely clear the FSM and its data)
- go oFsm.pDeviceHandler.removeOnuUpgradeFsm(ctx)
+ pLastUpgradeImageState := &voltha.ImageState{
+ Version: oFsm.imageVersion,
+ DownloadState: oFsm.volthaDownloadState,
+ Reason: oFsm.volthaDownloadReason,
+ ImageState: oFsm.volthaImageState,
+ }
+ go oFsm.pDeviceHandler.removeOnuUpgradeFsm(ctx, pLastUpgradeImageState)
}
}
@@ -929,7 +1045,7 @@
if !ok {
logger.Info(ctx, "OnuUpgradeFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
// but then we have to ensure a restart of the FSM as well - as exceptional procedure
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
break loop
}
logger.Debugw(ctx, "OnuUpgradeFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
@@ -965,16 +1081,14 @@
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for StartSwDlResponse",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
msgObj, msgOk := msgLayer.(*omci.StartSoftwareDownloadResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for StartSwDlResponse",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
logger.Debugw(ctx, "OnuUpgradeFsm StartSwDlResponse data", log.Fields{
@@ -982,9 +1096,7 @@
if msgObj.Result != me.Success {
logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse result error - later: drive FSM to abort state ?",
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
- // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
@@ -1015,9 +1127,7 @@
oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
- // TODO!!!: possibly repeat the start request (once)?
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
} //StartSoftwareDownloadResponseType
case omci.DownloadSectionResponseType:
@@ -1026,16 +1136,14 @@
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for DlSectionResponse",
log.Fields{"device-id": oFsm.deviceID, "omci-message": msg.OmciMsg})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
msgObj, msgOk := msgLayer.(*omci.DownloadSectionResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for DlSectionResponse",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
logger.Debugw(ctx, "OnuUpgradeFsm DlSectionResponse Data", log.Fields{
@@ -1043,8 +1151,7 @@
if msgObj.Result != me.Success {
logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse result error - later: repeat window once?", //TODO!!!
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
oFsm.mutexUpgradeParams.Lock()
@@ -1059,9 +1166,8 @@
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)??
oFsm.mutexUpgradeParams.Unlock()
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
oFsm.delayEndSwDl = true //ensure a delay for the EndSwDl message
@@ -1080,8 +1186,7 @@
log.Fields{"device-id": oFsm.deviceID, "actual-section": sectionNumber,
"expected section": oFsm.omciDownloadWindowSizeLimit})
oFsm.mutexUpgradeParams.Unlock()
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
oFsm.nextDownloadSectionsWindow = 0
@@ -1092,9 +1197,7 @@
oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm Omci StartSwDlResponse wrong ME instance: try again (later)?",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
- // TODO!!!: possibly repeat the download (section) (once)?
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
} //DownloadSectionResponseType
case omci.EndSoftwareDownloadResponseType:
@@ -1103,16 +1206,14 @@
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for EndSwDlResponse",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
msgObj, msgOk := msgLayer.(*omci.EndSoftwareDownloadResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for EndSwDlResponse",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
logger.Debugw(ctx, "OnuUpgradeFsm EndSwDlResponse data", log.Fields{
@@ -1126,34 +1227,44 @@
}
logger.Errorw(ctx, "OnuUpgradeFsm EndSwDlResponse result error - later: drive FSM to abort state ?",
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
- // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
}
oFsm.mutexUpgradeParams.Lock()
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
+ //EndSwDownloadSuccess is used to indicate 'DOWNLOAD_SUCCEEDED'
oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
- oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
- oFsm.mutexUpgradeParams.Unlock()
- logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
- oFsm.mutexIsAwaitingOnuDlResponse.RLock()
- if oFsm.isWaitingForOnuDlResponse {
- oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
- //use channel to indicate that the download to ONU was successful
- oFsm.chOnuDlReady <- true
+ if !oFsm.useAPIVersion43 {
+ //in the older API version the image version check was not possible
+ // - assume new loaded image as valid-inactive immediately
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
+ oFsm.mutexUpgradeParams.Unlock()
+ oFsm.mutexIsAwaitingOnuDlResponse.RLock()
+ if oFsm.isWaitingForOnuDlResponse {
+ oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
+ //use non-blocking channel to indicate that the download to ONU was successful
+ select {
+ case oFsm.chOnuDlReady <- true:
+ default:
+ }
+ } else {
+ oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
+ }
} else {
- oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
+ oFsm.mutexUpgradeParams.Unlock()
}
- oFsm.chReceiveExpectedResponse <- true //let the FSM proceed from the waitState
+ logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
+ //use non-blocking channel to let the FSM proceed from the waitState
+ select {
+ case oFsm.chReceiveExpectedResponse <- true:
+ default:
+ }
return
}
oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm StartSwDlResponse wrong ME instance: try again (later)?",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
- // TODO!!!: possibly repeat the end request (once)? or verify ONU upgrade state?
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_DOWNLOADING)
return
} //EndSoftwareDownloadResponseType
case omci.ActivateSoftwareResponseType:
@@ -1162,16 +1273,14 @@
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for ActivateSw",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
return
}
msgObj, msgOk := msgLayer.(*omci.ActivateSoftwareResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for ActivateSw",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
return
}
logger.Debugw(ctx, "OnuUpgradeFsm ActivateSwResponse data", log.Fields{
@@ -1179,13 +1288,12 @@
if msgObj.Result != me.Success {
logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse result error - later: drive FSM to abort state ?",
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
- // TODO!!!: error treatment?, perhaps in the end reset the FSM
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
return
}
oFsm.mutexUpgradeParams.Lock()
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
+ // the image is regarded as active really only after ONU reboot and according indication (ONU down/up procedure)
oFsm.mutexUpgradeParams.Unlock()
logger.Infow(ctx, "Expected ActivateSwResponse received",
log.Fields{"device-id": oFsm.deviceID, "commit": oFsm.commitImage})
@@ -1199,9 +1307,7 @@
oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
- // TODO!!!: error treatment?
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_ACTIVATION_ABORTED)
return
} //ActivateSoftwareResponseType
case omci.CommitSoftwareResponseType:
@@ -1210,22 +1316,20 @@
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for CommitResponse",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
return
}
msgObj, msgOk := msgLayer.(*omci.CommitSoftwareResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for CommitResponse",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
return
}
if msgObj.Result != me.Success {
logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse result error - later: drive FSM to abort state ?",
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
- // TODO!!!: error treatment?, perhaps in the end reset the FSM
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
return
}
oFsm.mutexUpgradeParams.RLock()
@@ -1239,9 +1343,7 @@
oFsm.mutexUpgradeParams.RUnlock()
logger.Errorw(ctx, "OnuUpgradeFsm SwImage CommitResponse wrong ME instance: abort",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
- // TODO!!!: error treatment?
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
return
} //CommitSoftwareResponseType
case omci.GetResponseType:
@@ -1250,16 +1352,14 @@
if msgLayer == nil {
logger.Errorw(ctx, "Omci Msg layer could not be detected for SwImage GetResponse",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
return
}
msgObj, msgOk := msgLayer.(*omci.GetResponse)
if !msgOk {
logger.Errorw(ctx, "Omci Msg layer could not be assigned for SwImage GetResponse",
log.Fields{"device-id": oFsm.deviceID})
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
return
}
logger.Debugw(ctx, "OnuUpgradeFsm SwImage GetResponse data", log.Fields{
@@ -1269,9 +1369,7 @@
if msgObj.Result != me.Success {
logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse result error - later: drive FSM to abort state ?",
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
- // TODO!!!: error treatment?, perhaps in the end reset the FSM
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ oFsm.abortOnOmciError(ctx, false, voltha.ImageState_IMAGE_COMMIT_ABORTED)
return
}
} else {
@@ -1288,7 +1386,80 @@
log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
"version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
+ if oFsm.pAdaptFsm.pFsm.Current() == upgradeStCheckImageName {
+ //image name check after EndSwDownload, this state (and block) can only be taken if APIVersion43 is used
+ oFsm.mutexUpgradeParams.Lock()
+ if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsInactive &&
+ imageIsCommitted == swIsUncommitted {
+ if imageVersion != oFsm.imageVersion {
+ //new stored inactive version indicated on OMCI from ONU is not the expected version
+ logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse version indication not matching requested upgrade",
+ log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
+ "onu-version": imageVersion, "expected-version": oFsm.imageVersion})
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED //not the expected image was downloaded
+ oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //something like 'DOWNLOADED' would be better - proto def
+ oFsm.mutexUpgradeParams.Unlock()
+ //stop the running ONU download timer
+ oFsm.mutexIsAwaitingOnuDlResponse.RLock()
+ if oFsm.isWaitingForOnuDlResponse {
+ oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
+ //use channel to indicate that the download to ONU was not successful
+ oFsm.chOnuDlReady <- false
+ } else {
+ oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
+ }
+ // TODO!!!: error treatment?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ }
+ //with APIVersion43 this is the point to consider the newly loaded image as valid (and inactive)
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_INACTIVE
+ //store the new inactive version to onuSwImageIndications (to keep them in sync)
+ oFsm.pDevEntry.modifySwImageInactiveVersion(ctx, oFsm.imageVersion)
+ //proceed within upgrade FSM
+ if oFsm.activateImage {
+ //immediate activation requested
+ oFsm.mutexUpgradeParams.Unlock()
+ logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, continue with activation",
+ log.Fields{"device-id": oFsm.deviceID})
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRequestActivate)
+ } else {
+ //have to wait on explicit activation request
+ // but a previously requested download activity (without activation) was successful here
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
+ oFsm.mutexUpgradeParams.Unlock()
+ logger.Infow(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU, wait for activate request",
+ log.Fields{"device-id": oFsm.deviceID})
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForActivate)
+ }
+ oFsm.mutexIsAwaitingOnuDlResponse.RLock()
+ if oFsm.isWaitingForOnuDlResponse {
+ oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
+ //use channel to indicate that the download to ONU was successful
+ oFsm.chOnuDlReady <- true
+ } else {
+ oFsm.mutexIsAwaitingOnuDlResponse.RUnlock()
+ }
+ return
+ }
+ //not the expected image/image state
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //real image state not known
+ oFsm.mutexUpgradeParams.Unlock()
+ logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
+ log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
+ // TODO!!!: error treatment?
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by ONU state indication)?
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ return
+ }
+
+ //assumed only relevant state here is upgradeStCheckCommitted
oFsm.mutexUpgradeParams.Lock()
+ oFsm.conditionalCancelRequested = false //getting here any set (conditional) cancelRequest is not relevant anymore
if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive {
//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)
@@ -1298,12 +1469,15 @@
if oFsm.useAPIVersion43 {
if imageVersion != oFsm.imageVersion {
//new active version indicated on OMCI from ONU is not the expected version
- logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
+ logger.Errorw(ctx, "OnuUpgradeFsm image-version not matching the requested upgrade",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance,
"onu-version": imageVersion, "expected-version": oFsm.imageVersion})
- oFsm.mutexUpgradeParams.Unlock()
// TODO!!!: error treatment?
- //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by wrong version)?
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED //not the expected image was committed
+ oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE //something like 'UNEXPECTED_VERSION' would be better - proto def
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_UNKNOWN //expected image not known
+ oFsm.mutexUpgradeParams.Unlock()
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
@@ -1311,17 +1485,23 @@
log.Fields{"device-id": oFsm.deviceID})
}
if imageIsCommitted == swIsCommitted {
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTED
+ //store the new commit flag to onuSwImageIndications (to keep them in sync)
+ oFsm.pDevEntry.modifySwImageActiveCommit(ctx, imageIsCommitted)
logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
- oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent)) //to let the handler now about success
+ //deviceProcStatusUpdate not used anymore,
+ // replaced by transferring the last (more) upgrade state information within removeOnuUpgradeFsm
oFsm.mutexUpgradeParams.Unlock()
- //releasing the upgrade FSM
+ //releasing the upgrade FSM on success
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
- oFsm.mutexUpgradeParams.Unlock()
- return //if the imageId is active but not committed let upgrade persist, maybe ONU reboot or manual commit may resolve the situation
+ //if not committed, abort upgrade as failed. There is no implementation here that would trigger this test again
}
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_CANCELLED_ON_ONU_STATE
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching requested upgrade",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
@@ -1339,12 +1519,48 @@
}
}
+//abortOnOmciError aborts the upgrade processing with OMCI_TRANSFER_ERROR indication
+func (oFsm *OnuUpgradeFsm) abortOnOmciError(ctx context.Context, aAsync bool,
+ aImageState voltha.ImageState_ImageActivationState) {
+ oFsm.mutexUpgradeParams.Lock()
+ oFsm.conditionalCancelRequested = false //any conditional cancelRequest is superseded by this abortion
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ oFsm.volthaDownloadReason = voltha.ImageState_OMCI_TRANSFER_ERROR
+ if aImageState != voltha.ImageState_IMAGE_UNKNOWN {
+ // update image state only in case some explicite state is given (otherwise the existing state is used)
+ oFsm.volthaImageState = aImageState
+ }
+ oFsm.mutexUpgradeParams.Unlock()
+ //TODO!!!: possibly send event information for aborted upgrade (aborted by omci processing)??
+ if oFsm.pAdaptFsm != nil {
+ var err error
+ if aAsync { //asynchronous call requested to ensure state transition
+ go func(a_pAFsm *AdapterFsm) {
+ if a_pAFsm.pFsm != nil {
+ err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ }
+ }(oFsm.pAdaptFsm)
+ } else {
+ if oFsm.pAdaptFsm.pFsm != nil {
+ err = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
+ }
+ }
+ if err != nil {
+ logger.Warnw(ctx, "onu upgrade fsm could not abort on omci error", log.Fields{
+ "device-id": oFsm.deviceID, "error": err})
+ }
+ }
+}
+
//waitOnDownloadToAdapterReady state can only be reached with useAPIVersion43 (usage of pFileManager)
-func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aWaitChannel chan bool) {
- downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
+// precondition: mutexIsAwaitingAdapterDlResponse is lockek on call
+func (oFsm *OnuUpgradeFsm) waitOnDownloadToAdapterReady(ctx context.Context, aSyncChannel chan<- struct{},
+ aWaitChannel chan bool) {
oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
+ downloadToAdapterTimeout := oFsm.pFileManager.GetDownloadTimeout(ctx)
oFsm.isWaitingForAdapterDlResponse = true
oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
+ aSyncChannel <- struct{}{}
select {
// maybe be also some outside cancel (but no context modeled for the moment ...)
// case <-ctx.Done():
@@ -1356,13 +1572,7 @@
oFsm.mutexIsAwaitingAdapterDlResponse.Lock()
oFsm.isWaitingForAdapterDlResponse = false
oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
- //the upgrade process has to be aborted
- pUpgradeFsm := oFsm.pAdaptFsm
- if pUpgradeFsm != nil {
- _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
- } else {
- logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
- }
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
return
case success := <-aWaitChannel:
@@ -1387,12 +1597,7 @@
oFsm.isWaitingForAdapterDlResponse = false
oFsm.mutexIsAwaitingAdapterDlResponse.Unlock()
//the upgrade process has to be aborted
- pUpgradeFsm := oFsm.pAdaptFsm
- if pUpgradeFsm != nil {
- _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
- } else {
- logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
- }
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
return
}
}
@@ -1416,12 +1621,7 @@
oFsm.isWaitingForOnuDlResponse = false
oFsm.mutexIsAwaitingOnuDlResponse.Unlock()
//the upgrade process has to be aborted
- pUpgradeFsm := oFsm.pAdaptFsm
- if pUpgradeFsm != nil {
- _ = pUpgradeFsm.pFsm.Event(upgradeEvAbort)
- } else {
- logger.Errorw(ctx, "pUpgradeFsm is nil", log.Fields{"device-id": oFsm.deviceID})
- }
+ oFsm.abortOnOmciError(ctx, true, voltha.ImageState_IMAGE_UNKNOWN) //no ImageState update
return
case success := <-aWaitChannel:
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index a6a51e1..91510c9 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -210,8 +210,8 @@
swIsCommitted = 1
)
const ( //definitions as per G.988 softwareImage::IsActive
- //swIsInactive = 0 not yet used
- swIsActive = 1
+ swIsInactive = 0
+ swIsActive = 1
)
const ( //definitions as per G.988 softwareImage::IsValid
//swIsInvalid = 0 not yet used
@@ -893,6 +893,24 @@
logger.Debugf(ctx, "mibDataSync updated - mds: %d - device-id: %s", oo.sOnuPersistentData.PersMibDataSyncAdpt, oo.deviceID)
}
+func (oo *OnuDeviceEntry) modifySwImageInactiveVersion(ctx context.Context, aImageVersion string) {
+ oo.mutexOnuSwImageIndications.Lock()
+ defer oo.mutexOnuSwImageIndications.Unlock()
+ logger.Debugw(ctx, "software-image set inactive version", log.Fields{
+ "device-id": oo.deviceID, "version": aImageVersion})
+ oo.onuSwImageIndications.inactiveEntityEntry.version = aImageVersion
+ //inactive SW version is not part of persistency data (yet) - no need to update that
+}
+
+func (oo *OnuDeviceEntry) modifySwImageActiveCommit(ctx context.Context, aCommitted uint8) {
+ oo.mutexOnuSwImageIndications.Lock()
+ defer oo.mutexOnuSwImageIndications.Unlock()
+ logger.Debugw(ctx, "software-image set active entity commit flag", log.Fields{
+ "device-id": oo.deviceID, "committed": aCommitted})
+ oo.onuSwImageIndications.activeEntityEntry.isCommitted = aCommitted
+ //commit flag is not part of persistency data (yet) - no need to update that
+}
+
func (oo *OnuDeviceEntry) getActiveImageVersion(ctx context.Context) string {
oo.mutexOnuSwImageIndications.RLock()
if oo.onuSwImageIndications.activeEntityEntry.valid {
diff --git a/internal/pkg/onuadaptercore/openonu.go b/internal/pkg/onuadaptercore/openonu.go
index c790592..babbda9 100644
--- a/internal/pkg/onuadaptercore/openonu.go
+++ b/internal/pkg/onuadaptercore/openonu.go
@@ -535,7 +535,7 @@
return nil, errors.New("unImplemented")
}
-//Activate_image_update requests downloading some Onu Software image to the INU via OMCI
+//Activate_image_update 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) Activate_image_update(ctx context.Context, device *voltha.Device, request *voltha.ImageDownload) (*voltha.ImageDownload, error) {
@@ -633,67 +633,90 @@
if request != nil && len((*request).DeviceId) > 0 && (*request).Image.Version != "" {
loResponse := voltha.DeviceImageResponse{}
imageIdentifier := (*request).Image.Version
- //inform the deviceHandler about (possibly new) requested ONU download requests
+ downloadedToAdapter := false
firstDevice := true
var vendorID string
for _, pCommonID := range (*request).DeviceId {
+ vendorIDMatch := true
loDeviceID := (*pCommonID).Id
- onuVolthaDevice, err := oo.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx),
- loDeviceID, loDeviceID)
- if err != nil || onuVolthaDevice == nil {
- logger.Warnw(ctx, "Failed to fetch Onu device for image 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, "download request for file", log.Fields{"image-id": imageIdentifier})
-
- if !oo.pFileManager.ImageExists(ctx, imageIdentifier) {
- logger.Debugw(ctx, "start image download", log.Fields{"image-description": request})
- // Download_image is not supposed to be blocking, anyway let's call the DownloadManager still synchronously to detect 'fast' problems
- // the download itself is later done in background
- if err := oo.pFileManager.StartDownload(ctx, imageIdentifier, (*request).Image.Url); err != nil {
- return nil, err
- }
- }
- // image already exists
- logger.Debugw(ctx, "image already downloaded", log.Fields{"image-description": 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
- }
- }
loDeviceImageState := voltha.DeviceImageState{}
loDeviceImageState.DeviceId = loDeviceID
loImageState := voltha.ImageState{}
loDeviceImageState.ImageState = &loImageState
loDeviceImageState.ImageState.Version = (*request).Image.Version
- // 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
+
+ onuVolthaDevice, err := oo.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx),
+ loDeviceID, loDeviceID)
+ if err != nil || onuVolthaDevice == nil {
+ logger.Warnw(ctx, "Failed to fetch Onu device for image download",
+ log.Fields{"device-id": loDeviceID, "err": err})
+ 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
} 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
- loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
+ 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, "download request for file", log.Fields{"image-id": imageIdentifier})
+
+ if !oo.pFileManager.ImageExists(ctx, imageIdentifier) {
+ logger.Debugw(ctx, "start image download", log.Fields{"image-description": request})
+ // Download_image is not supposed to be blocking, anyway let's call the DownloadManager still synchronously to detect 'fast' problems
+ // the download itself is later done in background
+ if err := oo.pFileManager.StartDownload(ctx, imageIdentifier, (*request).Image.Url); err == nil {
+ downloadedToAdapter = true
+ }
+ //else: treat any error here as 'INVALID_URL' (even though it might as well be some issue on local FS, eg. 'INSUFFICIENT_SPACE')
+ // otherwise a more sophisticated error evaluation is needed
+ } else {
+ // image already exists
+ downloadedToAdapter = true
+ logger.Debugw(ctx, "image already downloaded", log.Fields{"image-description": imageIdentifier})
+ // note: If the image (with vendorId+name) has already been downloaded before from some other
+ // valid URL, the current URL is just ignored. If the operators want to ensure that the new URL
+ // is really used, then they first have to use the 'abort' API to remove the existing image!
+ // (abort API can be used also after some successful download to just remove the image from adapter)
+ }
+ } 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})
+ vendorIDMatch = false
+ }
+ }
+ 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
+ }
+ } else {
+ loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ if !downloadedToAdapter {
+ loDeviceImageState.ImageState.Reason = voltha.ImageState_INVALID_URL
+ } else { //only logical option is !vendorIDMatch
+ loDeviceImageState.ImageState.Reason = voltha.ImageState_VENDOR_DEVICE_MISMATCH
+ }
+ loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
+ }
}
loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, &loDeviceImageState)
}
@@ -708,55 +731,73 @@
func (oo *OpenONUAC) Get_onu_image_status(ctx context.Context, in *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
if in != nil && len((*in).DeviceId) > 0 && (*in).Version != "" {
loResponse := voltha.DeviceImageResponse{}
- pDlToAdapterImageState := &voltha.ImageState{}
imageIdentifier := (*in).Version
+ var vendorIDSet bool
firstDevice := true
var vendorID string
for _, pCommonID := range (*in).DeviceId {
loDeviceID := (*pCommonID).Id
+ pDeviceImageState := &voltha.DeviceImageState{
+ DeviceId: loDeviceID,
+ }
+ vendorIDSet = false
onuVolthaDevice, err := oo.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx),
loDeviceID, loDeviceID)
if err != nil || onuVolthaDevice == nil {
logger.Warnw(ctx, "Failed to fetch Onu device to get image status",
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, "status request for image", log.Fields{"image-id": imageIdentifier})
- oo.pFileManager.RequestDownloadState(ctx, imageIdentifier, pDlToAdapterImageState)
- } 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
+ pImageState := &voltha.ImageState{
+ Version: (*in).Version,
+ DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN, //no statement about last activity possible
+ Reason: voltha.ImageState_UNKNOWN_ERROR, //something like "DEVICE_NOT_EXISTS" would be better (proto def)
+ ImageState: voltha.ImageState_IMAGE_UNKNOWN,
}
- }
- pDeviceImageState := &voltha.DeviceImageState{
- ImageState: &voltha.ImageState{
- DownloadState: (*pDlToAdapterImageState).DownloadState,
- Reason: (*pDlToAdapterImageState).Reason,
- },
- }
- // get the handler for the device
- if handler := oo.getDeviceHandler(ctx, loDeviceID, false); handler != nil {
- logger.Debugw(ctx, "image status request for", log.Fields{
- "image-id": imageIdentifier, "device-id": loDeviceID})
- //status request is called synchronously to collect the indications for all concerned devices
- handler.requestOnuSwUpgradeState(ctx, imageIdentifier, (*in).Version, pDeviceImageState)
+ pDeviceImageState.ImageState = pImageState
} else {
- //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
+ 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
+ vendorIDSet = true
+ logger.Debugw(ctx, "status request for image", 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})
+ } else {
+ vendorIDSet = true
+ }
+ }
+ if !vendorIDSet {
+ pImageState := &voltha.ImageState{
+ Version: (*in).Version,
+ DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN, //can't be sure that download for this device was really tried
+ Reason: voltha.ImageState_VENDOR_DEVICE_MISMATCH,
+ ImageState: voltha.ImageState_IMAGE_UNKNOWN,
+ }
+ pDeviceImageState.ImageState = pImageState
+ } else {
+ // get the handler for the device
+ if handler := oo.getDeviceHandler(ctx, loDeviceID, false); handler != nil {
+ logger.Debugw(ctx, "image status request for", log.Fields{
+ "image-id": imageIdentifier, "device-id": loDeviceID})
+ //status request is called synchronously to collect the indications for all concerned devices
+ pDeviceImageState.ImageState = handler.requestOnuSwUpgradeState(ctx, imageIdentifier, (*in).Version)
+ } else {
+ //cannot get the handler
+ logger.Warnw(ctx, "no handler found for image status request ", log.Fields{"device-id": loDeviceID})
+ pImageState := &voltha.ImageState{
+ Version: (*in).Version,
+ DownloadState: voltha.ImageState_DOWNLOAD_UNKNOWN, //no statement about last activity possible
+ Reason: voltha.ImageState_UNKNOWN_ERROR, //something like "DEVICE_NOT_EXISTS" would be better (proto def)
+ ImageState: voltha.ImageState_IMAGE_UNKNOWN,
+ }
+ pDeviceImageState.ImageState = pImageState
+ }
+ }
}
loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, pDeviceImageState)
}
@@ -809,14 +850,12 @@
//upgrade cancel is called synchronously to collect the imageResponse indications for all concerned devices
handler.cancelOnuSwUpgrade(ctx, imageIdentifier, (*in).Version, pDeviceImageState)
} else {
- //cannot start ONU download for requested device
+ //cannot start aborting ONU download for requested device
logger.Warnw(ctx, "no handler found for aborting upgrade ", log.Fields{"device-id": loDeviceID})
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.Reason = voltha.ImageState_CANCELLED_ON_REQUEST //something better would be possible with protos modification
pDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
}
loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, pDeviceImageState)
@@ -919,8 +958,8 @@
// 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
if pImageStates, err := handler.onuSwCommitRequest(ctx, imageIdentifier); err != nil {
- loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
- loDeviceImageState.ImageState.Reason = voltha.ImageState_UNKNOWN_ERROR
+ loDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_FAILED
+ loDeviceImageState.ImageState.Reason = voltha.ImageState_UNKNOWN_ERROR //can be multiple reasons here
loDeviceImageState.ImageState.ImageState = voltha.ImageState_IMAGE_COMMIT_ABORTED
} else {
loDeviceImageState.ImageState.DownloadState = pImageStates.DownloadState