ONU SW upgrade API change - step 2: added Abort and Get_onu_image_status functionality
Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I577442affd3f63f429367e012a67184429359f94
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index df3c477..3dd76ff 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -224,6 +224,7 @@
readyForOmciConfig bool
deletionInProgress bool
mutexDeletionInProgressFlag sync.RWMutex
+ upgradeSuccess bool
}
//newDeviceHandler creates a new device handler
@@ -766,7 +767,7 @@
func (dh *deviceHandler) reEnableDevice(ctx context.Context, device *voltha.Device) {
logger.Debugw(ctx, "reenable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
- //setting ReadyForSpecificOmciConfig here is just a workaround for BBSIM testing in the sequence
+ //setting readyForOmciConfig here is just a workaround for BBSIM testing in the sequence
// OnuSoftReboot-disable-enable, because BBSIM does not generate a new OnuIndication-Up event after SoftReboot
// which is the assumption for real ONU's, where the ready-state is then set according to the following MibUpload/Download
// for real ONU's that should have nearly no influence
@@ -1285,6 +1286,57 @@
"device-id": dh.deviceID, "error": err})
}
+func (dh *deviceHandler) requestOnuSwUpgradeState(ctx context.Context, aImageIdentifier string,
+ aVersion string, pDeviceImageState *voltha.DeviceImageState) {
+ pDeviceImageState.DeviceId = dh.deviceID
+ pDeviceImageState.ImageState.Version = aImageIdentifier
+ dh.lockUpgradeFsm.RLock()
+ 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
+ }
+ }
+}
+
+func (dh *deviceHandler) cancelOnuSwUpgrade(ctx context.Context, aImageIdentifier string,
+ aVersion string, pDeviceImageState *voltha.DeviceImageState) {
+ pDeviceImageState.DeviceId = dh.deviceID
+ pDeviceImageState.ImageState.Version = aImageIdentifier
+ 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
+ } else {
+ dh.lockUpgradeFsm.RUnlock()
+ pDeviceImageState.ImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
+ pDeviceImageState.ImageState.Reason = voltha.ImageState_NO_ERROR
+ }
+}
+
// deviceHandler methods that implement the adapters interface requests## end #########
// #####################################################################################
@@ -1867,6 +1919,7 @@
if pDevEntry.PDevOmciCC != nil {
pDevEntry.PDevOmciCC.CancelRequestMonitoring()
}
+
if includingMibSyncFsm {
pDevEntry.CancelProcessing(ctx)
}
@@ -2239,6 +2292,10 @@
{
dh.processOmciVlanFilterDoneEvent(ctx, devEvent)
}
+ case OmciOnuSwUpgradeDone:
+ {
+ dh.upgradeSuccess = true
+ }
default:
{
logger.Debugw(ctx, "unhandled-device-event", log.Fields{"device-id": dh.deviceID, "event": devEvent})
@@ -2484,6 +2541,7 @@
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!!!
@@ -3502,7 +3560,6 @@
dh.readyForOmciConfig = flagValue
dh.mutexReadyForOmciConfig.Unlock()
}
-
func (dh *deviceHandler) isReadyForOmciConfig() bool {
dh.mutexReadyForOmciConfig.RLock()
flagValue := dh.readyForOmciConfig
diff --git a/internal/pkg/onuadaptercore/file_download_manager.go b/internal/pkg/onuadaptercore/file_download_manager.go
index 0658c6f..1dfd50a 100644
--- a/internal/pkg/onuadaptercore/file_download_manager.go
+++ b/internal/pkg/onuadaptercore/file_download_manager.go
@@ -29,6 +29,7 @@
"time"
"github.com/opencord/voltha-lib-go/v4/pkg/log"
+ "github.com/opencord/voltha-protos/v4/go/voltha"
)
const cDefaultLocalDir = "/tmp" //this is the default local dir to download to
@@ -348,3 +349,48 @@
}()
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!)
+ 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
+ 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})
+ }
+ // and in the imageDsc slice by just not appending
+ } else {
+ tmpSlice = append(tmpSlice, dnldImgDsc)
+ }
+ }
+ dm.downloadImageDscSlice = tmpSlice
+ //image not found (by name)
+}
diff --git a/internal/pkg/onuadaptercore/omci_onu_upgrade.go b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
index 1e542ce..3da030d 100644
--- a/internal/pkg/onuadaptercore/omci_onu_upgrade.go
+++ b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
@@ -124,10 +124,10 @@
waitCountEndSwDl uint8 //number, how often is waited for EndSwDl at maximum
waitDelayEndSwDl time.Duration //duration, how long is waited before next request on EndSwDl
chReceiveExpectedResponse chan bool
- useAPIVersion43 bool //flag for indication on which API version is used (and accordingly which specific methods)
- mutexUpgradeParams sync.RWMutex
- imageVersion string //name of the image as used within OMCI (and on extrenal API interface)
- imageIdentifier string //name of the image as used in the adapter
+ useAPIVersion43 bool //flag for indication on which API version is used (and accordingly which specific methods)
+ mutexUpgradeParams sync.RWMutex //mutex to protect members for parallel function requests and omci response processing
+ imageVersion string //name of the image as used within OMCI (and on extrenal API interface)
+ imageIdentifier string //name of the image as used in the adapter
mutexIsAwaitingAdapterDlResponse sync.RWMutex
chAdapterDlReady chan bool
isWaitingForAdapterDlResponse bool
@@ -136,6 +136,9 @@
isWaitingForOnuDlResponse bool
activateImage bool
commitImage bool
+ volthaDownloadState voltha.ImageState_ImageDownloadState
+ volthaDownloadReason voltha.ImageState_ImageFailureReason
+ volthaImageState voltha.ImageState_ImageActivationState
}
//NewOnuUpgradeFsm is the 'constructor' for the state machine to config the PON ANI ports
@@ -154,6 +157,9 @@
omciSectionInterleaveDelay: cOmciSectionInterleaveMilliseconds,
waitCountEndSwDl: cWaitCountEndSwDl,
waitDelayEndSwDl: cWaitDelayEndSwDlSeconds,
+ 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,
}
instFsm.chReceiveExpectedResponse = make(chan bool)
instFsm.chAdapterDlReady = make(chan bool)
@@ -234,11 +240,13 @@
apImageDsc *voltha.ImageDownload, apDownloadManager *adapterDownloadManager) error {
pBaseFsm := oFsm.pAdaptFsm.pFsm
if pBaseFsm != nil && pBaseFsm.Is(upgradeStStarting) {
+ oFsm.mutexUpgradeParams.Lock()
logger.Debugw(ctx, "OnuUpgradeFsm Parameter setting", log.Fields{
"device-id": oFsm.deviceID, "image-description": apImageDsc})
oFsm.inactiveImageMeID = aInactiveImageID //upgrade state machines run on configured inactive ImageId
oFsm.pImageDsc = apImageDsc
oFsm.pDownloadManager = apDownloadManager
+ oFsm.mutexUpgradeParams.Unlock()
go func(aPBaseFsm *fsm.FSM) {
// let the upgrade FSM proceed to PreparingDL
@@ -406,6 +414,25 @@
return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
}
+//GetImageStates delivers the download states as per device proto buf or error indication
+func (oFsm *OnuUpgradeFsm) GetImageStates(ctx context.Context,
+ aImageIdentifier string, aVersion string) (*voltha.ImageState, error) {
+ pImageState := &voltha.ImageState{}
+ // check if the request refers to some active image/version of the processing
+ oFsm.mutexUpgradeParams.RLock()
+ if (aImageIdentifier == oFsm.imageIdentifier) || (aVersion == oFsm.imageVersion) {
+ pImageState.DownloadState = oFsm.volthaDownloadState
+ pImageState.Reason = oFsm.volthaDownloadReason
+ pImageState.ImageState = oFsm.volthaImageState
+ } else {
+ pImageState.DownloadState = voltha.ImageState_DOWNLOAD_UNKNOWN
+ pImageState.Reason = voltha.ImageState_NO_ERROR
+ pImageState.ImageState = voltha.ImageState_IMAGE_UNKNOWN
+ }
+ oFsm.mutexUpgradeParams.RUnlock()
+ return pImageState, nil
+}
+
//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
func (oFsm *OnuUpgradeFsm) CancelProcessing(ctx context.Context) {
//mutex protection is required for possible concurrent access to FSM members
@@ -460,6 +487,7 @@
var fileLen int64
var err error
+ oFsm.mutexUpgradeParams.Lock()
if oFsm.useAPIVersion43 {
//with the new API structure download to adapter is implicit and we have to wait until the image is available
fileLen, err = oFsm.pFileManager.GetImageBufferLen(ctx, oFsm.imageIdentifier)
@@ -467,6 +495,7 @@
fileLen, err = oFsm.pDownloadManager.getImageBufferLen(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
}
if err != nil || fileLen > int64(cMaxUint32) {
+ oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm abort: problems getting image buffer length", log.Fields{
"device-id": oFsm.deviceID, "error": err, "length": fileLen})
pBaseFsm := oFsm.pAdaptFsm
@@ -485,6 +514,7 @@
oFsm.imageBuffer, err = oFsm.pDownloadManager.getDownloadImageBuffer(ctx, oFsm.pImageDsc.Name, oFsm.pImageDsc.LocalDir)
}
if err != nil {
+ oFsm.mutexUpgradeParams.Unlock()
logger.Errorw(ctx, "OnuUpgradeFsm abort: can't get image buffer", log.Fields{
"device-id": oFsm.deviceID, "error": err})
pBaseFsm := oFsm.pAdaptFsm
@@ -504,13 +534,14 @@
}
oFsm.origImageLength = uint32(fileLen)
oFsm.imageLength = uint32(len(oFsm.imageBuffer))
-
- go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
-
logger.Infow(ctx, "OnuUpgradeFsm starts with StartSwDl values", log.Fields{
"MeId": oFsm.inactiveImageMeID, "windowSizeLimit": oFsm.omciDownloadWindowSizeLimit,
"ImageSize": oFsm.imageLength, "original file size": fileLen})
//"NumberOfCircuitPacks": oFsm.numberCircuitPacks, "CircuitPacks MeId": 0}) //parallel circuit packs download not supported
+
+ oFsm.mutexUpgradeParams.Unlock()
+ go oFsm.waitOnDownloadToOnuReady(ctx, oFsm.chOnuDlReady) // start supervision of the complete download-to-ONU procedure
+
err = oFsm.pOmciCC.sendStartSoftwareDownload(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, oFsm.omciDownloadWindowSizeLimit, oFsm.origImageLength)
if err != nil {
@@ -535,9 +566,11 @@
var bufferEndOffset uint32
var downloadSection []byte
framePrint := false //default no printing of downloadSection frames
+ oFsm.mutexUpgradeParams.Lock()
if oFsm.nextDownloadSectionsAbsolute == 0 {
//debug print of first section frame
framePrint = true
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_DOWNLOADING
}
for {
@@ -551,6 +584,7 @@
logger.Errorw(ctx, "OnuUpgradeFsm buffer error: exceeded length", log.Fields{
"device-id": oFsm.deviceID, "bufferStartOffset": bufferStartOffset,
"bufferEndOffset": bufferEndOffset, "imageLength": oFsm.imageLength})
+ oFsm.mutexUpgradeParams.Unlock()
//logical error -- reset the FSM
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
@@ -572,6 +606,7 @@
logger.Infow(ctx, "DlSection expect Response for last window (section)", log.Fields{
"device-id": oFsm.deviceID, "DlSectionNoAbsolute": oFsm.nextDownloadSectionsAbsolute})
}
+ oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
err := oFsm.pOmciCC.sendDownloadSection(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID, windowAckRequest, oFsm.nextDownloadSectionsWindow, downloadSection, framePrint)
if err != nil {
@@ -585,10 +620,12 @@
}(pBaseFsm)
return
}
+ oFsm.mutexUpgradeParams.Lock()
oFsm.nextDownloadSectionsAbsolute++ //always increase the absolute section counter after having sent one
if windowAckRequest == 1 {
pBaseFsm := oFsm.pAdaptFsm
// Can't call FSM Event directly, decoupling it
+ oFsm.mutexUpgradeParams.Unlock()
go func(a_pAFsm *AdapterFsm) {
_ = a_pAFsm.pFsm.Event(upgradeEvWaitWindowAck) //state transition to upgradeStVerifyWindow
}(pBaseFsm)
@@ -598,7 +635,9 @@
oFsm.nextDownloadSectionsWindow++ //increase the window related section counter only if not in the last section
if oFsm.omciSectionInterleaveDelay > 0 {
//ensure a defined intersection-time-gap to leave space for further processing, other ONU's ...
+ oFsm.mutexUpgradeParams.Unlock() //unlock here to give other functions some chance to process during/after the send request
time.Sleep(oFsm.omciSectionInterleaveDelay * time.Millisecond)
+ oFsm.mutexUpgradeParams.Lock()
}
}
}
@@ -612,10 +651,14 @@
logger.Infow(ctx, "OnuUpgradeFsm finalize DL", log.Fields{
"device-id": oFsm.deviceID, "crc": strconv.FormatInt(int64(oFsm.imageCRC), 16), "delay": oFsm.delayEndSwDl})
+ oFsm.mutexUpgradeParams.RLock()
if oFsm.delayEndSwDl {
+ oFsm.mutexUpgradeParams.RUnlock()
//give the ONU some time for image evaluation (hoping it does not base that on first EndSwDl itself)
// should not be set in case this state is used for real download abort (not yet implemented)
time.Sleep(cOmciEndSwDlDelaySeconds * time.Second)
+ } else {
+ oFsm.mutexUpgradeParams.RUnlock()
}
pBaseFsm := oFsm.pAdaptFsm
@@ -677,7 +720,9 @@
return
}
//retry End SW DL
+ oFsm.mutexUpgradeParams.Lock()
oFsm.delayEndSwDl = false //no more extra delay for the request
+ oFsm.mutexUpgradeParams.Unlock()
go func(a_pAFsm *AdapterFsm) {
_ = a_pAFsm.pFsm.Event(upgradeEvContinueFinalize)
}(pBaseFsm)
@@ -718,6 +763,10 @@
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 {
@@ -737,11 +786,15 @@
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
+ oFsm.mutexUpgradeParams.Lock()
if imageFit || activeImageID == oFsm.inactiveImageMeID {
+ inactiveImageID := oFsm.inactiveImageMeID
logger.Infow(ctx, "OnuUpgradeFsm commit SW", log.Fields{
- "device-id": oFsm.deviceID, "me-id": oFsm.inactiveImageMeID}) //more efficient activeImageID with above check
+ "device-id": oFsm.deviceID, "me-id": inactiveImageID}) //more efficient activeImageID with above check
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTING
+ oFsm.mutexUpgradeParams.Unlock()
err := oFsm.pOmciCC.sendCommitSoftware(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, false,
- oFsm.pAdaptFsm.commChan, oFsm.inactiveImageMeID) //more efficient activeImageID with above check
+ oFsm.pAdaptFsm.commChan, inactiveImageID) //more efficient activeImageID with above check
if err != nil {
logger.Errorw(ctx, "CommitSw abort: can't send commit sw frame", log.Fields{
"device-id": oFsm.deviceID, "error": err})
@@ -758,6 +811,8 @@
}
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
@@ -910,6 +965,8 @@
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
+
+ oFsm.mutexUpgradeParams.Lock()
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
logger.Debugw(ctx, "Expected StartSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
if msgObj.WindowSize != oFsm.omciDownloadWindowSizeLimit {
@@ -929,9 +986,11 @@
oFsm.nextDownloadSectionsWindow = 0
oFsm.nextDownloadWindow = 0
+ oFsm.mutexUpgradeParams.Unlock()
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvRxStartSwDownload)
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 start request (once)?
@@ -966,6 +1025,7 @@
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
+ oFsm.mutexUpgradeParams.Lock()
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
sectionNumber := msgObj.SectionNumber
logger.Infow(ctx, "DlSectionResponse received", log.Fields{
@@ -978,6 +1038,7 @@
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)
return
}
@@ -988,6 +1049,7 @@
var byteSlice []byte = make([]byte, 4)
binary.LittleEndian.PutUint32(byteSlice, uint32(imageCRC))
oFsm.imageCRC = binary.BigEndian.Uint32(byteSlice)
+ oFsm.mutexUpgradeParams.Unlock()
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvEndSwDownload)
return
}
@@ -995,14 +1057,17 @@
logger.Errorw(ctx, "OnuUpgradeFsm DlSectionResponse section error - later: repeat window once?", //TODO!!!
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)
return
}
oFsm.nextDownloadSectionsWindow = 0
+ oFsm.mutexUpgradeParams.Unlock()
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvContinueNextWindow)
return
}
+ 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)?
@@ -1044,7 +1109,9 @@
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
+ oFsm.mutexUpgradeParams.RLock()
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
+ oFsm.mutexUpgradeParams.RUnlock()
logger.Debugw(ctx, "Expected EndSwDlResponse received", log.Fields{"device-id": oFsm.deviceID})
oFsm.mutexIsAwaitingOnuDlResponse.RLock()
if oFsm.isWaitingForOnuDlResponse {
@@ -1057,6 +1124,7 @@
oFsm.chReceiveExpectedResponse <- true //let the FSM proceed from the waitState
return
}
+ oFsm.mutexUpgradeParams.RUnlock()
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?
@@ -1092,11 +1160,14 @@
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
return
}
+ oFsm.mutexUpgradeParams.RLock()
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
+ oFsm.mutexUpgradeParams.RUnlock()
logger.Infow(ctx, "Expected ActivateSwResponse received", log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvWaitForCommit)
return
}
+ oFsm.mutexUpgradeParams.RUnlock()
logger.Errorw(ctx, "OnuUpgradeFsm ActivateSwResponse wrong ME instance: abort",
log.Fields{"device-id": oFsm.deviceID, "ResponseMeId": msgObj.EntityInstance})
// TODO!!!: error treatment?
@@ -1128,12 +1199,15 @@
// TODO!!!: error treatment?, perhaps in the end reset the FSM
return
}
+ oFsm.mutexUpgradeParams.RLock()
if msgObj.EntityInstance == oFsm.inactiveImageMeID {
+ oFsm.mutexUpgradeParams.RUnlock()
logger.Debugw(ctx, "OnuUpgradeFsm Expected SwImage CommitResponse received", log.Fields{"device-id": oFsm.deviceID})
//verifying committed image
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvCheckCommitted)
return
}
+ 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?
@@ -1184,8 +1258,9 @@
logger.Debugw(ctx, "OnuUpgradeFsm - GetResponse Data for SoftwareImage",
log.Fields{"device-id": oFsm.deviceID, "entityID": msgObj.EntityInstance,
"version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted})
- if msgObj.EntityInstance == oFsm.inactiveImageMeID && imageIsActive == swIsActive &&
- imageIsCommitted == swIsCommitted {
+
+ oFsm.mutexUpgradeParams.Lock()
+ 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)
// so checking that might be quite unreliable
@@ -1197,6 +1272,7 @@
logger.Errorw(ctx, "OnuUpgradeFsm SwImage GetResponse indications not matching 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)??
_ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvAbort)
@@ -1205,11 +1281,21 @@
logger.Debugw(ctx, "OnuUpgradeFsm - expected ONU image version indicated by the ONU",
log.Fields{"device-id": oFsm.deviceID})
}
- logger.Infow(ctx, "requested SW image committed, releasing OnuUpgrade", log.Fields{"device-id": oFsm.deviceID})
- //releasing the upgrade FSM
- _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvReset)
- return
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_ACTIVE
+ if imageIsCommitted == swIsCommitted {
+ oFsm.volthaDownloadState = voltha.ImageState_DOWNLOAD_SUCCEEDED
+ oFsm.volthaImageState = voltha.ImageState_IMAGE_COMMITTED
+ 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
+ oFsm.mutexUpgradeParams.Unlock()
+ //releasing the upgrade FSM
+ _ = oFsm.pAdaptFsm.pFsm.Event(upgradeEvReset)
+ 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
}
+ 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?
diff --git a/internal/pkg/onuadaptercore/openonu.go b/internal/pkg/onuadaptercore/openonu.go
index c7f3e85..805944c 100644
--- a/internal/pkg/onuadaptercore/openonu.go
+++ b/internal/pkg/onuadaptercore/openonu.go
@@ -700,12 +700,127 @@
// Get_onu_image_status delivers the adapter-related information about the download/activation/commitment
// status for the requested image
func (oo *OpenONUAC) Get_onu_image_status(ctx context.Context, in *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
- return nil, errors.New("unImplemented")
+ if in != nil && len((*in).DeviceId) > 0 && (*in).Version != "" {
+ loResponse := voltha.DeviceImageResponse{}
+ pDlToAdapterImageState := &voltha.ImageState{}
+ imageIdentifier := (*in).Version
+ firstDevice := true
+ var vendorID string
+ for _, pCommonID := range (*in).DeviceId {
+ 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 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
+ }
+ }
+ 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)
+ } 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
+ }
+ loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, pDeviceImageState)
+ }
+ pImageResp := &loResponse
+ return pImageResp, nil
+ }
+ return nil, errors.New("invalid image status request parameters")
}
// Abort_onu_image_upgrade stops the actual download/activation/commitment process (on next possibly step)
func (oo *OpenONUAC) Abort_onu_image_upgrade(ctx context.Context, in *voltha.DeviceImageRequest) (*voltha.DeviceImageResponse, error) {
- return nil, errors.New("unImplemented")
+ if in != nil && len((*in).DeviceId) > 0 && (*in).Version != "" {
+ loResponse := voltha.DeviceImageResponse{}
+ imageIdentifier := (*in).Version
+ firstDevice := true
+ var vendorID string
+ for _, pCommonID := range (*in).DeviceId {
+ 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 to abort its download",
+ log.Fields{"device-id": loDeviceID, "err": err})
+ continue //try the work with next deviceId
+ }
+ pDeviceImageState := &voltha.DeviceImageState{}
+ if firstDevice {
+ //start/verify download of the image to the adapter based on first found device only
+ // use the OnuVendor identification from first given device
+ firstDevice = false
+ vendorID = onuVolthaDevice.VendorId
+ imageIdentifier = vendorID + imageIdentifier //head on vendor ID of the ONU
+ logger.Debugw(ctx, "abort request for file", log.Fields{"image-id": imageIdentifier})
+ } else {
+ //for all following devices verify the matching vendorID
+ if onuVolthaDevice.VendorId != vendorID {
+ logger.Warnw(ctx, "onu vendor id does not match image vendor id, device ignored",
+ log.Fields{"onu-vendor-id": onuVolthaDevice.VendorId, "image-vendor-id": vendorID})
+ continue //try the work with next deviceId
+ }
+ }
+
+ // cancel the ONU upgrade activity for each possible device
+ if handler := oo.getDeviceHandler(ctx, loDeviceID, false); handler != nil {
+ logger.Debugw(ctx, "image upgrade abort requested", log.Fields{
+ "image-id": imageIdentifier, "device-id": loDeviceID})
+ //upgrade cancel is called synchronously to collect the imageResponse indications for all concerned devices
+ handler.cancelOnuSwUpgrade(ctx, imageIdentifier, (*in).Version, pDeviceImageState)
+ } else {
+ //cannot start 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.ImageState = voltha.ImageState_IMAGE_UNKNOWN
+ }
+ loResponse.DeviceImageStates = append(loResponse.DeviceImageStates, pDeviceImageState)
+ }
+ if !firstDevice {
+ //if at least one valid device was found cancel also a possibly running download to adapter and remove the image
+ // this is to be done after the upgradeOnu cancel activities in order to not subduct the file for still running processes
+ oo.pFileManager.CancelDownload(ctx, imageIdentifier)
+ }
+ pImageResp := &loResponse
+ return pImageResp, nil
+ }
+ return nil, errors.New("invalid image upgrade abort parameters")
}
// Get_onu_images retrieves the ONU SW image status information via OMCI