Skip to content

Commit

Permalink
[#78] New status DOWNLOADED_FILE_STORED is added at the end of downlo…
Browse files Browse the repository at this point in the history
…ad success with reporting downloaded path in it

Signed-off-by: Mahesha Mutharayappa (SDS/EPE2) <[email protected]>
  • Loading branch information
Mahesha-M committed Feb 14, 2025
1 parent aceebb9 commit b4406cc
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 31 deletions.
3 changes: 3 additions & 0 deletions hawkbit/lib_software_module_id.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package hawkbit
const (
softwareModuleNameParam = "name"
softwareModuleVersionParam = "version"
softwareModuleStoredPath = "path"
)

// SoftwareModuleID represents an unique identifier for software modules.
Expand All @@ -24,4 +25,6 @@ type SoftwareModuleID struct {
Name string `json:"name"`
// Version of the software module.
Version string `json:"version"`
// Stored downloaded file path
Path string `json:"path,omitempty"`
}
35 changes: 18 additions & 17 deletions hawkbit/lib_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,22 @@ type Status string

// Supported operation statuses.
const (
StatusStarted Status = "STARTED"
StatusDownloading Status = "DOWNLOADING"
StatusDownloadingWaiting Status = "DOWNLOADING_WAITING"
StatusDownloaded Status = "DOWNLOADED"
StatusInstalling Status = "INSTALLING"
StatusInstallingWaiting Status = "INSTALLING_WAITING"
StatusInstalled Status = "INSTALLED"
StatusRemoving Status = "REMOVING"
StatusRemovingWaiting Status = "REMOVING_WAITING"
StatusRemoved Status = "REMOVED"
StatusCancelingWaiting Status = "CANCELING_WAITING"
StatusCancelRejected Status = "CANCEL_REJECTED"
StatusFinishedCanceled Status = "FINISHED_CANCELED"
StatusFinishedError Status = "FINISHED_ERROR"
StatusFinishedSuccess Status = "FINISHED_SUCCESS"
StatusFinishedWarning Status = "FINISHED_WARNING"
StatusFinishedRejected Status = "FINISHED_REJECTED"
StatusStarted Status = "STARTED"
StatusDownloading Status = "DOWNLOADING"
StatusDownloadingWaiting Status = "DOWNLOADING_WAITING"
StatusDownloaded Status = "DOWNLOADED"
StatusDownloadedFileStored Status = "DOWNLOADED_FILE_STORED"
StatusInstalling Status = "INSTALLING"
StatusInstallingWaiting Status = "INSTALLING_WAITING"
StatusInstalled Status = "INSTALLED"
StatusRemoving Status = "REMOVING"
StatusRemovingWaiting Status = "REMOVING_WAITING"
StatusRemoved Status = "REMOVED"
StatusCancelingWaiting Status = "CANCELING_WAITING"
StatusCancelRejected Status = "CANCEL_REJECTED"
StatusFinishedCanceled Status = "FINISHED_CANCELED"
StatusFinishedError Status = "FINISHED_ERROR"
StatusFinishedSuccess Status = "FINISHED_SUCCESS"
StatusFinishedWarning Status = "FINISHED_WARNING"
StatusFinishedRejected Status = "FINISHED_REJECTED"
)
13 changes: 12 additions & 1 deletion hawkbit/software_updatable.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,16 @@ func MapLastOperation(LastOperationPtr *OperationStatus) map[string]interface{}
lastOperationMap[statusParam] = LastOperationPtr.Status

if LastOperationPtr.SoftwareModule != nil {
lastOperationMap[softwareModuleParam] = map[string]interface{}{
innerMap := map[string]interface{}{
softwareModuleNameParam: LastOperationPtr.SoftwareModule.Name,
softwareModuleVersionParam: LastOperationPtr.SoftwareModule.Version,
}

if LastOperationPtr.SoftwareModule.Path != "" {
innerMap[softwareModuleStoredPath] = LastOperationPtr.SoftwareModule.Path
}

lastOperationMap[softwareModuleParam] = innerMap
}

if LastOperationPtr.Software != nil {
Expand Down Expand Up @@ -195,3 +201,8 @@ func (su *SoftwareUpdatable) SetLastOperation(os *OperationStatus) error {
}
return su.setProperty(suPropertyLastOperation, MapLastOperation(su.status.LastOperation))
}

// GetLastStatus returns the recorded last operation status
func (su *SoftwareUpdatable) GetLastStatus() *softwareUpdatableStatus {
return su.status
}
11 changes: 8 additions & 3 deletions internal/feature_download.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,14 @@ func (f *ScriptBasedSoftwareUpdatable) downloadModules(
}

// Archive all modules.
for i, module := range updatable.Modules {
if err := f.store.ArchiveModule(filepath.Join(toDir, strconv.Itoa(i))); err != nil {
logger.Errorf("failed to archive module [%s.%s]: %v", module.Name, module.Version, err)
if su.GetLastStatus().LastOperation.Status == hawkbit.StatusFinishedSuccess {
for i, module := range updatable.Modules {
if err := f.store.ArchiveModule(filepath.Join(toDir, strconv.Itoa(i)), &module.Path); err != nil {
logger.Errorf("failed to archive module [%s.%s]: %v", module.Name, module.Version, err)
} else {
logger.Debugf("Archived downloaded file path: %s", module.Path)
setLastOS(su, newOS(updatable.CorrelationID, module, hawkbit.StatusDownloadedFileStored))
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/feature_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ func (f *ScriptBasedSoftwareUpdatable) fail(cid string, modules []*hawkbit.Softw
// newOS returns newly created OperationStatus pointer.
func newOS(cid string, module *storage.Module, status hawkbit.Status) *hawkbit.OperationStatus {
return hawkbit.NewOperationStatusUpdate(cid, status,
&hawkbit.SoftwareModuleID{Name: module.Name, Version: module.Version})
&hawkbit.SoftwareModuleID{Name: module.Name, Version: module.Version, Path: module.Path})
}

// newFileOS returns newly created OperationStatus pointer, filled with the status file data.
Expand Down
26 changes: 19 additions & 7 deletions internal/feature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,18 @@ func testDisconnectWhileRunningOperation(feature *ScriptBasedSoftwareUpdatable,
postDisconnectEventCount := 3 // DOWNLOADING(100)/INSTALLING(100), DOWNLOADED(100)/INSTALLED(100), FINISHED_SUCCESS
if install {
preDisconnectEventCount = 5 // STARTED, DOWNLOADING(0), DOWNLOADING(100), DOWNLOADED(100), INSTALLING(0)
} else {
postDisconnectEventCount += 1 //DOWNLOADED_FILE_STORED
}
statuses := pullStatusChanges(mc, preDisconnectEventCount) // should go between DOWNLOADING/INSTALLING and next state

statuses := pullStatusChanges(mc, install, preDisconnectEventCount) // should go between DOWNLOADING/INSTALLING and next state

go func() { // decrements count number with 1, when disconnected
feature.Disconnect(false)
waitDisconnect.Done()
}()

statuses = append(statuses, pullStatusChanges(mc, postDisconnectEventCount)...)
statuses = append(statuses, pullStatusChanges(mc, install, postDisconnectEventCount)...)
waitDisconnect.Wait()
defer connectFeature(t, mc, feature, NewDefaultConfig().FeatureID)
if install {
Expand Down Expand Up @@ -310,13 +313,19 @@ func testScriptBasedSoftwareUpdatableOperationsLocal(t *testing.T, installDirs [
testDownloadInstall(feature, mc, artifacts, expectedSuccess, copyArtifacts, t)
}

func pullStatusChanges(mc *mockedClient, expectedCount int) []interface{} {
func pullStatusChanges(mc *mockedClient, install bool, expectedCount int) []interface{} {
var statuses []interface{}
for i := 0; i < expectedCount; i++ {
lo := mc.pullLastOperationStatus()
statuses = append(statuses, lo)
if lo["status"] == string(hawkbit.StatusFinishedSuccess) || lo["status"] == string(hawkbit.StatusFinishedError) {
break
if install {
if lo["status"] == string(hawkbit.StatusFinishedSuccess) || lo["status"] == string(hawkbit.StatusFinishedError) {
break
}
} else {
if lo["status"] == string(hawkbit.StatusDownloadedFileStored) || lo["status"] == string(hawkbit.StatusFinishedError) {
break
}
}
}
return statuses
Expand All @@ -334,7 +343,8 @@ func testDownloadInstall(feature *ScriptBasedSoftwareUpdatable, mc *mockedClient
// Try to execute a simple download operation.
feature.downloadHandler(sua, feature.su)

statuses := pullStatusChanges(mc, 5+extraDownloadingEventsCount) // STARTED, DOWNLOADING(0), DOWNLOADING(x extraDownloadingEventsCount), DOWNLOADING(100), DOWNLOADED(100), FINISHED_SUCCESS
statuses := pullStatusChanges(mc, false, 6+extraDownloadingEventsCount) // STARTED, DOWNLOADING(0), DOWNLOADING(x extraDownloadingEventsCount),
// DOWNLOADING(100), DOWNLOADED(100), FINISHED_SUCCESS, DOWNLOADED_FILE_STORED
if expectedSuccess {
checkDownloadStatusEvents(extraDownloadingEventsCount, statuses, t)
if copyArtifacts == "" {
Expand All @@ -349,7 +359,8 @@ func testDownloadInstall(feature *ScriptBasedSoftwareUpdatable, mc *mockedClient
// Try to execute a simple install operation.
feature.installHandler(sua, feature.su)

statuses = pullStatusChanges(mc, 8+extraDownloadingEventsCount) // STARTED, DOWNLOADING(0), DOWNLOADING(x extraDownloadingEventsCount), DOWNLOADING(100), DOWNLOADED(100),
statuses = pullStatusChanges(mc, true, 8+extraDownloadingEventsCount) // STARTED, DOWNLOADING(0), DOWNLOADING(x extraDownloadingEventsCount),
//DOWNLOADING(100), DOWNLOADED(100),
// INSTALLING(0), INSTALLING(100), INSTALLED(100), FINISHED_SUCCESS
if expectedSuccess {
checkInstallStatusEvents(extraDownloadingEventsCount, statuses, t)
Expand Down Expand Up @@ -391,6 +402,7 @@ func checkDownloadStatusEvents(extraDownloadingEventsCount int, actualStatuses [
createStatus(hawkbit.StatusDownloading, completeProgress, noMessage),
createStatus(hawkbit.StatusDownloaded, completeProgress, noMessage),
createStatus(hawkbit.StatusFinishedSuccess, nil, noMessage),
createStatus(hawkbit.StatusDownloadedFileStored, nil, noMessage),
)
checkStatusEvents(expectedStatuses, actualStatuses, t)
}
Expand Down
4 changes: 3 additions & 1 deletion internal/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type Updatable struct {
type Module struct {
Name string `json:"name"`
Version string `json:"version"`
Path string `json:"path,omitempty"`
Artifacts []*Artifact `json:"artifacts,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
Expand Down Expand Up @@ -212,12 +213,13 @@ func (st *Storage) MoveInstalledDeps(dir string, metadata map[string]string) err
}

// ArchiveModule to modules directory.
func (st *Storage) ArchiveModule(dir string) error {
func (st *Storage) ArchiveModule(dir string, dest *string) error {
logger.Debugf("Archive module from directory: %s", dir)
path, err := FindAvailableLocation(st.ModulesPath)
if err != nil {
return err
}
*dest = path
if err := os.MkdirAll(path, 0755); err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion internal/storage/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,11 @@ func TestDownloadArchiveModule(t *testing.T) {
existence(filepath.Join(path, art.FileName), true, "[initial download]", t)

// 2. Archive module.
storedPath := ""
if err := WriteLn(filepath.Join(path, InternalStatusName), m.Name+":"+m.Version); err != nil {
t.Fatalf("fail to write module id: %v", err)
}
if err := store.ArchiveModule(path); err != nil {
if err := store.ArchiveModule(path, &storedPath); err != nil {
t.Fatalf("fail to archive module: %v", err)
}
existence(filepath.Join(store.ModulesPath, "0", art.FileName), true, "[archive]", t)
Expand Down

0 comments on commit b4406cc

Please sign in to comment.