Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release-4.18] OCPBUGS-49864: handle runtime panic when validating ovnKubernetesConfig #9435

Open
wants to merge 1 commit into
base: release-4.18
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions pkg/types/validation/installconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ func validateOVNIPv4InternalJoinSubnet(n *types.Networking, fldPath *field.Path)
}
}

if largeEnough, err := isV4NodeSubnetLargeEnough(n.ClusterNetwork, ipv4JoinNet.String()); err == nil && !largeEnough {
if largeEnough, err := isV4NodeSubnetLargeEnough(n.ClusterNetwork, ipv4JoinNet); err == nil && !largeEnough {
errMsg := `ipv4InternalJoinSubnet is not large enough for the maximum number of nodes which can be supported by ClusterNetwork`
allErrs = append(allErrs, field.Invalid(fldPath, ipv4JoinNet.String(), errMsg))
} else if err != nil {
Expand Down Expand Up @@ -1412,28 +1412,27 @@ func validateReleaseArchitecture(controlPlanePool *types.MachinePool, computePoo
return allErrs
}

// isV4NodeSubnetLargeEnough is validation performed by the cluster network operator:
// https://github.com/openshift/cluster-network-operator/blob/6b615be1447aa79252ddc73b10675b4638ae13f7/pkg/network/ovn_kubernetes.go#L1761
// isV4NodeSubnetLargeEnough ensures the subnet is large enough for the maximum number of nodes supported by ClusterNetwork.
// This validation is performed by the cluster network operator: https://github.com/openshift/cluster-network-operator/blob/6b615be1447aa79252ddc73b10675b4638ae13f7/pkg/network/ovn_kubernetes.go#L1761.
// We need to duplicate it here to catch any issues with network customization prior to install.
func isV4NodeSubnetLargeEnough(cn []types.ClusterNetworkEntry, nodeSubnet string) (bool, error) {
func isV4NodeSubnetLargeEnough(cn []types.ClusterNetworkEntry, nodeSubnet *ipnet.IPNet) (bool, error) {
var maxNodesNum int
addrLen := 32
for _, n := range cn {
for i, n := range cn {
if utilsnet.IsIPv6CIDRString(n.CIDR.String()) {
continue
}
mask, err := strconv.Atoi(strings.Split(n.CIDR.String(), "/")[1])
if err != nil {
return false, fmt.Errorf("error converting cluster network %s CIDR mask to int: %w", n.CIDR.String(), err)

mask, _ := n.CIDR.Mask.Size()
if int(n.HostPrefix) < mask {
return false, fmt.Errorf("cannot determine the number of nodes supported by cluster network %d due to invalid hostPrefix", i)
}
nodesNum := 1 << (int(n.HostPrefix) - mask)
maxNodesNum += nodesNum
}
// We need to ensure each node can be assigned an IP address from the internal subnet
intSubnetMask, err := strconv.Atoi(strings.Split(nodeSubnet, "/")[1])
if err != nil {
return false, fmt.Errorf("error converting node subnet %s CIDR mask to int: %w", nodeSubnet, err)
}
intSubnetMask, _ := nodeSubnet.Mask.Size()

// reserve one IP for the gw, one IP for network and one for broadcasting
return maxNodesNum < (1<<(addrLen-intSubnetMask) - 3), nil
}
15 changes: 15 additions & 0 deletions pkg/types/validation/installconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,21 @@ func TestValidateInstallConfig(t *testing.T) {
}(),
expectedError: `^networking\.ovnKubernetesConfig\.ipv4\.internalJoinSubnet: Invalid value: "100\.64\.0\.0/24": ipv4InternalJoinSubnet is not large enough for the maximum number of nodes which can be supported by ClusterNetwork$`,
},
{
name: "valid user-provided IPv4 InternalJoinSubnet but invalid hostPrefix",
installConfig: func() *types.InstallConfig {
c := validInstallConfig()
c.Networking.OVNKubernetesConfig = &types.OVNKubernetesConfig{IPv4: &types.IPv4OVNKubernetesConfig{InternalJoinSubnet: ipnet.MustParseCIDR("100.64.0.0/24")}}
c.Networking.ClusterNetwork = []types.ClusterNetworkEntry{
{
CIDR: *ipnet.MustParseCIDR("10.128.0.0/24"),
HostPrefix: int32(23),
},
}
return c
}(),
expectedError: `^\[networking\.clusterNetwork\[0\]\.hostPrefix: Invalid value: 23: cluster network host subnetwork prefix must not be larger size than CIDR 10\.128\.0\.0/24, networking\.ovnKubernetesConfig\.ipv4\.internalJoinSubnet: Internal error: cannot determine the number of nodes supported by cluster network 0 due to invalid hostPrefix\]$`,
},
{
name: "missing machine networks",
installConfig: func() *types.InstallConfig {
Expand Down