From a1c0cfadb0021e9b73b4bca0e99a42a07aaa2785 Mon Sep 17 00:00:00 2001 From: Steven Fitzpatrick Date: Wed, 30 Nov 2022 08:33:33 +0000 Subject: [PATCH] Add FailureDomain to M3Cluster and Machine Signed-off-by: Steven Fitzpatrick --- api/v1alpha5/zz_generated.conversion.go | 31 ++++++++++++++----- api/v1beta1/metal3cluster_types.go | 5 +++ api/v1beta1/metal3machine_types.go | 4 +++ api/v1beta1/zz_generated.deepcopy.go | 12 +++++++ baremetal/metal3machine_manager.go | 11 +++++++ ...cture.cluster.x-k8s.io_metal3clusters.yaml | 21 +++++++++++++ ...cture.cluster.x-k8s.io_metal3machines.yaml | 4 +++ ...uster.x-k8s.io_metal3machinetemplates.yaml | 4 +++ 8 files changed, 85 insertions(+), 7 deletions(-) diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go index ab0ff9882..619ea37ef 100644 --- a/api/v1alpha5/zz_generated.conversion.go +++ b/api/v1alpha5/zz_generated.conversion.go @@ -1169,6 +1169,7 @@ func autoConvert_v1beta1_Metal3ClusterStatus_To_v1alpha5_Metal3ClusterStatus(in out.LastUpdated = (*v1.Time)(unsafe.Pointer(in.LastUpdated)) out.FailureReason = (*errors.ClusterStatusError)(unsafe.Pointer(in.FailureReason)) out.FailureMessage = (*string)(unsafe.Pointer(in.FailureMessage)) + // WARNING: in.FailureDomains requires manual conversion: does not exist in peer-type out.Ready = in.Ready // WARNING: in.Conditions requires manual conversion: does not exist in peer-type return nil @@ -1586,14 +1587,10 @@ func autoConvert_v1beta1_Metal3MachineSpec_To_v1alpha5_Metal3MachineSpec(in *v1b out.MetaData = (*corev1.SecretReference)(unsafe.Pointer(in.MetaData)) out.NetworkData = (*corev1.SecretReference)(unsafe.Pointer(in.NetworkData)) out.AutomatedCleaningMode = (*string)(unsafe.Pointer(in.AutomatedCleaningMode)) + // WARNING: in.FailureDomain requires manual conversion: does not exist in peer-type return nil } -// Convert_v1beta1_Metal3MachineSpec_To_v1alpha5_Metal3MachineSpec is an autogenerated conversion function. -func Convert_v1beta1_Metal3MachineSpec_To_v1alpha5_Metal3MachineSpec(in *v1beta1.Metal3MachineSpec, out *Metal3MachineSpec, s conversion.Scope) error { - return autoConvert_v1beta1_Metal3MachineSpec_To_v1alpha5_Metal3MachineSpec(in, out, s) -} - func autoConvert_v1alpha5_Metal3MachineStatus_To_v1beta1_Metal3MachineStatus(in *Metal3MachineStatus, out *v1beta1.Metal3MachineStatus, s conversion.Scope) error { out.LastUpdated = (*v1.Time)(unsafe.Pointer(in.LastUpdated)) out.FailureReason = (*errors.MachineStatusError)(unsafe.Pointer(in.FailureReason)) @@ -1656,7 +1653,17 @@ func Convert_v1beta1_Metal3MachineTemplate_To_v1alpha5_Metal3MachineTemplate(in func autoConvert_v1alpha5_Metal3MachineTemplateList_To_v1beta1_Metal3MachineTemplateList(in *Metal3MachineTemplateList, out *v1beta1.Metal3MachineTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]v1beta1.Metal3MachineTemplate)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta1.Metal3MachineTemplate, len(*in)) + for i := range *in { + if err := Convert_v1alpha5_Metal3MachineTemplate_To_v1beta1_Metal3MachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -1667,7 +1674,17 @@ func Convert_v1alpha5_Metal3MachineTemplateList_To_v1beta1_Metal3MachineTemplate func autoConvert_v1beta1_Metal3MachineTemplateList_To_v1alpha5_Metal3MachineTemplateList(in *v1beta1.Metal3MachineTemplateList, out *Metal3MachineTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]Metal3MachineTemplate)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Metal3MachineTemplate, len(*in)) + for i := range *in { + if err := Convert_v1beta1_Metal3MachineTemplate_To_v1alpha5_Metal3MachineTemplate(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } diff --git a/api/v1beta1/metal3cluster_types.go b/api/v1beta1/metal3cluster_types.go index 597e72538..e34a8c038 100644 --- a/api/v1beta1/metal3cluster_types.go +++ b/api/v1beta1/metal3cluster_types.go @@ -76,6 +76,11 @@ type Metal3ClusterStatus struct { // +optional FailureMessage *string `json:"failureMessage,omitempty"` + // FailureDomains specifies the failure domains available in the cluster. + // This will be used by Cluster API to try and spread the machines across failure domains + // +optional + FailureDomains clusterv1.FailureDomains `json:"failureDomains,omitempty"` + // Ready denotes that the Metal3 cluster (infrastructure) is ready. In // Baremetal case, it does not mean anything for now as no infrastructure // steps need to be performed. Required by Cluster API. Set to True by the diff --git a/api/v1beta1/metal3machine_types.go b/api/v1beta1/metal3machine_types.go index 2d1a8b4ac..90789dfe4 100644 --- a/api/v1beta1/metal3machine_types.go +++ b/api/v1beta1/metal3machine_types.go @@ -76,6 +76,10 @@ type Metal3MachineSpec struct { // +kubebuilder:validation:Enum:=metadata;disabled // +optional AutomatedCleaningMode *string `json:"automatedCleaningMode,omitempty"` + + // FailureDomain is the failure domain the machine will be created in. + // +optional + FailureDomain *string `json:"failureDomain,omitempty"` } // Metal3MachineStatus defines the observed state of Metal3Machine. diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index eecefb3e3..3034041f2 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -431,6 +431,13 @@ func (in *Metal3ClusterStatus) DeepCopyInto(out *Metal3ClusterStatus) { *out = new(string) **out = **in } + if in.FailureDomains != nil { + in, out := &in.FailureDomains, &out.FailureDomains + *out = make(apiv1beta1.FailureDomains, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make(apiv1beta1.Conditions, len(*in)) @@ -860,6 +867,11 @@ func (in *Metal3MachineSpec) DeepCopyInto(out *Metal3MachineSpec) { *out = new(string) **out = **in } + if in.FailureDomain != nil { + in, out := &in.FailureDomain, &out.FailureDomain + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Metal3MachineSpec. diff --git a/baremetal/metal3machine_manager.go b/baremetal/metal3machine_manager.go index 666a853bd..f160bb32f 100644 --- a/baremetal/metal3machine_manager.go +++ b/baremetal/metal3machine_manager.go @@ -71,6 +71,9 @@ const ( ProviderIDPrefix = "metal3://" // ProviderLabelPrefix is a label prefix for ProviderID. ProviderLabelPrefix = "metal3.io/uuid" + // FailureDomainLabelPrefix is a label prefix for FailureDomains + // TODO: Should this be customizable by an operator? + FailureDomainLabelPrefix = "infrastructure.cluster.x-k8s.io/failure-domain" ) var ( @@ -889,6 +892,14 @@ func (m *MachineManager) chooseHost(ctx context.Context) (*bmov1alpha1.BareMetal } reqs = append(reqs, *r) } + if m.Metal3Machine.Spec.FailureDomain != nil { + r, err := labels.NewRequirement(FailureDomainLabelPrefix, selection.Equals, []string{*m.Metal3Machine.Spec.FailureDomain}) + if err != nil { + m.Log.Error(err, "Failed to create FailureDomain MatchLabel requirement, not choosing host") + return nil, nil, err + } + reqs = append(reqs, *r) + } labelSelector = labelSelector.Add(reqs...) availableHosts := []*bmov1alpha1.BareMetalHost{} diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3clusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3clusters.yaml index cc4a896d5..a924389a3 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3clusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3clusters.yaml @@ -229,6 +229,27 @@ spec: - type type: object type: array + failureDomains: + additionalProperties: + description: FailureDomainSpec is the Schema for Cluster API failure + domains. It allows controllers to understand how many failure + domains a cluster can optionally span across. + properties: + attributes: + additionalProperties: + type: string + description: Attributes is a free form map of attributes an + infrastructure provider might use or require. + type: object + controlPlane: + description: ControlPlane determines if this failure domain + is suitable for use by control plane machines. + type: boolean + type: object + description: FailureDomains specifies the list of unique failure domains + available in the cluster. The list will be used by Cluster API to + try and spread the machines across failure domains + type: object failureMessage: description: FailureMessage indicates that there is a fatal problem reconciling the state, and will be set to a descriptive error message. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3machines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3machines.yaml index 3c9519fd4..9deed42ae 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3machines.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3machines.yaml @@ -468,6 +468,10 @@ spec: type: string type: object x-kubernetes-map-type: atomic + failureDomain: + description: FailureDomain is the failure domain the machine will + be created in. + type: string hostSelector: description: HostSelector specifies matching criteria for labels on BareMetalHosts. This is used to limit the set of BareMetalHost objects diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3machinetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3machinetemplates.yaml index 46a7e12cb..3e6b9eba8 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3machinetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_metal3machinetemplates.yaml @@ -323,6 +323,10 @@ spec: type: string type: object x-kubernetes-map-type: atomic + failureDomain: + description: FailureDomain is the failure domain the machine + will be created in. + type: string hostSelector: description: HostSelector specifies matching criteria for labels on BareMetalHosts. This is used to limit the set