-
Notifications
You must be signed in to change notification settings - Fork 680
Expand file tree
/
Copy pathhandlers.go
More file actions
212 lines (172 loc) · 6.48 KB
/
Copy pathhandlers.go
File metadata and controls
212 lines (172 loc) · 6.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2021 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package configcore
import (
"fmt"
"github.com/snapcore/snapd/sysconfig"
)
type configHandler interface {
validate(ConfGetter) error
handle(sysconfig.Device, ConfGetter, *fsOnlyContext) error
needsState() bool
flags() flags
}
// flags carries extra flags that influence how the handler is called.
type flags struct {
// coreOnlyConfig tells Run/FilesystemOnlyApply to apply the config on core
// systems only.
coreOnlyConfig bool
// modeenvOnlyConfig is set if the option can be applied only
// to systems with core-like booting.
modeenvOnlyConfig bool
// validatedOnlyStateConfig tells that the config requires only validation,
// its options are applied dynamically elsewhere.
validatedOnlyStateConfig bool
// earlyConfigFilter expresses whether the handler supports
// any early configuration options (that can and must be
// set before even seeding is finished).
// If set the function should copy such options from values
// to early.
earlyConfigFilter filterFunc
}
type fsOnlyHandler struct {
validateFunc func(ConfGetter) error
handleFunc func(sysconfig.Device, ConfGetter, *fsOnlyContext) error
configFlags flags
}
var handlers []configHandler
func init() {
// Most of these handlers are no-op on classic.
// TODO: consider allowing some of these on classic too?
// consider erroring on core-only options on classic?
coreOnly := &flags{coreOnlyConfig: true}
// watchdog.{runtime-timeout,shutdown-timeout}
addFSOnlyHandler(validateWatchdogOptions, handleWatchdogConfiguration, coreOnly)
// Export experimental.* flags to a place easily accessible from snapd helpers.
addFSOnlyHandler(validateExperimentalSettings, doExportExperimentalFlags, &flags{earlyConfigFilter: earlyExperimentalSettingsFilter})
// network.disable-ipv6
addFSOnlyHandler(validateNetworkSettings, handleNetworkConfiguration, coreOnly)
// service.*.disable
addFSOnlyHandler(validateServiceConfiguration, handleServiceConfiguration, coreOnly)
// system.power-key-action
addFSOnlyHandler(nil, handlePowerButtonConfiguration, coreOnly)
// system.disable-ctrl-alt-del
addFSOnlyHandler(nil, handleCtrlAltDelConfiguration, coreOnly)
// pi-config.*
addFSOnlyHandler(nil, handlePiConfiguration, coreOnly)
// system.disable-backlight-service
addFSOnlyHandler(validateBacklightServiceSettings, handleBacklightServiceConfiguration, coreOnly)
// swap.size
addFSOnlyHandler(validateSystemSwapConfiguration, handlesystemSwapConfiguration, coreOnly)
// system.kernel.printk.console-loglevel
addFSOnlyHandler(validateSysctlOptions, handleSysctlConfiguration, coreOnly)
// journal.persistent
addFSOnlyHandler(validateJournalSettings, handleJournalConfiguration, coreOnly)
// system.timezone
addFSOnlyHandler(validateTimezoneSettings, handleTimezoneConfiguration, coreOnly)
// system.hostname - note that the validation is done via hostnamectl
// when applying so there is no validation handler, see LP:1952740
addFSOnlyHandler(nil, handleHostnameConfiguration, coreOnly)
// home directory configuration
addFSOnlyHandler(validateHomedirsConfiguration, handleHomedirsConfiguration, nil)
// tmpfs.size
addFSOnlyHandler(validateTmpfsSettings, handleTmpfsConfiguration, coreOnly)
// system.faillock
addFSOnlyHandler(validateFaillockSettings, handleFaillockConfiguration, coreOnly)
// store.access
addFSOnlyHandler(validateStoreAccess, handleStoreAccess, coreOnly)
// system.coredump
addFSOnlyHandler(validateCoredumpSettings, handleCoredumpConfiguration, coreOnly)
// system.motd
addFSOnlyHandler(validateMotdConfiguration, handleMotdConfiguration, coreOnly)
// system.ntp.*
addFSOnlyHandler(validateNTPSettings, handleNTPConfiguration, coreOnly)
sysconfig.ApplyFilesystemOnlyDefaultsImpl = filesystemOnlyApply
}
// addFSOnlyHandler registers functions to validate and handle a subset of
// system config options that do not require to manipulate state but only
// the file system.
func addFSOnlyHandler(validate func(ConfGetter) error, handle func(sysconfig.Device, ConfGetter, *fsOnlyContext) error, flags *flags) {
if handle == nil {
panic("cannot have nil handle with fsOnlyHandler")
}
h := &fsOnlyHandler{
validateFunc: validate,
handleFunc: handle,
}
if flags != nil {
h.configFlags = *flags
}
handlers = append(handlers, h)
}
func (h *fsOnlyHandler) needsState() bool {
return false
}
func (h *fsOnlyHandler) flags() flags {
return h.configFlags
}
func (h *fsOnlyHandler) validate(cfg ConfGetter) error {
if h.validateFunc != nil {
return h.validateFunc(cfg)
}
return nil
}
func (h *fsOnlyHandler) handle(dev sysconfig.Device, cfg ConfGetter, opts *fsOnlyContext) error {
// handleFunc is guaranteed to be non-nil by addFSOnlyHandler
return h.handleFunc(dev, cfg, opts)
}
// filesystemOnlyApply applies filesystem modifications under rootDir, according to the
// cfg configuration. This is a subset of core config options that is important
// early during boot, before all the configuration is applied as part of
// normal execution of configure hook.
// Exposed for use via sysconfig.ApplyFilesystemOnlyDefaults.
func filesystemOnlyApply(dev sysconfig.Device, rootDir string, values map[string]any) error {
if rootDir == "" {
return fmt.Errorf("internal error: root directory for configcore.FilesystemOnlyApply() not set")
}
cfg := plainCoreConfig(values)
ctx := &fsOnlyContext{
RootDir: rootDir,
}
return filesystemOnlyRun(dev, cfg, ctx)
}
func filesystemOnlyRun(dev sysconfig.Device, cfg ConfGetter, ctx *fsOnlyContext) error {
for _, h := range handlers {
if h.needsState() {
continue
}
if err := h.validate(cfg); err != nil {
return err
}
}
for _, h := range handlers {
if h.needsState() {
continue
}
if h.flags().coreOnlyConfig && dev.Classic() {
continue
}
if h.flags().modeenvOnlyConfig && !dev.HasModeenv() {
continue
}
if err := h.handle(dev, cfg, ctx); err != nil {
return err
}
}
return nil
}