github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/overlord/configstate/configcore/refresh.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 // +build !nomanagers 3 4 /* 5 * Copyright (C) 2017-2018 Canonical Ltd 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 3 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 package configcore 22 23 import ( 24 "fmt" 25 "strconv" 26 "time" 27 28 "github.com/snapcore/snapd/overlord/configstate/config" 29 "github.com/snapcore/snapd/overlord/devicestate" 30 "github.com/snapcore/snapd/strutil" 31 "github.com/snapcore/snapd/timeutil" 32 ) 33 34 func init() { 35 supportedConfigurations["core.refresh.hold"] = true 36 supportedConfigurations["core.refresh.schedule"] = true 37 supportedConfigurations["core.refresh.timer"] = true 38 supportedConfigurations["core.refresh.metered"] = true 39 supportedConfigurations["core.refresh.retain"] = true 40 supportedConfigurations["core.refresh.rate-limit"] = true 41 } 42 43 func validateRefreshSchedule(tr config.Conf) error { 44 refreshRetainStr, err := coreCfg(tr, "refresh.retain") 45 if err != nil { 46 return err 47 } 48 if refreshRetainStr != "" { 49 if n, err := strconv.ParseUint(refreshRetainStr, 10, 8); err != nil || (n < 2 || n > 20) { 50 return fmt.Errorf("retain must be a number between 2 and 20, not %q", refreshRetainStr) 51 } 52 } 53 54 refreshHoldStr, err := coreCfg(tr, "refresh.hold") 55 if err != nil { 56 return err 57 } 58 if refreshHoldStr != "" { 59 if _, err := time.Parse(time.RFC3339, refreshHoldStr); err != nil { 60 return fmt.Errorf("refresh.hold cannot be parsed: %v", err) 61 } 62 } 63 64 refreshOnMeteredStr, err := coreCfg(tr, "refresh.metered") 65 if err != nil { 66 return err 67 } 68 switch refreshOnMeteredStr { 69 case "", "hold": 70 // noop 71 default: 72 return fmt.Errorf("refresh.metered value %q is invalid", refreshOnMeteredStr) 73 } 74 75 // check (new) refresh.timer 76 refreshTimerStr, err := coreCfg(tr, "refresh.timer") 77 if err != nil { 78 return err 79 } 80 if refreshTimerStr == "managed" { 81 st := tr.State() 82 st.Lock() 83 defer st.Unlock() 84 85 if !devicestate.CanManageRefreshes(st) { 86 return fmt.Errorf("cannot set schedule to managed") 87 } 88 return nil 89 } 90 if refreshTimerStr != "" { 91 // try legacy refresh.schedule setting if new-style 92 // refresh.timer is not set 93 if _, err = timeutil.ParseSchedule(refreshTimerStr); err != nil { 94 return err 95 } 96 } 97 98 // check (legacy) refresh.schedule 99 refreshScheduleStr, err := coreCfg(tr, "refresh.schedule") 100 if err != nil { 101 return err 102 } 103 if refreshScheduleStr == "" { 104 return nil 105 } 106 107 if refreshScheduleStr == "managed" { 108 st := tr.State() 109 st.Lock() 110 defer st.Unlock() 111 112 if !devicestate.CanManageRefreshes(st) { 113 return fmt.Errorf("cannot set schedule to managed") 114 } 115 return nil 116 } 117 118 _, err = timeutil.ParseLegacySchedule(refreshScheduleStr) 119 return err 120 } 121 122 func validateRefreshRateLimit(tr config.Conf) error { 123 refreshRateLimit, err := coreCfg(tr, "refresh.rate-limit") 124 if err != nil { 125 return err 126 } 127 // reset is fine 128 if len(refreshRateLimit) == 0 { 129 return nil 130 } 131 if _, err := strutil.ParseByteSize(refreshRateLimit); err != nil { 132 return err 133 } 134 return nil 135 }