diff --git a/features/features.go b/features/features.go index 4ea3797d595..e54b4d43e7a 100644 --- a/features/features.go +++ b/features/features.go @@ -752,8 +752,8 @@ var ( mustRegister() FeatureGateAWSDedicatedHosts = newFeatureGate("AWSDedicatedHosts"). - reportProblemsToJiraComponent("Installer"). - contactPerson("faermanj"). + reportProblemsToJiraComponent("splat"). + contactPerson("rvanderp3"). productScope(ocpSpecific). enhancementPR("https://github.com/openshift/enhancements/pull/1781"). enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). diff --git a/machine/v1beta1/types_awsprovider.go b/machine/v1beta1/types_awsprovider.go index b3b38bc6cc1..161f2324c27 100644 --- a/machine/v1beta1/types_awsprovider.go +++ b/machine/v1beta1/types_awsprovider.go @@ -114,6 +114,14 @@ type AWSMachineProviderConfig struct { // If this value is selected, capacityReservationID must be specified to identify the target reservation. // +optional MarketType MarketType `json:"marketType,omitempty"` + + // hostPlacement configures placement on AWS Dedicated Hosts. This allows admins to assign instances to specific host + // for a variety of needs including for regulatory compliance, to leverage existing per-socket or per-core software licenses (BYOL), + // and to gain visibility and control over instance placement on a physical server. + // When omitted, the instance is not constrained to a dedicated host. + // +openshift:enable:FeatureGate=AWSDedicatedHosts + // +optional + HostPlacement *HostPlacement `json:"hostPlacement,omitempty"` } // AWSConfidentialComputePolicy represents the confidential compute configuration for the instance. @@ -393,3 +401,46 @@ const ( // When set to CapacityBlock the instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations. MarketTypeCapacityBlock MarketType = "CapacityBlock" ) + +// HostPlacement is the type that will be used to configure the placement of AWS instances. +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.affinity == 'DedicatedHost' ? has(self.dedicatedHost) : !has(self.dedicatedHost)",message="dedicatedHost is required when affinity is DedicatedHost, and forbidden otherwise" +// +union +type HostPlacement struct { + // affinity specifies the affinity setting for the instance. + // Allowed values are AnyAvailable and DedicatedHost. + // When Affinity is set to DedicatedHost, an instance started onto a specific host always restarts on the same host if stopped. In this scenario, the `dedicatedHost` field must be set. + // When Affinity is set to AnyAvailable, and you stop and restart the instance, it can be restarted on any available host. + // +required + // +unionDiscriminator + Affinity *HostAffinity `json:"affinity,omitempty"` + + // dedicatedHost specifies the exact host that an instance should be restarted on if stopped. + // dedicatedHost is required when 'affinity' is set to DedicatedHost, and forbidden otherwise. + // +optional + // +unionMember + DedicatedHost *DedicatedHost `json:"dedicatedHost,omitempty"` +} + +// HostAffinity selects how an instance should be placed on AWS Dedicated Hosts. +// +kubebuilder:validation:Enum:=DedicatedHost;AnyAvailable +type HostAffinity string + +const ( + // HostAffinityAnyAvailable lets the platform select any available dedicated host. + HostAffinityAnyAvailable HostAffinity = "AnyAvailable" + + // HostAffinityDedicatedHost requires specifying a particular host via dedicatedHost.host.hostID. + HostAffinityDedicatedHost HostAffinity = "DedicatedHost" +) + +// DedicatedHost represents the configuration for the usage of dedicated host. +type DedicatedHost struct { + // id identifies the AWS Dedicated Host on which the instance must run. + // The value must start with "h-" followed by 17 lowercase hexadecimal characters (0-9 and a-f). + // Must be exactly 19 characters in length. + // +kubebuilder:validation:XValidation:rule="self.matches('^h-[0-9a-f]{17}$')",message="hostID must start with 'h-' followed by 17 lowercase hexadecimal characters (0-9 and a-f)" + // +kubebuilder:validation:MinLength=19 + // +kubebuilder:validation:MaxLength=19 + // +required + ID string `json:"id,omitempty"` +} diff --git a/machine/v1beta1/zz_generated.deepcopy.go b/machine/v1beta1/zz_generated.deepcopy.go index 5aa4f90a497..23aba5d1d6d 100644 --- a/machine/v1beta1/zz_generated.deepcopy.go +++ b/machine/v1beta1/zz_generated.deepcopy.go @@ -85,6 +85,11 @@ func (in *AWSMachineProviderConfig) DeepCopyInto(out *AWSMachineProviderConfig) *out = new(int32) **out = **in } + if in.HostPlacement != nil { + in, out := &in.HostPlacement, &out.HostPlacement + *out = new(HostPlacement) + (*in).DeepCopyInto(*out) + } return } @@ -509,6 +514,22 @@ func (in *DataDiskManagedDiskParameters) DeepCopy() *DataDiskManagedDiskParamete return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DedicatedHost) DeepCopyInto(out *DedicatedHost) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DedicatedHost. +func (in *DedicatedHost) DeepCopy() *DedicatedHost { + if in == nil { + return nil + } + out := new(DedicatedHost) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskEncryptionSetParameters) DeepCopyInto(out *DiskEncryptionSetParameters) { *out = *in @@ -898,6 +919,32 @@ func (in *GCPShieldedInstanceConfig) DeepCopy() *GCPShieldedInstanceConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HostPlacement) DeepCopyInto(out *HostPlacement) { + *out = *in + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(HostAffinity) + **out = **in + } + if in.DedicatedHost != nil { + in, out := &in.DedicatedHost, &out.DedicatedHost + *out = new(DedicatedHost) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPlacement. +func (in *HostPlacement) DeepCopy() *HostPlacement { + if in == nil { + return nil + } + out := new(HostPlacement) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Image) DeepCopyInto(out *Image) { *out = *in diff --git a/machine/v1beta1/zz_generated.swagger_doc_generated.go b/machine/v1beta1/zz_generated.swagger_doc_generated.go index 4a1b969a81e..2e540810821 100644 --- a/machine/v1beta1/zz_generated.swagger_doc_generated.go +++ b/machine/v1beta1/zz_generated.swagger_doc_generated.go @@ -35,6 +35,7 @@ var map_AWSMachineProviderConfig = map[string]string{ "placementGroupPartition": "placementGroupPartition is the partition number within the placement group in which to launch the instance. This must be an integer value between 1 and 7. It is only valid if the placement group, referred in `PlacementGroupName` was created with strategy set to partition.", "capacityReservationId": "capacityReservationId specifies the target Capacity Reservation into which the instance should be launched. The field size should be greater than 0 and the field input must start with cr-***", "marketType": "marketType specifies the type of market for the EC2 instance. Valid values are OnDemand, Spot, CapacityBlock and omitted.\n\nDefaults to OnDemand. When SpotMarketOptions is provided, the marketType defaults to \"Spot\".\n\nWhen set to OnDemand the instance runs as a standard OnDemand instance. When set to Spot the instance runs as a Spot instance. When set to CapacityBlock the instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations. If this value is selected, capacityReservationID must be specified to identify the target reservation.", + "hostPlacement": "hostPlacement configures placement on AWS Dedicated Hosts. This allows admins to assign instances to specific host for a variety of needs including for regulatory compliance, to leverage existing per-socket or per-core software licenses (BYOL), and to gain visibility and control over instance placement on a physical server. When omitted, the instance is not constrained to a dedicated host.", } func (AWSMachineProviderConfig) SwaggerDoc() map[string]string { @@ -92,6 +93,15 @@ func (CPUOptions) SwaggerDoc() map[string]string { return map_CPUOptions } +var map_DedicatedHost = map[string]string{ + "": "DedicatedHost represents the configuration for the usage of dedicated host.", + "id": "id identifies the AWS Dedicated Host on which the instance must run. The value must start with \"h-\" followed by 17 lowercase hexadecimal characters (0-9 and a-f). Must be exactly 19 characters in length.", +} + +func (DedicatedHost) SwaggerDoc() map[string]string { + return map_DedicatedHost +} + var map_EBSBlockDeviceSpec = map[string]string{ "": "EBSBlockDeviceSpec describes a block device for an EBS volume. https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/EbsBlockDevice", "deleteOnTermination": "Indicates whether the EBS volume is deleted on machine termination.\n\nDeprecated: setting this field has no effect.", @@ -116,6 +126,16 @@ func (Filter) SwaggerDoc() map[string]string { return map_Filter } +var map_HostPlacement = map[string]string{ + "": "HostPlacement is the type that will be used to configure the placement of AWS instances.", + "affinity": "affinity specifies the affinity setting for the instance. Allowed values are AnyAvailable and DedicatedHost. When Affinity is set to DedicatedHost, an instance started onto a specific host always restarts on the same host if stopped. In this scenario, the `dedicatedHost` field must be set. When Affinity is set to AnyAvailable, and you stop and restart the instance, it can be restarted on any available host.", + "dedicatedHost": "dedicatedHost specifies the exact host that an instance should be restarted on if stopped. dedicatedHost is required when 'affinity' is set to DedicatedHost, and forbidden otherwise.", +} + +func (HostPlacement) SwaggerDoc() map[string]string { + return map_HostPlacement +} + var map_LoadBalancerReference = map[string]string{ "": "LoadBalancerReference is a reference to a load balancer on AWS.", } diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go index 1a3f96c2bc7..0c41ebb46c2 100644 --- a/openapi/generated_openapi/zz_generated.openapi.go +++ b/openapi/generated_openapi/zz_generated.openapi.go @@ -794,6 +794,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/openshift/api/machine/v1beta1.ConfidentialVM": schema_openshift_api_machine_v1beta1_ConfidentialVM(ref), "github.com/openshift/api/machine/v1beta1.DataDisk": schema_openshift_api_machine_v1beta1_DataDisk(ref), "github.com/openshift/api/machine/v1beta1.DataDiskManagedDiskParameters": schema_openshift_api_machine_v1beta1_DataDiskManagedDiskParameters(ref), + "github.com/openshift/api/machine/v1beta1.DedicatedHost": schema_openshift_api_machine_v1beta1_DedicatedHost(ref), "github.com/openshift/api/machine/v1beta1.DiskEncryptionSetParameters": schema_openshift_api_machine_v1beta1_DiskEncryptionSetParameters(ref), "github.com/openshift/api/machine/v1beta1.DiskSettings": schema_openshift_api_machine_v1beta1_DiskSettings(ref), "github.com/openshift/api/machine/v1beta1.EBSBlockDeviceSpec": schema_openshift_api_machine_v1beta1_EBSBlockDeviceSpec(ref), @@ -808,6 +809,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/openshift/api/machine/v1beta1.GCPNetworkInterface": schema_openshift_api_machine_v1beta1_GCPNetworkInterface(ref), "github.com/openshift/api/machine/v1beta1.GCPServiceAccount": schema_openshift_api_machine_v1beta1_GCPServiceAccount(ref), "github.com/openshift/api/machine/v1beta1.GCPShieldedInstanceConfig": schema_openshift_api_machine_v1beta1_GCPShieldedInstanceConfig(ref), + "github.com/openshift/api/machine/v1beta1.HostPlacement": schema_openshift_api_machine_v1beta1_HostPlacement(ref), "github.com/openshift/api/machine/v1beta1.Image": schema_openshift_api_machine_v1beta1_Image(ref), "github.com/openshift/api/machine/v1beta1.LastOperation": schema_openshift_api_machine_v1beta1_LastOperation(ref), "github.com/openshift/api/machine/v1beta1.LifecycleHook": schema_openshift_api_machine_v1beta1_LifecycleHook(ref), @@ -39465,12 +39467,18 @@ func schema_openshift_api_machine_v1beta1_AWSMachineProviderConfig(ref common.Re Format: "", }, }, + "hostPlacement": { + SchemaProps: spec.SchemaProps{ + Description: "hostPlacement configures placement on AWS Dedicated Hosts. This allows admins to assign instances to specific host for a variety of needs including for regulatory compliance, to leverage existing per-socket or per-core software licenses (BYOL), and to gain visibility and control over instance placement on a physical server. When omitted, the instance is not constrained to a dedicated host.", + Ref: ref("github.com/openshift/api/machine/v1beta1.HostPlacement"), + }, + }, }, Required: []string{"ami", "instanceType", "deviceIndex", "subnet", "placement"}, }, }, Dependencies: []string{ - "github.com/openshift/api/machine/v1beta1.AWSResourceReference", "github.com/openshift/api/machine/v1beta1.BlockDeviceMappingSpec", "github.com/openshift/api/machine/v1beta1.CPUOptions", "github.com/openshift/api/machine/v1beta1.LoadBalancerReference", "github.com/openshift/api/machine/v1beta1.MetadataServiceOptions", "github.com/openshift/api/machine/v1beta1.Placement", "github.com/openshift/api/machine/v1beta1.SpotMarketOptions", "github.com/openshift/api/machine/v1beta1.TagSpecification", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + "github.com/openshift/api/machine/v1beta1.AWSResourceReference", "github.com/openshift/api/machine/v1beta1.BlockDeviceMappingSpec", "github.com/openshift/api/machine/v1beta1.CPUOptions", "github.com/openshift/api/machine/v1beta1.HostPlacement", "github.com/openshift/api/machine/v1beta1.LoadBalancerReference", "github.com/openshift/api/machine/v1beta1.MetadataServiceOptions", "github.com/openshift/api/machine/v1beta1.Placement", "github.com/openshift/api/machine/v1beta1.SpotMarketOptions", "github.com/openshift/api/machine/v1beta1.TagSpecification", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, } } @@ -40315,6 +40323,27 @@ func schema_openshift_api_machine_v1beta1_DataDiskManagedDiskParameters(ref comm } } +func schema_openshift_api_machine_v1beta1_DedicatedHost(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DedicatedHost represents the configuration for the usage of dedicated host.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "id": { + SchemaProps: spec.SchemaProps{ + Description: "id identifies the AWS Dedicated Host on which the instance must run. The value must start with \"h-\" followed by 17 lowercase hexadecimal characters (0-9 and a-f). Must be exactly 19 characters in length.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"id"}, + }, + }, + } +} + func schema_openshift_api_machine_v1beta1_DiskEncryptionSetParameters(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -41108,6 +41137,47 @@ func schema_openshift_api_machine_v1beta1_GCPShieldedInstanceConfig(ref common.R } } +func schema_openshift_api_machine_v1beta1_HostPlacement(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "HostPlacement is the type that will be used to configure the placement of AWS instances.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "affinity": { + SchemaProps: spec.SchemaProps{ + Description: "affinity specifies the affinity setting for the instance. Allowed values are AnyAvailable and DedicatedHost. When Affinity is set to DedicatedHost, an instance started onto a specific host always restarts on the same host if stopped. In this scenario, the `dedicatedHost` field must be set. When Affinity is set to AnyAvailable, and you stop and restart the instance, it can be restarted on any available host.", + Type: []string{"string"}, + Format: "", + }, + }, + "dedicatedHost": { + SchemaProps: spec.SchemaProps{ + Description: "dedicatedHost specifies the exact host that an instance should be restarted on if stopped. dedicatedHost is required when 'affinity' is set to DedicatedHost, and forbidden otherwise.", + Ref: ref("github.com/openshift/api/machine/v1beta1.DedicatedHost"), + }, + }, + }, + Required: []string{"affinity"}, + }, + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-unions": []interface{}{ + map[string]interface{}{ + "discriminator": "affinity", + "fields-to-discriminateBy": map[string]interface{}{ + "dedicatedHost": "DedicatedHost", + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/openshift/api/machine/v1beta1.DedicatedHost"}, + } +} + func schema_openshift_api_machine_v1beta1_Image(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/openapi/openapi.json b/openapi/openapi.json index bb1a7c899f3..2351f4717a8 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -22655,6 +22655,10 @@ "format": "int64", "default": 0 }, + "hostPlacement": { + "description": "hostPlacement configures placement on AWS Dedicated Hosts. This allows admins to assign instances to specific host for a variety of needs including for regulatory compliance, to leverage existing per-socket or per-core software licenses (BYOL), and to gain visibility and control over instance placement on a physical server. When omitted, the instance is not constrained to a dedicated host.", + "$ref": "#/definitions/com.github.openshift.api.machine.v1beta1.HostPlacement" + }, "iamInstanceProfile": { "description": "iamInstanceProfile is a reference to an IAM role to assign to the instance", "$ref": "#/definitions/com.github.openshift.api.machine.v1beta1.AWSResourceReference" @@ -23242,6 +23246,19 @@ } } }, + "com.github.openshift.api.machine.v1beta1.DedicatedHost": { + "description": "DedicatedHost represents the configuration for the usage of dedicated host.", + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "description": "id identifies the AWS Dedicated Host on which the instance must run. The value must start with \"h-\" followed by 17 lowercase hexadecimal characters (0-9 and a-f). Must be exactly 19 characters in length.", + "type": "string" + } + } + }, "com.github.openshift.api.machine.v1beta1.DiskEncryptionSetParameters": { "description": "DiskEncryptionSetParameters is the disk encryption set properties", "type": "object", @@ -23712,6 +23729,31 @@ } } }, + "com.github.openshift.api.machine.v1beta1.HostPlacement": { + "description": "HostPlacement is the type that will be used to configure the placement of AWS instances.", + "type": "object", + "required": [ + "affinity" + ], + "properties": { + "affinity": { + "description": "affinity specifies the affinity setting for the instance. Allowed values are AnyAvailable and DedicatedHost. When Affinity is set to DedicatedHost, an instance started onto a specific host always restarts on the same host if stopped. In this scenario, the `dedicatedHost` field must be set. When Affinity is set to AnyAvailable, and you stop and restart the instance, it can be restarted on any available host.", + "type": "string" + }, + "dedicatedHost": { + "description": "dedicatedHost specifies the exact host that an instance should be restarted on if stopped. dedicatedHost is required when 'affinity' is set to DedicatedHost, and forbidden otherwise.", + "$ref": "#/definitions/com.github.openshift.api.machine.v1beta1.DedicatedHost" + } + }, + "x-kubernetes-unions": [ + { + "discriminator": "affinity", + "fields-to-discriminateBy": { + "dedicatedHost": "DedicatedHost" + } + } + ] + }, "com.github.openshift.api.machine.v1beta1.Image": { "description": "Image is a mirror of azure sdk compute.ImageReference", "type": "object",