support Onu upgrade also if ActivateResponse is lost or even not generated by the ONU (but correctly started)

Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I49fbe61e5965d7e730d211baca5f9412a6c880a6
diff --git a/VERSION b/VERSION
index c725c59..a8cbc32 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.2-dev213
+1.3.2-dev214
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index b06c0e7..ff18216 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -21,11 +21,12 @@
 	"context"
 	"errors"
 	"fmt"
-	"github.com/opencord/voltha-protos/v4/go/tech_profile"
 	"strconv"
 	"sync"
 	"time"
 
+	"github.com/opencord/voltha-protos/v4/go/tech_profile"
+
 	"github.com/gogo/protobuf/proto"
 	"github.com/golang/protobuf/ptypes"
 	"github.com/looplab/fsm"
@@ -2718,15 +2719,43 @@
 		if pUpgradeStatemachine != nil {
 			// commit is only processed in case out upgrade FSM indicates the according state (for automatic commit)
 			//  (some manual forced commit could do without)
-			if pUpgradeStatemachine.Is(upgradeStWaitForCommit) {
+			upgradeState := pUpgradeStatemachine.Current()
+			if (upgradeState == upgradeStWaitForCommit) ||
+				(upgradeState == upgradeStRequestingActivate) {
+				// also include upgradeStRequestingActivate as it may be left in case the ActivateResponse just got lost
 				// here no need to update the upgrade image state to activated as the state will be immediately be set to committing
 				if pDevEntry.IsImageToBeCommitted(ctx, dh.pOnuUpradeFsm.inactiveImageMeID) {
-					if err := pUpgradeStatemachine.Event(upgradeEvCommitSw); err != nil {
-						logger.Errorw(ctx, "OnuSwUpgradeFSM: can't call commit event", log.Fields{"err": err})
+					activeImageID, errImg := pDevEntry.GetActiveImageMeID(ctx)
+					if errImg != nil {
+						logger.Errorw(ctx, "OnuSwUpgradeFSM abort - could not get active image after reboot",
+							log.Fields{"device-id": dh.deviceID})
+						_ = pUpgradeStatemachine.Event(upgradeEvAbort)
 						return
 					}
-					logger.Debugw(ctx, "OnuSwUpgradeFSM commit image requested", log.Fields{
-						"state": pUpgradeStatemachine.Current(), "device-id": dh.deviceID})
+					if activeImageID == dh.pOnuUpradeFsm.inactiveImageMeID {
+						if (upgradeState == upgradeStRequestingActivate) && !dh.pOnuUpradeFsm.GetCommitFlag(ctx) {
+							// if FSM was waiting on activateResponse, new image is active, but FSM shall not commit, then:
+							if err := pUpgradeStatemachine.Event(upgradeEvActivationDone); err != nil {
+								logger.Errorw(ctx, "OnuSwUpgradeFSM: can't call activate-done event", log.Fields{"err": err})
+								return
+							}
+							logger.Debugw(ctx, "OnuSwUpgradeFSM activate-done after reboot", log.Fields{
+								"state": upgradeState, "device-id": dh.deviceID})
+						} else {
+							//FSM in waitForCommit or (upgradeStRequestingActivate [lost ActivateResp] and commit allowed)
+							if err := pUpgradeStatemachine.Event(upgradeEvCommitSw); err != nil {
+								logger.Errorw(ctx, "OnuSwUpgradeFSM: can't call commit event", log.Fields{"err": err})
+								return
+							}
+							logger.Debugw(ctx, "OnuSwUpgradeFSM commit image requested", log.Fields{
+								"state": upgradeState, "device-id": dh.deviceID})
+						}
+					} 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)
+						return
+					}
 				} else {
 					logger.Errorw(ctx, "OnuSwUpgradeFSM waiting to commit, but nothing to commit on ONU - abort upgrade",
 						log.Fields{"device-id": dh.deviceID})
diff --git a/internal/pkg/onuadaptercore/omci_onu_upgrade.go b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
index 4f0ac62..88101b3 100644
--- a/internal/pkg/onuadaptercore/omci_onu_upgrade.go
+++ b/internal/pkg/onuadaptercore/omci_onu_upgrade.go
@@ -191,8 +191,8 @@
 				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, upgradeStWaitForCommit, upgradeStActivated},
-				Dst: upgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
+			{Name: upgradeEvCommitSw, Src: []string{upgradeStStarting, upgradeStRequestingActivate, upgradeStWaitForCommit,
+				upgradeStActivated}, Dst: upgradeStCommitSw}, //allows also for direct commitment (without download) [TODO!!!]
 			{Name: upgradeEvCheckCommitted, Src: []string{upgradeStCommitSw}, Dst: upgradeStCheckCommitted},
 
 			/*
@@ -202,10 +202,11 @@
 					upgradeStCreatingGemNCTPs, upgradeStCreatingGemIWs, upgradeStSettingPQs}, Dst: upgradeStStarting},
 			*/
 			// exceptional treatments
-			//on upgradeEvReset: upgradeStWaitForCommit and upgradeStActivated are not reset (to let the FSM survive the expected OnuDown indication)
+			//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,
-				upgradeStRequestingActivate, upgradeStCommitSw, upgradeStCheckCommitted},
+				upgradeStCommitSw, upgradeStCheckCommitted},
 				Dst: upgradeStResetting},
 			{Name: upgradeEvAbort, Src: []string{upgradeStStarting, upgradeStWaitingAdapterDL, upgradeStPreparingDL, upgradeStDLSection,
 				upgradeStVerifyWindow, upgradeStDLSection, upgradeStFinalizeDL, upgradeStWaitEndDL, upgradeStWaitForActivate,
@@ -422,6 +423,13 @@
 	return fmt.Errorf(fmt.Sprintf("OnuUpgradeFsm abort: invalid FSM base pointer or state for device-id: %s", oFsm.deviceID))
 }
 
+//GetCommitFlag delivers the commit flag that was configured here
+func (oFsm *OnuUpgradeFsm) GetCommitFlag(ctx context.Context) bool {
+	oFsm.mutexUpgradeParams.RLock()
+	defer oFsm.mutexUpgradeParams.RUnlock()
+	return oFsm.commitImage
+}
+
 //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) {
@@ -464,8 +472,7 @@
 	//chOnuDlReady is cleared as part of the FSM reset processing (from enterResetting())
 
 	// in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
-	// specific here: If the FSM is in upgradeStWaitForCommit, it is left there for possibly later commit
-	// this possibly also refers later to (not yet existing) upgradeStWaitForActivate (with ctl API changes)
+	// specific here: See definition of state changes: some states are excluded from reset for possible later commit
 	pAdaptFsm := oFsm.pAdaptFsm
 	if pAdaptFsm != nil {
 		// calling FSM events in background to avoid blocking of the caller