From 5a072e02ba2851c88dfff90aad5221a1a51be332 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Mon, 11 Mar 2024 13:33:57 +1300 Subject: [PATCH] Allow host to be in any MachineNetwork In the belongs-to-machine-cidr validation, allow the host to be a member of any MachineNetwork. In a dual-stack cluster, require it to be a member of both an IPv4 and an IPv6 network. Previously it was assumed that the only reason for multiple MachineNetworks to appear was that a dual stack cluster could contain exactly one IPv4 and one IPv6 MachineNetwork. --- internal/host/transition_test.go | 16 ++++++++-------- internal/host/validator.go | 4 ++-- internal/network/machine_network_cidr.go | 18 ++++++++++-------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/internal/host/transition_test.go b/internal/host/transition_test.go index 12b8d0ee11e..33470a2adea 100644 --- a/internal/host/transition_test.go +++ b/internal/host/transition_test.go @@ -3204,7 +3204,7 @@ var _ = Describe("Refresh Host", func() { imageStatuses: map[string]*models.ContainerImageAvailability{common.TestDefaultConfig.ImageName: common.TestImageStatusesFailure}, role: models.HostRoleWorker, statusInfoChecker: makeValueChecker(formatStatusInfoFailedValidation(statusInfoNotReadyForInstall, - "Host does not belong to machine network CIDRs. Verify that the host belongs to every CIDR listed under machine networks", + "Host does not belong to machine network CIDRs. Verify that the host belongs to a listed machine network CIDR for each IP stack in use", "Host couldn't synchronize with any NTP server", "Failed to fetch container images needed for installation from image. This may be due to a network hiccup. Retry to install again. If this problem persists, "+ "check your network settings to make sure you’re not blocked.")), @@ -3218,7 +3218,7 @@ var _ = Describe("Refresh Host", func() { HasCPUCoresForRole: {status: ValidationSuccess, messagePattern: "Sufficient CPU cores for role worker"}, HasMemoryForRole: {status: ValidationSuccess, messagePattern: "Sufficient RAM for role worker"}, IsHostnameUnique: {status: ValidationSuccess, messagePattern: "Hostname worker-1 is unique in cluster"}, - BelongsToMachineCidr: {status: ValidationFailure, messagePattern: "Host does not belong to machine network CIDRs. Verify that the host belongs to every CIDR listed under machine networks"}, + BelongsToMachineCidr: {status: ValidationFailure, messagePattern: "Host does not belong to machine network CIDRs. Verify that the host belongs to a listed machine network CIDR for each IP stack in use"}, IsPlatformNetworkSettingsValid: {status: ValidationSuccess, messagePattern: "Platform RHEL is allowed"}, CompatibleWithClusterPlatform: {status: ValidationSuccess, messagePattern: "Host is compatible with cluster platform baremetal"}, IsNTPSynced: {status: ValidationFailure, messagePattern: "Host couldn't synchronize with any NTP server"}, @@ -3239,7 +3239,7 @@ var _ = Describe("Refresh Host", func() { imageStatuses: map[string]*models.ContainerImageAvailability{common.TestDefaultConfig.ImageName: common.TestImageStatusesFailure}, role: models.HostRoleMaster, statusInfoChecker: makeValueChecker(formatStatusInfoFailedValidation(statusInfoNotReadyForInstall, - "Host does not belong to machine network CIDRs. Verify that the host belongs to every CIDR listed under machine networks", + "Host does not belong to machine network CIDRs. Verify that the host belongs to a listed machine network CIDR for each IP stack in use", "Require at least 4 CPU cores for master role, found only 2", "Require at least 16.00 GiB RAM for role master, found only 8.00 GiB", "Host couldn't synchronize with any NTP server", @@ -3255,7 +3255,7 @@ var _ = Describe("Refresh Host", func() { HasCPUCoresForRole: {status: ValidationFailure, messagePattern: "Require at least 4 CPU cores for master role, found only 2"}, HasMemoryForRole: {status: ValidationFailure, messagePattern: "Require at least 16.00 GiB RAM for role master, found only 8.00 GiB"}, IsHostnameUnique: {status: ValidationSuccess, messagePattern: "Hostname worker-1 is unique in cluster"}, - BelongsToMachineCidr: {status: ValidationFailure, messagePattern: "Host does not belong to machine network CIDRs. Verify that the host belongs to every CIDR listed under machine networks"}, + BelongsToMachineCidr: {status: ValidationFailure, messagePattern: "Host does not belong to machine network CIDRs. Verify that the host belongs to a listed machine network CIDR for each IP stack in use"}, IsPlatformNetworkSettingsValid: {status: ValidationSuccess, messagePattern: "Platform RHEL is allowed"}, CompatibleWithClusterPlatform: {status: ValidationSuccess, messagePattern: "Host is compatible with cluster platform baremetal"}, IsNTPSynced: {status: ValidationFailure, messagePattern: "Host couldn't synchronize with any NTP server"}, @@ -3369,7 +3369,7 @@ var _ = Describe("Refresh Host", func() { imageStatuses: map[string]*models.ContainerImageAvailability{common.TestDefaultConfig.ImageName: common.TestImageStatusesFailure}, role: models.HostRoleMaster, statusInfoChecker: makeValueChecker(formatStatusInfoFailedValidation(statusInfoNotReadyForInstall, - "Host does not belong to machine network CIDRs. Verify that the host belongs to every CIDR listed under machine networks", + "Host does not belong to machine network CIDRs. Verify that the host belongs to a listed machine network CIDR for each IP stack in use", "Host couldn't synchronize with any NTP server", "Failed to fetch container images needed for installation from image. This may be due to a network hiccup. Retry to install again. If this problem persists, "+ "check your network settings to make sure you’re not blocked.")), @@ -3402,7 +3402,7 @@ var _ = Describe("Refresh Host", func() { imageStatuses: map[string]*models.ContainerImageAvailability{common.TestDefaultConfig.ImageName: common.TestImageStatusesFailure}, role: models.HostRoleMaster, statusInfoChecker: makeValueChecker(formatStatusInfoFailedValidation(statusInfoNotReadyForInstall, - "Host does not belong to machine network CIDRs. Verify that the host belongs to every CIDR listed under machine networks", + "Host does not belong to machine network CIDRs. Verify that the host belongs to a listed machine network CIDR for each IP stack in use", "Host couldn't synchronize with any NTP server", "Failed to fetch container images needed for installation from image. This may be due to a network hiccup. Retry to install again. If this problem persists, "+ "check your network settings to make sure you’re not blocked.")), @@ -4234,7 +4234,7 @@ var _ = Describe("Refresh Host", func() { ntpSources: defaultNTPSources, role: models.HostRoleMaster, statusInfoChecker: makeValueChecker(formatStatusInfoFailedValidation(statusInfoNotReadyForInstall, - "Host does not belong to machine network CIDRs. Verify that the host belongs to every CIDR listed under machine networks")), + "Host does not belong to machine network CIDRs. Verify that the host belongs to a listed machine network CIDR for each IP stack in use")), validationsChecker: makeJsonChecker(map[validationID]validationCheckResult{ IsConnected: {status: ValidationSuccess, messagePattern: "Host is connected"}, HasInventory: {status: ValidationSuccess, messagePattern: "Valid inventory exists for the host"}, @@ -4245,7 +4245,7 @@ var _ = Describe("Refresh Host", func() { HasCPUCoresForRole: {status: ValidationSuccess, messagePattern: "Sufficient CPU cores for role master"}, HasMemoryForRole: {status: ValidationSuccess, messagePattern: "Sufficient RAM for role master"}, IsHostnameUnique: {status: ValidationSuccess, messagePattern: " is unique in cluster"}, - BelongsToMachineCidr: {status: ValidationFailure, messagePattern: "Host does not belong to machine network CIDRs. Verify that the host belongs to every CIDR listed under machine networks"}, + BelongsToMachineCidr: {status: ValidationFailure, messagePattern: "Host does not belong to machine network CIDRs. Verify that the host belongs to a listed machine network CIDR for each IP stack in use"}, IsHostnameValid: {status: ValidationSuccess, messagePattern: "Hostname .* is allowed"}, BelongsToMajorityGroup: {status: ValidationSuccess, messagePattern: "Host has connectivity to the majority of hosts in the cluster"}, IsNTPSynced: {status: ValidationSuccess, messagePattern: "Host NTP is synced"}, diff --git a/internal/host/validator.go b/internal/host/validator.go index 17ceaff14e0..8c8abce18ee 100644 --- a/internal/host/validator.go +++ b/internal/host/validator.go @@ -605,8 +605,8 @@ func (v *validator) belongsToMachineCidr(c *validationContext) (ValidationStatus if c.inventory == nil || !network.IsMachineCidrAvailable(c.cluster) { return ValidationPending, "Missing inventory or machine network CIDR" } - if !network.IsHostInPrimaryMachineNetCidr(v.log, c.cluster, c.host) { - return ValidationFailure, "Host does not belong to machine network CIDRs. Verify that the host belongs to every CIDR listed under machine networks" + if !network.IsHostInMachineNetCidrs(v.log, c.cluster, c.host) { + return ValidationFailure, "Host does not belong to machine network CIDRs. Verify that the host belongs to a listed machine network CIDR for each IP stack in use" } return ValidationSuccess, "Host belongs to all machine network CIDRs" } diff --git a/internal/network/machine_network_cidr.go b/internal/network/machine_network_cidr.go index 46226aaad58..f820553eb75 100644 --- a/internal/network/machine_network_cidr.go +++ b/internal/network/machine_network_cidr.go @@ -540,23 +540,25 @@ func GetDefaultRouteNetworkByFamily(h *models.Host, networks map[AddressFamily][ return ret, fmt.Errorf("can not find cidr by route: no inventory for host %s", h.ID.String()) } -func IsHostInPrimaryMachineNetCidr(log logrus.FieldLogger, cluster *common.Cluster, host *models.Host) bool { - // The host should belong to all the networks specified as Machine Networks. - - // TODO(mko) This rule should be revised as soon as OCP supports multiple machineNetwork - // entries using the same IP stack. - +func IsHostInMachineNetCidrs(log logrus.FieldLogger, cluster *common.Cluster, host *models.Host) bool { + // The host should belong to one of the networks specified as Machine + // Networks in each address family. if !IsMachineCidrAvailable(cluster) { return false } - ret := true + results := map[bool]bool{} for _, machineNet := range cluster.MachineNetworks { _, machineIpnet, err := net.ParseCIDR(string(machineNet.Cidr)) if err != nil { return false } - ret = ret && belongsToNetwork(log, host, machineIpnet) + isIPv4 := IsIPV4CIDR(string(machineNet.Cidr)) + results[isIPv4] = results[isIPv4] || belongsToNetwork(log, host, machineIpnet) + } + ret := true + for _, present := range results { + ret = ret && present } return ret }