// 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 provision import ( "errors" "net/netip" "slices" "time" "github.com/google/uuid" mounttypes "github.com/moby/moby/api/types/mount" "github.com/siderolabs/go-procfs/procfs" "github.com/siderolabs/talos/pkg/machinery/config" "github.com/siderolabs/talos/pkg/machinery/config/machine" "github.com/siderolabs/talos/pkg/machinery/imager/quirks" ) // ClusterRequest is the root object describing cluster to be provisioned. type ClusterRequest struct { Name string Network NetworkRequest Nodes NodeRequests // Docker specific parameters. Image string // Boot options (QEMU). KernelPath string InitramfsPath string ISOPath string USBPath string UKIPath string DiskImagePath string IPXEBootScript string // Encryption KMSEndpoint string // Path to talosctl executable to re-execute itself as needed. SelfExecutable string // Path to root of state directory (~/.talos/clusters by default). StateDirectory string SiderolinkRequest SiderolinkRequest } // CNIConfig describes CNI part of NetworkRequest. type CNIConfig struct { BinPath []string ConfDir string CacheDir string BundleURL string } // NetworkRequest describes cluster network. type NetworkRequest struct { Name string CIDRs []netip.Prefix NoMasqueradeCIDRs []netip.Prefix GatewayAddrs []netip.Addr MTU int Nameservers []netip.Addr LoadBalancerPorts []int // CNI-specific parameters. CNI CNIConfig // DHCP options DHCPSkipHostname bool // Docker-specific parameters. DockerDisableIPv6 bool // Network chaos parameters. NetworkChaos bool Jitter time.Duration Latency time.Duration PacketLoss float64 PacketReorder float64 PacketCorrupt float64 Bandwidth int // Airgapped limits VM network access to the provisioning network only (qemu/linux). Airgapped bool ImageCachePath string ImageCacheTLSCertFile string ImageCacheTLSKeyFile string ImageCachePort uint16 } // NodeRequests is a list of NodeRequest. type NodeRequests []NodeRequest // FindInitNode looks up init node, it returns an error if no init node is present or if it's duplicate. func (reqs NodeRequests) FindInitNode() (req NodeRequest, err error) { found := false for i := range reqs { if reqs[i].Config == nil { continue } if reqs[i].Config.Machine().Type() == machine.TypeInit { if found { err = errors.New("duplicate init node in requests") return req, err } req = reqs[i] found = true } } if !found { err = errors.New("no init node found in requests") } return req, err } // ControlPlaneNodes returns subset of nodes which are Init/ControlPlane type. func (reqs NodeRequests) ControlPlaneNodes() (nodes []NodeRequest) { for i := range reqs { if reqs[i].Type == machine.TypeInit || reqs[i].Type == machine.TypeControlPlane { nodes = append(nodes, reqs[i]) } } return nodes } // WorkerNodes returns subset of nodes which are Init/ControlPlane type. func (reqs NodeRequests) WorkerNodes() (nodes []NodeRequest) { for i := range reqs { if reqs[i].Type == machine.TypeWorker { nodes = append(nodes, reqs[i]) } } return nodes } // PXENodes returns subset of nodes which are PXE booted. func (reqs NodeRequests) PXENodes() (nodes []NodeRequest) { for i := range reqs { if reqs[i].PXEBooted { nodes = append(nodes, reqs[i]) } } return nodes } // Disk represents a disk size and name in NodeRequest. type Disk struct { // Size in bytes. Size uint64 // Whether to skip preallocating the disk space. SkipPreallocate bool // Driver for the disk. // // Supported types: "virtio", "ide", "ahci", "scsi", "nvme", "megaraid", "virtiofs" (special). Driver string // Block size for the disk, defaults to 512 if not set. BlockSize uint // Serial number for the disk. Serial string // Tag for the disk, only used for Virtiofs disks. Tag string } // ConfigInjectionMethod describes how to inject configuration into the node. type ConfigInjectionMethod int const ( // ConfigInjectionMethodHTTP injects configuration via HTTP. ConfigInjectionMethodHTTP ConfigInjectionMethod = iota // ConfigInjectionMethodMetalISO injects configuration via Metal ISO. ConfigInjectionMethodMetalISO ) // NodeRequest describes a request for a node. type NodeRequest struct { Name string IPs []netip.Addr Type machine.Type Quirks quirks.Quirks Config config.Provider ConfigInjectionMethod ConfigInjectionMethod // Share of CPUs, in 1e-9 fractions NanoCPUs int64 // Memory limit in bytes Memory int64 // Disks (volumes), if applicable (VM only) Disks []*Disk // Mounts (containers only) Mounts []mounttypes.Mount // Ports Ports []string // SkipInjectingConfig disables reading configuration from http server SkipInjectingConfig bool // DefaultBootOrder overrides default boot order "cn" (disk, then network boot). // // BootOrder can be forced to be "nc" (PXE boot) via the API in QEMU provisioner. DefaultBootOrder string // ExtraKernelArgs passes additional kernel args // to the initial boot from initramfs and vmlinuz. // // This doesn't apply to boots from ISO or from the disk image. ExtraKernelArgs *procfs.Cmdline // SDStubKernelArgs passes additional kernel args via the systemd-stub. // // This applies to boots from ISO and from the disk image. SDStubKernelArgs *procfs.Cmdline // UUID allows to specify the UUID of the node (VMs only). // // If not specified, a random UUID will be generated. UUID *uuid.UUID // Testing features // BadRTC resets RTC to well known time in the past (QEMU provisioner). BadRTC bool // PXE-booted VMs PXEBooted bool TFTPServer string IPXEBootFilename string } // SiderolinkRequest describes a request for SideroLink agent. type SiderolinkRequest struct { WireguardEndpoint string APIEndpoint string APICertificate []byte APIKey []byte SinkEndpoint string LogEndpoint string SiderolinkBind []SiderolinkBind } // GetAddr returns the address for the given UUID. func (sr *SiderolinkRequest) GetAddr(u *uuid.UUID) (netip.Addr, bool) { if idx := slices.IndexFunc(sr.SiderolinkBind, func(sb SiderolinkBind) bool { return sb.UUID == *u }); idx != -1 { return sr.SiderolinkBind[idx].Addr, true } return netip.Addr{}, false } // SiderolinkBind describes a pair of prebinded UUID->Addr for SideroLink agent. type SiderolinkBind struct { UUID uuid.UUID Addr netip.Addr }