-
Notifications
You must be signed in to change notification settings - Fork 594
/
Copy pathsysconfig.go
160 lines (132 loc) · 4.99 KB
/
sysconfig.go
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
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2020 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 sysconfig
import (
"fmt"
"path/filepath"
"github.com/snapcore/snapd/asserts"
"github.com/snapcore/snapd/gadget"
"github.com/snapcore/snapd/snap"
)
// See https://github.com/snapcore/core20/pull/46
const writableDefaultsDir = "_writable_defaults"
// Options is the set of options used to configure the run system
type Options struct {
// CloudInitSrcDir is where to find the cloud-init data when installing it,
// i.e. in early boot install mode it could be something like
// filepath.Join(boot.InitramfsUbuntuSeedDir,"data")
CloudInitSrcDir string
// TargetRootDir is the root directory where to install configure
// data, i.e. for cloud-init during the initramfs it will be something like
// boot.InstallHostWritableDir
TargetRootDir string
// AllowCloudInit is whether to allow cloud-init to run or not in the
// TargetRootDir.
AllowCloudInit bool
// GadgetDir is the path of the mounted gadget snap.
GadgetDir string
// GadgetSnap is a snap.Container of the gadget snap. This is used in
// priority over GadgetDir if set.
GadgetSnap snap.Container
}
// Device carries information about the device model and mode that is
// relevant to sysconfig.
type Device interface {
RunMode() bool
Classic() bool
Kernel() string
//Base() string
HasModeenv() bool
//Model() *asserts.Model
}
type configedDevice struct {
model *asserts.Model
}
func (di *configedDevice) RunMode() bool {
// the functions in sysconfig are used to configure not yet
// running systems.
return false
}
func (d *configedDevice) Classic() bool {
return d.model.Classic()
}
func (d *configedDevice) Kernel() string {
return d.model.Kernel()
}
func (d *configedDevice) HasModeenv() bool {
return d.model.Grade() != asserts.ModelGradeUnset
}
// ApplyFilesystemOnlyDefaultsImpl is initialized by init() of configcore.
var ApplyFilesystemOnlyDefaultsImpl = func(dev Device, rootDir string, defaults map[string]interface{}) error {
panic("ApplyFilesystemOnlyDefaultsImpl is unset, import overlord/configstate/configcore")
}
// ApplyFilesystemOnlyDefaults applies (via configcore.filesystemOnlyApply())
// filesystem modifications under rootDir, according to the defaults.
// 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.
func ApplyFilesystemOnlyDefaults(model *asserts.Model, rootDir string, defaults map[string]interface{}) error {
dev := &configedDevice{model: model}
return ApplyFilesystemOnlyDefaultsImpl(dev, rootDir, defaults)
}
// ConfigureTargetSystem configures the ubuntu-data partition with
// any configuration needed from e.g. the gadget or for cloud-init (and also for
// cloud-init from the gadget).
// It is okay to use both from install mode for run mode, as well as from the
// initramfs for recover mode.
// It is only meant to be used with models that have a grade (i.e. UC20+).
func ConfigureTargetSystem(model *asserts.Model, opts *Options) error {
// check that we have a uc20 model
if model.Grade() == asserts.ModelGradeUnset {
return fmt.Errorf("internal error: ConfigureTargetSystem can only be used with a model with a grade")
}
if err := configureCloudInit(model, opts); err != nil {
return err
}
var gadgetInfo *gadget.Info
var err error
switch {
case opts.GadgetSnap != nil:
// we do not perform consistency validation here because
// such unlikely problems are better surfaced in different
// and less surprising contexts like the seeding itself
gadgetInfo, err = gadget.ReadInfoFromSnapFileNoValidate(opts.GadgetSnap, nil)
case opts.GadgetDir != "":
gadgetInfo, err = gadget.ReadInfo(opts.GadgetDir, nil)
}
if err != nil {
return err
}
if gadgetInfo != nil {
defaults := gadget.SystemDefaults(gadgetInfo.Defaults)
if len(defaults) > 0 {
// TODO for classic with modes we do not want it under
// _writable_defaults folder.
if err := ApplyFilesystemOnlyDefaults(model, WritableDefaultsDir(opts.TargetRootDir), defaults); err != nil {
return err
}
}
}
return nil
}
// WritableDefaultsDir returns the full path of the joined subdir under the
// subtree for default content for system data living at rootdir,
// i.e. rootdir/_writable_defaults/subdir...
func WritableDefaultsDir(rootdir string, subdir ...string) string {
return filepath.Join(rootdir, writableDefaultsDir, filepath.Join(subdir...))
}