From a2b782263e979af9cf01629f463cb50babfd8801 Mon Sep 17 00:00:00 2001 From: electricface Date: Tue, 20 Jan 2026 16:14:59 +0800 Subject: [PATCH] feat: Support intranet update environment checks and notification strategies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added logic to determine intranet updates (IsPrivateLastore) and changed the method for obtaining update sources; - Implemented pre-checks for the update environment, executing scripts to verify and report results; - Added pre-check logic for backups; - Optimized cron job logic to use different trigger commands during intranet updates; - Adjusted notification sending logic to use专属 icons and expiration times for intranet updates; - Enriched update status workflow event reporting, covering stages such as backup, download, and installation; - Added error and status reporting at multiple points to ensure the update platform accurately captures status; - Introduced automated periodic event handling to enhance auto-update capabilities. Task: https://pms.uniontech.com/task-view-385321.html --- src/internal/config/config.go | 9 ++ src/internal/system/system.go | 8 +- src/internal/system/update_type.go | 17 ++- src/lastore-daemon/common.go | 4 +- src/lastore-daemon/dbusutil.go | 4 + src/lastore-daemon/job.go | 14 ++- src/lastore-daemon/main.go | 12 +- src/lastore-daemon/manager.go | 44 +++++++- src/lastore-daemon/manager_check.go | 12 +- src/lastore-daemon/manager_download.go | 81 ++++++++++++-- src/lastore-daemon/manager_unit.go | 42 ++++++- src/lastore-daemon/manager_update.go | 148 +++++++++++++++++++++++-- src/lastore-daemon/manager_upgrade.go | 105 ++++++++++++++++-- 13 files changed, 454 insertions(+), 46 deletions(-) diff --git a/src/internal/config/config.go b/src/internal/config/config.go index a2b96f5a9..73ce16a6b 100644 --- a/src/internal/config/config.go +++ b/src/internal/config/config.go @@ -60,6 +60,7 @@ type Config struct { UpdateMode system.UpdateType CheckUpdateMode system.UpdateType IncrementalUpdate bool + IntranetUpdate bool // 缓存大小超出限制时的清理时间间隔 CleanIntervalCacheOverLimit time.Duration @@ -199,6 +200,7 @@ const ( dSettingsKeySecurityRepoType = "security-repo-type" dSettingsKeyPlatformRepoComponents = "platform-repo-components" dSettingsKeyIncrementalUpdate = "incremental-update" + dSettingsKeyIntranetUpdate = "intranet-update" dSettingsKeyGetHardwareIdByHelper = "hardware-id-from-helper" dSettingsKeyCheckPolicyInterval = "check-policy-interval" ) @@ -275,6 +277,13 @@ func getConfigFromDSettings() *Config { c.IncrementalUpdate = v.Value().(bool) } + v, err = c.dsLastoreManager.Value(0, dSettingsKeyIntranetUpdate) + if err != nil { + logger.Warning(err) + } else { + c.IntranetUpdate = v.Value().(bool) + } + v, err = c.dsLastoreManager.Value(0, dSettingsKeyMirrorSource) if err != nil { logger.Warning(err) diff --git a/src/internal/system/system.go b/src/internal/system/system.go index 1fcff1ba9..813949a3b 100644 --- a/src/internal/system/system.go +++ b/src/internal/system/system.go @@ -11,8 +11,8 @@ import ( ) const VarLibDir = "/var/lib/lastore" +const IupPath = "/usr/lib/iup-daemon" -// TODO: Assign value later var IsPrivateLastore bool type Status string @@ -57,8 +57,10 @@ const ( ) const ( - NotifyExpireTimeoutDefault = -1 - NotifyExpireTimeoutNoHide = 0 + NotifyExpireTimeoutDefault = -1 + NotifyExpireTimeoutNoHide = 0 + NotifyExpireTimeoutPrivate = 10000 + NotifyExpireTimeoutPrivateLong = 600000 ) type JobProgressInfo struct { diff --git a/src/internal/system/update_type.go b/src/internal/system/update_type.go index b4c527801..cb60817e1 100644 --- a/src/internal/system/update_type.go +++ b/src/internal/system/update_type.go @@ -305,11 +305,15 @@ func UpdateOtherSystemSourceDir(otherSourceList []string) error { // CustomSourceWrapper 根据updateType组合source文件,doRealAction完成实际操作,unref用于释放资源 func CustomSourceWrapper(updateType UpdateType, doRealAction func(path string, unref func()) error) error { var sourcePathList []string - for _, t := range AllCheckUpdateType() { - category := updateType & t - if category != 0 { - sourcePath := GetCategorySourceMap()[t] - sourcePathList = append(sourcePathList, sourcePath) + if IsPrivateLastore { + sourcePathList = append(sourcePathList, SystemUpdateSource) + } else { + for _, t := range AllCheckUpdateType() { + category := updateType & t + if category != 0 { + sourcePath := GetCategorySourceMap()[t] + sourcePathList = append(sourcePathList, sourcePath) + } } } // 由于103x版本兼容,检查更新时需要检查商店仓库 @@ -322,6 +326,9 @@ func CustomSourceWrapper(updateType UpdateType, doRealAction func(path string, u case 1: // 如果只有一个仓库,证明是单项的更新,可以直接使用默认的文件夹 if doRealAction != nil { + if IsPrivateLastore { + return doRealAction(sourcePathList[0], nil) + } return doRealAction(GetCategorySourceMap()[updateType], nil) } return errors.New("doRealAction is nil") diff --git a/src/lastore-daemon/common.go b/src/lastore-daemon/common.go index c57134d64..5bb45c0dd 100644 --- a/src/lastore-daemon/common.go +++ b/src/lastore-daemon/common.go @@ -26,10 +26,10 @@ import ( "github.com/linuxdeepin/dde-api/polkit" utils2 "github.com/linuxdeepin/go-lib/utils" "github.com/linuxdeepin/lastore-daemon/src/internal/config" + . "github.com/linuxdeepin/lastore-daemon/src/internal/config" "github.com/linuxdeepin/lastore-daemon/src/internal/system" "github.com/linuxdeepin/lastore-daemon/src/internal/system/apt" "github.com/linuxdeepin/lastore-daemon/src/internal/utils" - . "github.com/linuxdeepin/lastore-daemon/src/internal/config" "github.com/godbus/dbus/v5" "github.com/linuxdeepin/go-lib/dbusutil" @@ -39,6 +39,8 @@ import ( var _urlReg = regexp.MustCompile(`^[ ]*deb .*((?:https?|ftp|file|p2p)://[^ ]+)`) +const lastoreGatherInfo = "lastoreGatherInfo" + // 获取list文件或list.d文件夹中所有list文件的未被屏蔽的仓库地址 func getUpgradeUrls(path string) []string { var upgradeUrls []string diff --git a/src/lastore-daemon/dbusutil.go b/src/lastore-daemon/dbusutil.go index 3856f1825..27b71eb2a 100644 --- a/src/lastore-daemon/dbusutil.go +++ b/src/lastore-daemon/dbusutil.go @@ -243,6 +243,10 @@ func (v *Job) emitPropChangedDownloadSize(value int64) error { return v.service.EmitPropertyChanged(v, "DownloadSize", value) } +func (v *Job) emitPropChangedUpdatePolicy(value int) error { + return v.service.EmitPropertyChanged(v, "PolicyTyp", value) +} + func (v *Job) setPropType(value string) (changed bool) { if v.Type != value { v.Type = value diff --git a/src/lastore-daemon/job.go b/src/lastore-daemon/job.go index 862920328..12c5cd015 100644 --- a/src/lastore-daemon/job.go +++ b/src/lastore-daemon/job.go @@ -12,6 +12,7 @@ import ( "time" "github.com/linuxdeepin/lastore-daemon/src/internal/system" + "github.com/linuxdeepin/lastore-daemon/src/internal/updateplatform" "github.com/linuxdeepin/go-lib/dbusutil" ) @@ -29,7 +30,8 @@ type Job struct { CreateTime int64 DownloadSize int64 - Type string + Type string + PolicyTyp int Status system.Status caller methodCaller @@ -119,6 +121,16 @@ func (j *Job) initDownloadSize() { j.PropsMu.Unlock() } +func (j *Job) setUpdatePolicy(policyTyp updateplatform.UpdateTp) { + j.PropsMu.Lock() + policy := int(policyTyp) + if j.PolicyTyp != policy { + j.PolicyTyp = policy + _ = j.emitPropChangedUpdatePolicy(policy) + } + j.PropsMu.Unlock() +} + func (j *Job) String() string { return fmt.Sprintf("Job{Id:%q:%q,Type:%q(%v,%v), %q(%.2f)}@%q", j.Id, j.Packages, diff --git a/src/lastore-daemon/main.go b/src/lastore-daemon/main.go index 84828dda7..9b1d75de9 100644 --- a/src/lastore-daemon/main.go +++ b/src/lastore-daemon/main.go @@ -73,8 +73,18 @@ func main() { if os.Getenv("DBUS_STARTER_BUS_TYPE") != "" { _ = os.Setenv("PATH", os.Getenv("PATH")+":/bin:/sbin:/usr/bin:/usr/sbin") } - config := NewConfig(path.Join(system.VarLibDir, "config.json")) + logger.Info("intranet update:", config.IntranetUpdate) + system.IsPrivateLastore = config.IntranetUpdate + if system.IsPrivateLastore { + go func() { + out, err := exec.Command("/usr/bin/lastore-tools", "gatherinfo", "-type=post").CombinedOutput() + if err != nil { + logger.Warning(string(out)) + } + }() + } + aptImpl := dut.NewSystem(config.NonUnknownList, config.OtherSourceList, config.IncrementalUpdate) system.SetSystemUpdate(config.PlatformUpdate) // 设置是否通过平台更新 allowInstallPackageExecPaths = append(allowInstallPackageExecPaths, config.AllowInstallRemovePkgExecPaths...) diff --git a/src/lastore-daemon/manager.go b/src/lastore-daemon/manager.go index 01e74f5ed..54b75c4d0 100644 --- a/src/lastore-daemon/manager.go +++ b/src/lastore-daemon/manager.go @@ -108,6 +108,9 @@ type Manager struct { checkDpkgCapabilityOnce sync.Once supportDpkgScriptIgnore bool + envIsValid bool + preBackUpCheck bool + logFds []*os.File logFdsMu sync.Mutex logTmpFile *os.File @@ -140,6 +143,8 @@ func NewManager(service *dbusutil.Service, updateApi system.System, c *config.Co abObj: abrecovery.NewABRecovery(service.Conn()), securitySourceConfig: make(UpdateSourceConfig), systemSourceConfig: make(UpdateSourceConfig), + envIsValid: true, + preBackUpCheck: true, } m.reloadOemConfig(true) m.signalLoop.Start() @@ -149,8 +154,9 @@ func NewManager(service *dbusutil.Service, updateApi system.System, c *config.Co go m.handleOSSignal() m.updateJobList() m.initStatusManager() - m.HardwareId = updateplatform.GetHardwareId(m.config.IncludeDiskInfo, m.config.GetHardwareIdByHelper) - + go func() { + m.setPropHardwareId(updateplatform.GetHardwareId(m.config.IncludeDiskInfo, m.config.GetHardwareIdByHelper)) + }() m.initDbusSignalListen() m.initDSettingsChangedHandle() m.syncThirdPartyDconfig() @@ -160,10 +166,18 @@ func NewManager(service *dbusutil.Service, updateApi system.System, c *config.Co m.rebootTimeoutTimer = time.AfterFunc(600*time.Second, func() { // 启动后600s如果没有触发检查,那么上报更新失败 + msg := "the check has not been triggered after reboot for 600 seconds" m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", - Detail: "the check has not been triggered after reboot for 600 seconds", + Detail: msg, }, true) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.GetUpdateEvent, + EventStatus: false, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) err = m.delRebootCheckOption(all) if err != nil { @@ -249,7 +263,8 @@ func (m *Manager) initAgent() { func (m *Manager) initPlatformManager() { m.updatePlatform = updateplatform.NewUpdatePlatformManager(m.config, false) - if isFirstBoot() { + // TODO: 可能缺少 m.loadPlatformCache() + if isFirstBoot() || system.IsPrivateLastore { // 不能阻塞初始化流程,防止dbus服务激活超时 go m.updatePlatform.RetryPostHistory() // 此处调用还没有export以及dispatch job,因此可以判断是否需要check. } @@ -654,6 +669,23 @@ func (m *Manager) categorySupportAutoInstall(category system.UpdateType) bool { return autoInstallUpdates && (autoInstallUpdateType&category != 0) } +// handleAutoCheckRegularlyEvent handles the regular automatic update check event. +// It triggers a partial system upgrade when the system is in CanUpgrade state or +// when local cache exists. The update platform type is set to UpdateRegularly +// to indicate this is a scheduled regular update rather than a user-initiated one. +func (m *Manager) handleAutoCheckRegularlyEvent() error { + if m.statusManager.updateModeStatusObj[system.SystemUpgradeJobType] == system.CanUpgrade || + utils.IsFileExist(system.LocalCachePath) { + m.updatePlatform.Tp = updateplatform.UpdateRegularly + _, err := m.distUpgradePartly(dbus.Sender(m.service.Conn().Names()[0]), system.SystemUpdate, true) + if err != nil { + logger.Warning(err) + return err + } + } + return nil +} + func (m *Manager) handleAutoCheckEvent() error { if m.config.AutoCheckUpdates && !m.ImmutableAutoRecovery { _, err := m.updateSource(dbus.Sender(m.service.Conn().Names()[0])) @@ -835,8 +867,12 @@ const ( func (m *Manager) sendNotify(appName string, replacesId uint32, appIcon string, summary string, body string, actions []string, hints map[string]dbus.Variant, expireTimeout int32) uint32 { if !m.updater.UpdateNotify { + logger.Info("UpdateNotify is false") return 0 } + if system.IsPrivateLastore { + appIcon = "intranet-update-platform-notification" + } agent := m.userAgents.getActiveLastoreAgent() if agent != nil { id, err := agent.SendNotify(0, appName, replacesId, appIcon, summary, body, actions, hints, expireTimeout) diff --git a/src/lastore-daemon/manager_check.go b/src/lastore-daemon/manager_check.go index cac522075..540b92353 100644 --- a/src/lastore-daemon/manager_check.go +++ b/src/lastore-daemon/manager_check.go @@ -111,17 +111,27 @@ func (m *Manager) checkUpgrade(sender dbus.Sender, checkMode system.UpdateType, }, string(system.FailedStatus): func() error { m.updatePlatform.PostUpgradeStatus(uuid, updateplatform.UpgradeFailed, job.Description) + // TODO 可能丢失调用 m.updatePlatform.SaveJobPostMsgByUUID(uuid, updateplatform.UpgradeFailed, job.Description) go func() { m.inhibitAutoQuitCountAdd() defer m.inhibitAutoQuitCountSub() + msg := fmt.Sprintf("%v postcheck error: %v", checkOrder.JobType(), job.Description) m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", UpdateType: checkOrder.JobType(), JobDescription: job.Description, - Detail: fmt.Sprintf("%v postcheck error: %v", checkOrder.JobType(), job.Description), + Detail: msg, }, false) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.CheckEnv, + EventStatus: false, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) + // TODO: 可能丢失调用 m.updatePlatform.PostSystemUpgradeMessage(uuid) m.reportLog(upgradeStatusReport, false, job.Description) }() inhibit(false) diff --git a/src/lastore-daemon/manager_download.go b/src/lastore-daemon/manager_download.go index d6e640b23..a0a32ce30 100644 --- a/src/lastore-daemon/manager_download.go +++ b/src/lastore-daemon/manager_download.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + "os" "os/exec" "strconv" "strings" @@ -131,6 +132,17 @@ func (m *Manager) prepareDistUpgrade(sender dbus.Sender, origin system.UpdateTyp if isExist { return job, nil } + if system.IsPrivateLastore { + msg := gettext.Tr("New version available! The download of the update package will begin shortly") + go m.sendNotify(updateNotifyShow, 0, "preferences-system", "", msg, nil, nil, system.NotifyExpireTimeoutPrivate) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.StartDownload, + EventStatus: true, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) + } job.initiator = initiator currentJob := job var sendDownloadingOnce sync.Once @@ -146,19 +158,24 @@ func (m *Manager) prepareDistUpgrade(sender dbus.Sender, origin system.UpdateTyp // 下载限速的配置修改需要在job失败重试的时候修改配置(此处失败为手动终止设置的失败状态) m.handleDownloadLimitChanged(job) } + // TODO: 可能丢失 j.initDownloadSize(totalNeedDownloadSize) j.realRunningHookFn = func() { m.PropsMu.Lock() m.PropsMu.Unlock() m.statusManager.SetUpdateStatus(mode, system.IsDownloading) - if !m.updatePlatform.UpdateNowForce { // 立即更新则不发通知 + if !m.updatePlatform.UpdateNowForce || system.IsPrivateLastore { // 立即更新则不发通知 sendDownloadingOnce.Do(func() { msg := gettext.Tr("New version available! Downloading...") action := []string{ "view", gettext.Tr("View"), } - hints := map[string]dbus.Variant{"x-deepin-action-view": dbus.MakeVariant("dde-control-center,-m,update")} - go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutDefault) + if system.IsPrivateLastore { + go m.sendNotify(updateNotifyShow, 0, "preferences-system", "", msg, nil, nil, system.NotifyExpireTimeoutPrivate) + } else { + hints := map[string]dbus.Variant{"x-deepin-action-view": dbus.MakeVariant("dde-control-center,-m,update")} + go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutDefault) + } }) } return @@ -169,6 +186,10 @@ func (m *Manager) prepareDistUpgrade(sender dbus.Sender, origin system.UpdateTyp return nil }, string(system.FailedStatus): func() error { + if system.IsPrivateLastore { + cacheFile := "/tmp/checkpolicy.cache" + _ = os.RemoveAll(cacheFile) + } // 失败的单独设置失败类型的状态,其他的还原成未下载(其中下载完成的由于限制不会被修改) m.statusManager.SetUpdateStatus(j.updateTyp, system.DownloadErr) m.statusManager.SetUpdateStatus(mode, system.NotDownload) @@ -190,7 +211,12 @@ func (m *Manager) prepareDistUpgrade(sender dbus.Sender, origin system.UpdateTyp cleanAllCache() msg := gettext.Tr("Updates failed: damaged files. Please update again.") action := []string{"retry", gettext.Tr("Try Again")} - hints := map[string]dbus.Variant{"x-deepin-action-retry": dbus.MakeVariant("dde-control-center,-m,update")} + var hints map[string]dbus.Variant + if system.IsPrivateLastore { + hints = map[string]dbus.Variant{"x-deepin-action-retry": dbus.MakeVariant("dde-control-center,-m,updateprivate")} + } else { + hints = map[string]dbus.Variant{"x-deepin-action-retry": dbus.MakeVariant("dde-control-center,-m,update")} + } go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutDefault) } else if strings.Contains(errorContent.ErrType.String(), system.ErrorFetchFailed.String()) { // 网络原因下载更新失败 @@ -205,16 +231,39 @@ func (m *Manager) prepareDistUpgrade(sender dbus.Sender, origin system.UpdateTyp defer m.inhibitAutoQuitCountSub() m.reportLog(downloadStatusReport, false, j.Description) // 上报下载失败状态 + msg := fmt.Sprintf("download %v package failed, detail is %v", mode.JobType(), job.Description) m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", UpdateType: mode.JobType(), JobDescription: job.Description, - Detail: fmt.Sprintf("download %v package failed, detail is %v", mode.JobType(), job.Description), + Detail: msg, }, true) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.StartDownload, + EventStatus: false, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) }() return nil }, string(system.SucceedStatus): func() error { + msg := fmt.Sprintf("download %v package success", j.updateTyp.JobType()) + m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ + Type: "info", + UpdateType: mode.JobType(), + JobDescription: j.Description, + Detail: msg, + }, false) // 上报下载成功状态 + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.DownloadComplete, + EventStatus: true, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) // 上报下载成功状态 + logger.Infof("enter download job succeed callback, UpdateNowForce: %v", m.updatePlatform.UpdateNowForce) m.statusManager.SetUpdateStatus(j.updateTyp, system.CanUpgrade) if j.next == nil { go func() { @@ -228,8 +277,24 @@ func (m *Manager) prepareDistUpgrade(sender dbus.Sender, origin system.UpdateTyp "ignore", gettext.Tr("Dismiss"), } - hints := map[string]dbus.Variant{"x-deepin-action-updateNow": dbus.MakeVariant("dde-control-center,-m,update")} - m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutDefault) + if system.IsPrivateLastore { + if m.updatePlatform.Tp == updateplatform.UpdateRegularly { + timeStr := m.updatePlatform.UpdateTime.Format("15:04:05") + if timeStr != m.updateTime { + m.updateTime = timeStr + } + msg = fmt.Sprintf(gettext.Tr("Downloading completed. The computer will be updated at %s"), m.updateTime) + go m.sendNotify(updateNotifyShow, 0, "preferences-system", "", msg, nil, nil, system.NotifyExpireTimeoutPrivate) + } + if m.updatePlatform.Tp == updateplatform.UpdateShutdown { + m.sendNotify(updateNotifyShow, 0, "preferences-system", "", msg, nil, nil, system.NotifyExpireTimeoutPrivate) + } + } else { + hints := map[string]dbus.Variant{"x-deepin-action-updateNow": dbus.MakeVariant("dde-control-center,-m,update")} + + m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutDefault) + } + } m.reportLog(downloadStatusReport, true, "") }() @@ -242,6 +307,8 @@ func (m *Manager) prepareDistUpgrade(sender dbus.Sender, origin system.UpdateTyp } m.inhibitAutoQuitCountSub() } + } else { + logger.Infof("job next is not empty, job id: %v", job.next.Id) } // 上报下载成功状态 diff --git a/src/lastore-daemon/manager_unit.go b/src/lastore-daemon/manager_unit.go index 332dff35c..a15b9c666 100644 --- a/src/lastore-daemon/manager_unit.go +++ b/src/lastore-daemon/manager_unit.go @@ -47,6 +47,7 @@ const ( AbortAutoDownload systemdEventType = "AbortAutoDownload" UpdateTimer systemdEventType = "UpdateTimer" RetryPostUpgradeResult systemdEventType = "RetryPostUpgradeResult" + AutoCheckRegularly systemdEventType = "AutoCheckRegularly" ) type UnitName string @@ -126,11 +127,28 @@ func (m *Manager) getLastoreSystemUnitMap() lastoreUnitMap { updateTime = updateTime.Add(time.Duration(24) * time.Hour) } // 提前60s触发 - unitMap[lastoreRegularlyUpdate] = []string{ - fmt.Sprintf("--on-active=%d", int(updateTime.Sub(nowTime)/time.Second-60)), - "/bin/bash", - "-c", - fmt.Sprintf(`%s string:"%s"`, lastoreDBusCmd, AutoCheck), + if system.IsPrivateLastore { + unitMap[lastoreRegularlyUpdate] = []string{ + fmt.Sprintf("--on-active=%d", int(updateTime.Sub(nowTime)/time.Second-60)), + "/bin/bash", + "-c", + fmt.Sprintf(`%s string:"%s"`, lastoreDBusCmd, AutoCheckRegularly), + } + } else { + unitMap[lastoreRegularlyUpdate] = []string{ + fmt.Sprintf("--on-active=%d", int(updateTime.Sub(nowTime)/time.Second-60)), + "/bin/bash", + "-c", + fmt.Sprintf(`%s string:"%s"`, lastoreDBusCmd, AutoCheck), + } + } + } + if system.IsPrivateLastore { + unitMap[lastoreGatherInfo] = []string{ + fmt.Sprintf("--on-active=%d", rand.New(rand.NewSource(time.Now().UnixNano())).Intn(600)+60), + "--uid=root", + "/usr/bin/lastore-tools", + "posthardware", } } @@ -377,6 +395,13 @@ func (m *Manager) delHandleSystemEvent(sender dbus.Sender, eventType string) err m.service.DelayAutoQuit() switch evType { + case AutoCheckRegularly: + go func() { + err := m.handleAutoCheckRegularlyEvent() + if err != nil { + logger.Warning(err) + } + }() case AutoCheck: go func() { err := m.handleAutoCheckEvent() @@ -393,7 +418,12 @@ func (m *Manager) delHandleSystemEvent(sender dbus.Sender, eventType string) err } }() case OsVersionChanged: - go updateplatform.UpdateTokenConfigFile(m.config.IncludeDiskInfo, m.config.GetHardwareIdByHelper) + logger.Info("enter update token from OsVersionChanged") + if system.IsPrivateLastore { + updateplatform.UpdateTokenConfigFile(m.config.IncludeDiskInfo, m.config.GetHardwareIdByHelper) + } else { + go updateplatform.UpdateTokenConfigFile(m.config.IncludeDiskInfo, m.config.GetHardwareIdByHelper) + } case InitIdleDownload: m.updater.initIdleDownloadConfig() case AutoDownload: diff --git a/src/lastore-daemon/manager_update.go b/src/lastore-daemon/manager_update.go index a4c9569b1..af018dee7 100644 --- a/src/lastore-daemon/manager_update.go +++ b/src/lastore-daemon/manager_update.go @@ -10,14 +10,17 @@ import ( "encoding/json" "errors" "fmt" + "math/rand" "os" "os/exec" "path/filepath" "strings" "sync" + "time" "github.com/godbus/dbus/v5" "github.com/linuxdeepin/go-lib/gettext" + "github.com/linuxdeepin/go-lib/utils" "github.com/linuxdeepin/lastore-daemon/src/internal/system" "github.com/linuxdeepin/lastore-daemon/src/internal/system/apt" "github.com/linuxdeepin/lastore-daemon/src/internal/updateplatform" @@ -46,6 +49,62 @@ func prepareUpdateSource() { } +func (m *Manager) beforeUpdateSourceEnvCheck() bool { + preCheckFilePath := filepath.Join(system.IupPath, "ext/iup-check.sh") + var flag bool + var errMsg string + if !utils.IsFileExist(preCheckFilePath) { + flag = false + errMsg = fmt.Sprintf("%s does not exist", preCheckFilePath) + logger.Warning(errMsg) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.CheckEnv, + EventStatus: flag, + EventContent: errMsg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) + return flag + } + cmd := exec.Command("/bin/bash", preCheckFilePath) + var outBuf bytes.Buffer + cmd.Stdout = &outBuf + var errBuf bytes.Buffer + cmd.Stderr = &errBuf + err := cmd.Run() + if err != nil { + flag = false + errMsg = errBuf.String() + logger.Warningf("Error executing command: %v, output: %v", err, errMsg) + } else { + flag = true + } + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.CheckEnv, + EventStatus: flag, + EventContent: errMsg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) + return flag +} + +func (m *Manager) preCheckBackUp() { + canBackup, abErr := m.abObj.CanBackup(0) + if abErr != nil || !canBackup { + logger.Info("can not backup,", abErr) + m.preBackUpCheck = false + } + hasBackedUp, err := m.abObj.HasBackedUp().Get(0) + if err != nil && !hasBackedUp { + abErr = m.abObj.StartBackup(0) + if abErr != nil { + logger.Info("can not backup,", abErr) + m.preBackUpCheck = false + } + } +} + // updateSource 检查更新主要步骤:1.从更新平台获取数据并解析;2.apt update;3.最终可更新内容确定(模拟安装的方式);4.数据上报; // 任务进度划分: 0-10%-80%-90%-100% func (m *Manager) updateSource(sender dbus.Sender) (*Job, error) { @@ -76,6 +135,7 @@ func (m *Manager) updateSource(sender dbus.Sender) (*Job, error) { if err != nil { return nil, err } + m.preCheckBackUp() prepareUpdateSource() m.reloadOemConfig(true) m.updatePlatform.Token = updateplatform.UpdateTokenConfigFile(m.config.IncludeDiskInfo, m.config.GetHardwareIdByHelper) @@ -129,11 +189,19 @@ func (m *Manager) updateSource(sender dbus.Sender) (*Job, error) { return nil }, string(system.SucceedStatus): func() error { + job.setUpdatePolicy(m.updatePlatform.Tp) m.refreshUpdateInfos(true) m.PropsMu.Lock() m.updateSourceOnce = true m.PropsMu.Unlock() if len(m.UpgradableApps) > 0 { + if !m.envIsValid { + job.retry = 0 + return &system.JobError{ + ErrType: system.ErrorDpkgError, + ErrDetail: "before update env check failed", + } + } go m.reportLog(updateStatusReport, true, "") // 开启自动下载时触发自动下载,发自动下载通知,不发送可更新通知; // 关闭自动下载时,发可更新的通知; @@ -141,8 +209,17 @@ func (m *Manager) updateSource(sender dbus.Sender) (*Job, error) { // msg := gettext.Tr("New system edition available") msg := gettext.Tr("New version available!") action := []string{"view", gettext.Tr("View")} - hints := map[string]dbus.Variant{"x-deepin-action-view": dbus.MakeVariant("dde-control-center,-m,update")} - go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutDefault) + var hints map[string]dbus.Variant + if system.IsPrivateLastore { + hints = map[string]dbus.Variant{"x-deepin-action-view": dbus.MakeVariant("dde-control-center,-m,updateprivate")} + if m.updatePlatform.Tp == updateplatform.NormalUpdate { + msg = gettext.Tr("New version available! Plesse go to control-center to check") + go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutPrivate) + } + } else { + hints = map[string]dbus.Variant{"x-deepin-action-view": dbus.MakeVariant("dde-control-center,-m,update")} + go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutDefault) + } } } else { go m.reportLog(updateStatusReport, false, "") @@ -161,6 +238,10 @@ func (m *Manager) updateSource(sender dbus.Sender) (*Job, error) { }, string(system.FailedStatus): func() error { // 网络问题检查更新失败和空间不足下载索引失败,需要发通知 + if system.IsPrivateLastore { + cacheFile := "/tmp/checkpolicy.cache" + _ = os.RemoveAll(cacheFile) + } var errorContent system.JobError err = json.Unmarshal([]byte(job.Description), &errorContent) if err == nil { @@ -180,12 +261,19 @@ func (m *Manager) updateSource(sender dbus.Sender) (*Job, error) { m.inhibitAutoQuitCountAdd() defer m.inhibitAutoQuitCountSub() m.reportLog(updateStatusReport, false, job.Description) - + msg := fmt.Sprintf("apt-get update failed, detail is %v , option is %+v", job.Description, job.option) m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", JobDescription: job.Description, - Detail: fmt.Sprintf("apt-get update failed, detail is %v , option is %+v", job.Description, job.option), + Detail: msg, }, false) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.GetUpdateEvent, + EventStatus: false, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) }() return nil }, @@ -200,6 +288,10 @@ func (m *Manager) updateSource(sender dbus.Sender) (*Job, error) { job.setAfterHooks(map[string]func() error{ string(system.RunningStatus): func() error { job.setPropProgress(0.01) + if system.IsPrivateLastore { + // 独立客户端为了减少更新平台的瞬时负载,采取0-58秒内随机开始检查更新任务 + time.Sleep(time.Duration(rand.Intn(59)) * time.Second) + } _ = os.Setenv("http_proxy", environ["http_proxy"]) _ = os.Setenv("https_proxy", environ["https_proxy"]) // 检查任务开始后,从更新平台获取仓库、更新注记等信息 @@ -217,6 +309,10 @@ func (m *Manager) updateSource(sender dbus.Sender) (*Job, error) { return nil } } + if m.updatePlatform.TimerHasChanged { + msg := gettext.Tr("timer has changed. Please reboot to take effect") + go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, nil, nil, system.NotifyExpireTimeoutPrivate) + } err = m.updatePlatform.UpdateAllPlatformDataSync() if err != nil { @@ -473,6 +569,13 @@ const TimeOnly = "15:04:05" func (m *Manager) refreshUpdateInfos(sync bool) { // 检查更新时,同步修改canUpgrade状态;检查更新时需要同步操作 if sync { + // TODO 是否有必要? + if system.IsPrivateLastore { + err := exec.Command("/var/lib/lastore/scripts/build_system_info", "-now").Run() + if err != nil { + logger.Warning(err) + } + } // 检查更新后,先下载解析coreList,获取必装清单 m.coreList = m.getCoreList(true) logger.Debug("generateUpdateInfo get coreList:", m.coreList) @@ -480,10 +583,18 @@ func (m *Manager) refreshUpdateInfos(sync bool) { go func() { m.inhibitAutoQuitCountAdd() defer m.inhibitAutoQuitCountSub() + msg := fmt.Sprintf("generate package list error, detail is %v:", e) m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", - Detail: fmt.Sprintf("generate package list error, detail is %v:", e), + Detail: msg, }, false) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.GetUpdateEvent, + EventStatus: false, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) }() logger.Warning(e) } @@ -499,12 +610,18 @@ func (m *Manager) refreshUpdateInfos(sync bool) { go func() { m.inhibitAutoQuitCountAdd() defer m.inhibitAutoQuitCountSub() - + msg := fmt.Sprintf("generate package list error, detail is %v:", e) m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", - Detail: fmt.Sprintf("generate package list error, detail is %v:", e), + Detail: msg, }, false) - + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.GetUpdateEvent, + EventStatus: false, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) }() logger.Warning(e) } @@ -515,6 +632,21 @@ func (m *Manager) refreshUpdateInfos(sync bool) { } m.updateUpdatableProp(m.updater.ClassifiedUpdatablePackages) m.statusManager.SetFrontForceUpdate(m.updatePlatform.Tp == updateplatform.UpdateShutdown) + if len(m.UpgradableApps) > 0 { + if !m.beforeUpdateSourceEnvCheck() { + logger.Warning("before update env check failed") + m.envIsValid = false + return + } + m.envIsValid = true + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.GetUpdateEvent, + EventStatus: true, + EventContent: "update source success", + } + m.updatePlatform.PostProcessEventMessage(procEvent) + } if updateplatform.IsForceUpdate(m.updatePlatform.Tp) { go func() { m.inhibitAutoQuitCountAdd() diff --git a/src/lastore-daemon/manager_upgrade.go b/src/lastore-daemon/manager_upgrade.go index fa8a157ee..98b7c1d8f 100644 --- a/src/lastore-daemon/manager_upgrade.go +++ b/src/lastore-daemon/manager_upgrade.go @@ -73,6 +73,7 @@ func (m *Manager) retryDistUpgrade(upgradeJob *Job, needBackup bool) error { func (m *Manager) distUpgradePartly(sender dbus.Sender, origin system.UpdateType, needBackup bool) (job dbus.ObjectPath, busErr *dbus.Error) { // 创建job,但是不添加到任务队列中 + logger.Infof("enter distUpgradePartly, policy tp: %v, origin: %v", m.updatePlatform.Tp, origin) var upgradeJob *Job var createJobErr error var startJobErr error @@ -130,6 +131,19 @@ func (m *Manager) distUpgradePartly(sender dbus.Sender, origin system.UpdateType m.inhibitAutoQuitCountSub() m.do.Lock() defer m.do.Unlock() + msg := fmt.Sprintf("start install package, update mode: %v", mode) + m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ + Type: "info", + UpdateType: mode.JobType(), + Detail: msg, + }, true) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.StartInstall, + EventStatus: true, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) return m.jobManager.MarkStart(upgradeJob.Id) } @@ -186,15 +200,41 @@ func (m *Manager) distUpgradePartly(sender dbus.Sender, origin system.UpdateType m.statusManager.SetABStatus(mode, system.BackingUp, system.NoABError) // 设置UpdateStatus为WaitRunUpgrade,隐藏更新并关机/重启按钮 m.statusManager.SetUpdateStatus(mode, system.WaitRunUpgrade) + if system.IsPrivateLastore { + msg := gettext.Tr("Start to update.Please dont shutdown") + go m.sendNotify(updateNotifyShow, 0, "preferences-system", "", msg, nil, nil, system.NotifyExpireTimeoutNoHide) + } + + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.StartBackUp, + EventStatus: true, + EventContent: "start backup", + } + m.updatePlatform.PostProcessEventMessage(procEvent) return nil }, string(system.SucceedStatus): func() error { m.statusManager.SetABStatus(mode, system.HasBackedUp, system.NoABError) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.BackUpComplete, + EventStatus: true, + EventContent: "backup successfully completed", + } + m.updatePlatform.PostProcessEventMessage(procEvent) inhibit(false) return nil }, string(system.FailedStatus): func() error { m.statusManager.SetABStatus(mode, system.BackupFailed, system.OtherError) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.BackUpComplete, + EventStatus: false, + EventContent: "backup failed", + } + m.updatePlatform.PostProcessEventMessage(procEvent) // 备份失败时重置UpdateStatus为CanUpgrade,让用户可以重新操作 m.statusManager.SetUpdateStatus(mode, system.CanUpgrade) inhibit(false) @@ -361,11 +401,19 @@ func (m *Manager) distUpgrade(sender dbus.Sender, mode system.UpdateType, needAd if err != nil { logger.Warning(err) + msg := fmt.Sprintf("%v gen dut meta failed, detail is: %v", mode.JobType(), err.Error()) m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", UpdateType: mode.JobType(), - Detail: fmt.Sprintf("%v gen dut meta failed, detail is: %v", mode.JobType(), err.Error()), + Detail: msg, }, true) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.StartInstall, + EventStatus: false, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) if unref != nil { unref() @@ -377,12 +425,20 @@ func (m *Manager) distUpgrade(sender dbus.Sender, mode system.UpdateType, needAd systemErr := dut.CheckSystem(dut.PreCheck, nil) // 只是为了执行precheck的hook脚本 if systemErr != nil { logger.Info(systemErr) - + msg := fmt.Sprintf("%v CheckSystem pre-check failed, detail is: %v", mode.JobType(), + systemErr.Error()) m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", UpdateType: mode.JobType(), - Detail: fmt.Sprintf("CheckSystem failed, detail is: %v", systemErr.Error()), + Detail: msg, }, true) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.StartInstall, + EventStatus: false, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) return systemErr } if !system.CheckInstallAddSize(mode) { @@ -407,11 +463,19 @@ func (m *Manager) distUpgrade(sender dbus.Sender, mode system.UpdateType, needAd if systemErr != nil { logger.Info(systemErr) + msg := fmt.Sprintf("%v CheckSystem mid-check failed, detail is: %v", mode.JobType(), systemErr.Error()) m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", UpdateType: mode.JobType(), - Detail: fmt.Sprintf("%v CheckSystem failed, detail is: %v", mode.JobType(), systemErr.Error()), + Detail: msg, }, true) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.StartInstall, + EventStatus: false, + EventContent: msg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) return systemErr } if m.statusManager.abStatus == system.HasBackedUp { @@ -566,16 +630,28 @@ func (m *Manager) preFailedHook(job *Job, mode system.UpdateType, uuid string) e cleanAllCache() msg := gettext.Tr("Updates failed: damaged files. Please update again.") action := []string{"retry", gettext.Tr("Try Again")} - hints := map[string]dbus.Variant{"x-deepin-action-retry": dbus.MakeVariant("dde-control-center,-m,update")} - go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutDefault) + if system.IsPrivateLastore { + go m.sendNotify(updateNotifyShow, 0, "preferences-system", "", msg, nil, nil, system.NotifyExpireTimeoutPrivateLong) + } else { + hints := map[string]dbus.Variant{"x-deepin-action-retry": dbus.MakeVariant("dde-control-center,-m,update")} + go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, hints, system.NotifyExpireTimeoutDefault) + } } else if strings.Contains(errType, system.ErrorInsufficientSpace.String()) { msg := gettext.Tr("Updates failed: insufficient disk space.") action := []string{} - go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, nil, system.NotifyExpireTimeoutDefault) + if system.IsPrivateLastore { + go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, nil, system.NotifyExpireTimeoutPrivateLong) + } else { + go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, nil, system.NotifyExpireTimeoutDefault) + } } else { msg := gettext.Tr("Updates failed.") action := []string{} - go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, nil, system.NotifyExpireTimeoutDefault) + if system.IsPrivateLastore { + go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, nil, system.NotifyExpireTimeoutPrivateLong) + } else { + go m.sendNotify(updateNotifyShowOptional, 0, "preferences-system", "", msg, action, nil, system.NotifyExpireTimeoutDefault) + } } } if errorContent.IsCheckError { @@ -607,11 +683,19 @@ func (m *Manager) preFailedHook(job *Job, mode system.UpdateType, uuid string) e allErrMsg = append(allErrMsg, fmt.Sprintf("upgrade failed time is %v \n", time.Now())) allErrMsg = append(allErrMsg, string(msg)) } + detailMsg := fmt.Sprintf("%v upgrade failed, detail is: %v; all error message is %v", mode.JobType(), job.Description, strings.Join(allErrMsg, "\n")) m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "error", UpdateType: mode.JobType(), - Detail: fmt.Sprintf("upgrade failed, detail is: %v; all error message is %v", job.Description, strings.Join(allErrMsg, "\n")), + Detail: detailMsg, }, true) + procEvent := updateplatform.ProcessEvent{ + TaskID: 1, + EventType: updateplatform.StartInstall, + EventStatus: false, + EventContent: detailMsg, + } + m.updatePlatform.PostProcessEventMessage(procEvent) } }() m.statusManager.SetUpdateStatus(mode, system.UpgradeErr) @@ -632,6 +716,9 @@ func (m *Manager) preUpgradeCmdSuccessHook(job *Job, needChangeGrub bool, mode s } m.statusManager.SetUpdateStatus(mode, system.Upgraded) job.setPropProgress(1.00) + if system.IsPrivateLastore { + m.cleanArchives(false) + } m.updatePlatform.PostStatusMessage(updateplatform.StatusMessage{ Type: "info",