From c6db6029f61cd802ae41f430437583acd0673cf6 Mon Sep 17 00:00:00 2001 From: Stephen Benjamin Date: Thu, 5 Dec 2019 12:20:54 -0500 Subject: [PATCH] baremetal: make provisioning networks more configurable This change adds 4 new options to the baremetal platform: - ProvisioningNetworkInterface - ProvisioningNetworkCIDR - ProvisioningDHCPExternal - ProvisioningDHCPRange This makes the provisioning network more configurable, by allowing users to specify a specific network interface, which network, and settings for whether the cluster should provide DHCP services on the provisioning network, or if it will be managed externally. If we will provide DHCP services on the network, the user may further customize which range to use. This change is a prerequisite to a number of additional high-priority work items for the baremetal IPI platform, including single-stack IPv6 provisioning, external DHCP support, and end-to-end seamless deployment without a manually created config map. Co-authored-by: Ian Main Co-authored-by: Stephen Benjamin --- .../usr/local/bin/startironic.sh.template | 8 +- docs/user/metal/install_ipi.md | 16 +- .../ignition/bootstrap/baremetal/template.go | 39 ++ .../bootstrap/baremetal/template_test.go | 39 ++ pkg/asset/ignition/bootstrap/bootstrap.go | 18 + pkg/types/baremetal/defaults/platform.go | 56 +- pkg/types/baremetal/defaults/platform_test.go | 120 +++++ pkg/types/baremetal/platform.go | 27 +- pkg/types/baremetal/validation/platform.go | 33 ++ .../baremetal/validation/platform_test.go | 479 ++++++++++++------ pkg/types/validation/installconfig_test.go | 22 +- 11 files changed, 670 insertions(+), 187 deletions(-) create mode 100644 pkg/asset/ignition/bootstrap/baremetal/template.go create mode 100644 pkg/asset/ignition/bootstrap/baremetal/template_test.go create mode 100644 pkg/types/baremetal/defaults/platform_test.go diff --git a/data/data/bootstrap/baremetal/files/usr/local/bin/startironic.sh.template b/data/data/bootstrap/baremetal/files/usr/local/bin/startironic.sh.template index 8e795b3e50a..ed2b588ca16 100755 --- a/data/data/bootstrap/baremetal/files/usr/local/bin/startironic.sh.template +++ b/data/data/bootstrap/baremetal/files/usr/local/bin/startironic.sh.template @@ -11,6 +11,10 @@ COREOS_DOWNLOADER_IMAGE=$(image_for ironic-machine-os-downloader || image_for ir # This image is templated in via the installer pkg/asset/ignition/bootstrap/bootstrap.go RHCOS_BOOT_IMAGE_URL="{{.BootImage}}" +# This DHCP range is used by dnsmasq to serve DHCP to the cluster. If empty +# dnsmasq will only serve TFTP, and DHCP will be disabled. +DHCP_RANGE="{{.PlatformData.BareMetal.ProvisioningDHCPRange}}" + # First we stop any previously started containers, because ExecStop only runs when the ExecStart process # e.g this script is still running, but we exit if *any* of the containers exits unexpectedly for name in ironic-api ironic-conductor ironic-inspector dnsmasq httpd mariadb ipa-downloader coreos-downloader; do @@ -19,10 +23,9 @@ for name in ironic-api ironic-conductor ironic-inspector dnsmasq httpd mariadb i done # Start the provisioning nic if not already started -# Note removal of the hard-coded subnet tracked via https://github.com/openshift/installer/issues/2091 PROVISIONING_NIC=ens4 if ! nmcli -t device | grep "$PROVISIONING_NIC:ethernet:connected:provisioning"; then - nmcli c add type ethernet ifname $PROVISIONING_NIC con-name provisioning ip4 172.22.0.2/24 gw4 172.22.0.1 + nmcli c add type ethernet ifname $PROVISIONING_NIC con-name provisioning {{ if .PlatformData.BareMetal.ProvisioningIPv6 }} ip6 {{ else }} ip4 {{ end }} {{.PlatformData.BareMetal.ProvisioningIP}}/{{.PlatformData.BareMetal.ProvisioningCIDR}} nmcli c up provisioning fi @@ -63,6 +66,7 @@ podman run -d --net host --privileged --name mariadb \ podman run -d --net host --privileged --name dnsmasq \ --env PROVISIONING_INTERFACE=$PROVISIONING_NIC \ + --env DHCP_RANGE=$DHCP_RANGE \ -v $IRONIC_SHARED_VOLUME:/shared:z --entrypoint /bin/rundnsmasq ${IRONIC_IMAGE} podman run -d --net host --privileged --name httpd \ diff --git a/docs/user/metal/install_ipi.md b/docs/user/metal/install_ipi.md index 277ec116b2f..8256aa9f653 100644 --- a/docs/user/metal/install_ipi.md +++ b/docs/user/metal/install_ipi.md @@ -46,10 +46,18 @@ purposes: * `*.apps..` - pointing to the Ingress VIP * **NIC #2 - Provisioning Network** - * A private, non-routed network, used for PXE based provisioning. - * DHCP is automated for this network. - * Addressing for this network is currently hard coded as `172.22.0.0/24`, but - will be made configurable in the future. + * A private network used for PXE based provisioning. + * DHCP is automated for this network by default, to rely on external + DHCP, set the platform's `provisioningDHCPExternal` option to `true` + * Addressing for this network defaults to `172.22.0.0/24`, but is + configurable by setting the `provisioningNetworkCIDR` option. + * Two IP's are required to be available for use, one for the bootstrap + host, and one as a provisioning IP in the running cluster. By + default, these are the 2nd and 3rd addresses in the + `provisioningNetworkCIDR` (e.g. 172.22.0.2, and 172.22.0.3). + * To specify the name of the provisioning network interface, + set the `provisioningNetworkInterface` option. This is the network interface + on a master that is connected to the provisioning network. * **Out-of-band Management Network** * Servers will typically have an additional NIC used by the onboard diff --git a/pkg/asset/ignition/bootstrap/baremetal/template.go b/pkg/asset/ignition/bootstrap/baremetal/template.go new file mode 100644 index 00000000000..526481e64f0 --- /dev/null +++ b/pkg/asset/ignition/bootstrap/baremetal/template.go @@ -0,0 +1,39 @@ +package baremetal + +import ( + "github.com/openshift/installer/pkg/types/baremetal" +) + +// TemplateData holds data specific to templates used for the baremetal platform. +type TemplateData struct { + // ProvisioningIP holds the IP the bootstrap node will use to service Ironic, TFTP, etc. + ProvisioningIP string + + // ProvisioningIPv6 determines if we are using IPv6 or not. + ProvisioningIPv6 bool + + // ProvisioningCIDR has the integer CIDR notation, e.g. 255.255.255.0 should be "24" + ProvisioningCIDR int + + // ProvisioningDHCPRange has the DHCP range, if DHCP is not external. Otherwise it + // should be blank. + ProvisioningDHCPRange string +} + +// GetTemplateData returns platform-specific data for bootstrap templates. +func GetTemplateData(config *baremetal.Platform) *TemplateData { + var templateData TemplateData + + templateData.ProvisioningIP = config.BootstrapProvisioningIP + + cidr, _ := config.ProvisioningNetworkCIDR.Mask.Size() + templateData.ProvisioningCIDR = cidr + + templateData.ProvisioningIPv6 = config.ProvisioningNetworkCIDR.IP.To4() == nil + + if !config.ProvisioningDHCPExternal { + templateData.ProvisioningDHCPRange = config.ProvisioningDHCPRange + } + + return &templateData +} diff --git a/pkg/asset/ignition/bootstrap/baremetal/template_test.go b/pkg/asset/ignition/bootstrap/baremetal/template_test.go new file mode 100644 index 00000000000..2e2d837dbb0 --- /dev/null +++ b/pkg/asset/ignition/bootstrap/baremetal/template_test.go @@ -0,0 +1,39 @@ +package baremetal + +import ( + "github.com/openshift/installer/pkg/ipnet" + "github.com/openshift/installer/pkg/types/baremetal" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestTemplatingIPv4(t *testing.T) { + bareMetalConfig := baremetal.Platform{ + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + BootstrapProvisioningIP: "172.22.0.2", + ProvisioningDHCPExternal: false, + ProvisioningDHCPRange: "172.22.0.10,172.22.0.100", + } + + result := GetTemplateData(&bareMetalConfig) + + assert.Equal(t, result.ProvisioningDHCPRange, "172.22.0.10,172.22.0.100") + assert.Equal(t, result.ProvisioningCIDR, 24) + assert.Equal(t, result.ProvisioningIPv6, false) + assert.Equal(t, result.ProvisioningIP, "172.22.0.2") +} + +func TestTemplatingIPv6(t *testing.T) { + bareMetalConfig := baremetal.Platform{ + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("fd2e:6f44:5dd8:b856::0/64"), + BootstrapProvisioningIP: "fd2e:6f44:5dd8:b856::2", + ProvisioningDHCPExternal: true, + } + + result := GetTemplateData(&bareMetalConfig) + + assert.Equal(t, result.ProvisioningDHCPRange, "") + assert.Equal(t, result.ProvisioningCIDR, 64) + assert.Equal(t, result.ProvisioningIPv6, true) + assert.Equal(t, result.ProvisioningIP, "fd2e:6f44:5dd8:b856::2") +} diff --git a/pkg/asset/ignition/bootstrap/bootstrap.go b/pkg/asset/ignition/bootstrap/bootstrap.go index 14b53ccd2dd..e3ac199d286 100644 --- a/pkg/asset/ignition/bootstrap/bootstrap.go +++ b/pkg/asset/ignition/bootstrap/bootstrap.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "github.com/openshift/installer/pkg/asset/ignition/bootstrap/baremetal" "io" "io/ioutil" "os" @@ -30,6 +31,7 @@ import ( "github.com/openshift/installer/pkg/asset/rhcos" "github.com/openshift/installer/pkg/asset/tls" "github.com/openshift/installer/pkg/types" + baremetaltypes "github.com/openshift/installer/pkg/types/baremetal" ) const ( @@ -50,6 +52,13 @@ type bootstrapTemplateData struct { Registries []sysregistriesv2.Registry BootImage string ClusterDomain string + PlatformData platformTemplateData +} + +// platformTemplateData is the data to use to replace values in bootstrap +// template files that are specific to one platform. +type platformTemplateData struct { + BareMetal *baremetal.TemplateData } // Bootstrap is an asset that generates the ignition config for bootstrap nodes. @@ -223,6 +232,14 @@ func (a *Bootstrap) getTemplateData(installConfig *types.InstallConfig, releaseI registries = append(registries, registry) } + // Generate platform-specific baremetal data + var platformData platformTemplateData + + switch installConfig.Platform.Name() { + case baremetaltypes.Name: + platformData.BareMetal = baremetal.GetTemplateData(installConfig.Platform.BareMetal) + } + return &bootstrapTemplateData{ AdditionalTrustBundle: installConfig.AdditionalTrustBundle, FIPS: installConfig.FIPS, @@ -233,6 +250,7 @@ func (a *Bootstrap) getTemplateData(installConfig *types.InstallConfig, releaseI Registries: registries, BootImage: string(*rhcosImage), ClusterDomain: installConfig.ClusterDomain(), + PlatformData: platformData, }, nil } diff --git a/pkg/types/baremetal/defaults/platform.go b/pkg/types/baremetal/defaults/platform.go index 47e03cc3e50..b5abedab538 100644 --- a/pkg/types/baremetal/defaults/platform.go +++ b/pkg/types/baremetal/defaults/platform.go @@ -2,36 +2,64 @@ package defaults import ( "fmt" + "github.com/openshift/installer/pkg/ipnet" "net" + "github.com/apparentlymart/go-cidr/cidr" "github.com/openshift/installer/pkg/types" "github.com/openshift/installer/pkg/types/baremetal" ) // Defaults for the baremetal platform. const ( - LibvirtURI = "qemu:///system" - BootstrapProvisioningIP = "172.22.0.2" - ClusterProvisioningIP = "172.22.0.3" - ExternalBridge = "baremetal" - ProvisioningBridge = "provisioning" - HardwareProfile = "default" - APIVIP = "" - IngressVIP = "" + LibvirtURI = "qemu:///system" + ProvisioningNetworkCIDR = "172.22.0.0/24" + ExternalBridge = "baremetal" + ProvisioningBridge = "provisioning" + ProvisioningNetworkInterface = "ens3" + HardwareProfile = "default" + APIVIP = "" + IngressVIP = "" ) +// Wrapper for net.LookupHost so we can override in the test +var lookupHost = func(host string) (addrs []string, err error) { + return net.LookupHost(host) +} + // SetPlatformDefaults sets the defaults for the platform. func SetPlatformDefaults(p *baremetal.Platform, c *types.InstallConfig) { if p.LibvirtURI == "" { p.LibvirtURI = LibvirtURI } + if p.ProvisioningNetworkCIDR == nil { + p.ProvisioningNetworkCIDR = ipnet.MustParseCIDR(ProvisioningNetworkCIDR) + } + + // If the user doesn't provide an explicit DHCP range, and DHCP is not + // disabled, then we set a default value from the 10th to 100th + // address in the network. + if !p.ProvisioningDHCPExternal && p.ProvisioningDHCPRange == "" { + startIP, _ := cidr.Host(&p.ProvisioningNetworkCIDR.IPNet, 10) + endIP, _ := cidr.Host(&p.ProvisioningNetworkCIDR.IPNet, 100) + p.ProvisioningDHCPRange = fmt.Sprintf("%s,%s", startIP, endIP) + } + if p.BootstrapProvisioningIP == "" { - p.BootstrapProvisioningIP = BootstrapProvisioningIP + // Default to the second address in provisioning network, e.g 172.22.0.2 + ip, err := cidr.Host(&p.ProvisioningNetworkCIDR.IPNet, 2) + if err == nil { + p.BootstrapProvisioningIP = ip.String() + } } if p.ClusterProvisioningIP == "" { - p.ClusterProvisioningIP = ClusterProvisioningIP + // Default to the third address in provisioning network, e.g 172.22.0.3 + ip, err := cidr.Host(&p.ProvisioningNetworkCIDR.IPNet, 3) + if err == nil { + p.ClusterProvisioningIP = ip.String() + } } if p.ExternalBridge == "" { @@ -42,6 +70,10 @@ func SetPlatformDefaults(p *baremetal.Platform, c *types.InstallConfig) { p.ProvisioningBridge = ProvisioningBridge } + if p.ProvisioningNetworkInterface == "" { + p.ProvisioningNetworkInterface = ProvisioningNetworkInterface + } + for _, host := range p.Hosts { if host.HardwareProfile == "" { host.HardwareProfile = HardwareProfile @@ -50,7 +82,7 @@ func SetPlatformDefaults(p *baremetal.Platform, c *types.InstallConfig) { if p.APIVIP == APIVIP { // This name should resolve to exactly one address - vip, err := net.LookupHost("api." + c.ClusterDomain()) + vip, err := lookupHost("api." + c.ClusterDomain()) if err != nil { // This will fail validation and abort the install p.APIVIP = fmt.Sprintf("DNS lookup failure: %s", err.Error()) @@ -61,7 +93,7 @@ func SetPlatformDefaults(p *baremetal.Platform, c *types.InstallConfig) { if p.IngressVIP == IngressVIP { // This name should resolve to exactly one address - vip, err := net.LookupHost("test.apps." + c.ClusterDomain()) + vip, err := lookupHost("test.apps." + c.ClusterDomain()) if err != nil { // This will fail validation and abort the install p.IngressVIP = fmt.Sprintf("DNS lookup failure: %s", err.Error()) diff --git a/pkg/types/baremetal/defaults/platform_test.go b/pkg/types/baremetal/defaults/platform_test.go new file mode 100644 index 00000000000..52de957ccec --- /dev/null +++ b/pkg/types/baremetal/defaults/platform_test.go @@ -0,0 +1,120 @@ +package defaults + +import ( + "errors" + "github.com/openshift/installer/pkg/ipnet" + "testing" + + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/openshift/installer/pkg/types" + "github.com/openshift/installer/pkg/types/baremetal" +) + +const testClusterName = "test-cluster" + +func TestSetPlatformDefaults(t *testing.T) { + // Stub the call to net.LookupHost + lookupHost = func(host string) (addrs []string, err error) { + if host == "api.test-cluster.test" { + ips := []string{"192.168.111.2"} + return ips, nil + } else if host == "test.apps.test-cluster.test" { + ips := []string{"192.168.111.3"} + return ips, nil + } else { + return nil, errors.New("Unknown Host " + host) + } + } + + cases := []struct { + name string + platform *baremetal.Platform + expected *baremetal.Platform + }{ + { + name: "default_empty", + platform: &baremetal.Platform{}, + expected: &baremetal.Platform{ + LibvirtURI: "qemu:///system", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "baremetal", + ProvisioningBridge: "provisioning", + APIVIP: "192.168.111.2", + IngressVIP: "192.168.111.3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ProvisioningDHCPRange: "172.22.0.10,172.22.0.100", + ProvisioningNetworkInterface: "ens3", + }, + }, + { + name: "alternate_cidr", + platform: &baremetal.Platform{ + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.23.0.0/24"), + }, + expected: &baremetal.Platform{ + LibvirtURI: "qemu:///system", + ClusterProvisioningIP: "172.23.0.3", + BootstrapProvisioningIP: "172.23.0.2", + ExternalBridge: "baremetal", + ProvisioningBridge: "provisioning", + APIVIP: "192.168.111.2", + IngressVIP: "192.168.111.3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.23.0.0/24"), + ProvisioningDHCPRange: "172.23.0.10,172.23.0.100", + ProvisioningNetworkInterface: "ens3", + }, + }, + { + name: "alternate_cidr_ipv6", + platform: &baremetal.Platform{ + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("fd2e:6f44:5dd8:b856::/64"), + }, + expected: &baremetal.Platform{ + LibvirtURI: "qemu:///system", + ClusterProvisioningIP: "fd2e:6f44:5dd8:b856::3", + BootstrapProvisioningIP: "fd2e:6f44:5dd8:b856::2", + ExternalBridge: "baremetal", + ProvisioningBridge: "provisioning", + APIVIP: "192.168.111.2", + IngressVIP: "192.168.111.3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("fd2e:6f44:5dd8:b856::/64"), + ProvisioningDHCPRange: "fd2e:6f44:5dd8:b856::a,fd2e:6f44:5dd8:b856::64", + ProvisioningNetworkInterface: "ens3", + }, + }, + { + name: "alternate_cidr_dhcp_disabled", + platform: &baremetal.Platform{ + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.23.0.0/24"), + ProvisioningDHCPExternal: true, + }, + expected: &baremetal.Platform{ + LibvirtURI: "qemu:///system", + ClusterProvisioningIP: "172.23.0.3", + BootstrapProvisioningIP: "172.23.0.2", + ExternalBridge: "baremetal", + ProvisioningBridge: "provisioning", + APIVIP: "192.168.111.2", + IngressVIP: "192.168.111.3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.23.0.0/24"), + ProvisioningDHCPExternal: true, + ProvisioningNetworkInterface: "ens3", + }, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ic := &types.InstallConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: testClusterName, + }, + BaseDomain: "test", + } + SetPlatformDefaults(tc.platform, ic) + assert.Equal(t, tc.expected, tc.platform, "unexpected platform") + }) + } +} diff --git a/pkg/types/baremetal/platform.go b/pkg/types/baremetal/platform.go index 84fad0fa96b..d7f4a3538f6 100644 --- a/pkg/types/baremetal/platform.go +++ b/pkg/types/baremetal/platform.go @@ -1,5 +1,9 @@ package baremetal +import ( + "github.com/openshift/installer/pkg/ipnet" +) + // BMC stores the information about a baremetal host's management controller. type BMC struct { Username string `json:"username"` @@ -40,10 +44,31 @@ type Platform struct { // +optional ExternalBridge string `json:"externalBridge,omitempty"` - // Provisioning bridge is used for provisioning nodes. + // Provisioning bridge is used for provisioning nodes, on the host that + // will run the bootstrap VM. // +optional ProvisioningBridge string `json:"provisioningBridge,omitempty"` + // ProvisioningNetworkInterface is the name of the network interface on a control plane + // baremetal host that is connected to the provisioning network. + ProvisioningNetworkInterface string `json:"provisioningNetworkInterface"` + + // ProvisioningNetworkCIDR defines the network to use for provisioning. + // +optional + ProvisioningNetworkCIDR *ipnet.IPNet `json:"provisioningNetworkCIDR,omitempty"` + + // ProvisioningDHCPExternal indicates that DHCP is provided by an external service, appropriately + // configured with next-server set to BootstrapProvisioningIP for the control plane, and + // ClusterProvisioningIP for workers. The default for this field is false, which means we will + // start and manage a DHCP server on the provisioning network. + // +optional + ProvisioningDHCPExternal bool `json:"provisioningDHCPExternal,omitempty"` + + // ProvisioningDHCPRange is used to provide DHCP services to hosts + // for provisioning. + // +optional + ProvisioningDHCPRange string `json:"provisioningDHCPRange,omitempty"` + // Hosts is the information needed to create the objects in Ironic. Hosts []*Host `json:"hosts"` diff --git a/pkg/types/baremetal/validation/platform.go b/pkg/types/baremetal/validation/platform.go index 41505bc50f5..e24dc3c3232 100644 --- a/pkg/types/baremetal/validation/platform.go +++ b/pkg/types/baremetal/validation/platform.go @@ -9,6 +9,7 @@ import ( "github.com/openshift/installer/pkg/types/baremetal" "github.com/openshift/installer/pkg/validate" "k8s.io/apimachinery/pkg/util/validation/field" + "strings" ) // dynamicValidator is a function that validates certain fields in the platform. @@ -71,10 +72,42 @@ func ValidatePlatform(p *baremetal.Platform, n *types.Networking, fldPath *field allErrs = append(allErrs, field.Invalid(fldPath.Child("provisioningHostIP"), p.ClusterProvisioningIP, err.Error())) } + if p.ProvisioningNetworkCIDR != nil && !p.ProvisioningNetworkCIDR.Contains(net.ParseIP(p.ClusterProvisioningIP)) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("clusterProvisioningIP"), p.ClusterProvisioningIP, fmt.Sprintf("%q is not in the provisioning network", p.ClusterProvisioningIP))) + } + if err := validate.IP(p.BootstrapProvisioningIP); err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("bootstrapProvisioningIP"), p.BootstrapProvisioningIP, err.Error())) } + if p.ProvisioningNetworkCIDR != nil && !p.ProvisioningNetworkCIDR.Contains(net.ParseIP(p.BootstrapProvisioningIP)) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("bootstrapProvisioningIP"), p.BootstrapProvisioningIP, fmt.Sprintf("%q is not in the provisioning network", p.BootstrapProvisioningIP))) + } + + if p.ProvisioningDHCPRange != "" { + dhcpRange := strings.Split(p.ProvisioningDHCPRange, ",") + if len(dhcpRange) != 2 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("provisioningDHCPRange"), p.ProvisioningDHCPRange, "provisioning dhcp range should be in format: start_ip,end_ip")) + } else { + for _, ip := range dhcpRange { + // Ensure IP is valid + if err := validate.IP(ip); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath.Child("provisioningDHCPRange"), p.ProvisioningDHCPRange, fmt.Sprintf("%s: %s", ip, err.Error()))) + } + + // Validate IP is in the provisioning network + if p.ProvisioningNetworkCIDR != nil && !p.ProvisioningNetworkCIDR.Contains(net.ParseIP(ip)) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("provisioningDHCPRange"), p.ProvisioningDHCPRange, fmt.Sprintf("%q is not in the provisioning network", ip))) + } + } + } + } + + // Make sure the provisioning interface is set. Very little we can do to validate this as it's not on this machine. + if p.ProvisioningNetworkInterface == "" { + allErrs = append(allErrs, field.Invalid(fldPath.Child("provisioningNetworkInterface"), p.ProvisioningNetworkInterface, "No baremetal provisioning network interface is configured.")) + } + if p.Hosts == nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("hosts"), p.Hosts, "bare metal hosts are missing")) } diff --git a/pkg/types/baremetal/validation/platform_test.go b/pkg/types/baremetal/validation/platform_test.go index 0f38dc1a7be..2a91cf9be12 100644 --- a/pkg/types/baremetal/validation/platform_test.go +++ b/pkg/types/baremetal/validation/platform_test.go @@ -38,47 +38,146 @@ func TestValidatePlatform(t *testing.T) { { name: "valid", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + ProvisioningNetworkInterface: "ens3", }, network: network, }, + { + name: "valid_ipv6_provisioning", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("fd2e:6f44:5dd8:b856::/64"), + ClusterProvisioningIP: "fd2e:6f44:5dd8:b856::3", + BootstrapProvisioningIP: "fd2e:6f44:5dd8:b856::2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + ProvisioningNetworkInterface: "ens3", + }, + network: network, + }, + { name: "valid_with_os_image_overrides", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", - BootstrapOSImage: "http://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", - ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + BootstrapOSImage: "http://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", + ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", + ProvisioningNetworkInterface: "ens3", + }, + network: network, + }, + { + name: "valid_provisioningDHCPRange", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ProvisioningDHCPRange: "172.22.0.10,172.22.0.50", + ProvisioningNetworkInterface: "ens3", + ExternalBridge: "br0", + ProvisioningBridge: "br1", }, network: network, }, + { + name: "invalid_provisioningDHCPRange_missing_pair", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ProvisioningDHCPRange: "172.22.0.10,", + ProvisioningNetworkInterface: "ens3", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + }, + network: network, + expected: "provisioningDHCPRange: Invalid value: \"172.22.0.10,\": : \"\" is not a valid IP", + }, + { + name: "invalid_provisioningDHCPRange_not_a_range", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ProvisioningDHCPRange: "172.22.0.19", + ProvisioningNetworkInterface: "ens3", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + }, + network: network, + expected: "Invalid value: \"172.22.0.19\": provisioning dhcp range should be in format: start_ip,end_ip", + }, + { + name: "invalid_provisioningDHCPRange_wrong_CIDR", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ProvisioningNetworkInterface: "ens3", + ProvisioningDHCPRange: "192.168.128.1,172.22.0.100", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + }, + network: network, + expected: "Invalid value: \"192.168.128.1,172.22.0.100\": \"192.168.128.1\" is not in the provisioning network", + }, { name: "invalid_apivip", platform: &baremetal.Platform{ - APIVIP: "192.168.222.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", + APIVIP: "192.168.222.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ProvisioningNetworkInterface: "ens3", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", }, network: network, expected: "Invalid value: \"192.168.222.2\": the virtual IP is expected to be in one of the machine networks", @@ -86,15 +185,17 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_dnsvip", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.222.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.222.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ProvisioningNetworkInterface: "ens3", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", }, network: network, expected: "Invalid value: \"192.168.222.3\": the virtual IP is expected to be in one of the machine networks", @@ -102,15 +203,17 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_ingressvip", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.222.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.222.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", }, network: network, expected: "Invalid value: \"192.168.222.4\": the virtual IP is expected to be in one of the machine networks", @@ -118,15 +221,17 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_hosts", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: nil, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: nil, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", }, network: network, expected: "bare metal hosts are missing", @@ -134,15 +239,17 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_libvirturi", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", }, network: network, expected: "invalid URI \"\"", @@ -150,15 +257,17 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_extbridge", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "noexist", - ProvisioningBridge: "br1", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "noexist", + ProvisioningBridge: "br1", }, network: network, expected: "Invalid value: \"noexist\": invalid external bridge", @@ -166,48 +275,73 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_provbridge", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "noexist", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "noexist", }, network: network, expected: "Invalid value: \"noexist\": invalid provisioning bridge", }, { - name: "invalid_clusterprovip", + name: "invalid_clusterprovip_machineCIDR", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "192.168.111.5", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "192.168.111.5", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", }, network: network, expected: "Invalid value: \"192.168.111.5\": the IP must not be in one of the machine networks", }, { - name: "invalid_bootstrapprovip", + name: "invalid_clusterprovip_wrongCIDR", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "192.168.128.1", + BootstrapProvisioningIP: "172.22.0.2", + ProvisioningDHCPRange: "172.22.0.10,172.22.0.100", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + }, + network: network, + expected: "Invalid value: \"192.168.128.1\": \"192.168.128.1\" is not in the provisioning network", + }, + { + name: "invalid_bootstrapprovip_machineCIDR", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "192.168.111.5", - ExternalBridge: "br0", - ProvisioningBridge: "br1", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "192.168.111.5", + ExternalBridge: "br0", + ProvisioningBridge: "br1", }, network: network, expected: "Invalid value: \"192.168.111.5\": the IP must not be in one of the machine networks", @@ -215,17 +349,19 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_bootstraposimage", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", - BootstrapOSImage: "192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", - ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + BootstrapOSImage: "192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", + ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", }, network: network, expected: "the URI provided.*is invalid", @@ -233,17 +369,19 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_clusterosimage", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", - BootstrapOSImage: "http://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", - ClusterOSImage: "http//192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ClusterProvisioningIP: "172.22.0.3", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + BootstrapOSImage: "http://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", + ClusterOSImage: "http//192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", }, network: network, expected: "the URI provided.*is invalid", @@ -251,17 +389,19 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_bootstraposimage_checksum", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", - BootstrapOSImage: "http://192.168.111.1/images/qemu.x86_64.qcow2.gz?md5sum=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", - ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + BootstrapOSImage: "http://192.168.111.1/images/qemu.x86_64.qcow2.gz?md5sum=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", + ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", }, network: network, expected: "the sha256 parameter in the.*URI is missing", @@ -269,17 +409,19 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_clusterosimage_checksum", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", - BootstrapOSImage: "http://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", - ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=3ee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + BootstrapOSImage: "http://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", + ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=3ee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", }, network: network, expected: "the sha256 parameter in the.*URI is invalid", @@ -287,21 +429,42 @@ func TestValidatePlatform(t *testing.T) { { name: "invalid_bootstraposimage_uri_scheme", platform: &baremetal.Platform{ - APIVIP: "192.168.111.2", - DNSVIP: "192.168.111.3", - IngressVIP: "192.168.111.4", - Hosts: []*baremetal.Host{}, - LibvirtURI: "qemu://system", - ClusterProvisioningIP: "172.22.0.3", - BootstrapProvisioningIP: "172.22.0.2", - ExternalBridge: "br0", - ProvisioningBridge: "br1", - BootstrapOSImage: "xttp://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", - ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ProvisioningNetworkInterface: "ens3", + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "172.22.0.2", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + BootstrapOSImage: "xttp://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f", + ClusterOSImage: "http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da", }, network: network, expected: "the URI provided.*must begin with http/https", }, + { + name: "invalid_bootstrapprovip_wrongCIDR", + platform: &baremetal.Platform{ + APIVIP: "192.168.111.2", + DNSVIP: "192.168.111.3", + IngressVIP: "192.168.111.4", + Hosts: []*baremetal.Host{}, + LibvirtURI: "qemu://system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("172.22.0.0/24"), + ClusterProvisioningIP: "172.22.0.3", + BootstrapProvisioningIP: "192.168.128.1", + ProvisioningDHCPRange: "172.22.0.10,172.22.0.100", + ExternalBridge: "br0", + ProvisioningBridge: "br1", + }, + network: network, + expected: "Invalid value: \"192.168.128.1\": \"192.168.128.1\" is not in the provisioning network", + }, } for _, tc := range cases { diff --git a/pkg/types/validation/installconfig_test.go b/pkg/types/validation/installconfig_test.go index 3a905fb9da1..f2008697dab 100644 --- a/pkg/types/validation/installconfig_test.go +++ b/pkg/types/validation/installconfig_test.go @@ -92,16 +92,18 @@ func validVSpherePlatform() *vsphere.Platform { func validBareMetalPlatform() *baremetal.Platform { iface, _ := net.Interfaces() return &baremetal.Platform{ - LibvirtURI: "qemu+tcp://192.168.122.1/system", - BootstrapProvisioningIP: "127.0.0.1", - ClusterProvisioningIP: "192.168.111.1", - Hosts: []*baremetal.Host{}, - ExternalBridge: iface[0].Name, - ProvisioningBridge: iface[0].Name, - DefaultMachinePlatform: &baremetal.MachinePool{}, - APIVIP: "10.0.0.5", - IngressVIP: "10.0.0.4", - DNSVIP: "10.0.0.2", + LibvirtURI: "qemu+tcp://192.168.122.1/system", + ProvisioningNetworkInterface: "ens3", + ProvisioningNetworkCIDR: ipnet.MustParseCIDR("192.168.111.0/24"), + BootstrapProvisioningIP: "192.168.111.1", + ClusterProvisioningIP: "192.168.111.2", + Hosts: []*baremetal.Host{}, + ExternalBridge: iface[0].Name, + ProvisioningBridge: iface[0].Name, + DefaultMachinePlatform: &baremetal.MachinePool{}, + APIVIP: "10.0.0.5", + IngressVIP: "10.0.0.4", + DNSVIP: "10.0.0.2", } }