Andrey Smirnov b453385bd9
feat: support volume configuration, provisioning, etc
This implements the first round of changes, replacing the volume backend
with the new implementation, while keeping most of the external
interfaces intact.

See #8367

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
2024-08-30 18:32:34 +04:00

136 lines
3.5 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package install
import (
"bytes"
"compress/gzip"
"context"
"fmt"
"io"
"log"
"os"
"runtime"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
pkgkernel "github.com/siderolabs/talos/pkg/kernel"
"github.com/siderolabs/talos/pkg/machinery/client"
"github.com/siderolabs/talos/pkg/machinery/compatibility"
"github.com/siderolabs/talos/pkg/machinery/constants"
"github.com/siderolabs/talos/pkg/machinery/kernel"
"github.com/siderolabs/talos/pkg/machinery/role"
)
// errataArm64ZBoot handles the case when upgrading from Talos < 1.8.0 on arm64 to compressed kernel.
func errataArm64ZBoot() {
if runtime.GOARCH != "arm64" {
return
}
oldConfig, err := os.OpenFile("/proc/config.gz", os.O_RDONLY, 0)
if err != nil {
log.Printf("failed to open /proc/config.gz: %s", err)
return
}
defer oldConfig.Close() //nolint:errcheck
r, err := gzip.NewReader(oldConfig)
if err != nil {
log.Printf("failed to read /proc/config.gz: %s", err)
return
}
contents, err := io.ReadAll(r)
if err != nil {
log.Printf("failed to read /proc/config.gz: %s", err)
return
}
if bytes.Contains(contents, []byte("CONFIG_ARM64_ZBOOT=y")) {
// nothing to do
return
}
log.Printf("disabling kexec due to upgrade to the compressed kernel")
if err = pkgkernel.WriteParam(&kernel.Param{
Key: "proc.sys.kernel.kexec_load_disabled",
Value: "1",
}); err != nil {
log.Printf("failed to disable kexec: %s", err)
}
}
// errataNetIfnames appends the `net.ifnames=0` kernel parameter to the kernel command line if upgrading
// from an old enough version of Talos.
func (i *Installer) errataNetIfnames(talosVersion *compatibility.TalosVersion) {
if i.cmdline.Get(constants.KernelParamNetIfnames).First() != nil {
// net.ifnames is already set, nothing to do
return
}
oldTalos := upgradeFromPreIfnamesTalos(talosVersion)
if oldTalos {
log.Printf("appending net.ifnames=0 to the kernel command line")
i.cmdline.Append(constants.KernelParamNetIfnames, "0")
}
}
func readHostTalosVersion() (*compatibility.TalosVersion, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
if _, err := os.Stat(constants.MachineSocketPath); err != nil {
// can't read Talos version
return nil, nil
}
c, err := client.New(ctx,
client.WithUnixSocket(constants.MachineSocketPath),
client.WithGRPCDialOptions(grpc.WithTransportCredentials(insecure.NewCredentials())),
)
if err != nil {
return nil, fmt.Errorf("error connecting to the machine service: %w", err)
}
defer c.Close() //nolint:errcheck
// inject "fake" authorization
ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs(constants.APIAuthzRoleMetadataKey, string(role.Admin)))
resp, err := c.Version(ctx)
if err != nil {
return nil, fmt.Errorf("error getting Talos version: %w", err)
}
hostVersion := unpack(resp.Messages)
talosVersion, err := compatibility.ParseTalosVersion(hostVersion.Version)
if err != nil {
return nil, fmt.Errorf("error parsing Talos version: %w", err)
}
return talosVersion, nil
}
func upgradeFromPreIfnamesTalos(talosVersion *compatibility.TalosVersion) bool {
if talosVersion == nil {
// old Talos version, include fallback
return true
}
return talosVersion.DisablePredictableNetworkInterfaces()
}