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

MGMT-15736: Align feature support level to support HighAvailabilityMode #6077

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 34 additions & 0 deletions client/installer/get_supported_features_parameters.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 16 additions & 8 deletions internal/bminventory/inventory.go
Expand Up @@ -1598,7 +1598,7 @@ func (b *bareMetalInventory) GetClusterSupportedPlatformsInternal(
var supportedPlatforms []models.PlatformType
for _, platformType := range hostsSupportedPlatforms {
featureId := provider.GetPlatformFeatureID(platformType)
if featureId == "" || featuresupport.IsFeatureAvailable(featureId, cluster.OpenshiftVersion, &cluster.CPUArchitecture) {
if featureId == "" || featuresupport.IsFeatureAvailable(featureId, cluster.OpenshiftVersion, &cluster.CPUArchitecture, cluster.HighAvailabilityMode) {
supportedPlatforms = append(supportedPlatforms, platformType)
} else {
b.log.Debugf("The platform %s was removed from cluster %s supported-platforms because it is not compatible with "+
Expand All @@ -1619,7 +1619,14 @@ func (b *bareMetalInventory) GetClusterSupportedPlatforms(ctx context.Context, p
}

func (b *bareMetalInventory) GetFeatureSupportLevelListInternal(_ context.Context, params installer.GetSupportedFeaturesParams) (models.SupportLevels, error) {
return featuresupport.GetFeatureSupportList(params.OpenshiftVersion, params.CPUArchitecture, (*models.PlatformType)(params.PlatformType), params.ExternalPlatformName), nil
featureFilter := featuresupport.SupportLevelFilters{
OpenshiftVersion: params.OpenshiftVersion,
CPUArchitecture: params.CPUArchitecture,
PlatformType: (*models.PlatformType)(params.PlatformType),
ExternalPlatformName: params.ExternalPlatformName,
HighAvailabilityMode: params.HighAvailabilityMode,
}
return featuresupport.GetFeatureSupportList(featureFilter), nil
}

func (b *bareMetalInventory) GetArchitecturesSupportLevelListInternal(_ context.Context, params installer.GetSupportedArchitecturesParams) (models.SupportLevels, error) {
Expand Down Expand Up @@ -1740,7 +1747,7 @@ func (b *bareMetalInventory) generateClusterInstallConfig(ctx context.Context, c
}

installerReleaseImageOverride := ""
if isBaremetalBinaryFromAnotherReleaseImageRequired(cluster.CPUArchitecture, cluster.OpenshiftVersion) {
if isBaremetalBinaryFromAnotherReleaseImageRequired(cluster) {
defaultArchImage, err := b.versionsHandler.GetReleaseImage(ctx, cluster.OpenshiftVersion, common.DefaultCPUArchitecture, cluster.PullSecret)
if err != nil {
msg := fmt.Sprintf("failed to get image for installer image override "+
Expand Down Expand Up @@ -2582,7 +2589,7 @@ func (b *bareMetalInventory) updateNetworkParams(params installer.V2UpdateCluste
if params.ClusterUpdateParams.UserManagedNetworking != nil && swag.BoolValue(params.ClusterUpdateParams.UserManagedNetworking) != userManagedNetworking {
if !swag.BoolValue(params.ClusterUpdateParams.UserManagedNetworking) &&
(cluster.CPUArchitecture != common.DefaultCPUArchitecture &&
!featuresupport.IsFeatureAvailable(models.FeatureSupportLevelIDCLUSTERMANAGEDNETWORKING, cluster.OpenshiftVersion, swag.String(cluster.CPUArchitecture))) {
!featuresupport.IsFeatureAvailable(models.FeatureSupportLevelIDCLUSTERMANAGEDNETWORKING, cluster.OpenshiftVersion, swag.String(cluster.CPUArchitecture), cluster.HighAvailabilityMode)) {
err = errors.Errorf("disabling User Managed Networking is not allowed for clusters with non-x86_64 CPU architecture")
return common.NewApiError(http.StatusBadRequest, err)
}
Expand Down Expand Up @@ -6366,10 +6373,11 @@ func (b *bareMetalInventory) GetKnownApprovedHosts(clusterId strfmt.UUID) ([]*co
// This flow does not affect the multiarch release images and is meant purely for using arm64 release image with the x86 hub.
// Implementation of handling the multiarch images is done directly in the `oc` binary and relies on the fact that `oc adm release extract`
// will automatically use the image matching the Hub's architecture.
func isBaremetalBinaryFromAnotherReleaseImageRequired(cpuArchitecture, version string) bool {
return cpuArchitecture != common.MultiCPUArchitecture &&
cpuArchitecture != common.NormalizeCPUArchitecture(runtime.GOARCH) &&
featuresupport.IsFeatureAvailable(models.FeatureSupportLevelIDCLUSTERMANAGEDNETWORKING, version, swag.String(models.ClusterCPUArchitectureArm64))
func isBaremetalBinaryFromAnotherReleaseImageRequired(cluster common.Cluster) bool {
return cluster.CPUArchitecture != common.MultiCPUArchitecture &&
cluster.CPUArchitecture != common.NormalizeCPUArchitecture(runtime.GOARCH) &&
featuresupport.IsFeatureAvailable(models.FeatureSupportLevelIDCLUSTERMANAGEDNETWORKING, cluster.OpenshiftVersion,
swag.String(models.ClusterCPUArchitectureArm64), cluster.HighAvailabilityMode)
}

// updateMonitoredOperators checks the content of the installer configuration and updates the list
Expand Down
4 changes: 2 additions & 2 deletions internal/cluster/validations/validations.go
Expand Up @@ -402,7 +402,7 @@ func ValidateClusterCreateIPAddresses(ipV6Supported bool, clusterId strfmt.UUID,
targetConfiguration := common.Cluster{}

if (len(params.APIVips) > 1 || len(params.IngressVips) > 1) &&
!featuresupport.IsFeatureAvailable(models.FeatureSupportLevelIDDUALSTACKVIPS, swag.StringValue(params.OpenshiftVersion), swag.String(params.CPUArchitecture)) {
!featuresupport.IsFeatureAvailable(models.FeatureSupportLevelIDDUALSTACKVIPS, swag.StringValue(params.OpenshiftVersion), swag.String(params.CPUArchitecture), params.HighAvailabilityMode) {

return common.NewApiError(http.StatusBadRequest, errors.Errorf("%s %s", "dual-stack VIPs are not supported in OpenShift", *params.OpenshiftVersion))
}
Expand Down Expand Up @@ -467,7 +467,7 @@ func ValidateClusterUpdateVIPAddresses(ipV6Supported bool, cluster *common.Clust
ingressVips = params.IngressVips

if (len(params.APIVips) > 1 || len(params.IngressVips) > 1) &&
!featuresupport.IsFeatureAvailable(models.FeatureSupportLevelIDDUALSTACKVIPS, cluster.OpenshiftVersion, swag.String(cluster.CPUArchitecture)) {
!featuresupport.IsFeatureAvailable(models.FeatureSupportLevelIDDUALSTACKVIPS, cluster.OpenshiftVersion, swag.String(cluster.CPUArchitecture), cluster.HighAvailabilityMode) {

return common.NewApiError(http.StatusBadRequest, errors.Errorf("%s %s", "dual-stack VIPs are not supported in OpenShift", cluster.OpenshiftVersion))
}
Expand Down
17 changes: 13 additions & 4 deletions internal/featuresupport/architecture_support_level.go
@@ -1,6 +1,7 @@
package featuresupport

import (
"github.com/go-openapi/swag"
"github.com/openshift/assisted-service/models"
)

Expand Down Expand Up @@ -34,8 +35,11 @@ func getArchitectureSupportList(features map[models.ArchitectureSupportLevelID]S
// return a list of unsupported features
func overrideInvalidRequest(features map[models.FeatureSupportLevelID]SupportLevelFeature, cpuArchitecture, openshiftVersion string) models.SupportLevels {
supportLevels := models.SupportLevels{}
cpuArchID := cpuArchitectureFeatureIdMap[cpuArchitecture]
if !isArchitectureSupported(cpuArchID, openshiftVersion) {
supportfilter := SupportLevelFilters{
OpenshiftVersion: openshiftVersion,
CPUArchitecture: swag.String(cpuArchitecture),
}
if !isArchitectureSupported(supportfilter) {
for _, feature := range features {
supportLevels[string(feature.getId())] = models.SupportLevelUnavailable
}
Expand All @@ -48,7 +52,12 @@ func GetCpuArchitectureSupportList(openshiftVersion string) models.SupportLevels
return getArchitectureSupportList(cpuFeaturesList, openshiftVersion)
}

func isArchitectureSupported(featureId models.ArchitectureSupportLevelID, openshiftVersion string) bool {
supportLevel := GetSupportLevel(featureId, openshiftVersion)
func isArchitectureSupported(filters SupportLevelFilters) bool {
if filters.CPUArchitecture == nil {
return true
}

featureId := cpuArchitectureFeatureIdMap[*filters.CPUArchitecture]
supportLevel := GetSupportLevel(featureId, filters)
return supportLevel != models.SupportLevelUnsupported && supportLevel != models.SupportLevelUnavailable
}
15 changes: 10 additions & 5 deletions internal/featuresupport/common.go
Expand Up @@ -11,11 +11,11 @@ import (
"github.com/thoas/go-funk"
)

func GetSupportLevel[T models.FeatureSupportLevelID | models.ArchitectureSupportLevelID](featureId T, filters interface{}) models.SupportLevel {
func GetSupportLevel[T models.FeatureSupportLevelID | models.ArchitectureSupportLevelID](featureId T, filters SupportLevelFilters) models.SupportLevel {
if reflect.TypeOf(featureId).Name() == "FeatureSupportLevelID" {
return featuresList[models.FeatureSupportLevelID(featureId)].getSupportLevel(filters.(SupportLevelFilters))
return featuresList[models.FeatureSupportLevelID(featureId)].getSupportLevel(filters)
}
return cpuFeaturesList[models.ArchitectureSupportLevelID(featureId)].getSupportLevel(filters.(string))
return cpuFeaturesList[models.ArchitectureSupportLevelID(featureId)].getSupportLevel(filters.OpenshiftVersion)
}

func ValidateActiveFeatures(log logrus.FieldLogger, cluster *common.Cluster, infraEnv *models.InfraEnv, updateParams interface{}) error {
Expand Down Expand Up @@ -48,17 +48,22 @@ func ValidateActiveFeatures(log logrus.FieldLogger, cluster *common.Cluster, inf

func ValidateIncompatibleFeatures(log logrus.FieldLogger, cpuArchitecture string, cluster *common.Cluster, infraEnv *models.InfraEnv, updateParams interface{}) error {
var openshiftVersion *string
var highAvailabilityMode *string = swag.String("")
if cluster != nil {
openshiftVersion = &cluster.OpenshiftVersion
if cluster.HighAvailabilityMode != nil {
highAvailabilityMode = cluster.HighAvailabilityMode
}
}

activatedFeatures := getActivatedFeatures(log, cluster, infraEnv, updateParams)
if cpuArchitecture != "" && swag.StringValue(openshiftVersion) != "" {
if isSupported := isArchitectureSupported(cpuArchitectureFeatureIdMap[cpuArchitecture], swag.StringValue(openshiftVersion)); !isSupported {
filters := SupportLevelFilters{OpenshiftVersion: *openshiftVersion, CPUArchitecture: &cpuArchitecture, HighAvailabilityMode: highAvailabilityMode}
if isSupported := isArchitectureSupported(filters); !isSupported {
return fmt.Errorf("cannot use %s architecture because it's not compatible on version %s of OpenShift", cpuArchitecture, cluster.OpenshiftVersion)
}

if err := isFeaturesCompatible(swag.StringValue(openshiftVersion), cpuArchitecture, activatedFeatures); err != nil {
if err := isFeaturesCompatible(swag.StringValue(openshiftVersion), cpuArchitecture, highAvailabilityMode, activatedFeatures); err != nil {
return err
}

Expand Down
31 changes: 16 additions & 15 deletions internal/featuresupport/feature_support_level.go
Expand Up @@ -80,19 +80,16 @@ func removeEmptySupportLevel(supportLevels models.SupportLevels) {
}

// GetFeatureSupportList Get features support level list, cpuArchitecture is optional and the default value is x86
func GetFeatureSupportList(openshiftVersion string, cpuArchitecture *string, platformType *models.PlatformType, externalPlatformName *string) models.SupportLevels {
filters := SupportLevelFilters{
OpenshiftVersion: openshiftVersion,
CPUArchitecture: cpuArchitecture,
PlatformType: platformType,
ExternalPlatformName: externalPlatformName,
}

if cpuArchitecture == nil {
func GetFeatureSupportList(filters SupportLevelFilters) models.SupportLevels {
if filters.CPUArchitecture == nil {
filters.CPUArchitecture = swag.String(common.DefaultCPUArchitecture)
}
featuresSupportList := overrideInvalidRequest(featuresList, *filters.CPUArchitecture, openshiftVersion)

featuresSupportList := overrideInvalidRequest(featuresList, swag.StringValue(filters.CPUArchitecture), filters.OpenshiftVersion)
if featuresSupportList == nil {
if filters.HighAvailabilityMode == nil {
filters.HighAvailabilityMode = swag.String("")
}
featuresSupportList = getFeatureSupportList(featuresList, filters)
}

Expand All @@ -104,10 +101,14 @@ func GetFeatureSupportList(openshiftVersion string, cpuArchitecture *string, pla

// IsFeatureAvailable Get the support level of a given feature, cpuArchitecture is optional
// with default value of x86_64
func IsFeatureAvailable(featureId models.FeatureSupportLevelID, openshiftVersion string, cpuArchitecture *string) bool {
func IsFeatureAvailable(featureId models.FeatureSupportLevelID, openshiftVersion string, cpuArchitecture *string, highAvailabilityMode *string) bool {
if highAvailabilityMode == nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in which case we will get highAvailabilityMode == nil?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not configured, mostly in API call for featuresupport - but also subsystem test and unit tests

highAvailabilityMode = swag.String("")
}
filters := SupportLevelFilters{
OpenshiftVersion: openshiftVersion,
CPUArchitecture: cpuArchitecture,
OpenshiftVersion: openshiftVersion,
CPUArchitecture: cpuArchitecture,
HighAvailabilityMode: highAvailabilityMode,
}

if cpuArchitecture == nil {
Expand Down Expand Up @@ -142,10 +143,10 @@ func isFeaturesCompatibleWithFeatures(openshiftVersion string, activatedFeatures
}

// isFeaturesCompatible Determine if feature is compatible with CPU architecture in a given openshift-version
func isFeaturesCompatible(openshiftVersion, cpuArchitecture string, activatedFeatures []SupportLevelFeature) error {
func isFeaturesCompatible(openshiftVersion, cpuArchitecture string, highAvailabilityMode *string, activatedFeatures []SupportLevelFeature) error {
for _, feature := range activatedFeatures {
if !isFeatureCompatibleWithArchitecture(feature, openshiftVersion, cpuArchitecture) ||
!IsFeatureAvailable(feature.getId(), openshiftVersion, swag.String(cpuArchitecture)) {
!IsFeatureAvailable(feature.getId(), openshiftVersion, swag.String(cpuArchitecture), highAvailabilityMode) {
return fmt.Errorf("cannot use %s because it's not compatible with the %s architecture "+
"on version %s of OpenShift", feature.GetName(), cpuArchitecture, openshiftVersion)
}
Expand Down