diff --git a/src/internal/config/config.go b/src/internal/config/config.go index 068181306..621541e15 100644 --- a/src/internal/config/config.go +++ b/src/internal/config/config.go @@ -111,7 +111,6 @@ type Config struct { PlatformUrl string // 更新接口地址 StartCheckRange []int // 开机检查更新区间 - CheckPolicyInterval int // 策略检查时间间隔(单位:秒) GetHardwareIdByHelper bool // machineID是否直接从sync helper获取 IncludeDiskInfo bool // machineID是否包含硬盘信息 PostUpgradeCron string // 更新上报间隔 @@ -224,7 +223,6 @@ const ( DSettingsKeyIncrementalUpdate = "incremental-update" dSettingsKeyIntranetUpdate = "intranet-update" dSettingsKeyGetHardwareIdByHelper = "hardware-id-from-helper" - dSettingsKeyCheckPolicyInterval = "check-policy-interval" dSettingsKeyDeliveryRemoteDownloadGlobalLimit = "delivery-remote-download-global-limit" dSettingsKeyDeliveryRemoteUploadGlobalLimit = "delivery-remote-upload-global-limit" dSettingsKeyDeliveryRemoteDownloadPeakLimit = "delivery-remote-download-peak-limit" @@ -757,17 +755,6 @@ func getConfigFromDSettings() *Config { c.GetHardwareIdByHelper = v.Value().(bool) } - v, err = c.dsLastoreManager.Value(0, dSettingsKeyCheckPolicyInterval) - if err != nil { - logger.Warning(err) - } else { - if val, ok := v.Value().(int64); ok { - c.CheckPolicyInterval = int(val) - } else { - logger.Warningf("dSettings key %s: value is not int64", dSettingsKeyCheckPolicyInterval) - } - } - err = c.recoveryAndApplyOemFlag(system.SystemUpdate) if err != nil { logger.Warning(err) @@ -1222,11 +1209,6 @@ func (c *Config) SetSecurityRepoType(typ RepoType) error { return c.save(dSettingsKeySecurityRepoType, typ) } -func (c *Config) SetCheckPolicyInterval(interval int) error { - c.CheckPolicyInterval = interval - return c.save(dSettingsKeyCheckPolicyInterval, interval) -} - func (c *Config) SetStartCheckRange(checkRange []int) error { c.StartCheckRange = checkRange diff --git a/src/internal/updateplatform/message_report.go b/src/internal/updateplatform/message_report.go index c66425adb..03d45333c 100644 --- a/src/internal/updateplatform/message_report.go +++ b/src/internal/updateplatform/message_report.go @@ -778,7 +778,7 @@ func getResponseData(response *http.Response, reqType requestType) (json.RawMess } return msg.Data, nil } else { - return nil, fmt.Errorf("request for %s failed, response code=%d", response.Request.RequestURI, response.StatusCode) + return nil, fmt.Errorf("request for %s failed, response code=%d", response.Request.URL, response.StatusCode) } } @@ -897,8 +897,8 @@ func (m *UpdatePlatformManager) genUpdatePolicyByToken(updateInRelease bool) err m.UpdateTime, _ = time.Parse(time.RFC3339, msg.Policy.Data.UpdateTime) } m.TimerHasChanged = false - if !utils.IsElementEqual(m.config.CheckPolicyInterval, msg.ClientPollSetting.CheckPolicyInterval) && msg.ClientPollSetting.CheckPolicyInterval > 0 { - m.config.SetCheckPolicyInterval(msg.ClientPollSetting.CheckPolicyInterval) + if !utils.IsElementEqual(m.config.CheckInterval, msg.ClientPollSetting.CheckPolicyInterval*1000*1000*1000) && msg.ClientPollSetting.CheckPolicyInterval > 0 { + m.config.SetCheckInterval(time.Duration(msg.ClientPollSetting.CheckPolicyInterval) * time.Second) m.TimerHasChanged = true } if !utils.IsElementEqual(m.config.StartCheckRange, msg.ClientPollSetting.StartCheckRange) && msg.ClientPollSetting.StartCheckRange != nil { @@ -2182,3 +2182,84 @@ func (m *UpdatePlatformManager) UpdateDeliverySpeedLimit() error { return nil } + +const checkPolicyCacheFile = "/tmp/checkpolicy.cache" + +func (m *UpdatePlatformManager) CheckPolicyChanged() (bool, error) { + response, err := m.genVersionResponse() + if err != nil { + return false, fmt.Errorf("do request failed: %w", err) + } + defer response.Body.Close() + + body, err := io.ReadAll(response.Body) + if err != nil { + return false, fmt.Errorf("read response body failed: %w", err) + } + + if response.StatusCode != http.StatusOK { + return false, fmt.Errorf("request failed with status: %d", response.StatusCode) + } + + sum := sha256.Sum256(body) + newSum := hex.EncodeToString(sum[:]) + + oldSum, _ := m.getCheckPolicyCache() + + if oldSum != newSum { + m.saveCheckPolicyCache(newSum) + return true, nil + } + + return false, nil +} + +func (m *UpdatePlatformManager) getCheckPolicyCache() (string, time.Time) { + readFile, err := os.Open(checkPolicyCacheFile) + if err != nil { + return "", time.Time{} + } + defer readFile.Close() + + reader := bufio.NewReader(readFile) + var sum string + var checkTime time.Time + + data, _, err := reader.ReadLine() + if err == nil { + sum = string(data) + } + data, _, err = reader.ReadLine() + if err == nil { + checkTime, _ = time.Parse(time.RFC3339, string(data)) + } + + return sum, checkTime +} + +func (m *UpdatePlatformManager) saveCheckPolicyCache(sum string) error { + writeFile, err := os.OpenFile(checkPolicyCacheFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return err + } + defer writeFile.Close() + + if _, err := writeFile.WriteString(sum); err != nil { + logger.Warning("failed to write sum:", err) + return err + } + if _, err := writeFile.WriteString("\n"); err != nil { + logger.Warning("failed to write newline:", err) + return err + } + if _, err := writeFile.WriteString(time.Now().Format(time.RFC3339)); err != nil { + logger.Warning("failed to write time:", err) + return err + } + if _, err := writeFile.WriteString("\n"); err != nil { + logger.Warning("failed to write newline:", err) + return err + } + + return nil +} diff --git a/src/lastore-daemon/main.go b/src/lastore-daemon/main.go index 42a8a6686..119ff6c9d 100644 --- a/src/lastore-daemon/main.go +++ b/src/lastore-daemon/main.go @@ -100,8 +100,8 @@ func main() { manager.initAgent() manager.initPlatformManager() if config.IntranetUpdate { - //私有化更新的Cron是核心业务场景,不再依赖检查更新或者online定时器触发,而是直接创建 - manager.TryToStartCronCheck() + //不再依赖检查更新或者online定时器触发,而是直接创建 + manager.TryToStartAutoCheck() } err = serverObject.SetWriteCallback(updater, "AutoInstallUpdates", updater.autoInstallUpdatesWriteCallback) if err != nil { diff --git a/src/lastore-daemon/manager.go b/src/lastore-daemon/manager.go index 620eb16d5..c7dfaa529 100644 --- a/src/lastore-daemon/manager.go +++ b/src/lastore-daemon/manager.go @@ -304,11 +304,11 @@ func (m *Manager) initPlatformManager() { } } -func (m *Manager) TryToStartCronCheck() { - if isTimerUnitFileExists(lastoreCronCheck) { +func (m *Manager) TryToStartAutoCheck() { + if isTimerUnitFileExists(lastoreAutoCheck) { return } - m.startCheckPolicyTask() + m.updateAutoCheckSystemUnit() } func (m *Manager) delUpdatePackage(sender dbus.Sender, jobName string, packages string) (*Job, error) { @@ -728,16 +728,56 @@ func (m *Manager) handleAutoCheckRegularlyEvent() error { } func (m *Manager) handleAutoCheckEvent() error { - if m.config.AutoCheckUpdates && !m.ImmutableAutoRecovery { - _, err := m.updateSource(dbus.Sender(m.service.Conn().Names()[0])) - if err != nil { + if m.ImmutableAutoRecovery { + return nil + } + + if !m.config.AutoCheckUpdates { // 不再需要自动检查更新 + return nil + } + + if m.config.PlatformUpdate { + return m.handleAutoCheckWithPlatform() + } + + _, err := m.updateSource(dbus.Sender(m.service.Conn().Names()[0])) + if err != nil { + logger.Warning(err) + return err + } + return nil +} + +func (m *Manager) handleAutoCheckWithPlatform() error { + needUpdate, err := m.checkPlatformPolicy() + if err != nil { + logger.Warningf("check platform policy failed: %v", err) + if _, err := m.updateSource(dbus.Sender(m.service.Conn().Names()[0])); err != nil { + logger.Warning(err) + } + return err + } + + if needUpdate { + if _, err := m.updateSource(dbus.Sender(m.service.Conn().Names()[0])); err != nil { logger.Warning(err) return err } + } else { + if err := m.updateAutoCheckSystemUnit(); err != nil { + logger.Warning(err) + } } return nil } +func (m *Manager) checkPlatformPolicy() (bool, error) { + if !m.config.PlatformUpdate { + return true, nil + } + return m.updatePlatform.CheckPolicyChanged() +} + func (m *Manager) handleAutoCleanEvent() error { const MaxCacheSize = 500.0 // size MB doClean := func() error { diff --git a/src/lastore-daemon/manager_unit.go b/src/lastore-daemon/manager_unit.go index 6b4343a4e..ffe510694 100644 --- a/src/lastore-daemon/manager_unit.go +++ b/src/lastore-daemon/manager_unit.go @@ -54,14 +54,35 @@ const ( type UnitName string +// lastoreAutoCheck: automatic update check scheduled task unit +// +// Complete workflow: +// 1. System startup phase +// startOfflineTask() -> getLastoreSystemUnitMap() +// -> Create lastoreAutoCheck.timer +// -> Delay time = getNextAutoCheckDelay() +// +// ↓ +// +// 2. Timer trigger phase +// systemd-run executes dbus-send +// -> Call Manager.HandleSystemEvent("AutoCheck") +// +// ↓ +// +// 3. Event processing phase +// delHandleSystemEvent() -> handleAutoCheckEvent() +// -> Execute actual update check operations (UpdateSource/platform version request) +// -> Update LastCheckTime +// -> Call updateAutoCheckSystemUnit() to reset timer + const ( lastoreAutoClean UnitName = "lastoreAutoClean" lastoreAutoCheck UnitName = "lastoreAutoCheck" lastoreAutoUpdateToken UnitName = "lastoreAutoUpdateToken" watchOsVersion UnitName = "watchOsVersion" lastoreInitIdleDownload UnitName = "lastoreInitIdleDownload" - lastoreRegularlyUpdate UnitName = "lastoreRegularlyUpdate" // 到触发时间后开始检查更新->下载更新->安装更新 - lastoreCronCheck UnitName = "lastoreCronCheck" + lastoreRegularlyUpdate UnitName = "lastoreRegularlyUpdate" lastorePostUpgrade UnitName = "lastorePostUpgrade" lastoreRetryPostMsg UnitName = "lastoreRetryPostMsg" ) @@ -79,8 +100,7 @@ func (m *Manager) getLastoreSystemUnitMap() lastoreUnitMap { unitMap := make(lastoreUnitMap) if (m.config.GetLastoreDaemonStatus()&config.DisableUpdate) == 0 && !m.ImmutableAutoRecovery { // 更新禁用未开启且无忧还原未开启时 unitMap[lastoreAutoCheck] = genHandleEventCmdArgs([]string{ - // 随机数范围1800-21600,时间为0.5~6小时 - fmt.Sprintf("--on-active=%d", int(m.getNextUpdateDelay()/time.Second)+rand.New(rand.NewSource(time.Now().UnixNano())).Intn(m.config.StartCheckRange[1]-m.config.StartCheckRange[0])+m.config.StartCheckRange[0])}, AutoCheck) // 根据上次检查时间,设置下一次自动检查时间 + fmt.Sprintf("--on-active=%d", m.getNextAutoCheckDelay())}, AutoCheck) } unitMap[lastoreAutoClean] = genHandleEventCmdArgs([]string{ "--on-active=600"}, AutoClean) // 10分钟后自动检查是否需要清理 @@ -260,31 +280,6 @@ func (m *Manager) updateTimerUnit(unitName UnitName) error { return nil } -func (m *Manager) startCheckPolicyTask() { - if m.config.CheckPolicyInterval == 0 { - logger.Info("config: not CheckPolicyInterval") - return - } - - args := []string{ - fmt.Sprintf("--unit=%s", lastoreCronCheck), - fmt.Sprintf("--on-active=%d", m.config.CheckPolicyInterval), - fmt.Sprintf(`--on-unit-active=%d`, m.config.CheckPolicyInterval), - "--uid=root", - "/usr/bin/lastore-tools", - "checkpolicy", - } - cmd := exec.Command(run, args...) - logger.Info(cmd.String()) - var errBuffer bytes.Buffer - cmd.Stderr = &errBuffer - err := cmd.Run() - if err != nil { - logger.Warning(err) - logger.Warning(errBuffer.String()) - } -} - func (m *Manager) handleAutoDownload() { if m.ImmutableAutoRecovery { logger.Debug("Immutable auto recovery is enabled, don't allow to auto download") @@ -332,6 +327,24 @@ func (m *Manager) getNextUpdateDelay() time.Duration { return remained + _minDelayTime } +func (m *Manager) getNextAutoCheckDelay() int { + checkInterval := m.config.CheckInterval + if checkInterval < 0 { + checkInterval = 0 + } + + elapsed := time.Since(m.config.LastCheckTime) + remained := int((checkInterval - elapsed) / time.Second) + if remained < 0 { + remained = 0 + } + + randomDelay := rand.New(rand.NewSource(time.Now().UnixNano())).Intn(m.config.StartCheckRange[1]-m.config.StartCheckRange[0]) + m.config.StartCheckRange[0] + autoCheckDelay := remained + randomDelay + logger.Infof("get next auto check delay, StartCheckRange=%v, randomDelay=%d, autoCheckDelay=%d", m.config.StartCheckRange, randomDelay, autoCheckDelay) + return autoCheckDelay +} + // isAllowedToTriggerSystemEvent checks if the uid is allowed to trigger system events func isAllowedToTriggerSystemEvent(uid uint32, eventType systemdEventType) bool { // Allow regular users to trigger OsVersionChanged event @@ -384,7 +397,6 @@ func (m *Manager) delHandleSystemEvent(sender dbus.Sender, eventType string) err if err != nil { logger.Warning(err) } - m.startCheckPolicyTask() // 在第一次自动检查更新后再加任务 }() case AutoClean: go func() { diff --git a/usr/share/dsg/configs/org.deepin.dde.lastore/org.deepin.dde.lastore.json b/usr/share/dsg/configs/org.deepin.dde.lastore/org.deepin.dde.lastore.json index f771c4406..b6b0d7bda 100644 --- a/usr/share/dsg/configs/org.deepin.dde.lastore/org.deepin.dde.lastore.json +++ b/usr/share/dsg/configs/org.deepin.dde.lastore/org.deepin.dde.lastore.json @@ -611,17 +611,6 @@ "permissions": "readwrite", "visibility": "private" }, - "check-policy-interval": { - "value": 0, - "serial": 0, - "flags": [ - "global" - ], - "name": "CheckPolicyInterval", - "description": "check policy interval (seconds)", - "permissions": "readwrite", - "visibility": "private" - }, "incremental-update": { "value": true, "serial": 0,