1
// This Source Code Form is subject to the terms of the Mozilla Public
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
17
"github.com/coreos/go-iptables/iptables"
18
"github.com/hashicorp/go-getter/v2"
20
"github.com/siderolabs/talos/pkg/machinery/constants"
21
"github.com/siderolabs/talos/pkg/provision"
24
func (p *provisioner) preflightChecks(ctx context.Context, request provision.ClusterRequest, options provision.Options, arch Arch) error {
25
checkContext := preflightCheckContext{
31
for _, check := range []func(ctx context.Context) error{
32
checkContext.verifyRoot,
33
checkContext.checkKVM,
34
checkContext.qemuExecutable,
35
checkContext.checkFlashImages,
36
checkContext.swtpmExecutable,
37
checkContext.cniDirectories,
38
checkContext.cniBundle,
39
checkContext.checkIptables,
41
if err := check(ctx); err != nil {
49
type preflightCheckContext struct {
50
request provision.ClusterRequest
51
options provision.Options
55
func (check *preflightCheckContext) verifyRoot(ctx context.Context) error {
56
if os.Geteuid() != 0 {
57
return errors.New("error: please run as root user (CNI requirement), we recommend running with `sudo -E`")
63
func (check *preflightCheckContext) checkKVM(ctx context.Context) error {
64
f, err := os.OpenFile("/dev/kvm", os.O_RDWR, 0)
66
return fmt.Errorf("error opening /dev/kvm, please make sure KVM support is enabled in Linux kernel: %w", err)
72
func (check *preflightCheckContext) qemuExecutable(ctx context.Context) error {
73
if check.arch.QemuExecutable() == "" {
74
return fmt.Errorf("QEMU executable (qemu-system-%s or qemu-kvm) not found, please install QEMU with package manager", check.arch.QemuArch())
80
func (check *preflightCheckContext) checkFlashImages(ctx context.Context) error {
81
for _, flashImage := range check.arch.PFlash(check.options.UEFIEnabled, check.options.ExtraUEFISearchPaths) {
82
if len(flashImage.SourcePaths) == 0 {
88
for _, path := range flashImage.SourcePaths {
89
_, err := os.Stat(path)
98
return fmt.Errorf("the required flash image was not found in any of the expected paths for (%q), "+
99
"please install it with the package manager or specify --extra-uefi-search-paths", flashImage.SourcePaths)
106
func (check *preflightCheckContext) swtpmExecutable(ctx context.Context) error {
107
if check.options.TPM2Enabled {
108
if _, err := exec.LookPath("swtpm"); err != nil {
109
return fmt.Errorf("swtpm not found in PATH, please install swtpm-tools with the package manager: %w", err)
116
func (check *preflightCheckContext) cniDirectories(ctx context.Context) error {
117
cniDirs := append([]string{}, check.request.Network.CNI.BinPath...)
118
cniDirs = append(cniDirs, check.request.Network.CNI.CacheDir, check.request.Network.CNI.ConfDir)
120
for _, cniDir := range cniDirs {
121
st, err := os.Stat(cniDir)
123
if !os.IsNotExist(err) {
124
return fmt.Errorf("error checking CNI directory %q: %w", cniDir, err)
127
fmt.Fprintf(os.Stderr, "creating %q\n", cniDir)
129
err = os.MkdirAll(cniDir, 0o777)
138
return fmt.Errorf("CNI path %q exists, but it's not a directory", cniDir)
145
func (check *preflightCheckContext) cniBundle(ctx context.Context) error {
148
requiredCNIPlugins := []string{"bridge", "firewall", "static", "tc-redirect-tap"}
150
for _, cniPlugin := range requiredCNIPlugins {
153
for _, binPath := range check.request.Network.CNI.BinPath {
154
_, err := os.Stat(filepath.Join(binPath, cniPlugin))
171
if check.request.Network.CNI.BundleURL == "" {
172
return fmt.Errorf("error: required CNI plugins %q were not found in %q", requiredCNIPlugins, check.request.Network.CNI.BinPath)
175
pwd, err := os.Getwd()
180
client := getter.Client{}
181
src := strings.ReplaceAll(check.request.Network.CNI.BundleURL, constants.ArchVariable, runtime.GOARCH)
182
dst := check.request.Network.CNI.BinPath[0]
184
fmt.Fprintf(os.Stderr, "downloading CNI bundle from %q to %q\n", src, dst)
186
_, err = client.Get(ctx, &getter.Request{
190
GetMode: getter.ModeDir,
196
func (check *preflightCheckContext) checkIptables(ctx context.Context) error {
197
_, err := iptables.New()
199
return fmt.Errorf("error accessing iptables: %w", err)