mirror of https://github.com/jetkvm/kvm.git
cleanup: ota state
This commit is contained in:
parent
2447e8fff2
commit
9e8ada32b3
|
|
@ -27,14 +27,14 @@ func (s *State) updateApp(ctx context.Context, appUpdate *componentUpdateStatus)
|
||||||
|
|
||||||
l := s.l.With().Str("path", appUpdatePath).Logger()
|
l := s.l.With().Str("path", appUpdatePath).Logger()
|
||||||
|
|
||||||
if err := s.downloadFile(ctx, appUpdatePath, appUpdate.url, &appUpdate.downloadProgress); err != nil {
|
if err := s.downloadFile(ctx, appUpdatePath, appUpdate.url, "app"); err != nil {
|
||||||
return s.componentUpdateError("Error downloading app update", err, &l)
|
return s.componentUpdateError("Error downloading app update", err, &l)
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadFinished := time.Now()
|
downloadFinished := time.Now()
|
||||||
appUpdate.downloadFinishedAt = downloadFinished
|
appUpdate.downloadFinishedAt = downloadFinished
|
||||||
appUpdate.downloadProgress = 1
|
appUpdate.downloadProgress = 1
|
||||||
s.triggerStateUpdate()
|
s.triggerComponentUpdateState("app", appUpdate)
|
||||||
|
|
||||||
if err := s.verifyFile(
|
if err := s.verifyFile(
|
||||||
appUpdatePath,
|
appUpdatePath,
|
||||||
|
|
@ -48,7 +48,7 @@ func (s *State) updateApp(ctx context.Context, appUpdate *componentUpdateStatus)
|
||||||
appUpdate.verificationProgress = 1
|
appUpdate.verificationProgress = 1
|
||||||
appUpdate.updatedAt = verifyFinished
|
appUpdate.updatedAt = verifyFinished
|
||||||
appUpdate.updateProgress = 1
|
appUpdate.updateProgress = 1
|
||||||
s.triggerStateUpdate()
|
s.triggerComponentUpdateState("app", appUpdate)
|
||||||
|
|
||||||
l.Info().Msg("App update downloaded")
|
l.Info().Msg("App update downloaded")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,11 @@ func (s *State) triggerStateUpdate() {
|
||||||
s.onStateUpdate(s.ToRPCState())
|
s.onStateUpdate(s.ToRPCState())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *State) triggerComponentUpdateState(component string, update *componentUpdateStatus) {
|
||||||
|
s.componentUpdateStatuses[component] = *update
|
||||||
|
s.triggerStateUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *State) doUpdate(ctx context.Context, params UpdateParams) error {
|
func (s *State) doUpdate(ctx context.Context, params UpdateParams) error {
|
||||||
scopedLogger := s.l.With().
|
scopedLogger := s.l.With().
|
||||||
Interface("params", params).
|
Interface("params", params).
|
||||||
|
|
@ -102,32 +107,35 @@ func (s *State) doUpdate(ctx context.Context, params UpdateParams) error {
|
||||||
return fmt.Errorf("update already in progress")
|
return fmt.Errorf("update already in progress")
|
||||||
}
|
}
|
||||||
|
|
||||||
s.updating = true
|
if !params.CheckOnly {
|
||||||
s.triggerStateUpdate()
|
s.updating = true
|
||||||
|
|
||||||
defer func() {
|
|
||||||
s.updating = false
|
|
||||||
s.triggerStateUpdate()
|
s.triggerStateUpdate()
|
||||||
}()
|
defer func() {
|
||||||
|
s.updating = false
|
||||||
|
s.triggerStateUpdate()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
appUpdate, systemUpdate, err := s.getUpdateStatus(ctx, params)
|
appUpdate, systemUpdate, err := s.getUpdateStatus(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return s.componentUpdateError("Error checking for updates", err, &scopedLogger)
|
return s.componentUpdateError("Error checking for updates", err, &scopedLogger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.metadataFetchedAt = time.Now()
|
||||||
|
s.triggerStateUpdate()
|
||||||
|
|
||||||
if params.CheckOnly {
|
if params.CheckOnly {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
s.metadataFetchedAt = time.Now()
|
|
||||||
s.triggerStateUpdate()
|
|
||||||
|
|
||||||
if appUpdate.available || appUpdate.downgradeAvailable {
|
if appUpdate.available || appUpdate.downgradeAvailable {
|
||||||
appUpdate.pending = true
|
appUpdate.pending = true
|
||||||
|
s.triggerComponentUpdateState("app", appUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
if systemUpdate.available || systemUpdate.downgradeAvailable {
|
if systemUpdate.available || systemUpdate.downgradeAvailable {
|
||||||
systemUpdate.pending = true
|
systemUpdate.pending = true
|
||||||
|
s.triggerComponentUpdateState("system", systemUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
if appUpdate.pending {
|
if appUpdate.pending {
|
||||||
|
|
|
||||||
|
|
@ -67,25 +67,25 @@ type componentUpdateStatus struct {
|
||||||
|
|
||||||
// RPCState represents the current OTA state for the RPC API
|
// RPCState represents the current OTA state for the RPC API
|
||||||
type RPCState struct {
|
type RPCState struct {
|
||||||
Updating bool `json:"updating"`
|
Updating bool `json:"updating"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
MetadataFetchedAt time.Time `json:"metadataFetchedAt,omitempty"`
|
MetadataFetchedAt *time.Time `json:"metadataFetchedAt,omitempty"`
|
||||||
AppUpdatePending bool `json:"appUpdatePending"`
|
AppUpdatePending bool `json:"appUpdatePending"`
|
||||||
SystemUpdatePending bool `json:"systemUpdatePending"`
|
SystemUpdatePending bool `json:"systemUpdatePending"`
|
||||||
AppDownloadProgress float32 `json:"appDownloadProgress,omitempty"` //TODO: implement for progress bar
|
AppDownloadProgress *float32 `json:"appDownloadProgress,omitempty"` //TODO: implement for progress bar
|
||||||
AppDownloadFinishedAt time.Time `json:"appDownloadFinishedAt,omitempty"`
|
AppDownloadFinishedAt *time.Time `json:"appDownloadFinishedAt,omitempty"`
|
||||||
SystemDownloadProgress float32 `json:"systemDownloadProgress,omitempty"` //TODO: implement for progress bar
|
SystemDownloadProgress *float32 `json:"systemDownloadProgress,omitempty"` //TODO: implement for progress bar
|
||||||
SystemDownloadFinishedAt time.Time `json:"systemDownloadFinishedAt,omitempty"`
|
SystemDownloadFinishedAt *time.Time `json:"systemDownloadFinishedAt,omitempty"`
|
||||||
AppVerificationProgress float32 `json:"appVerificationProgress,omitempty"`
|
AppVerificationProgress *float32 `json:"appVerificationProgress,omitempty"`
|
||||||
AppVerifiedAt time.Time `json:"appVerifiedAt,omitempty"`
|
AppVerifiedAt *time.Time `json:"appVerifiedAt,omitempty"`
|
||||||
SystemVerificationProgress float32 `json:"systemVerificationProgress,omitempty"`
|
SystemVerificationProgress *float32 `json:"systemVerificationProgress,omitempty"`
|
||||||
SystemVerifiedAt time.Time `json:"systemVerifiedAt,omitempty"`
|
SystemVerifiedAt *time.Time `json:"systemVerifiedAt,omitempty"`
|
||||||
AppUpdateProgress float32 `json:"appUpdateProgress,omitempty"` //TODO: implement for progress bar
|
AppUpdateProgress *float32 `json:"appUpdateProgress,omitempty"` //TODO: implement for progress bar
|
||||||
AppUpdatedAt time.Time `json:"appUpdatedAt,omitempty"`
|
AppUpdatedAt *time.Time `json:"appUpdatedAt,omitempty"`
|
||||||
SystemUpdateProgress float32 `json:"systemUpdateProgress,omitempty"` //TODO: port rk_ota, then implement
|
SystemUpdateProgress *float32 `json:"systemUpdateProgress,omitempty"` //TODO: port rk_ota, then implement
|
||||||
SystemUpdatedAt time.Time `json:"systemUpdatedAt,omitempty"`
|
SystemUpdatedAt *time.Time `json:"systemUpdatedAt,omitempty"`
|
||||||
SystemTargetVersion string `json:"systemTargetVersion,omitempty"`
|
SystemTargetVersion *string `json:"systemTargetVersion,omitempty"`
|
||||||
AppTargetVersion string `json:"appTargetVersion,omitempty"`
|
AppTargetVersion *string `json:"appTargetVersion,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HwRebootFunc is a function that reboots the hardware
|
// HwRebootFunc is a function that reboots the hardware
|
||||||
|
|
@ -221,35 +221,48 @@ func NewState(opts Options) *State {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToRPCState converts the State to the RPCState
|
// ToRPCState converts the State to the RPCState
|
||||||
|
// probably we need a generator for this ...
|
||||||
func (s *State) ToRPCState() *RPCState {
|
func (s *State) ToRPCState() *RPCState {
|
||||||
r := &RPCState{
|
r := &RPCState{
|
||||||
Updating: s.updating,
|
Updating: s.updating,
|
||||||
Error: s.error,
|
Error: s.error,
|
||||||
MetadataFetchedAt: s.metadataFetchedAt,
|
MetadataFetchedAt: &s.metadataFetchedAt,
|
||||||
}
|
}
|
||||||
|
|
||||||
app, ok := s.componentUpdateStatuses["app"]
|
app, ok := s.componentUpdateStatuses["app"]
|
||||||
if ok {
|
if ok {
|
||||||
r.AppUpdatePending = app.pending
|
r.AppUpdatePending = app.pending
|
||||||
r.AppDownloadProgress = app.downloadProgress
|
r.AppDownloadProgress = &app.downloadProgress
|
||||||
r.AppDownloadFinishedAt = app.downloadFinishedAt
|
if !app.downloadFinishedAt.IsZero() {
|
||||||
r.AppVerificationProgress = app.verificationProgress
|
r.AppDownloadFinishedAt = &app.downloadFinishedAt
|
||||||
r.AppVerifiedAt = app.verifiedAt
|
}
|
||||||
r.AppUpdateProgress = app.updateProgress
|
r.AppVerificationProgress = &app.verificationProgress
|
||||||
r.AppUpdatedAt = app.updatedAt
|
if !app.verifiedAt.IsZero() {
|
||||||
r.AppTargetVersion = app.targetVersion
|
r.AppVerifiedAt = &app.verifiedAt
|
||||||
|
}
|
||||||
|
r.AppUpdateProgress = &app.updateProgress
|
||||||
|
if !app.updatedAt.IsZero() {
|
||||||
|
r.AppUpdatedAt = &app.updatedAt
|
||||||
|
}
|
||||||
|
r.AppTargetVersion = &app.targetVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
system, ok := s.componentUpdateStatuses["system"]
|
system, ok := s.componentUpdateStatuses["system"]
|
||||||
if ok {
|
if ok {
|
||||||
r.SystemUpdatePending = system.pending
|
r.SystemUpdatePending = system.pending
|
||||||
r.SystemDownloadProgress = system.downloadProgress
|
r.SystemDownloadProgress = &system.downloadProgress
|
||||||
r.SystemDownloadFinishedAt = system.downloadFinishedAt
|
if !system.downloadFinishedAt.IsZero() {
|
||||||
r.SystemVerificationProgress = system.verificationProgress
|
r.SystemDownloadFinishedAt = &system.downloadFinishedAt
|
||||||
r.SystemVerifiedAt = system.verifiedAt
|
}
|
||||||
r.SystemUpdateProgress = system.updateProgress
|
r.SystemVerificationProgress = &system.verificationProgress
|
||||||
r.SystemUpdatedAt = system.updatedAt
|
if !system.verifiedAt.IsZero() {
|
||||||
r.SystemTargetVersion = system.targetVersion
|
r.SystemVerifiedAt = &system.verifiedAt
|
||||||
|
}
|
||||||
|
r.SystemUpdateProgress = &system.updateProgress
|
||||||
|
if !system.updatedAt.IsZero() {
|
||||||
|
r.SystemUpdatedAt = &system.updatedAt
|
||||||
|
}
|
||||||
|
r.SystemTargetVersion = &system.targetVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,14 @@ func (s *State) updateSystem(ctx context.Context, systemUpdate *componentUpdateS
|
||||||
|
|
||||||
l := s.l.With().Str("path", systemUpdatePath).Logger()
|
l := s.l.With().Str("path", systemUpdatePath).Logger()
|
||||||
|
|
||||||
if err := s.downloadFile(ctx, systemUpdatePath, systemUpdate.url, &systemUpdate.downloadProgress); err != nil {
|
if err := s.downloadFile(ctx, systemUpdatePath, systemUpdate.url, "system"); err != nil {
|
||||||
return s.componentUpdateError("Error downloading system update", err, &l)
|
return s.componentUpdateError("Error downloading system update", err, &l)
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadFinished := time.Now()
|
downloadFinished := time.Now()
|
||||||
systemUpdate.downloadFinishedAt = downloadFinished
|
systemUpdate.downloadFinishedAt = downloadFinished
|
||||||
systemUpdate.downloadProgress = 1
|
systemUpdate.downloadProgress = 1
|
||||||
s.triggerStateUpdate()
|
s.triggerComponentUpdateState("system", systemUpdate)
|
||||||
|
|
||||||
if err := s.verifyFile(
|
if err := s.verifyFile(
|
||||||
systemUpdatePath,
|
systemUpdatePath,
|
||||||
|
|
@ -38,7 +38,7 @@ func (s *State) updateSystem(ctx context.Context, systemUpdate *componentUpdateS
|
||||||
systemUpdate.verificationProgress = 1
|
systemUpdate.verificationProgress = 1
|
||||||
systemUpdate.updatedAt = verifyFinished
|
systemUpdate.updatedAt = verifyFinished
|
||||||
systemUpdate.updateProgress = 1
|
systemUpdate.updateProgress = 1
|
||||||
s.triggerStateUpdate()
|
s.triggerComponentUpdateState("system", systemUpdate)
|
||||||
|
|
||||||
l.Info().Msg("System update downloaded")
|
l.Info().Msg("System update downloaded")
|
||||||
|
|
||||||
|
|
@ -68,7 +68,7 @@ func (s *State) updateSystem(ctx context.Context, systemUpdate *componentUpdateS
|
||||||
if systemUpdate.updateProgress > 0.99 {
|
if systemUpdate.updateProgress > 0.99 {
|
||||||
systemUpdate.updateProgress = 0.99
|
systemUpdate.updateProgress = 0.99
|
||||||
}
|
}
|
||||||
s.triggerStateUpdate()
|
s.triggerComponentUpdateState("system", systemUpdate)
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +86,7 @@ func (s *State) updateSystem(ctx context.Context, systemUpdate *componentUpdateS
|
||||||
rkLogger.Info().Msg("rk_ota success")
|
rkLogger.Info().Msg("rk_ota success")
|
||||||
systemUpdate.updateProgress = 1
|
systemUpdate.updateProgress = 1
|
||||||
systemUpdate.updatedAt = verifyFinished
|
systemUpdate.updatedAt = verifyFinished
|
||||||
s.triggerStateUpdate()
|
s.triggerComponentUpdateState("system", systemUpdate)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,14 @@ func syncFilesystem() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) downloadFile(ctx context.Context, path string, url string, downloadProgress *float32) error {
|
func (s *State) downloadFile(ctx context.Context, path string, url string, component string) error {
|
||||||
|
componentUpdate, ok := s.componentUpdateStatuses[component]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("component %s not found", component)
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadProgress := componentUpdate.downloadProgress
|
||||||
|
|
||||||
if _, err := os.Stat(path); err == nil {
|
if _, err := os.Stat(path); err == nil {
|
||||||
if err := os.Remove(path); err != nil {
|
if err := os.Remove(path); err != nil {
|
||||||
return fmt.Errorf("error removing existing file: %w", err)
|
return fmt.Errorf("error removing existing file: %w", err)
|
||||||
|
|
@ -80,9 +87,9 @@ func (s *State) downloadFile(ctx context.Context, path string, url string, downl
|
||||||
return fmt.Errorf("error writing to file: %w", ew)
|
return fmt.Errorf("error writing to file: %w", ew)
|
||||||
}
|
}
|
||||||
progress := float32(written) / float32(totalSize)
|
progress := float32(written) / float32(totalSize)
|
||||||
if progress-*downloadProgress >= 0.01 {
|
if progress-downloadProgress >= 0.01 {
|
||||||
*downloadProgress = progress
|
componentUpdate.downloadProgress = progress
|
||||||
s.triggerStateUpdate()
|
s.triggerComponentUpdateState(component, &componentUpdate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if er != nil {
|
if er != nil {
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ export default function SettingsAdvancedRoute() {
|
||||||
// Navigate to update page
|
// Navigate to update page
|
||||||
navigateTo("/settings/general/update");
|
navigateTo("/settings/general/update");
|
||||||
});
|
});
|
||||||
}, [updateTarget, appVersion, systemVersion, devChannel, send, navigateTo]);
|
}, [appVersion, systemVersion, devChannel, send, navigateTo]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue