From f9cddb9e6d97af3543ee9fc10bf371fb7a4e24d1 Mon Sep 17 00:00:00 2001 From: Artem Bortnikov Date: Tue, 17 Dec 2024 05:56:36 +0200 Subject: [PATCH] remove bios settings Signed-off-by: Artem Bortnikov --- api/v1alpha1/server_types.go | 45 ++++----- api/v1alpha1/zz_generated.deepcopy.go | 33 +------ .../crd/bases/metal.ironcore.dev_servers.yaml | 51 +++------- docs/api-reference/api.md | 73 +++----------- internal/controller/server_controller.go | 99 ++----------------- 5 files changed, 61 insertions(+), 240 deletions(-) diff --git a/api/v1alpha1/server_types.go b/api/v1alpha1/server_types.go index fd0a911..60e001a 100644 --- a/api/v1alpha1/server_types.go +++ b/api/v1alpha1/server_types.go @@ -66,14 +66,6 @@ type BootOrder struct { Device string `json:"device"` } -// BIOSSettings represents the BIOS settings for a server. -type BIOSSettings struct { - // Version specifies the version of the server BIOS for which the settings are defined. - Version string `json:"version"` - // Settings is a map of key-value pairs representing the BIOS settings. - Settings map[string]string `json:"settings,omitempty"` -} - // ServerSpec defines the desired state of a Server. type ServerSpec struct { // UUID is the unique identifier for the server. @@ -108,8 +100,10 @@ type ServerSpec struct { // BootOrder specifies the boot order of the server. BootOrder []BootOrder `json:"bootOrder,omitempty"` - // BIOS specifies the BIOS settings for the server. - BIOS []BIOSSettings `json:"BIOS,omitempty"` + + // BIOSSettingsRef is a reference to a ServerBIOS object that specifies + // the BIOS configuration for this server. + BIOSSettingsRef v1.LocalObjectReference `json:"biosSettingsRef,omitempty"` } // ServerState defines the possible states of a server. @@ -128,6 +122,9 @@ const ( // ServerStateReserved indicates that the server is reserved for a specific use or user. ServerStateReserved ServerState = "Reserved" + // ServerStateMaintenance indicates that the server is in maintenance mode. + ServerStateMaintenance ServerState = "Maintenance" + // ServerStateError indicates that there is an error with the server. ServerStateError ServerState = "Error" ) @@ -193,8 +190,6 @@ type ServerStatus struct { // Storages is a list of storages associated with the server. Storages []Storage `json:"storages,omitempty"` - BIOS BIOSSettings `json:"BIOS,omitempty"` - // Conditions represents the latest available observations of the server's current state. // +patchStrategy=merge // +patchMergeKey=type @@ -261,18 +256,18 @@ type Storage struct { Drives []StorageDrive `json:"drives,omitempty"` } -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status -//+kubebuilder:resource:scope=Cluster -//+kubebuilder:printcolumn:name="UUID",type=string,JSONPath=`.spec.uuid` -//+kubebuilder:printcolumn:name="Manufacturer",type=string,JSONPath=`.status.manufacturer` -//+kubebuilder:printcolumn:name="Model",type=string,JSONPath=`.status.model` -//+kubebuilder:printcolumn:name="SKU",type=string,JSONPath=`.status.sku`,priority=100 -//+kubebuilder:printcolumn:name="SerialNumber",type=string,JSONPath=`.status.serialNumber`,priority=100 -//+kubebuilder:printcolumn:name="PowerState",type=string,JSONPath=`.status.powerState` -//+kubebuilder:printcolumn:name="IndicatorLED",type=string,JSONPath=`.status.indicatorLED`,priority=100 -//+kubebuilder:printcolumn:name="State",type=string,JSONPath=`.status.state` -//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:printcolumn:name="UUID",type=string,JSONPath=`.spec.uuid` +// +kubebuilder:printcolumn:name="Manufacturer",type=string,JSONPath=`.status.manufacturer` +// +kubebuilder:printcolumn:name="Model",type=string,JSONPath=`.status.model` +// +kubebuilder:printcolumn:name="SKU",type=string,JSONPath=`.status.sku`,priority=100 +// +kubebuilder:printcolumn:name="SerialNumber",type=string,JSONPath=`.status.serialNumber`,priority=100 +// +kubebuilder:printcolumn:name="PowerState",type=string,JSONPath=`.status.powerState` +// +kubebuilder:printcolumn:name="IndicatorLED",type=string,JSONPath=`.status.indicatorLED`,priority=100 +// +kubebuilder:printcolumn:name="State",type=string,JSONPath=`.status.state` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` // Server is the Schema for the servers API type Server struct { @@ -283,7 +278,7 @@ type Server struct { Status ServerStatus `json:"status,omitempty"` } -//+kubebuilder:object:root=true +// +kubebuilder:object:root=true // ServerList contains a list of Server type ServerList struct { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index f764e86..88b3926 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -8,33 +8,11 @@ package v1alpha1 import ( - v1 "k8s.io/api/core/v1" + "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *BIOSSettings) DeepCopyInto(out *BIOSSettings) { - *out = *in - if in.Settings != nil { - in, out := &in.Settings, &out.Settings - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BIOSSettings. -func (in *BIOSSettings) DeepCopy() *BIOSSettings { - if in == nil { - return nil - } - out := new(BIOSSettings) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BMC) DeepCopyInto(out *BMC) { *out = *in @@ -704,13 +682,7 @@ func (in *ServerSpec) DeepCopyInto(out *ServerSpec) { *out = make([]BootOrder, len(*in)) copy(*out, *in) } - if in.BIOS != nil { - in, out := &in.BIOS, &out.BIOS - *out = make([]BIOSSettings, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } + out.BIOSSettingsRef = in.BIOSSettingsRef } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerSpec. @@ -745,7 +717,6 @@ func (in *ServerStatus) DeepCopyInto(out *ServerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - in.BIOS.DeepCopyInto(&out.BIOS) if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]metav1.Condition, len(*in)) diff --git a/config/crd/bases/metal.ironcore.dev_servers.yaml b/config/crd/bases/metal.ironcore.dev_servers.yaml index be46967..81b7558 100644 --- a/config/crd/bases/metal.ironcore.dev_servers.yaml +++ b/config/crd/bases/metal.ironcore.dev_servers.yaml @@ -70,25 +70,22 @@ spec: spec: description: ServerSpec defines the desired state of a Server. properties: - BIOS: - description: BIOS specifies the BIOS settings for the server. - items: - description: BIOSSettings represents the BIOS settings for a server. - properties: - settings: - additionalProperties: - type: string - description: Settings is a map of key-value pairs representing - the BIOS settings. - type: object - version: - description: Version specifies the version of the server BIOS - for which the settings are defined. - type: string - required: - - version - type: object - type: array + biosSettingsRef: + description: |- + BIOSSettingsRef is a reference to a ServerBIOS object that specifies + the BIOS configuration for this server. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic bmc: description: |- BMC contains the access details for the BMC. @@ -285,22 +282,6 @@ spec: status: description: ServerStatus defines the observed state of Server. properties: - BIOS: - description: BIOSSettings represents the BIOS settings for a server. - properties: - settings: - additionalProperties: - type: string - description: Settings is a map of key-value pairs representing - the BIOS settings. - type: object - version: - description: Version specifies the version of the server BIOS - for which the settings are defined. - type: string - required: - - version - type: object conditions: description: Conditions represents the latest available observations of the server's current state. diff --git a/docs/api-reference/api.md b/docs/api-reference/api.md index e764b4c..7b95347 100644 --- a/docs/api-reference/api.md +++ b/docs/api-reference/api.md @@ -10,46 +10,6 @@ Resource Types: -

BIOSSettings -

-

-(Appears on:ServerSpec, ServerStatus) -

-
-

BIOSSettings represents the BIOS settings for a server.

-
- - - - - - - - - - - - - - - - - -
FieldDescription
-version
- -string - -
-

Version specifies the version of the server BIOS for which the settings are defined.

-
-settings
- -map[string]string - -
-

Settings is a map of key-value pairs representing the BIOS settings.

-

BMC

@@ -1328,15 +1288,16 @@ if no boot configuration is specified.

-BIOS
+biosSettingsRef
- -[]BIOSSettings + +Kubernetes core/v1.LocalObjectReference -

BIOS specifies the BIOS settings for the server.

+

BIOSSettingsRef is a reference to a ServerBIOS object that specifies +the BIOS configuration for this server.

@@ -1976,15 +1937,16 @@ if no boot configuration is specified.

-BIOS
+biosSettingsRef
- -[]BIOSSettings + +Kubernetes core/v1.LocalObjectReference -

BIOS specifies the BIOS settings for the server.

+

BIOSSettingsRef is a reference to a ServerBIOS object that specifies +the BIOS configuration for this server.

@@ -2016,6 +1978,9 @@ if no boot configuration is specified.

"Initial"

ServerStateInitial indicates that the server is in its initial state.

+

"Maintenance"

+

ServerStateMaintenance indicates that the server is in maintenance mode.

+

"Reserved"

ServerStateReserved indicates that the server is reserved for a specific use or user.

@@ -2161,18 +2126,6 @@ k8s.io/apimachinery/pkg/api/resource.Quantity -BIOS
- - -BIOSSettings - - - - - - - - conditions
diff --git a/internal/controller/server_controller.go b/internal/controller/server_controller.go index dac5733..c5df5af 100644 --- a/internal/controller/server_controller.go +++ b/internal/controller/server_controller.go @@ -23,7 +23,6 @@ import ( "github.com/stmcginnis/gofish/redfish" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" - meta "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -68,15 +67,15 @@ type ServerReconciler struct { DiscoveryTimeout time.Duration } -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs,verbs=get;list;watch -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcsecrets,verbs=get;list;watch -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints,verbs=get;list;watch -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=servers,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=servers/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=servers/finalizers,verbs=update -//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=serverconfigurations,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups="batch",resources=jobs,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs,verbs=get;list;watch +// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcsecrets,verbs=get;list;watch +// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints,verbs=get;list;watch +// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=servers,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=servers/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=servers/finalizers,verbs=update +// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=serverconfigurations,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups="batch",resources=jobs,verbs=get;list;watch;create;update;patch;delete // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. @@ -163,11 +162,6 @@ func (r *ServerReconciler) reconcile(ctx context.Context, log logr.Logger, serve } log.V(1).Info("Updated Server status", "Status", server.Status.State) - if err := r.applyBiosSettings(ctx, log, server); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to update server bios settings: %w", err) - } - log.V(1).Info("Updated Server BIOS settings") - if err := r.applyBootOrder(ctx, log, server); err != nil { return ctrl.Result{}, fmt.Errorf("failed to update server bios boot order: %w", err) } @@ -379,7 +373,7 @@ func (r *ServerReconciler) handleReservedState(ctx context.Context, log logr.Log } log.V(1).Info("Server boot configuration is ready") - //TODO: handle working Reserved Server that was suddenly powered off but needs to boot from disk + // TODO: handle working Reserved Server that was suddenly powered off but needs to boot from disk if server.Status.PowerState == metalv1alpha1.ServerOffPowerState { if err := r.pxeBootServer(ctx, log, server); err != nil { return false, fmt.Errorf("failed to boot server: %w", err) @@ -438,27 +432,6 @@ func (r *ServerReconciler) updateServerStatus(ctx context.Context, log logr.Logg server.Status.IndicatorLED = metalv1alpha1.IndicatorLED(systemInfo.IndicatorLED) server.Status.TotalSystemMemory = &systemInfo.TotalSystemMemory - currentBiosVersion, err := bmcClient.GetBiosVersion(ctx, server.Spec.SystemUUID) - if err != nil { - return fmt.Errorf("failed to load bios version: %w", err) - } - - for _, bios := range server.Spec.BIOS { - if bios.Version == currentBiosVersion { - // with go 1.23: switch to maps.Keys(bios.Settings) - keys := make([]string, 0, len(bios.Settings)) - for k := range bios.Settings { - keys = append(keys, k) - } - attributes, err := bmcClient.GetBiosAttributeValues(ctx, server.Spec.SystemUUID, keys) - if err != nil { - return fmt.Errorf("failed load bios settings: %w", err) - } - server.Status.BIOS.Version = currentBiosVersion - server.Status.BIOS.Settings = attributes - } - } - if err := r.Status().Patch(ctx, server, client.MergeFrom(serverBase)); err != nil { return fmt.Errorf("failed to patch Server status: %w", err) } @@ -846,58 +819,6 @@ func (r *ServerReconciler) applyBootOrder(ctx context.Context, log logr.Logger, return nil } -func (r *ServerReconciler) applyBiosSettings(ctx context.Context, log logr.Logger, server *metalv1alpha1.Server) error { - serverBase := server.DeepCopy() - if server.Spec.BMCRef == nil && server.Spec.BMC == nil { - log.V(1).Info("Server has no BMC connection configured") - return nil - } - bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure, r.BMCOptions) - if err != nil { - return fmt.Errorf("failed to create BMC client: %w", err) - } - defer bmcClient.Logout() - - version, err := bmcClient.GetBiosVersion(ctx, server.Spec.SystemUUID) - if err != nil { - return fmt.Errorf("failed to create BMC client: %w", err) - } - - versionMatch := false - diff := map[string]string{} - for _, bios := range server.Spec.BIOS { - if bios.Version == version { - versionMatch = true - for key, value := range bios.Settings { - if res, ok := server.Status.BIOS.Settings[key]; !ok { - if !ok || res != value { - diff[key] = value - } - } - } - reset, err := bmcClient.SetBiosAttributes(ctx, server.Spec.SystemUUID, diff) - if err != nil { - return err - } - if reset { - if changed := meta.SetStatusCondition(&server.Status.Conditions, metav1.Condition{ - Type: "Reboot needed", - }); changed { - if err := r.Status().Patch(ctx, server, client.MergeFrom(serverBase)); err != nil { - return fmt.Errorf("failed to patch Server status: %w", err) - } - } - } - break - } - } - if !versionMatch { - log.V(1).Info("None of the Bios versions match") - return nil - } - return nil -} - func (r *ServerReconciler) handleAnnotionOperations(ctx context.Context, log logr.Logger, server *metalv1alpha1.Server) (bool, error) { annotations := server.GetAnnotations() operation, ok := annotations[metalv1alpha1.OperationAnnotation]