From 9333c7dc39daaf0a86b12c0d5ace3f1d26fe9e8d Mon Sep 17 00:00:00 2001 From: Stefan Hipfel Date: Mon, 13 Oct 2025 11:24:20 +0200 Subject: [PATCH 1/8] Add event subscription management for server events and metrics --- bmc/bmc.go | 6 + bmc/redfish.go | 65 ++++++++++ cmd/serverevents/main.go | 53 ++++++++ internal/controller/server_controller.go | 22 ++++ internal/serverevents/metrics.go | 28 +++++ internal/serverevents/server.go | 148 +++++++++++++++++++++++ internal/serverevents/subscription.go | 46 +++++++ 7 files changed, 368 insertions(+) create mode 100644 cmd/serverevents/main.go create mode 100644 internal/serverevents/metrics.go create mode 100644 internal/serverevents/server.go create mode 100644 internal/serverevents/subscription.go diff --git a/bmc/bmc.go b/bmc/bmc.go index e7bd1cd0..f024a1f1 100644 --- a/bmc/bmc.go +++ b/bmc/bmc.go @@ -121,6 +121,12 @@ type BMC interface { // GetBMCUpgradeTask retrieves the task for the BMC upgrade. GetBMCUpgradeTask(ctx context.Context, manufacturer string, taskURI string) (*redfish.Task, error) + + // CreateEventSubscription creates an event subscription for the manager.q + CreateEventSubscription(ctx context.Context, destination string, eventType redfish.EventFormatType, protocol redfish.DeliveryRetryPolicy) error + + // DeleteEventSubscription deletes an event subscription for the manager. + DeleteEventSubscription(ctx context.Context, destination string) error } // OEMManagerInterface defines methods for OEM-specific BMC management. diff --git a/bmc/redfish.go b/bmc/redfish.go index 37699ec6..24d54d77 100644 --- a/bmc/redfish.go +++ b/bmc/redfish.go @@ -965,3 +965,68 @@ func (r *RedfishBMC) GetBMCUpgradeTask(ctx context.Context, manufacturer string, return oem.GetTaskMonitorDetails(ctx, respTask) } + +type subscriptionPayload struct { + Destination string `json:"Destination,omitempty"` + EventTypes []redfish.EventType `json:"EventTypes,omitempty"` + EventFormatType redfish.EventFormatType `json:"EventFormatType,omitempty"` + RegistryPrefixes []string `json:"RegistryPrefixes,omitempty"` + ResourceTypes []string `json:"ResourceTypes,omitempty"` + DeliveryRetryPolicy redfish.DeliveryRetryPolicy `json:"DeliveryRetryPolicy,omitempty"` + HTTPHeaders map[string]string `json:"HttpHeaders,omitempty"` + Oem interface{} `json:"Oem,omitempty"` + Protocol redfish.EventDestinationProtocol `json:"Protocol,omitempty"` + Context string `json:"Context,omitempty"` +} + +func (r *RedfishBMC) CreateEventSubscription( + ctx context.Context, + destination string, + eventFormatType redfish.EventFormatType, + retry redfish.DeliveryRetryPolicy, +) error { + service := r.client.GetService() + ev, err := service.EventService() + if err != nil { + return fmt.Errorf("failed to get event service: %w", err) + } + if !ev.ServiceEnabled { + return fmt.Errorf("event service is not enabled") + } + + payload := &subscriptionPayload{ + Destination: destination, + EventFormatType: eventFormatType, // event or metricreport + Protocol: redfish.RedfishEventDestinationProtocol, + DeliveryRetryPolicy: retry, + Context: "metal3-operator", + } + client := ev.GetClient() + // some implementations (like Dell) do not support ResourceTypes and RegistryPrefixes + if len(ev.ResourceTypes) == 0 { + payload.EventTypes = []redfish.EventType{} + } else { + payload.RegistryPrefixes = []string{""} // Filters by the prefix of the event's MessageId, which points to a Message Registry: [Base, ResourceEvent, iLOEvents] + payload.ResourceTypes = []string{""} // Filters by the schema name (Resource Type) of the event's OriginOfCondition: [Chassis, ComputerSystem, Power] + } + _, err = client.Post(ev.Subscriptions, payload) + if err != nil { + return err + } + return nil +} + +func (r RedfishBMC) DeleteEventSubscription(ctx context.Context, destination string) error { + service := r.client.GetService() + ev, err := service.EventService() + if err != nil { + return fmt.Errorf("failed to get event service: %w", err) + } + if !ev.ServiceEnabled { + return fmt.Errorf("event service is not enabled") + } + if err := ev.DeleteEventSubscription(destination); err != nil { + return fmt.Errorf("failed to delete event subscription: %w", err) + } + return nil +} diff --git a/cmd/serverevents/main.go b/cmd/serverevents/main.go new file mode 100644 index 00000000..3fb3ff76 --- /dev/null +++ b/cmd/serverevents/main.go @@ -0,0 +1,53 @@ +package main + +import ( + "flag" + "os" + "time" + + "github.com/ironcore-dev/metal-operator/internal/serverevents" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +var ( + setupLog = ctrl.Log.WithName("setup") +) + +func main() { + var registryURL string + var serverUUID string + var duration time.Duration + + flag.StringVar(®istryURL, "registry-url", "", "Registry URL where the probe will register itself.") + flag.StringVar(&serverUUID, "server-uuid", "", "Agent UUID to register with the registry.") + flag.DurationVar(&duration, "duration", 5*time.Second, "Duration of time to wait between checks.") + + opts := zap.Options{ + Development: true, + } + opts.BindFlags(flag.CommandLine) + flag.Parse() + + ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + + if serverUUID == "" { + setupLog.Error(nil, "server uuid is missing") + os.Exit(1) + } + + if registryURL == "" { + setupLog.Error(nil, "registry URL is missing") + os.Exit(1) + } + + ctx := ctrl.SetupSignalHandler() + + setupLog.Info("starting serverevent agent") + server := serverevents.NewServer(setupLog, ":8888") + + if err := server.Start(ctx); err != nil { + setupLog.Error(err, "problem running telemetry server") + os.Exit(1) + } +} diff --git a/internal/controller/server_controller.go b/internal/controller/server_controller.go index ef48ae25..35b50d75 100644 --- a/internal/controller/server_controller.go +++ b/internal/controller/server_controller.go @@ -24,6 +24,7 @@ import ( "github.com/ironcore-dev/metal-operator/internal/api/registry" "github.com/ironcore-dev/metal-operator/internal/bmcutils" "github.com/ironcore-dev/metal-operator/internal/ignition" + "github.com/ironcore-dev/metal-operator/internal/serverevents" "github.com/stmcginnis/gofish/redfish" "golang.org/x/crypto/bcrypt" "golang.org/x/crypto/ssh" @@ -165,6 +166,19 @@ func (r *ServerReconciler) delete(ctx context.Context, log logr.Logger, server * log.V(1).Info("BIOS settings was deleted") } + bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure, r.BMCOptions) + if err != nil { + return ctrl.Result{}, fmt.Errorf("failed to get BMC client for server: %w", err) + } + if err := bmcClient.DeleteEventSubscription(ctx, fmt.Sprintf("https://localhost:8888/%s/%s/metrics", server.Status.Manufacturer, server.Spec.UUID)); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to delete metrics event subscription: %w", err) + } + log.V(1).Info("Deleted metrics event subscription") + if err := bmcClient.DeleteEventSubscription(ctx, fmt.Sprintf("https://localhost:8888/%s/%s/alerts", server.Status.Manufacturer, server.Spec.UUID)); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to delete alerts event subscription: %w", err) + } + log.V(1).Info("Deleted alerts event subscription") + log.V(1).Info("Ensuring that the finalizer is removed") if modified, err := clientutils.PatchEnsureNoFinalizer(ctx, r.Client, server, ServerFinalizer); err != nil || modified { return ctrl.Result{}, err @@ -385,6 +399,14 @@ func (r *ServerReconciler) handleDiscoveryState(ctx context.Context, log logr.Lo } log.V(1).Info("Removed Server from Registry") + if err := serverevents.SubscribeMetricsReport(ctx, server.Status.Manufacturer, server.Spec.UUID, bmcClient); err != nil { + return false, fmt.Errorf("failed to subscribe to server metrics report: %w", err) + } + + if err := serverevents.SubscribeEvents(ctx, server.Status.Manufacturer, server.Spec.UUID, bmcClient); err != nil { + return false, fmt.Errorf("failed to subscribe to server alerts: %w", err) + } + log.V(1).Info("Setting Server state set to available") if modified, err := r.patchServerState(ctx, server, metalv1alpha1.ServerStateAvailable); err != nil || modified { return false, err diff --git a/internal/serverevents/metrics.go b/internal/serverevents/metrics.go new file mode 100644 index 00000000..6c154a39 --- /dev/null +++ b/internal/serverevents/metrics.go @@ -0,0 +1,28 @@ +package serverevents + +type MetricsReport struct { + Data Data `json:"data"` +} + +type Data struct { + MetricsValues []MetricsValue `json:"MetricsValues"` +} +type MetricsValue struct { + MetricId string `json:"MetricId"` + MetricProperty string `json:"MetricProperty"` + MetricValue string `json:"MetricValue"` + Timestamp string `json:"Timestamp"` + Oem interface{} `json:"Oem"` +} + +type EventData struct { + Events []Event `json:"Alerts"` + Name string `json:"Name"` +} + +type Event struct { + EventID string `json:"EventId"` + Message string `json:"Message"` + Severity string `json:"Severity"` + EventTimestamp string `json:"EventTimestamp"` +} diff --git a/internal/serverevents/server.go b/internal/serverevents/server.go new file mode 100644 index 00000000..4ea0d1e7 --- /dev/null +++ b/internal/serverevents/server.go @@ -0,0 +1,148 @@ +package serverevents + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "path" + "strconv" + + "github.com/go-logr/logr" + "github.com/prometheus/client_golang/prometheus" + "sigs.k8s.io/controller-runtime/pkg/metrics" +) + +type Server struct { + addr string + mux *http.ServeMux + log logr.Logger +} + +var ( + alertsGauge = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "redfish_alerts_total", + Help: "Number of redfish alerts", + }, + []string{"hostname", "vendor", "severity"}, + ) + metricsReportCollectors map[string]*prometheus.GaugeVec +) + +func init() { + // Register custom metrics with the global prometheus registry + metrics.Registry.MustRegister(alertsGauge) +} + +func NewServer(log logr.Logger, addr string) *Server { + mux := http.NewServeMux() + server := &Server{ + addr: addr, + mux: mux, + log: log, + } + server.routes() + return server +} + +func (s *Server) routes() { + s.mux.HandleFunc("/serverevents/alerts", s.alertHandler) + s.mux.HandleFunc("/serverevents/metricsreport", s.metricsreportHandler) +} + +func (s *Server) alertHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Only POST method is allowed", http.StatusMethodNotAllowed) + return + } + s.log.Info("Received alert data") + // expected path: /serverevents/alerts/{vendor}/{hostname} + hostname := path.Base(r.URL.Path) + vendor := path.Base(path.Dir(r.URL.Path)) + eventData := EventData{} + if err := json.NewDecoder(r.Body).Decode(&eventData); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + totalWarnings := 0 + totalCriticals := 0 + for _, event := range eventData.Events { + if event.Severity == "Warning" { + totalWarnings++ + } + if event.Severity == "Critical" { + totalCriticals++ + } + } + alertsGauge.WithLabelValues(hostname, vendor, "Warning").Set(float64(totalWarnings)) + alertsGauge.WithLabelValues(hostname, vendor, "Critical").Set(float64(totalCriticals)) + w.WriteHeader(http.StatusOK) + w.Write([]byte("Alert data received")) +} + +func (s *Server) metricsreportHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Only POST method is allowed", http.StatusMethodNotAllowed) + return + } + // expected path: /serverevents/metricsreport/{vendor}/{hostname} + hostname := path.Base(r.URL.Path) + vendor := path.Base(path.Dir(r.URL.Path)) + s.log.Info("receieved metrics report", "uuid", hostname) + metricsReport := MetricsReport{} + if err := json.NewDecoder(r.Body).Decode(&metricsReport); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + } + for _, mv := range metricsReport.Data.MetricsValues { + if _, ok := metricsReportCollectors[mv.MetricId]; !ok { + gauge := prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: mv.MetricProperty, + Help: "Metric with ID " + mv.MetricId, + }, + []string{"hostname", "vendor"}, + ) + floatVal, err := strconv.ParseFloat(mv.MetricValue, 64) + if err != nil { + if mv.MetricValue == "Up" || mv.MetricValue == "Operational" { + floatVal = 1 + } + } + gauge.WithLabelValues(hostname, vendor).Set(floatVal) + metricsReportCollectors[mv.MetricId] = gauge + metrics.Registry.MustRegister(gauge) + } + s.log.Info("Metric", "id", mv.MetricId, "property", mv.MetricProperty, "value", mv.MetricValue, "timestamp", mv.Timestamp) + } + w.WriteHeader(http.StatusOK) + w.Write([]byte("Metrics report data received")) +} + +// Start starts the server on the specified address and adds logging for key events. +func (s *Server) Start(ctx context.Context) error { + s.log.Info("Starting registry server", "address", s.addr) + server := &http.Server{Addr: s.addr, Handler: s.mux} + + errChan := make(chan error, 1) + go func() { + if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { + errChan <- fmt.Errorf("HTTP registry server ListenAndServe: %w", err) + } + }() + select { + case <-ctx.Done(): + s.log.Info("Shutting down registry server...") + if err := server.Shutdown(ctx); err != nil { + return fmt.Errorf("HTTP server Shutdown: %w", err) + } + s.log.Info("Registry server graciously stopped") + return nil + case err := <-errChan: + if shutdownErr := server.Shutdown(ctx); shutdownErr != nil { + s.log.Error(shutdownErr, "Error shutting down registry server") + } + return err + } +} diff --git a/internal/serverevents/subscription.go b/internal/serverevents/subscription.go new file mode 100644 index 00000000..4c138d17 --- /dev/null +++ b/internal/serverevents/subscription.go @@ -0,0 +1,46 @@ +package serverevents + +import ( + "context" + "fmt" + + "github.com/ironcore-dev/metal-operator/bmc" + "github.com/stmcginnis/gofish/redfish" +) + +func SubscribeMetricsReport(ctx context.Context, vendor, hostname string, bmcClient bmc.BMC) error { + if err := bmcClient.CreateEventSubscription( + ctx, + fmt.Sprintf("https://localhost:8888/%s/%s/metrics", vendor, hostname), + redfish.MetricReportEventFormatType, + redfish.TerminateAfterRetriesDeliveryRetryPolicy, + ); err != nil { + return fmt.Errorf("failed to create event subscription: %w", err) + } + return nil +} + +func UnsubscribeMetricsReport(ctx context.Context, vendor, hostname string, bmcClient bmc.BMC) error { + if err := bmcClient.DeleteEventSubscription(ctx, fmt.Sprintf("https://localhost:8888/%s/%s/metrics", vendor, hostname)); err != nil { + return fmt.Errorf("failed to delete event subscription: %w", err) + } + return nil +} + +func SubscribeEvents(ctx context.Context, vendor, hostname string, bmcClient bmc.BMC) error { + if err := bmcClient.CreateEventSubscription( + ctx, + fmt.Sprintf("https://localhost:8888/%s/%s/alerts", vendor, hostname), + redfish.EventEventFormatType, + redfish.TerminateAfterRetriesDeliveryRetryPolicy, + ); err != nil { + return fmt.Errorf("failed to create alert subscription: %w", err) + } + return nil +} +func UnsubscribeEvents(ctx context.Context, vendor, hostname string, bmcClient bmc.BMC) error { + if err := bmcClient.DeleteEventSubscription(ctx, fmt.Sprintf("https://localhost:8888/%s/%s/alerts", vendor, hostname)); err != nil { + return fmt.Errorf("failed to delete alert subscription: %w", err) + } + return nil +} From ecec4f80a6b5648985073607348d3fd97b4b2ac9 Mon Sep 17 00:00:00 2001 From: Stefan Hipfel Date: Mon, 13 Oct 2025 12:11:09 +0200 Subject: [PATCH 2/8] Add SPDX license headers --- cmd/serverevents/main.go | 3 +++ internal/serverevents/metrics.go | 3 +++ internal/serverevents/server.go | 5 +++-- internal/serverevents/subscription.go | 3 +++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cmd/serverevents/main.go b/cmd/serverevents/main.go index 3fb3ff76..28088dfb 100644 --- a/cmd/serverevents/main.go +++ b/cmd/serverevents/main.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 + package main import ( diff --git a/internal/serverevents/metrics.go b/internal/serverevents/metrics.go index 6c154a39..0b9bbbf1 100644 --- a/internal/serverevents/metrics.go +++ b/internal/serverevents/metrics.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 + package serverevents type MetricsReport struct { diff --git a/internal/serverevents/server.go b/internal/serverevents/server.go index 4ea0d1e7..2f80aaf8 100644 --- a/internal/serverevents/server.go +++ b/internal/serverevents/server.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 + package serverevents import ( @@ -79,7 +82,6 @@ func (s *Server) alertHandler(w http.ResponseWriter, r *http.Request) { alertsGauge.WithLabelValues(hostname, vendor, "Warning").Set(float64(totalWarnings)) alertsGauge.WithLabelValues(hostname, vendor, "Critical").Set(float64(totalCriticals)) w.WriteHeader(http.StatusOK) - w.Write([]byte("Alert data received")) } func (s *Server) metricsreportHandler(w http.ResponseWriter, r *http.Request) { @@ -117,7 +119,6 @@ func (s *Server) metricsreportHandler(w http.ResponseWriter, r *http.Request) { s.log.Info("Metric", "id", mv.MetricId, "property", mv.MetricProperty, "value", mv.MetricValue, "timestamp", mv.Timestamp) } w.WriteHeader(http.StatusOK) - w.Write([]byte("Metrics report data received")) } // Start starts the server on the specified address and adds logging for key events. diff --git a/internal/serverevents/subscription.go b/internal/serverevents/subscription.go index 4c138d17..be46d589 100644 --- a/internal/serverevents/subscription.go +++ b/internal/serverevents/subscription.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 + package serverevents import ( From ea45555b7b73147485ad93901a8949fe488b58e3 Mon Sep 17 00:00:00 2001 From: Stefan Hipfel Date: Wed, 29 Oct 2025 15:29:55 +0100 Subject: [PATCH 3/8] Add metrics and events subscription links to ServerStatus and update BMC interface methods --- api/v1alpha1/server_types.go | 8 +++ bmc/bmc.go | 4 +- bmc/redfish.go | 31 +++++++---- cmd/manager/main.go | 28 ++++++++++ internal/controller/server_controller.go | 67 ++++++++++++++++++------ internal/serverevents/metrics.go | 31 ----------- internal/serverevents/server.go | 28 +++++++++- internal/serverevents/subscription.go | 39 +++++--------- {cmd => test}/serverevents/main.go | 0 9 files changed, 152 insertions(+), 84 deletions(-) delete mode 100644 internal/serverevents/metrics.go rename {cmd => test}/serverevents/main.go (100%) diff --git a/api/v1alpha1/server_types.go b/api/v1alpha1/server_types.go index 5557ed71..fa548736 100644 --- a/api/v1alpha1/server_types.go +++ b/api/v1alpha1/server_types.go @@ -216,6 +216,14 @@ type ServerStatus struct { // +optional State ServerState `json:"state,omitempty"` + // MetricsReportSubscriptionLink is the link to the metrics report subscription for the server. + // +optional + MetricsReportSubscriptionLink string `json:"metricsReportSubscriptionLink,omitempty"` + + // EventsSubscriptionLink is the link to the events subscription for the server. + // +optional + EventsSubscriptionLink string `json:"eventsSubscriptionLink,omitempty"` + // NetworkInterfaces is a list of network interfaces associated with the server. // +optional NetworkInterfaces []NetworkInterface `json:"networkInterfaces,omitempty"` diff --git a/bmc/bmc.go b/bmc/bmc.go index f024a1f1..acabaa12 100644 --- a/bmc/bmc.go +++ b/bmc/bmc.go @@ -123,10 +123,10 @@ type BMC interface { GetBMCUpgradeTask(ctx context.Context, manufacturer string, taskURI string) (*redfish.Task, error) // CreateEventSubscription creates an event subscription for the manager.q - CreateEventSubscription(ctx context.Context, destination string, eventType redfish.EventFormatType, protocol redfish.DeliveryRetryPolicy) error + CreateEventSubscription(ctx context.Context, destination string, eventType redfish.EventFormatType, protocol redfish.DeliveryRetryPolicy) (string, error) // DeleteEventSubscription deletes an event subscription for the manager. - DeleteEventSubscription(ctx context.Context, destination string) error + DeleteEventSubscription(ctx context.Context, uri string) error } // OEMManagerInterface defines methods for OEM-specific BMC management. diff --git a/bmc/redfish.go b/bmc/redfish.go index 24d54d77..e3623f35 100644 --- a/bmc/redfish.go +++ b/bmc/redfish.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "net/http" + "net/url" "slices" "strings" "time" @@ -984,16 +985,15 @@ func (r *RedfishBMC) CreateEventSubscription( destination string, eventFormatType redfish.EventFormatType, retry redfish.DeliveryRetryPolicy, -) error { +) (string, error) { service := r.client.GetService() ev, err := service.EventService() if err != nil { - return fmt.Errorf("failed to get event service: %w", err) + return "", fmt.Errorf("failed to get event service: %w", err) } if !ev.ServiceEnabled { - return fmt.Errorf("event service is not enabled") + return "", fmt.Errorf("event service is not enabled") } - payload := &subscriptionPayload{ Destination: destination, EventFormatType: eventFormatType, // event or metricreport @@ -1009,14 +1009,20 @@ func (r *RedfishBMC) CreateEventSubscription( payload.RegistryPrefixes = []string{""} // Filters by the prefix of the event's MessageId, which points to a Message Registry: [Base, ResourceEvent, iLOEvents] payload.ResourceTypes = []string{""} // Filters by the schema name (Resource Type) of the event's OriginOfCondition: [Chassis, ComputerSystem, Power] } - _, err = client.Post(ev.Subscriptions, payload) + resp, err := client.Post(ev.Subscriptions, payload) if err != nil { - return err + return "", err } - return nil + // return subscription link from returned location + subscriptionLink := resp.Header.Get("Location") + urlParser, err := url.ParseRequestURI(subscriptionLink) + if err == nil { + subscriptionLink = urlParser.RequestURI() + } + return subscriptionLink, nil } -func (r RedfishBMC) DeleteEventSubscription(ctx context.Context, destination string) error { +func (r RedfishBMC) DeleteEventSubscription(ctx context.Context, uri string) error { service := r.client.GetService() ev, err := service.EventService() if err != nil { @@ -1025,7 +1031,14 @@ func (r RedfishBMC) DeleteEventSubscription(ctx context.Context, destination str if !ev.ServiceEnabled { return fmt.Errorf("event service is not enabled") } - if err := ev.DeleteEventSubscription(destination); err != nil { + event, err := ev.GetEventSubscription(uri) + if err != nil { + return fmt.Errorf("failed to get event subscription: %w", err) + } + if event == nil { + return nil + } + if err := ev.DeleteEventSubscription(uri); err != nil { return fmt.Errorf("failed to delete event subscription: %w", err) } return nil diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 0dfba887..b96c8e6f 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -11,6 +11,7 @@ import ( "path/filepath" "time" + "github.com/ironcore-dev/metal-operator/internal/serverevents" webhookmetalv1alpha1 "github.com/ironcore-dev/metal-operator/internal/webhook/v1alpha1" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) @@ -70,6 +71,9 @@ func main() { // nolint: gocyclo registryPort int registryProtocol string registryURL string + eventPort int + eventURL string + eventProtocol string registryResyncInterval time.Duration webhookPort int enforceFirstBoot bool @@ -106,6 +110,9 @@ func main() { // nolint: gocyclo flag.StringVar(®istryURL, "registry-url", "", "The URL of the registry.") flag.StringVar(®istryProtocol, "registry-protocol", "http", "The protocol to use for the registry.") flag.IntVar(®istryPort, "registry-port", 10000, "The port to use for the registry.") + flag.StringVar(&eventURL, "event-url", "", "The URL of the server events endpoint for alerts and metrics.") + flag.IntVar(&eventPort, "event-port", 10001, "The port to use for the server events endpoint for alerts and metrics.") + flag.StringVar(&eventProtocol, "event-protocol", "http", "The protocol to use for the server events endpoint for alerts and metrics.") flag.StringVar(&probeImage, "probe-image", "", "Image for the first boot probing of a Server.") flag.StringVar(&probeOSImage, "probe-os-image", "", "OS image for the first boot probing of a Server.") flag.StringVar(&managerNamespace, "manager-namespace", "default", "Namespace the manager is running in.") @@ -177,6 +184,15 @@ func main() { // nolint: gocyclo registryURL = fmt.Sprintf("%s://%s:%d", registryProtocol, registryAddr, registryPort) } + // set the correct event URL by getting the address from the environment + var eventAddr string + if eventURL == "" { + eventAddr = os.Getenv("EVENT_ADDRESS") + if eventAddr != "" { + eventURL = fmt.Sprintf("%s://%s:%d", eventProtocol, eventAddr, eventPort) + } + } + // if the enable-http2 flag is false (the default), http/2 should be disabled // due to its vulnerabilities. More specifically, disabling http/2 will // prevent from being vulnerable to the HTTP/2 Stream Cancelation and @@ -330,6 +346,7 @@ func main() { // nolint: gocyclo ProbeImage: probeImage, ProbeOSImage: probeOSImage, RegistryURL: registryURL, + EventURL: eventURL, RegistryResyncInterval: registryResyncInterval, ResyncInterval: serverResyncInterval, EnforceFirstBoot: enforceFirstBoot, @@ -525,6 +542,17 @@ func main() { // nolint: gocyclo } }() + if eventAddr != "" { + setupLog.Info("starting event server for alerts and metrics", "EventURL", eventURL) + eventServer := serverevents.NewServer(setupLog, fmt.Sprintf(":%d", eventPort)) + go func() { + if err := eventServer.Start(ctx); err != nil { + setupLog.Error(err, "problem running event server") + os.Exit(1) + } + }() + } + setupLog.Info("starting manager") if err := mgr.Start(ctx); err != nil { setupLog.Error(err, "problem running manager") diff --git a/internal/controller/server_controller.go b/internal/controller/server_controller.go index 35b50d75..71345013 100644 --- a/internal/controller/server_controller.go +++ b/internal/controller/server_controller.go @@ -83,6 +83,7 @@ type ServerReconciler struct { ManagerNamespace string ProbeImage string RegistryURL string + EventURL string ProbeOSImage string RegistryResyncInterval time.Duration EnforceFirstBoot bool @@ -170,21 +171,14 @@ func (r *ServerReconciler) delete(ctx context.Context, log logr.Logger, server * if err != nil { return ctrl.Result{}, fmt.Errorf("failed to get BMC client for server: %w", err) } - if err := bmcClient.DeleteEventSubscription(ctx, fmt.Sprintf("https://localhost:8888/%s/%s/metrics", server.Status.Manufacturer, server.Spec.UUID)); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to delete metrics event subscription: %w", err) + if err := r.deleteEventSubscription(ctx, log, bmcClient, server); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to delete event subscription: %w", err) } - log.V(1).Info("Deleted metrics event subscription") - if err := bmcClient.DeleteEventSubscription(ctx, fmt.Sprintf("https://localhost:8888/%s/%s/alerts", server.Status.Manufacturer, server.Spec.UUID)); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to delete alerts event subscription: %w", err) - } - log.V(1).Info("Deleted alerts event subscription") - log.V(1).Info("Ensuring that the finalizer is removed") if modified, err := clientutils.PatchEnsureNoFinalizer(ctx, r.Client, server, ServerFinalizer); err != nil || modified { return ctrl.Result{}, err } log.V(1).Info("Ensured that the finalizer has been removed") - log.V(1).Info("Deleted server") return ctrl.Result{}, nil } @@ -399,12 +393,8 @@ func (r *ServerReconciler) handleDiscoveryState(ctx context.Context, log logr.Lo } log.V(1).Info("Removed Server from Registry") - if err := serverevents.SubscribeMetricsReport(ctx, server.Status.Manufacturer, server.Spec.UUID, bmcClient); err != nil { - return false, fmt.Errorf("failed to subscribe to server metrics report: %w", err) - } - - if err := serverevents.SubscribeEvents(ctx, server.Status.Manufacturer, server.Spec.UUID, bmcClient); err != nil { - return false, fmt.Errorf("failed to subscribe to server alerts: %w", err) + if modified, err := r.handleEventSubscriptions(ctx, log, bmcClient, server); err != nil || modified { + return false, err } log.V(1).Info("Setting Server state set to available") @@ -1089,6 +1079,53 @@ func (r *ServerReconciler) handleAnnotionOperations(ctx context.Context, log log return true, nil } +func (r *ServerReconciler) handleEventSubscriptions(ctx context.Context, log logr.Logger, bmcClient bmc.BMC, server *metalv1alpha1.Server) (bool, error) { + if r.EventURL == "" { + return false, nil + } + metricsReportLink := "" + eventLink := "" + + if server.Status.MetricsReportSubscriptionLink != "" && server.Status.EventsSubscriptionLink != "" { + return false, nil + } + metricsReportLink, err := serverevents.SubscribeMetricsReport(ctx, r.EventURL, server.Status.Manufacturer, server.Spec.UUID, bmcClient) + if err != nil { + return false, fmt.Errorf("failed to subscribe to server metrics report: %w", err) + } + eventLink, err = serverevents.SubscribeEvents(ctx, r.EventURL, server.Status.Manufacturer, server.Spec.UUID, bmcClient) + if err != nil { + return false, fmt.Errorf("failed to subscribe to server alerts: %w", err) + } + serverBase := server.DeepCopy() + server.Status.MetricsReportSubscriptionLink = metricsReportLink + server.Status.EventsSubscriptionLink = eventLink + if err := r.Status().Patch(ctx, server, client.MergeFrom(serverBase)); err != nil { + return false, fmt.Errorf("failed to patch server status with subscription links: %w", err) + } + log.V(1).Info("Subscribed to server events and metrics") + return true, nil +} + +func (r *ServerReconciler) deleteEventSubscription(ctx context.Context, log logr.Logger, bmcClient bmc.BMC, server *metalv1alpha1.Server) error { + if r.EventURL == "" { + return nil + } + if server.Status.MetricsReportSubscriptionLink != "" { + if err := bmcClient.DeleteEventSubscription(ctx, server.Status.MetricsReportSubscriptionLink); err != nil { + return fmt.Errorf("failed to unsubscribe from server metrics report: %w", err) + } + log.V(1).Info("Unsubscribed from server metrics report") + } + if server.Status.EventsSubscriptionLink != "" { + if err := bmcClient.DeleteEventSubscription(ctx, server.Status.EventsSubscriptionLink); err != nil { + return fmt.Errorf("failed to unsubscribe from server events: %w", err) + } + log.V(1).Info("Unsubscribed from server events") + } + return nil +} + func (r *ServerReconciler) checkLastStatusUpdateAfter(duration time.Duration, server *metalv1alpha1.Server) bool { length := len(server.ManagedFields) - 1 if server.ManagedFields[length].Operation == "Update" { diff --git a/internal/serverevents/metrics.go b/internal/serverevents/metrics.go deleted file mode 100644 index 0b9bbbf1..00000000 --- a/internal/serverevents/metrics.go +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors -// SPDX-License-Identifier: Apache-2.0 - -package serverevents - -type MetricsReport struct { - Data Data `json:"data"` -} - -type Data struct { - MetricsValues []MetricsValue `json:"MetricsValues"` -} -type MetricsValue struct { - MetricId string `json:"MetricId"` - MetricProperty string `json:"MetricProperty"` - MetricValue string `json:"MetricValue"` - Timestamp string `json:"Timestamp"` - Oem interface{} `json:"Oem"` -} - -type EventData struct { - Events []Event `json:"Alerts"` - Name string `json:"Name"` -} - -type Event struct { - EventID string `json:"EventId"` - Message string `json:"Message"` - Severity string `json:"Severity"` - EventTimestamp string `json:"EventTimestamp"` -} diff --git a/internal/serverevents/server.go b/internal/serverevents/server.go index 2f80aaf8..bcb63107 100644 --- a/internal/serverevents/server.go +++ b/internal/serverevents/server.go @@ -34,6 +34,30 @@ var ( metricsReportCollectors map[string]*prometheus.GaugeVec ) +type MetricsReport struct { + MetricsValues []MetricsValue `json:"MetricsValues"` +} + +type MetricsValue struct { + MetricId string `json:"MetricId"` + MetricProperty string `json:"MetricProperty"` + MetricValue string `json:"MetricValue"` + Timestamp string `json:"Timestamp"` + Oem interface{} `json:"Oem"` +} + +type EventData struct { + Events []Event `json:"Alerts"` + Name string `json:"Name"` +} + +type Event struct { + EventID string `json:"EventId"` + Message string `json:"Message"` + Severity string `json:"Severity"` + EventTimestamp string `json:"EventTimestamp"` +} + func init() { // Register custom metrics with the global prometheus registry metrics.Registry.MustRegister(alertsGauge) @@ -92,12 +116,12 @@ func (s *Server) metricsreportHandler(w http.ResponseWriter, r *http.Request) { // expected path: /serverevents/metricsreport/{vendor}/{hostname} hostname := path.Base(r.URL.Path) vendor := path.Base(path.Dir(r.URL.Path)) - s.log.Info("receieved metrics report", "uuid", hostname) + s.log.Info("receieved metrics report", "hostname", hostname) metricsReport := MetricsReport{} if err := json.NewDecoder(r.Body).Decode(&metricsReport); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } - for _, mv := range metricsReport.Data.MetricsValues { + for _, mv := range metricsReport.MetricsValues { if _, ok := metricsReportCollectors[mv.MetricId]; !ok { gauge := prometheus.NewGaugeVec( prometheus.GaugeOpts{ diff --git a/internal/serverevents/subscription.go b/internal/serverevents/subscription.go index be46d589..a13f9c8b 100644 --- a/internal/serverevents/subscription.go +++ b/internal/serverevents/subscription.go @@ -11,39 +11,28 @@ import ( "github.com/stmcginnis/gofish/redfish" ) -func SubscribeMetricsReport(ctx context.Context, vendor, hostname string, bmcClient bmc.BMC) error { - if err := bmcClient.CreateEventSubscription( +func SubscribeMetricsReport(ctx context.Context, url, vendor, hostname string, bmcClient bmc.BMC) (string, error) { + link, err := bmcClient.CreateEventSubscription( ctx, - fmt.Sprintf("https://localhost:8888/%s/%s/metrics", vendor, hostname), + fmt.Sprintf("%s/%s/%s/metrics", url, vendor, hostname), redfish.MetricReportEventFormatType, redfish.TerminateAfterRetriesDeliveryRetryPolicy, - ); err != nil { - return fmt.Errorf("failed to create event subscription: %w", err) + ) + if err != nil { + return link, fmt.Errorf("failed to create event subscription: %w", err) } - return nil + return link, nil } -func UnsubscribeMetricsReport(ctx context.Context, vendor, hostname string, bmcClient bmc.BMC) error { - if err := bmcClient.DeleteEventSubscription(ctx, fmt.Sprintf("https://localhost:8888/%s/%s/metrics", vendor, hostname)); err != nil { - return fmt.Errorf("failed to delete event subscription: %w", err) - } - return nil -} - -func SubscribeEvents(ctx context.Context, vendor, hostname string, bmcClient bmc.BMC) error { - if err := bmcClient.CreateEventSubscription( +func SubscribeEvents(ctx context.Context, url, vendor, hostname string, bmcClient bmc.BMC) (string, error) { + link, err := bmcClient.CreateEventSubscription( ctx, - fmt.Sprintf("https://localhost:8888/%s/%s/alerts", vendor, hostname), + fmt.Sprintf("%s/%s/%s/alerts", url, vendor, hostname), redfish.EventEventFormatType, redfish.TerminateAfterRetriesDeliveryRetryPolicy, - ); err != nil { - return fmt.Errorf("failed to create alert subscription: %w", err) - } - return nil -} -func UnsubscribeEvents(ctx context.Context, vendor, hostname string, bmcClient bmc.BMC) error { - if err := bmcClient.DeleteEventSubscription(ctx, fmt.Sprintf("https://localhost:8888/%s/%s/alerts", vendor, hostname)); err != nil { - return fmt.Errorf("failed to delete alert subscription: %w", err) + ) + if err != nil { + return "", fmt.Errorf("failed to create alert subscription: %w", err) } - return nil + return link, nil } diff --git a/cmd/serverevents/main.go b/test/serverevents/main.go similarity index 100% rename from cmd/serverevents/main.go rename to test/serverevents/main.go From dbad795147f64cd377b332fdc47212f7fcb4a15b Mon Sep 17 00:00:00 2001 From: Stefan Hipfel Date: Wed, 29 Oct 2025 16:55:44 +0100 Subject: [PATCH 4/8] make check --- cmd/manager/main.go | 3 ++- .../crd/bases/metal.ironcore.dev_servers.yaml | 8 +++++++ docs/api-reference/api.md | 24 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index b96c8e6f..6587ed69 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -112,7 +112,8 @@ func main() { // nolint: gocyclo flag.IntVar(®istryPort, "registry-port", 10000, "The port to use for the registry.") flag.StringVar(&eventURL, "event-url", "", "The URL of the server events endpoint for alerts and metrics.") flag.IntVar(&eventPort, "event-port", 10001, "The port to use for the server events endpoint for alerts and metrics.") - flag.StringVar(&eventProtocol, "event-protocol", "http", "The protocol to use for the server events endpoint for alerts and metrics.") + flag.StringVar(&eventProtocol, "event-protocol", "http", + "The protocol to use for the server events endpoint for alerts and metrics.") flag.StringVar(&probeImage, "probe-image", "", "Image for the first boot probing of a Server.") flag.StringVar(&probeOSImage, "probe-os-image", "", "OS image for the first boot probing of a Server.") flag.StringVar(&managerNamespace, "manager-namespace", "default", "Namespace the manager is running in.") diff --git a/config/crd/bases/metal.ironcore.dev_servers.yaml b/config/crd/bases/metal.ironcore.dev_servers.yaml index a54f23b0..2a05baea 100644 --- a/config/crd/bases/metal.ironcore.dev_servers.yaml +++ b/config/crd/bases/metal.ironcore.dev_servers.yaml @@ -442,6 +442,10 @@ spec: - type type: object type: array + eventsSubscriptionLink: + description: EventsSubscriptionLink is the link to the events subscription + for the server. + type: string indicatorLED: description: IndicatorLED specifies the current state of the server's indicator LED. @@ -449,6 +453,10 @@ spec: manufacturer: description: Manufacturer is the name of the server manufacturer. type: string + metricsReportSubscriptionLink: + description: MetricsReportSubscriptionLink is the link to the metrics + report subscription for the server. + type: string model: description: Model is the model of the server. type: string diff --git a/docs/api-reference/api.md b/docs/api-reference/api.md index b58f76af..71ba40e1 100644 --- a/docs/api-reference/api.md +++ b/docs/api-reference/api.md @@ -4822,6 +4822,30 @@ ServerState +metricsReportSubscriptionLink
+ +string + + + +(Optional) +

MetricsReportSubscriptionLink is the link to the metrics report subscription for the server.

+ + + + +eventsSubscriptionLink
+ +string + + + +(Optional) +

EventsSubscriptionLink is the link to the events subscription for the server.

+ + + + networkInterfaces
From 4e40c3722a216ea799d33d7cba63b79e83183126 Mon Sep 17 00:00:00 2001 From: Stefan Hipfel Date: Thu, 30 Oct 2025 09:55:58 +0100 Subject: [PATCH 5/8] make generate && make docs && make helm --- dist/chart/templates/crd/metal.ironcore.dev_servers.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dist/chart/templates/crd/metal.ironcore.dev_servers.yaml b/dist/chart/templates/crd/metal.ironcore.dev_servers.yaml index 155f67c5..26ed2db6 100755 --- a/dist/chart/templates/crd/metal.ironcore.dev_servers.yaml +++ b/dist/chart/templates/crd/metal.ironcore.dev_servers.yaml @@ -448,6 +448,10 @@ spec: - type type: object type: array + eventsSubscriptionLink: + description: EventsSubscriptionLink is the link to the events subscription + for the server. + type: string indicatorLED: description: IndicatorLED specifies the current state of the server's indicator LED. @@ -455,6 +459,10 @@ spec: manufacturer: description: Manufacturer is the name of the server manufacturer. type: string + metricsReportSubscriptionLink: + description: MetricsReportSubscriptionLink is the link to the metrics + report subscription for the server. + type: string model: description: Model is the model of the server. type: string From bbad483f35aaebe8d3d3c196e9105c793fa413d3 Mon Sep 17 00:00:00 2001 From: Stefan Hipfel Date: Wed, 5 Nov 2025 14:22:21 +0100 Subject: [PATCH 6/8] moves event subscription to bmc --- api/v1alpha1/bmc_types.go | 8 ++ api/v1alpha1/server_types.go | 8 -- bmc/mock/server/data/Managers/BMC/index.json | 3 +- bmc/mock/server/server.go | 108 +++++++++++++++++- config/crd/bases/metal.ironcore.dev_bmcs.yaml | 8 ++ .../crd/bases/metal.ironcore.dev_servers.yaml | 8 -- .../crd/metal.ironcore.dev_bmcs.yaml | 8 ++ .../crd/metal.ironcore.dev_servers.yaml | 8 -- docs/api-reference/api.md | 48 ++++---- internal/controller/bmc_controller.go | 63 ++++++++++ internal/controller/bmc_controller_test.go | 4 + internal/controller/server_controller.go | 59 ---------- internal/controller/suite_test.go | 4 + internal/serverevents/server.go | 14 +-- internal/serverevents/subscription.go | 8 +- 15 files changed, 238 insertions(+), 121 deletions(-) diff --git a/api/v1alpha1/bmc_types.go b/api/v1alpha1/bmc_types.go index e18e7a3e..458eb97e 100644 --- a/api/v1alpha1/bmc_types.go +++ b/api/v1alpha1/bmc_types.go @@ -208,6 +208,14 @@ type BMCStatus struct { // +optional LastResetTime *metav1.Time `json:"lastResetTime,omitempty"` + // MetricsReportSubscriptionLink is the link to the metrics report subscription of the bmc. + // +optional + MetricsReportSubscriptionLink string `json:"metricsReportSubscriptionLink,omitempty"` + + // EventsSubscriptionLink is the link to the events subscription of the bmc. + // +optional + EventsSubscriptionLink string `json:"eventsSubscriptionLink,omitempty"` + // Conditions represents the latest available observations of the BMC's current state. // +patchStrategy=merge // +patchMergeKey=type diff --git a/api/v1alpha1/server_types.go b/api/v1alpha1/server_types.go index f1f3c20e..4f06d88a 100644 --- a/api/v1alpha1/server_types.go +++ b/api/v1alpha1/server_types.go @@ -222,14 +222,6 @@ type ServerStatus struct { // +optional State ServerState `json:"state,omitempty"` - // MetricsReportSubscriptionLink is the link to the metrics report subscription for the server. - // +optional - MetricsReportSubscriptionLink string `json:"metricsReportSubscriptionLink,omitempty"` - - // EventsSubscriptionLink is the link to the events subscription for the server. - // +optional - EventsSubscriptionLink string `json:"eventsSubscriptionLink,omitempty"` - // NetworkInterfaces is a list of network interfaces associated with the server. // +optional NetworkInterfaces []NetworkInterface `json:"networkInterfaces,omitempty"` diff --git a/bmc/mock/server/data/Managers/BMC/index.json b/bmc/mock/server/data/Managers/BMC/index.json index be410bbe..c99534fa 100644 --- a/bmc/mock/server/data/Managers/BMC/index.json +++ b/bmc/mock/server/data/Managers/BMC/index.json @@ -4,6 +4,7 @@ "Name": "Manager", "ManagerType": "BMC", "Description": "Contoso BMC", + "Manufacturer": "Contoso", "ServiceEntryPointUUID": "92384634-2938-2342-8820-489239905423", "UUID": "58893887-8974-2487-2389-841168418919", "Model": "Joo Janta 200", @@ -96,4 +97,4 @@ }, "@odata.id": "/redfish/v1/Managers/BMC", "@Redfish.Copyright": "Copyright 2014-2023 DMTF. For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright." -} \ No newline at end of file +} diff --git a/bmc/mock/server/server.go b/bmc/mock/server/server.go index fb5ab471..df4c7604 100644 --- a/bmc/mock/server/server.go +++ b/bmc/mock/server/server.go @@ -24,6 +24,14 @@ var ( dataFS embed.FS ) +type Collection struct { + Members []Member `json:"Members"` +} + +type Member struct { + OdataID string `json:"@odata.id"` +} + type MockServer struct { log logr.Logger addr string @@ -56,6 +64,8 @@ func (s *MockServer) redfishHandler(w http.ResponseWriter, r *http.Request) { s.handleRedfishPOST(w, r) case http.MethodPatch: s.handleRedfishPATCH(w, r) + case http.MethodDelete: + s.handleRedfishDelete(w, r) default: http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) } @@ -140,6 +150,47 @@ func resolvePath(urlPath string) string { return path.Join("data", trimmed, "index.json") } +func (s *MockServer) handleRedfishDelete(w http.ResponseWriter, r *http.Request) { + s.log.Info("Received request", "method", r.Method, "path", r.URL.Path) + + urlPath := resolvePath(r.URL.Path) + s.mu.RLock() + defer s.mu.Unlock() + _, hasOverride := s.overrides[urlPath] + if hasOverride { + // remove the resource + delete(s.overrides, urlPath) + } + // get collection of the resource + collectionPath := path.Dir(urlPath) + cached, hasOverride := s.overrides[collectionPath] + var collection Collection + if hasOverride { + collection = cached.(Collection) + } else { + data, err := dataFS.ReadFile(collectionPath) + if err != nil { + http.NotFound(w, r) + return + } + if err := json.Unmarshal(data, &collection); err != nil { + http.Error(w, "Corrupt embedded JSON", http.StatusInternalServerError) + return + } + } + // remove member from collection + newMembers := make([]Member, 0) + for _, member := range collection.Members { + if member.OdataID != r.URL.Path { + newMembers = append(newMembers, member) + } + } + s.log.Info("Removing member from collection", "members", newMembers, "collection", collectionPath) + collection.Members = newMembers + s.overrides[collectionPath] = collection + w.WriteHeader(http.StatusNoContent) +} + func (s *MockServer) handleRedfishGET(w http.ResponseWriter, r *http.Request) { urlPath := resolvePath(r.URL.Path) @@ -186,7 +237,6 @@ func mergeJSON(base, update map[string]interface{}) { func (s *MockServer) handleRedfishPOST(w http.ResponseWriter, r *http.Request) { s.log.Info("Received request", "method", r.Method, "path", r.URL.Path) - body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Invalid body", http.StatusBadRequest) @@ -199,8 +249,62 @@ func (s *MockServer) handleRedfishPOST(w http.ResponseWriter, r *http.Request) { } }(r.Body) - s.log.Info("POST body received", "body", string(body)) + var update map[string]any + if err := json.Unmarshal(body, &update); err != nil { + http.Error(w, "Invalid JSON", http.StatusBadRequest) + return + } + s.log.Info("POST body received", "body", string(body)) + urlPath := resolvePath(r.URL.Path) + s.mu.Lock() + defer s.mu.Unlock() + cached, hasOverride := s.overrides[urlPath] + var base Collection + if hasOverride { + s.log.Info("Using overridden data for POST", "path", urlPath) + base = cached.(Collection) + } else { + s.log.Info("Using embedded data for POST", "path", urlPath) + data, err := dataFS.ReadFile(urlPath) + if err != nil { + s.log.Error(err, "Failed to read embedded data for POST", "path", urlPath) + http.NotFound(w, r) + return + } + if err := json.Unmarshal(data, &base); err != nil { + http.Error(w, "Corrupt embedded JSON", http.StatusInternalServerError) + return + } + } + // If resource collection (has "Members"), add a new member + if len(base.Members) > 0 { + newID := fmt.Sprintf("%d", len(base.Members)+1) + location := path.Join(r.URL.Path, newID) + newMemberPath := resolvePath(location) + base.Members = append(base.Members, Member{ + OdataID: location, + }) + s.log.Info("Adding new member", "id", newID, "location", location, "memberPath", newMemberPath) + if strings.HasSuffix(r.URL.Path, "/Subscriptions") { + w.Header().Set("Location", location) + } + s.overrides[urlPath] = base + s.overrides[newMemberPath] = update + } else { + base.Members = make([]Member, 0) + location := r.URL.JoinPath("1").String() + base.Members = []Member{ + { + OdataID: r.URL.JoinPath("1").String(), + }, + } + s.overrides[urlPath] = base + if strings.HasSuffix(r.URL.Path, "/Subscriptions") { + w.Header().Set("Location", location) + } + } + s.log.Info("Storing updated data for POST", "path", urlPath, "data", update) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) _, err = w.Write([]byte(`{"status": "created"}`)) diff --git a/config/crd/bases/metal.ironcore.dev_bmcs.yaml b/config/crd/bases/metal.ironcore.dev_bmcs.yaml index a7206687..b26f2dca 100644 --- a/config/crd/bases/metal.ironcore.dev_bmcs.yaml +++ b/config/crd/bases/metal.ironcore.dev_bmcs.yaml @@ -255,6 +255,10 @@ spec: - type type: object type: array + eventsSubscriptionLink: + description: EventsSubscriptionLink is the link to the events subscription + of the bmc. + type: string firmwareVersion: description: FirmwareVersion is the version of the firmware currently running on the BMC. @@ -278,6 +282,10 @@ spec: manufacturer: description: Manufacturer is the name of the BMC manufacturer. type: string + metricsReportSubscriptionLink: + description: MetricsReportSubscriptionLink is the link to the metrics + report subscription of the bmc. + type: string model: description: Model is the model number or name of the BMC. type: string diff --git a/config/crd/bases/metal.ironcore.dev_servers.yaml b/config/crd/bases/metal.ironcore.dev_servers.yaml index d25f41ab..dd699246 100644 --- a/config/crd/bases/metal.ironcore.dev_servers.yaml +++ b/config/crd/bases/metal.ironcore.dev_servers.yaml @@ -442,10 +442,6 @@ spec: - type type: object type: array - eventsSubscriptionLink: - description: EventsSubscriptionLink is the link to the events subscription - for the server. - type: string indicatorLED: description: IndicatorLED specifies the current state of the server's indicator LED. @@ -453,10 +449,6 @@ spec: manufacturer: description: Manufacturer is the name of the server manufacturer. type: string - metricsReportSubscriptionLink: - description: MetricsReportSubscriptionLink is the link to the metrics - report subscription for the server. - type: string model: description: Model is the model of the server. type: string diff --git a/dist/chart/templates/crd/metal.ironcore.dev_bmcs.yaml b/dist/chart/templates/crd/metal.ironcore.dev_bmcs.yaml index 37a4531f..83d5a226 100755 --- a/dist/chart/templates/crd/metal.ironcore.dev_bmcs.yaml +++ b/dist/chart/templates/crd/metal.ironcore.dev_bmcs.yaml @@ -261,6 +261,10 @@ spec: - type type: object type: array + eventsSubscriptionLink: + description: EventsSubscriptionLink is the link to the events subscription + of the bmc. + type: string firmwareVersion: description: FirmwareVersion is the version of the firmware currently running on the BMC. @@ -284,6 +288,10 @@ spec: manufacturer: description: Manufacturer is the name of the BMC manufacturer. type: string + metricsReportSubscriptionLink: + description: MetricsReportSubscriptionLink is the link to the metrics + report subscription of the bmc. + type: string model: description: Model is the model number or name of the BMC. type: string diff --git a/dist/chart/templates/crd/metal.ironcore.dev_servers.yaml b/dist/chart/templates/crd/metal.ironcore.dev_servers.yaml index 739cd635..9e84b616 100755 --- a/dist/chart/templates/crd/metal.ironcore.dev_servers.yaml +++ b/dist/chart/templates/crd/metal.ironcore.dev_servers.yaml @@ -448,10 +448,6 @@ spec: - type type: object type: array - eventsSubscriptionLink: - description: EventsSubscriptionLink is the link to the events subscription - for the server. - type: string indicatorLED: description: IndicatorLED specifies the current state of the server's indicator LED. @@ -459,10 +455,6 @@ spec: manufacturer: description: Manufacturer is the name of the server manufacturer. type: string - metricsReportSubscriptionLink: - description: MetricsReportSubscriptionLink is the link to the metrics - report subscription for the server. - type: string model: description: Model is the model of the server. type: string diff --git a/docs/api-reference/api.md b/docs/api-reference/api.md index a51b1cde..d9324447 100644 --- a/docs/api-reference/api.md +++ b/docs/api-reference/api.md @@ -2050,6 +2050,30 @@ Kubernetes meta/v1.Time +metricsReportSubscriptionLink
+ +string + + + +(Optional) +

MetricsReportSubscriptionLink is the link to the metrics report subscription of the bmc.

+ + + + +eventsSubscriptionLink
+ +string + + + +(Optional) +

EventsSubscriptionLink is the link to the events subscription of the bmc.

+ + + + conditions
@@ -4822,30 +4846,6 @@ ServerState -metricsReportSubscriptionLink
- -string - - - -(Optional) -

MetricsReportSubscriptionLink is the link to the metrics report subscription for the server.

- - - - -eventsSubscriptionLink
- -string - - - -(Optional) -

EventsSubscriptionLink is the link to the events subscription for the server.

- - - - networkInterfaces
diff --git a/internal/controller/bmc_controller.go b/internal/controller/bmc_controller.go index 4e7df682..fa220f40 100644 --- a/internal/controller/bmc_controller.go +++ b/internal/controller/bmc_controller.go @@ -20,6 +20,7 @@ import ( metalv1alpha1 "github.com/ironcore-dev/metal-operator/api/v1alpha1" "github.com/ironcore-dev/metal-operator/bmc" "github.com/ironcore-dev/metal-operator/internal/bmcutils" + "github.com/ironcore-dev/metal-operator/internal/serverevents" "github.com/stmcginnis/gofish/common" "github.com/stmcginnis/gofish/redfish" @@ -57,6 +58,7 @@ type BMCReconciler struct { BMCFailureResetDelay time.Duration BMCOptions bmc.Options ManagerNamespace string + EventURL string } //+kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints,verbs=get;list;watch @@ -96,6 +98,14 @@ func (r *BMCReconciler) delete(ctx context.Context, log logr.Logger, bmcObj *met } } + bmcClient, err := bmcutils.GetBMCClientFromBMC(ctx, r.Client, bmcObj, r.Insecure, r.BMCOptions) + if err == nil { + defer bmcClient.Logout() + if err := r.deleteEventSubscription(ctx, log, bmcClient, bmcObj); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to delete event subscriptions: %w", err) + } + } + if _, err := clientutils.PatchEnsureNoFinalizer(ctx, r.Client, bmcObj, BMCFinalizer); err != nil { return ctrl.Result{}, err } @@ -152,6 +162,10 @@ func (r *BMCReconciler) reconcile(ctx context.Context, log logr.Logger, bmcObj * } log.V(1).Info("Discovered servers") + if modified, err := r.handleEventSubscriptions(ctx, log, bmcClient, bmcObj); err != nil || modified { + return ctrl.Result{}, err + } + log.V(1).Info("Reconciled BMC") return ctrl.Result{}, nil } @@ -390,6 +404,55 @@ func (r *BMCReconciler) updateConditions(ctx context.Context, bmcObj *metalv1alp return nil } +func (r *BMCReconciler) handleEventSubscriptions(ctx context.Context, log logr.Logger, bmcClient bmc.BMC, bmc *metalv1alpha1.BMC) (bool, error) { + if r.EventURL == "" { + return false, nil + } + log.V(1).Info("Handling event subscriptions for BMC") + metricsReportLink := "" + eventLink := "" + + if bmc.Status.MetricsReportSubscriptionLink != "" && bmc.Status.EventsSubscriptionLink != "" { + return false, nil + } + metricsReportLink, err := serverevents.SubscribeMetricsReport(ctx, r.EventURL, bmc.Name, bmcClient) + if err != nil { + return false, fmt.Errorf("failed to subscribe to server metrics report: %w", err) + } + eventLink, err = serverevents.SubscribeEvents(ctx, r.EventURL, bmc.Name, bmcClient) + if err != nil { + return false, fmt.Errorf("failed to subscribe to server alerts: %w", err) + } + log.Info("event subscriptions created", "metricsReportLink", metricsReportLink, "eventLink", eventLink) + bmcBase := bmc.DeepCopy() + bmc.Status.MetricsReportSubscriptionLink = metricsReportLink + bmc.Status.EventsSubscriptionLink = eventLink + if err := r.Status().Patch(ctx, bmc, client.MergeFrom(bmcBase)); err != nil { + return false, fmt.Errorf("failed to patch server status with subscription links: %w", err) + } + log.Info("Subscribed to server events and metrics") + return true, nil +} + +func (r *BMCReconciler) deleteEventSubscription(ctx context.Context, log logr.Logger, bmcClient bmc.BMC, bmc *metalv1alpha1.BMC) error { + if r.EventURL == "" { + return nil + } + if bmc.Status.MetricsReportSubscriptionLink != "" { + if err := bmcClient.DeleteEventSubscription(ctx, bmc.Status.MetricsReportSubscriptionLink); err != nil { + return fmt.Errorf("failed to unsubscribe from server metrics report: %w", err) + } + log.V(1).Info("Unsubscribed from server metrics report") + } + if bmc.Status.EventsSubscriptionLink != "" { + if err := bmcClient.DeleteEventSubscription(ctx, bmc.Status.EventsSubscriptionLink); err != nil { + return fmt.Errorf("failed to unsubscribe from server events: %w", err) + } + log.V(1).Info("Unsubscribed from server events") + } + return nil +} + func (r *BMCReconciler) enqueueBMCByEndpoint(ctx context.Context, obj client.Object) []ctrl.Request { return []ctrl.Request{ { diff --git a/internal/controller/bmc_controller_test.go b/internal/controller/bmc_controller_test.go index 8944b69b..1103e389 100644 --- a/internal/controller/bmc_controller_test.go +++ b/internal/controller/bmc_controller_test.go @@ -69,6 +69,8 @@ var _ = Describe("BMC Controller", func() { HaveField("Status.State", metalv1alpha1.BMCStateEnabled), HaveField("Status.PowerState", metalv1alpha1.OnPowerState), HaveField("Status.FirmwareVersion", "1.45.455b66-rev4"), + HaveField("Status.MetricsReportSubscriptionLink", Equal("/redfish/v1/EventService/Subscriptions/5")), + HaveField("Status.EventsSubscriptionLink", Equal("/redfish/v1/EventService/Subscriptions/6")), )) By("Ensuring that the Server resource has been created") @@ -134,6 +136,8 @@ var _ = Describe("BMC Controller", func() { HaveField("Status.State", metalv1alpha1.BMCStateEnabled), HaveField("Status.PowerState", metalv1alpha1.OnPowerState), HaveField("Status.FirmwareVersion", "1.45.455b66-rev4"), + HaveField("Status.MetricsReportSubscriptionLink", Equal("/redfish/v1/EventService/Subscriptions/5")), + HaveField("Status.EventsSubscriptionLink", Equal("/redfish/v1/EventService/Subscriptions/6")), )) By("Ensuring that the Server resource has been created") diff --git a/internal/controller/server_controller.go b/internal/controller/server_controller.go index 71345013..2c916e8a 100644 --- a/internal/controller/server_controller.go +++ b/internal/controller/server_controller.go @@ -24,7 +24,6 @@ import ( "github.com/ironcore-dev/metal-operator/internal/api/registry" "github.com/ironcore-dev/metal-operator/internal/bmcutils" "github.com/ironcore-dev/metal-operator/internal/ignition" - "github.com/ironcore-dev/metal-operator/internal/serverevents" "github.com/stmcginnis/gofish/redfish" "golang.org/x/crypto/bcrypt" "golang.org/x/crypto/ssh" @@ -167,13 +166,6 @@ func (r *ServerReconciler) delete(ctx context.Context, log logr.Logger, server * log.V(1).Info("BIOS settings was deleted") } - bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure, r.BMCOptions) - if err != nil { - return ctrl.Result{}, fmt.Errorf("failed to get BMC client for server: %w", err) - } - if err := r.deleteEventSubscription(ctx, log, bmcClient, server); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to delete event subscription: %w", err) - } log.V(1).Info("Ensuring that the finalizer is removed") if modified, err := clientutils.PatchEnsureNoFinalizer(ctx, r.Client, server, ServerFinalizer); err != nil || modified { return ctrl.Result{}, err @@ -393,10 +385,6 @@ func (r *ServerReconciler) handleDiscoveryState(ctx context.Context, log logr.Lo } log.V(1).Info("Removed Server from Registry") - if modified, err := r.handleEventSubscriptions(ctx, log, bmcClient, server); err != nil || modified { - return false, err - } - log.V(1).Info("Setting Server state set to available") if modified, err := r.patchServerState(ctx, server, metalv1alpha1.ServerStateAvailable); err != nil || modified { return false, err @@ -1079,53 +1067,6 @@ func (r *ServerReconciler) handleAnnotionOperations(ctx context.Context, log log return true, nil } -func (r *ServerReconciler) handleEventSubscriptions(ctx context.Context, log logr.Logger, bmcClient bmc.BMC, server *metalv1alpha1.Server) (bool, error) { - if r.EventURL == "" { - return false, nil - } - metricsReportLink := "" - eventLink := "" - - if server.Status.MetricsReportSubscriptionLink != "" && server.Status.EventsSubscriptionLink != "" { - return false, nil - } - metricsReportLink, err := serverevents.SubscribeMetricsReport(ctx, r.EventURL, server.Status.Manufacturer, server.Spec.UUID, bmcClient) - if err != nil { - return false, fmt.Errorf("failed to subscribe to server metrics report: %w", err) - } - eventLink, err = serverevents.SubscribeEvents(ctx, r.EventURL, server.Status.Manufacturer, server.Spec.UUID, bmcClient) - if err != nil { - return false, fmt.Errorf("failed to subscribe to server alerts: %w", err) - } - serverBase := server.DeepCopy() - server.Status.MetricsReportSubscriptionLink = metricsReportLink - server.Status.EventsSubscriptionLink = eventLink - if err := r.Status().Patch(ctx, server, client.MergeFrom(serverBase)); err != nil { - return false, fmt.Errorf("failed to patch server status with subscription links: %w", err) - } - log.V(1).Info("Subscribed to server events and metrics") - return true, nil -} - -func (r *ServerReconciler) deleteEventSubscription(ctx context.Context, log logr.Logger, bmcClient bmc.BMC, server *metalv1alpha1.Server) error { - if r.EventURL == "" { - return nil - } - if server.Status.MetricsReportSubscriptionLink != "" { - if err := bmcClient.DeleteEventSubscription(ctx, server.Status.MetricsReportSubscriptionLink); err != nil { - return fmt.Errorf("failed to unsubscribe from server metrics report: %w", err) - } - log.V(1).Info("Unsubscribed from server metrics report") - } - if server.Status.EventsSubscriptionLink != "" { - if err := bmcClient.DeleteEventSubscription(ctx, server.Status.EventsSubscriptionLink); err != nil { - return fmt.Errorf("failed to unsubscribe from server events: %w", err) - } - log.V(1).Info("Unsubscribed from server events") - } - return nil -} - func (r *ServerReconciler) checkLastStatusUpdateAfter(duration time.Duration, server *metalv1alpha1.Server) bool { length := len(server.ManagedFields) - 1 if server.ManagedFields[length].Operation == "Update" { diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 1cd9fa19..7beab34c 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -13,6 +13,8 @@ import ( "github.com/ironcore-dev/controller-utils/clientutils" metalv1alpha1 "github.com/ironcore-dev/metal-operator/api/v1alpha1" + "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/ironcore-dev/metal-operator/bmc" "github.com/ironcore-dev/metal-operator/bmc/mock/server" "github.com/ironcore-dev/metal-operator/internal/api/macdb" @@ -160,6 +162,7 @@ var _ = BeforeSuite(func() { Expect(registryServer.Start(mgrCtx)).To(Succeed(), "failed to start registry server") }() + log.SetLogger(GinkgoLogr) bmc.InitMockUp() }) @@ -225,6 +228,7 @@ func SetupTest() *corev1.Namespace { Expect((&BMCReconciler{ Client: k8sManager.GetClient(), Scheme: k8sManager.GetScheme(), + EventURL: "http://localhost:8008", Insecure: true, ManagerNamespace: ns.Name, }).SetupWithManager(k8sManager)).To(Succeed()) diff --git a/internal/serverevents/server.go b/internal/serverevents/server.go index bcb63107..1340a7df 100644 --- a/internal/serverevents/server.go +++ b/internal/serverevents/server.go @@ -130,16 +130,16 @@ func (s *Server) metricsreportHandler(w http.ResponseWriter, r *http.Request) { }, []string{"hostname", "vendor"}, ) - floatVal, err := strconv.ParseFloat(mv.MetricValue, 64) - if err != nil { - if mv.MetricValue == "Up" || mv.MetricValue == "Operational" { - floatVal = 1 - } - } - gauge.WithLabelValues(hostname, vendor).Set(floatVal) metricsReportCollectors[mv.MetricId] = gauge metrics.Registry.MustRegister(gauge) } + floatVal, err := strconv.ParseFloat(mv.MetricValue, 64) + if err != nil { + if mv.MetricValue == "Up" || mv.MetricValue == "Operational" { + floatVal = 1 + } + } + metricsReportCollectors[mv.MetricId].WithLabelValues(hostname, vendor).Set(floatVal) s.log.Info("Metric", "id", mv.MetricId, "property", mv.MetricProperty, "value", mv.MetricValue, "timestamp", mv.Timestamp) } w.WriteHeader(http.StatusOK) diff --git a/internal/serverevents/subscription.go b/internal/serverevents/subscription.go index a13f9c8b..bd2d6e48 100644 --- a/internal/serverevents/subscription.go +++ b/internal/serverevents/subscription.go @@ -11,10 +11,10 @@ import ( "github.com/stmcginnis/gofish/redfish" ) -func SubscribeMetricsReport(ctx context.Context, url, vendor, hostname string, bmcClient bmc.BMC) (string, error) { +func SubscribeMetricsReport(ctx context.Context, url, hostname string, bmcClient bmc.BMC) (string, error) { link, err := bmcClient.CreateEventSubscription( ctx, - fmt.Sprintf("%s/%s/%s/metrics", url, vendor, hostname), + fmt.Sprintf("%s/%s/metrics", url, hostname), redfish.MetricReportEventFormatType, redfish.TerminateAfterRetriesDeliveryRetryPolicy, ) @@ -24,10 +24,10 @@ func SubscribeMetricsReport(ctx context.Context, url, vendor, hostname string, b return link, nil } -func SubscribeEvents(ctx context.Context, url, vendor, hostname string, bmcClient bmc.BMC) (string, error) { +func SubscribeEvents(ctx context.Context, url, hostname string, bmcClient bmc.BMC) (string, error) { link, err := bmcClient.CreateEventSubscription( ctx, - fmt.Sprintf("%s/%s/%s/alerts", url, vendor, hostname), + fmt.Sprintf("%s/%s/alerts", url, hostname), redfish.EventEventFormatType, redfish.TerminateAfterRetriesDeliveryRetryPolicy, ) From f41134ac400a004432c8ce1eb4631056a5d33877 Mon Sep 17 00:00:00 2001 From: Stefan Hipfel Date: Mon, 29 Dec 2025 10:48:25 +0100 Subject: [PATCH 7/8] Fix SubscribeMetricsReport to return an empty string on error and add documentation for SubscribeMetricsReport and SubscribeEvents functions. --- docs/api-reference/api.md | 5360 +------------------------ internal/serverevents/subscription.go | 4 +- 2 files changed, 5 insertions(+), 5359 deletions(-) diff --git a/docs/api-reference/api.md b/docs/api-reference/api.md index 4cf80427..85338779 100644 --- a/docs/api-reference/api.md +++ b/docs/api-reference/api.md @@ -1,5361 +1,3 @@ -

Packages:

-
-

metal.ironcore.dev/v1alpha1

-
-

Package v1alpha1 contains API Schema definitions for the settings.gardener.cloud API group

-
-Resource Types: -
    -

    BIOSSettings -

    -
    -

    BIOSSettings is the Schema for the biossettings API.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -BIOSSettingsSpec - - -
    -
    -
    - - - - - - - - - -
    -BIOSSettingsTemplate
    - - -BIOSSettingsTemplate - - -
    -

    -(Members of BIOSSettingsTemplate are embedded into this type.) -

    -

    BIOSSettingsTemplate defines the template for BIOS Settings to be applied on the servers.

    -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    ServerRef is a reference to a specific server to apply bios setting on.

    -
    -
    -status
    - - -BIOSSettingsStatus - - -
    -
    -

    BIOSSettingsFlowState -(string alias)

    -

    -(Appears on:BIOSSettingsFlowStatus) -

    -
    -
    - - - - - - - - - - - - - - - - -
    ValueDescription

    "Applied"

    BIOSSettingsFlowStateApplied specifies that the bios setting has been completed for current Priority

    -

    "Failed"

    BIOSSettingsFlowStateFailed specifies that the bios setting update has failed.

    -

    "InProgress"

    BIOSSettingsFlowStateInProgress specifies that the BIOSSetting Controller is updating the settings for current Priority

    -

    "Pending"

    BIOSSettingsFlowStatePending specifies that the BIOSSetting Controller is updating the settings for current Priority

    -
    -

    BIOSSettingsFlowStatus -

    -

    -(Appears on:BIOSSettingsStatus) -

    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -flowState
    - - -BIOSSettingsFlowState - - -
    -(Optional) -

    State represents the current state of the bios configuration task for current priority.

    -
    -name
    - -string - -
    -(Optional) -

    Name identifies current priority settings from the Spec

    -
    -priority
    - -int32 - -
    -(Optional) -

    Priority identifies the settings priority from the Spec

    -
    -conditions
    - - -[]Kubernetes meta/v1.Condition - - -
    -(Optional) -

    Conditions represents the latest available observations of the BIOSSettings’s current Flowstate.

    -
    -lastAppliedTime
    - - -Kubernetes meta/v1.Time - - -
    -(Optional) -

    LastAppliedTime represents the timestamp when the last setting was successfully applied.

    -
    -

    BIOSSettingsSet -

    -
    -

    BIOSSettingsSet is the Schema for the biossettingssets API.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -BIOSSettingsSetSpec - - -
    -
    -
    - - - - - - - - - -
    -biosSettingsTemplate
    - - -BIOSSettingsTemplate - - -
    -

    BiosSettingsTemplate defines the template for the BIOSSettings Resource to be applied to the servers.

    -
    -serverSelector
    - - -Kubernetes meta/v1.LabelSelector - - -
    -

    ServerSelector specifies a label selector to identify the servers that are to be selected.

    -
    -
    -status
    - - -BIOSSettingsSetStatus - - -
    -
    -

    BIOSSettingsSetSpec -

    -

    -(Appears on:BIOSSettingsSet) -

    -
    -

    BIOSSettingsSetSpec defines the desired state of BIOSSettingsSet.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -biosSettingsTemplate
    - - -BIOSSettingsTemplate - - -
    -

    BiosSettingsTemplate defines the template for the BIOSSettings Resource to be applied to the servers.

    -
    -serverSelector
    - - -Kubernetes meta/v1.LabelSelector - - -
    -

    ServerSelector specifies a label selector to identify the servers that are to be selected.

    -
    -

    BIOSSettingsSetStatus -

    -

    -(Appears on:BIOSSettingsSet) -

    -
    -

    BIOSSettingsSetStatus defines the observed state of BIOSSettingsSet.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -fullyLabeledServers
    - -int32 - -
    -

    FullyLabeledServers is the number of server in the set.

    -
    -availableBIOSSettings
    - -int32 - -
    -

    AvailableBIOSVersion is the number of Settings current created by the set.

    -
    -pendingBIOSSettings
    - -int32 - -
    -

    PendingBIOSSettings is the total number of pending server in the set.

    -
    -inProgressBIOSSettings
    - -int32 - -
    -

    InProgressBIOSSettings is the total number of server in the set that are currently in InProgress.

    -
    -completedBIOSSettings
    - -int32 - -
    -

    CompletedBIOSSettings is the total number of completed server in the set.

    -
    -failedBIOSSettings
    - -int32 - -
    -

    FailedBIOSSettings is the total number of failed server in the set.

    -
    -

    BIOSSettingsSpec -

    -

    -(Appears on:BIOSSettings) -

    -
    -

    BIOSSettingsSpec defines the desired state of BIOSSettings.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -BIOSSettingsTemplate
    - - -BIOSSettingsTemplate - - -
    -

    -(Members of BIOSSettingsTemplate are embedded into this type.) -

    -

    BIOSSettingsTemplate defines the template for BIOS Settings to be applied on the servers.

    -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    ServerRef is a reference to a specific server to apply bios setting on.

    -
    -

    BIOSSettingsState -(string alias)

    -

    -(Appears on:BIOSSettingsStatus) -

    -
    -

    BIOSSettingsState specifies the current state of the BIOS Settings update.

    -
    - - - - - - - - - - - - - - - - -
    ValueDescription

    "Applied"

    BIOSSettingsStateApplied specifies that the bios setting update has been completed.

    -

    "Failed"

    BIOSSettingsStateFailed specifies that the bios setting update has failed.

    -

    "InProgress"

    BIOSSettingsStateInProgress specifies that the BIOSSetting Controller is updating the settings

    -

    "Pending"

    BIOSSettingsStatePending specifies that the bios setting update is waiting

    -
    -

    BIOSSettingsStatus -

    -

    -(Appears on:BIOSSettings) -

    -
    -

    BIOSSettingsStatus defines the observed state of BIOSSettings.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -state
    - - -BIOSSettingsState - - -
    -(Optional) -

    State represents the current state of the bios configuration task.

    -
    -flowState
    - - -[]BIOSSettingsFlowStatus - - -
    -
    -lastAppliedTime
    - - -Kubernetes meta/v1.Time - - -
    -(Optional) -

    LastAppliedTime represents the timestamp when the last setting was successfully applied.

    -
    -conditions
    - - -[]Kubernetes meta/v1.Condition - - -
    -(Optional) -

    Conditions represents the latest available observations of the BIOSSettings’s current state.

    -
    -

    BIOSSettingsTemplate -

    -

    -(Appears on:BIOSSettingsSetSpec, BIOSSettingsSpec) -

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

    Version contains software (eg: BIOS, BMC) version this settings applies to

    -
    -settingsFlow
    - - -[]SettingsFlowItem - - -
    -(Optional) -

    SettingsFlow contains BIOS settings sequence to apply on the BIOS in given order

    -
    -serverMaintenancePolicy
    - - -ServerMaintenancePolicy - - -
    -(Optional) -

    ServerMaintenancePolicy is a maintenance policy to be enforced on the server.

    -
    -serverMaintenanceRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    ServerMaintenanceRef is a reference to a ServerMaintenance object that BiosSetting has requested for the referred server.

    -
    -

    BIOSVersion -

    -
    -

    BIOSVersion is the Schema for the biosversions API.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -BIOSVersionSpec - - -
    -
    -
    - - - - - - - - - -
    -BIOSVersionTemplate
    - - -BIOSVersionTemplate - - -
    -

    -(Members of BIOSVersionTemplate are embedded into this type.) -

    -

    BIOSVersionTemplate defines the template for Version to be applied on the servers.

    -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    ServerRef is a reference to a specific server to apply bios upgrade on.

    -
    -
    -status
    - - -BIOSVersionStatus - - -
    -
    -

    BIOSVersionSet -

    -
    -

    BIOSVersionSet is the Schema for the biosversionsets API.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -BIOSVersionSetSpec - - -
    -
    -
    - - - - - - - - - -
    -serverSelector
    - - -Kubernetes meta/v1.LabelSelector - - -
    -

    ServerSelector specifies a label selector to identify the servers that are to be selected.

    -
    -biosVersionTemplate
    - - -BIOSVersionTemplate - - -
    -

    BIOSVersionTemplate defines the template for the BIOSversion Resource to be applied to the servers.

    -
    -
    -status
    - - -BIOSVersionSetStatus - - -
    -
    -

    BIOSVersionSetSpec -

    -

    -(Appears on:BIOSVersionSet) -

    -
    -

    BIOSVersionSetSpec defines the desired state of BIOSVersionSet.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -serverSelector
    - - -Kubernetes meta/v1.LabelSelector - - -
    -

    ServerSelector specifies a label selector to identify the servers that are to be selected.

    -
    -biosVersionTemplate
    - - -BIOSVersionTemplate - - -
    -

    BIOSVersionTemplate defines the template for the BIOSversion Resource to be applied to the servers.

    -
    -

    BIOSVersionSetStatus -

    -

    -(Appears on:BIOSVersionSet) -

    -
    -

    BIOSVersionSetStatus defines the observed state of BIOSVersionSet.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -fullyLabeledServers
    - -int32 - -
    -

    FullyLabeledServers is the number of servers in the set.

    -
    -availableBIOSVersion
    - -int32 - -
    -

    AvailableBIOSVersion is the number of BIOSVersion created by the set.

    -
    -pendingBIOSVersion
    - -int32 - -
    -

    PendingBIOSVersion is the total number of pending BIOSVersion in the set.

    -
    -inProgressBIOSVersion
    - -int32 - -
    -

    InProgressBIOSVersion is the total number of BIOSVersion in the set that are currently in InProgress.

    -
    -completedBIOSVersion
    - -int32 - -
    -

    CompletedBIOSVersion is the total number of completed BIOSVersion in the set.

    -
    -failedBIOSVersion
    - -int32 - -
    -

    FailedBIOSVersion is the total number of failed BIOSVersion in the set.

    -
    -

    BIOSVersionSpec -

    -

    -(Appears on:BIOSVersion) -

    -
    -

    BIOSVersionSpec defines the desired state of BIOSVersion.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -BIOSVersionTemplate
    - - -BIOSVersionTemplate - - -
    -

    -(Members of BIOSVersionTemplate are embedded into this type.) -

    -

    BIOSVersionTemplate defines the template for Version to be applied on the servers.

    -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    ServerRef is a reference to a specific server to apply bios upgrade on.

    -
    -

    BIOSVersionState -(string alias)

    -

    -(Appears on:BIOSVersionStatus) -

    -
    -
    - - - - - - - - - - - - - - - - -
    ValueDescription

    "Completed"

    BIOSVersionStateCompleted specifies that the bios upgrade maintenance has been completed.

    -

    "Failed"

    BIOSVersionStateFailed specifies that the bios upgrade maintenance has failed.

    -

    "Processing"

    BIOSVersionStateInProgress specifies that upgrading bios is in progress.

    -

    "Pending"

    BIOSVersionStatePending specifies that the bios upgrade maintenance is waiting

    -
    -

    BIOSVersionStatus -

    -

    -(Appears on:BIOSVersion) -

    -
    -

    BIOSVersionStatus defines the observed state of BIOSVersion.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -state
    - - -BIOSVersionState - - -
    -(Optional) -

    State represents the current state of the bios configuration task.

    -
    -upgradeTask
    - - -Task - - -
    -(Optional) -

    UpgradeTask contains the state of the Upgrade Task created by the BMC

    -
    -conditions
    - - -[]Kubernetes meta/v1.Condition - - -
    -(Optional) -

    Conditions represents the latest available observations of the Bios version upgrade state.

    -
    -

    BIOSVersionTemplate -

    -

    -(Appears on:BIOSVersionSetSpec, BIOSVersionSpec) -

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

    Version contains a BIOS version to upgrade to

    -
    -updatePolicy
    - - -UpdatePolicy - - -
    -(Optional) -

    UpdatePolicy An indication of whether the server’s upgrade service should bypass vendor update policies

    -
    -image
    - - -ImageSpec - - -
    -

    details regarding the image to use to upgrade to given BIOS version

    -
    -serverMaintenancePolicy
    - - -ServerMaintenancePolicy - - -
    -(Optional) -

    ServerMaintenancePolicy is a maintenance policy to be enforced on the server.

    -
    -serverMaintenanceRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    ServerMaintenanceRef is a reference to a ServerMaintenance object that that Controller has requested for the referred server.

    -
    -

    BMC -

    -
    -

    BMC is the Schema for the bmcs API

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -BMCSpec - - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -bmcUUID
    - -string - -
    -(Optional) -

    BMCUUID is the unique identifier for the BMC as defined in Redfish API.

    -
    -endpointRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    EndpointRef is a reference to the Kubernetes object that contains the endpoint information for the BMC. -This reference is typically used to locate the BMC endpoint within the cluster.

    -
    -access
    - - -InlineEndpoint - - -
    -(Optional) -

    Endpoint allows inline configuration of network access details for the BMC. -Use this field if access settings like address are to be configured directly within the BMC resource.

    -
    -bmcSecretRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    BMCSecretRef is a reference to the Kubernetes Secret object that contains the credentials -required to access the BMC. This secret includes sensitive information such as usernames and passwords.

    -
    -protocol
    - - -Protocol - - -
    -

    Protocol specifies the protocol to be used for communicating with the BMC. -It could be a standard protocol such as IPMI or Redfish.

    -
    -consoleProtocol
    - - -ConsoleProtocol - - -
    -(Optional) -

    ConsoleProtocol specifies the protocol to be used for console access to the BMC. -This field is optional and can be omitted if console access is not required.

    -
    -bmcSettingsRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    BMCSettingRef is a reference to a BMCSettings object that specifies -the BMC configuration for this BMC.

    -
    -
    -status
    - - -BMCStatus - - -
    -
    -

    BMCAccess -

    -

    -(Appears on:ServerSpec) -

    -
    -

    BMCAccess defines the access details for the BMC.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -protocol
    - - -Protocol - - -
    -

    Protocol specifies the protocol to be used for communicating with the BMC.

    -
    -address
    - -string - -
    -

    Address is the address of the BMC.

    -
    -bmcSecretRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    BMCSecretRef is a reference to the Kubernetes Secret object that contains the credentials -required to access the BMC. This secret includes sensitive information such as usernames and passwords.

    -
    -

    BMCPowerState -(string alias)

    -

    -(Appears on:BMCStatus) -

    -
    -

    BMCPowerState defines the possible power states for a BMC.

    -
    - - - - - - - - - - - - - - - - - - -
    ValueDescription

    "Off"

    OffPowerState the system is powered off, although some components may -continue to have AUX power such as management controller.

    -

    "On"

    OnPowerState the system is powered on.

    -

    "Paused"

    PausedPowerState the system is paused.

    -

    "PoweringOff"

    PoweringOffPowerState A temporary state between On and Off. The power -off action can take time while the OS is in the shutdown process.

    -

    "PoweringOn"

    PoweringOnPowerState A temporary state between Off and On. This -temporary state can be very short.

    -
    -

    BMCSecret -

    -
    -

    BMCSecret is the Schema for the bmcsecrets API

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -(Optional) -

    Standard object’s metadata. -More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -immutable
    - -bool - -
    -(Optional) -

    Immutable, if set to true, ensures that data stored in the Secret cannot -be updated (only object metadata can be modified). -If not set to true, the field can be modified at any time. -Defaulted to nil.

    -
    -data
    - -map[string][]byte - -
    -(Optional) -

    Data contains the secret data. Each key must consist of alphanumeric -characters, ‘-’, ‘_’ or ‘.’. The serialized form of the secret data is a -base64 encoded string, representing the arbitrary (possibly non-string) -data value here. Described in https://tools.ietf.org/html/rfc4648#section-4

    -
    -stringData
    - -map[string]string - -
    -(Optional) -

    stringData allows specifying non-binary secret data in string form. -It is provided as a write-only input field for convenience. -All keys and values are merged into the data field on write, overwriting any existing values. -The stringData field is never output when reading from the API.

    -
    -type
    - - -Kubernetes core/v1.SecretType - - -
    -(Optional) -

    Used to facilitate programmatic handling of secret data. -More info: https://kubernetes.io/docs/concepts/configuration/secret/#secret-types

    -
    -

    BMCSettings -

    -
    -

    BMCSettings is the Schema for the BMCSettings API.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -BMCSettingsSpec - - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - -
    -version
    - -string - -
    -

    Version defines the BMC firmware for which the settings should be applied.

    -
    -settings
    - -map[string]string - -
    -(Optional) -

    SettingsMap contains bmc settings as map

    -
    -BMCRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    BMCRef is a reference to a specific BMC to apply setting to.

    -
    -serverMaintenancePolicy
    - - -ServerMaintenancePolicy - - -
    -(Optional) -

    ServerMaintenancePolicy is a maintenance policy to be applied on the server.

    -
    -serverMaintenanceRefs
    - - -[]ServerMaintenanceRefItem - - -
    -(Optional) -

    ServerMaintenanceRefs are references to ServerMaintenance objects which are created by the controller for each -server that needs to be updated with the BMC settings.

    -
    -
    -status
    - - -BMCSettingsStatus - - -
    -
    -

    BMCSettingsSpec -

    -

    -(Appears on:BMCSettings) -

    -
    -

    BMCSettingsSpec defines the desired state of BMCSettings.

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

    Version defines the BMC firmware for which the settings should be applied.

    -
    -settings
    - -map[string]string - -
    -(Optional) -

    SettingsMap contains bmc settings as map

    -
    -BMCRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    BMCRef is a reference to a specific BMC to apply setting to.

    -
    -serverMaintenancePolicy
    - - -ServerMaintenancePolicy - - -
    -(Optional) -

    ServerMaintenancePolicy is a maintenance policy to be applied on the server.

    -
    -serverMaintenanceRefs
    - - -[]ServerMaintenanceRefItem - - -
    -(Optional) -

    ServerMaintenanceRefs are references to ServerMaintenance objects which are created by the controller for each -server that needs to be updated with the BMC settings.

    -
    -

    BMCSettingsState -(string alias)

    -

    -(Appears on:BMCSettingsStatus) -

    -
    -

    BMCSettingsState specifies the current state of the server maintenance.

    -
    - - - - - - - - - - - - - - - - -
    ValueDescription

    "Applied"

    BMCSettingsStateApplied specifies that the BMC maintenance has been completed.

    -

    "Failed"

    BMCSettingsStateFailed specifies that the BMC maintenance has failed.

    -

    "InProgress"

    BMCSettingsStateInProgress specifies that the BMC setting changes are in progress

    -

    "Pending"

    BMCSettingsStatePending specifies that the BMC maintenance is waiting

    -
    -

    BMCSettingsStatus -

    -

    -(Appears on:BMCSettings) -

    -
    -

    BMCSettingsStatus defines the observed state of BMCSettings.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    -state
    - - -BMCSettingsState - - -
    -(Optional) -

    State represents the current state of the BMC configuration task.

    -
    -

    BMCSpec -

    -

    -(Appears on:BMC) -

    -
    -

    BMCSpec defines the desired state of BMC

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -bmcUUID
    - -string - -
    -(Optional) -

    BMCUUID is the unique identifier for the BMC as defined in Redfish API.

    -
    -endpointRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    EndpointRef is a reference to the Kubernetes object that contains the endpoint information for the BMC. -This reference is typically used to locate the BMC endpoint within the cluster.

    -
    -access
    - - -InlineEndpoint - - -
    -(Optional) -

    Endpoint allows inline configuration of network access details for the BMC. -Use this field if access settings like address are to be configured directly within the BMC resource.

    -
    -bmcSecretRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    BMCSecretRef is a reference to the Kubernetes Secret object that contains the credentials -required to access the BMC. This secret includes sensitive information such as usernames and passwords.

    -
    -protocol
    - - -Protocol - - -
    -

    Protocol specifies the protocol to be used for communicating with the BMC. -It could be a standard protocol such as IPMI or Redfish.

    -
    -consoleProtocol
    - - -ConsoleProtocol - - -
    -(Optional) -

    ConsoleProtocol specifies the protocol to be used for console access to the BMC. -This field is optional and can be omitted if console access is not required.

    -
    -bmcSettingsRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    BMCSettingRef is a reference to a BMCSettings object that specifies -the BMC configuration for this BMC.

    -
    -

    BMCState -(string alias)

    -

    -(Appears on:BMCStatus) -

    -
    -

    BMCState defines the possible states of a BMC.

    -
    - - - - - - - - - - - - -
    ValueDescription

    "Enabled"

    BMCStateEnabled indicates that the BMC is enabled and functioning correctly.

    -

    "Error"

    BMCStateError indicates that there is an error with the BMC.

    -
    -

    BMCStatus -

    -

    -(Appears on:BMC) -

    -
    -

    BMCStatus defines the observed state of BMC.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -macAddress
    - -string - -
    -(Optional) -

    MACAddress is the MAC address of the BMC. -The format is validated using a regular expression pattern.

    -
    -ip
    - - -IP - - -
    -(Optional) -

    IP is the IP address of the BMC. -The type is specified as string and is schemaless.

    -
    -manufacturer
    - -string - -
    -(Optional) -

    Manufacturer is the name of the BMC manufacturer.

    -
    -model
    - -string - -
    -(Optional) -

    Model is the model number or name of the BMC.

    -
    -sku
    - -string - -
    -(Optional) -

    SKU is the stock keeping unit identifier for the BMC.

    -
    -serialNumber
    - -string - -
    -(Optional) -

    SerialNumber is the serial number of the BMC.

    -
    -firmwareVersion
    - -string - -
    -(Optional) -

    FirmwareVersion is the version of the firmware currently running on the BMC.

    -
    -state
    - - -BMCState - - -
    -(Optional) -

    State represents the current state of the BMC.

    -
    -powerState
    - - -BMCPowerState - - -
    -(Optional) -

    PowerState represents the current power state of the BMC.

    -
    -lastResetTime
    - - -Kubernetes meta/v1.Time - - -
    -(Optional) -

    LastResetTime is the timestamp of the last reset operation performed on the BMC.

    -
    -metricsReportSubscriptionLink
    - -string - -
    -(Optional) -

    MetricsReportSubscriptionLink is the link to the metrics report subscription of the bmc.

    -
    -eventsSubscriptionLink
    - -string - -
    -(Optional) -

    EventsSubscriptionLink is the link to the events subscription of the bmc.

    -
    -conditions
    - - -[]Kubernetes meta/v1.Condition - - -
    -(Optional) -

    Conditions represents the latest available observations of the BMC’s current state.

    -
    -

    BMCVersion -

    -
    -

    BMCVersion is the Schema for the bmcversions API.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -BMCVersionSpec - - -
    -
    -
    - - - - - - - - - -
    -BMCVersionTemplate
    - - -BMCVersionTemplate - - -
    -

    -(Members of BMCVersionTemplate are embedded into this type.) -

    -

    BMCVersionTemplate defines the template for BMC version to be applied on the server’s BMC.

    -
    -bmcRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    BMCRef is a reference to a specific BMC to apply BMC upgrade on.

    -
    -
    -status
    - - -BMCVersionStatus - - -
    -
    -

    BMCVersionSet -

    -
    -

    BMCVersionSet is the Schema for the bmcversionsets API.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -BMCVersionSetSpec - - -
    -
    -
    - - - - - - - - - -
    -bmcSelector
    - - -Kubernetes meta/v1.LabelSelector - - -
    -

    BMCSelector specifies a label selector to identify the BMC that are to be selected.

    -
    -bmcVersionTemplate
    - - -BMCVersionTemplate - - -
    -

    BMCVersionTemplate defines the template for the BMCversion Resource to be applied to the servers.

    -
    -
    -status
    - - -BMCVersionSetStatus - - -
    -
    -

    BMCVersionSetSpec -

    -

    -(Appears on:BMCVersionSet) -

    -
    -

    BMCVersionSetSpec defines the desired state of BMCVersionSet.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -bmcSelector
    - - -Kubernetes meta/v1.LabelSelector - - -
    -

    BMCSelector specifies a label selector to identify the BMC that are to be selected.

    -
    -bmcVersionTemplate
    - - -BMCVersionTemplate - - -
    -

    BMCVersionTemplate defines the template for the BMCversion Resource to be applied to the servers.

    -
    -

    BMCVersionSetStatus -

    -

    -(Appears on:BMCVersionSet) -

    -
    -

    BMCVersionSetStatus defines the observed state of BMCVersionSet.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -fullyLabeledBMCs
    - -int32 - -
    -

    FullyLabeledBMCs is the number of server in the set.

    -
    -availableBMCVersion
    - -int32 - -
    -

    AvailableBMCVersion is the number of BMCVersion current created by the set.

    -
    -pendingBMCVersion
    - -int32 - -
    -

    PendingBMCVersion is the total number of pending BMCVersion in the set.

    -
    -inProgressBMCVersion
    - -int32 - -
    -

    InProgressBMCVersion is the total number of BMCVersion in the set that are currently in InProgress.

    -
    -completedBMCVersion
    - -int32 - -
    -

    CompletedBMCVersion is the total number of completed BMCVersion in the set.

    -
    -failedBMCVersion
    - -int32 - -
    -

    FailedBMCVersion is the total number of failed BMCVersion in the set.

    -
    -

    BMCVersionSpec -

    -

    -(Appears on:BMCVersion) -

    -
    -

    BMCVersionSpec defines the desired state of BMCVersion.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -BMCVersionTemplate
    - - -BMCVersionTemplate - - -
    -

    -(Members of BMCVersionTemplate are embedded into this type.) -

    -

    BMCVersionTemplate defines the template for BMC version to be applied on the server’s BMC.

    -
    -bmcRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    BMCRef is a reference to a specific BMC to apply BMC upgrade on.

    -
    -

    BMCVersionState -(string alias)

    -

    -(Appears on:BMCVersionStatus) -

    -
    -
    - - - - - - - - - - - - - - - - -
    ValueDescription

    "Completed"

    BMCVersionStateCompleted specifies that the BMC upgrade maintenance has been completed.

    -

    "Failed"

    BMCVersionStateFailed specifies that the BMC upgrade maintenance has failed.

    -

    "InProgress"

    BMCVersionStateInProgress specifies that upgrading BMC is in progress.

    -

    "Pending"

    BMCVersionStatePending specifies that the BMC upgrade maintenance is waiting

    -
    -

    BMCVersionStatus -

    -

    -(Appears on:BMCVersion) -

    -
    -

    BMCVersionStatus defines the observed state of BMCVersion.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -state
    - - -BMCVersionState - - -
    -

    State represents the current state of the BMC configuration task.

    -
    -upgradeTask
    - - -Task - - -
    -

    UpgradeTask contains the state of the Upgrade Task created by the BMC

    -
    -conditions
    - - -[]Kubernetes meta/v1.Condition - - -
    -(Optional) -

    Conditions represents the latest available observations of the BMC version upgrade state.

    -
    -

    BMCVersionTemplate -

    -

    -(Appears on:BMCVersionSetSpec, BMCVersionSpec) -

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

    Version contains a BMC version to upgrade to

    -
    -updatePolicy
    - - -UpdatePolicy - - -
    -(Optional) -

    UpdatePolicy is an indication of whether the server’s upgrade service should bypass vendor update policies

    -
    -image
    - - -ImageSpec - - -
    -

    details regarding the image to use to upgrade to given BMC version

    -
    -serverMaintenancePolicy
    - - -ServerMaintenancePolicy - - -
    -(Optional) -

    ServerMaintenancePolicy is a maintenance policy to be enforced on the server managed by referred BMC.

    -
    -serverMaintenanceRefs
    - - -[]ServerMaintenanceRefItem - - -
    -(Optional) -

    ServerMaintenanceRefs are references to a ServerMaintenance objects that Controller has requested for the each of the related server.

    -
    -

    BootOrder -

    -

    -(Appears on:ServerSpec) -

    -
    -

    BootOrder represents the boot order of the server.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    Name is the name of the boot device.

    -
    -priority
    - -int - -
    -

    Priority is the priority of the boot device.

    -
    -device
    - -string - -
    -

    Device is the device to boot from.

    -
    -

    ConsoleProtocol -

    -

    -(Appears on:BMCSpec) -

    -
    -

    ConsoleProtocol defines the protocol and port used for console access to the BMC.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - - -ConsoleProtocolName - - -
    -

    Name specifies the name of the console protocol. -This could be a protocol such as “SSH”, “Telnet”, etc.

    -
    -port
    - -int32 - -
    -

    Port specifies the port number used for console access. -This port is used by the specified console protocol to establish connections.

    -
    -

    ConsoleProtocolName -(string alias)

    -

    -(Appears on:ConsoleProtocol) -

    -
    -

    ConsoleProtocolName defines the possible names for console protocols.

    -
    - - - - - - - - - - - - - - -
    ValueDescription

    "IPMI"

    ConsoleProtocolNameIPMI represents the IPMI console protocol.

    -

    "SSH"

    ConsoleProtocolNameSSH represents the SSH console protocol.

    -

    "SSHLenovo"

    ConsoleProtocolNameSSHLenovo represents the SSH console protocol specific to Lenovo hardware.

    -
    -

    Endpoint -

    -
    -

    Endpoint is the Schema for the endpoints API

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -EndpointSpec - - -
    -
    -
    - - - - - - - - - -
    -macAddress
    - -string - -
    -(Optional) -

    MACAddress is the MAC address of the endpoint.

    -
    -ip
    - - -IP - - -
    -(Optional) -

    IP is the IP address of the endpoint.

    -
    -
    -status
    - - -EndpointStatus - - -
    -
    -

    EndpointSpec -

    -

    -(Appears on:Endpoint) -

    -
    -

    EndpointSpec defines the desired state of Endpoint

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -macAddress
    - -string - -
    -(Optional) -

    MACAddress is the MAC address of the endpoint.

    -
    -ip
    - - -IP - - -
    -(Optional) -

    IP is the IP address of the endpoint.

    -
    -

    EndpointStatus -

    -

    -(Appears on:Endpoint) -

    -
    -

    EndpointStatus defines the observed state of Endpoint

    -
    -

    IP -

    -

    -(Appears on:BMCStatus, EndpointSpec, InlineEndpoint, NetworkInterface) -

    -
    -

    IP is an IP address.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    --
    - - -net/netip.Addr - - -
    -
    -

    IPPrefix -

    -
    -

    IPPrefix represents a network prefix.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    --
    - - -net/netip.Prefix - - -
    -
    -

    ImageSpec -

    -

    -(Appears on:BIOSVersionTemplate, BMCVersionTemplate) -

    -
    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -secretRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    ImageSecretRef is a reference to the Kubernetes Secret (of type SecretTypeBasicAuth) object that contains the credentials -to access the ImageURI. This secret includes sensitive information such as usernames and passwords.

    -
    -transferProtocol
    - -string - -
    -(Optional) -

    The network protocol that the server’s update service uses to retrieve ‘ImageURI’

    -
    -URI
    - -string - -
    -

    The URI of the software image to update/install.”

    -
    -

    IndicatorLED -(string alias)

    -

    -(Appears on:ServerSpec, ServerStatus) -

    -
    -

    IndicatorLED represents LED indicator states

    -
    - - - - - - - - - - - - - - - - -
    ValueDescription

    "Blinking"

    BlinkingIndicatorLED indicates the Indicator LED is blinking.

    -

    "Lit"

    LitIndicatorLED indicates the Indicator LED is lit.

    -

    "Off"

    OffIndicatorLED indicates the Indicator LED is off.

    -

    "Unknown"

    UnknownIndicatorLED indicates the state of the Indicator LED cannot be -determined.

    -
    -

    InlineEndpoint -

    -

    -(Appears on:BMCSpec) -

    -
    -

    InlineEndpoint defines inline network access configuration for the BMC.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -macAddress
    - -string - -
    -(Optional) -

    MACAddress is the MAC address of the endpoint.

    -
    -ip
    - - -IP - - -
    -(Optional) -

    IP is the IP address of the BMC.

    -
    -

    NetworkInterface -

    -

    -(Appears on:ServerStatus) -

    -
    -

    NetworkInterface defines the details of a network interface.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    Name is the name of the network interface.

    -
    -ip
    - - -IP - - -
    -

    IP is the IP address assigned to the network interface. -The type is specified as string and is schemaless.

    -
    -macAddress
    - -string - -
    -

    MACAddress is the MAC address of the network interface.

    -
    -

    Phase -(string alias)

    -

    -(Appears on:ServerClaimStatus) -

    -
    -

    Phase defines the possible phases of a ServerClaim.

    -
    - - - - - - - - - - - - -
    ValueDescription

    "Bound"

    PhaseBound indicates that the server claim is bound to a server.

    -

    "Unbound"

    PhaseUnbound indicates that the server claim is not bound to any server.

    -
    -

    Power -(string alias)

    -

    -(Appears on:ServerClaimSpec, ServerMaintenanceSpec, ServerSpec) -

    -
    -

    Power defines the possible power states for a device.

    -
    - - - - - - - - - - - - -
    ValueDescription

    "Off"

    PowerOff indicates that the device is powered off.

    -

    "On"

    PowerOn indicates that the device is powered on.

    -
    -

    Processor -

    -

    -(Appears on:ServerStatus) -

    -
    -

    Processor defines the details of a Processor.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -id
    - -string - -
    -

    ID is the name of the Processor.

    -
    -type
    - -string - -
    -(Optional) -

    Type is the type of the Processor.

    -
    -architecture
    - -string - -
    -(Optional) -

    Architecture is the architecture of the Processor.

    -
    -instructionSet
    - -string - -
    -(Optional) -

    InstructionSet is the instruction set of the Processor.

    -
    -manufacturer
    - -string - -
    -(Optional) -

    Manufacturer is the manufacturer of the Processor.

    -
    -model
    - -string - -
    -(Optional) -

    Model is the model of the Processor.

    -
    -maxSpeedMHz
    - -int32 - -
    -(Optional) -

    MaxSpeedMHz is the maximum speed of the Processor in MHz.

    -
    -totalCores
    - -int32 - -
    -(Optional) -

    TotalCores is the total number of cores in the Processor.

    -
    -totalThreads
    - -int32 - -
    -(Optional) -

    TotalThreads is the total number of threads in the Processor.

    -
    -

    Protocol -

    -

    -(Appears on:BMCAccess, BMCSpec) -

    -
    -

    Protocol defines the protocol and port used for communicating with the BMC.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - - -ProtocolName - - -
    -

    Name specifies the name of the protocol. -This could be a protocol such as “IPMI”, “Redfish”, etc.

    -
    -port
    - -int32 - -
    -

    Port specifies the port number used for communication. -This port is used by the specified protocol to establish connections.

    -
    -scheme
    - - -ProtocolScheme - - -
    -

    Scheme specifies the scheme used for communication.

    -
    -

    ProtocolName -(string alias)

    -

    -(Appears on:Protocol) -

    -
    -

    ProtocolName defines the possible names for protocols used for communicating with the BMC.

    -
    - - - - - - - - - - - - - - -
    ValueDescription

    "IPMI"

    ProtocolNameIPMI represents the IPMI protocol.

    -

    "Redfish"

    ProtocolNameRedfish represents the Redfish protocol.

    -

    "SSH"

    ProtocolNameSSH represents the SSH protocol.

    -
    -

    ProtocolScheme -(string alias)

    -

    -(Appears on:Protocol) -

    -
    -

    ProtocolScheme is a string that contains the protocol scheme

    -
    - - - - - - - - - - - - -
    ValueDescription

    "http"

    HTTPProtocolScheme is the http protocol scheme

    -

    "https"

    HTTPSProtocolScheme is the https protocol scheme

    -
    -

    Server -

    -
    -

    Server is the Schema for the servers API

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -ServerSpec - - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -uuid
    - -string - -
    -

    UUID is the unique identifier for the server. -Deprecated in favor of systemUUID.

    -
    -systemUUID
    - -string - -
    -(Optional) -

    SystemUUID is the unique identifier for the server.

    -
    -systemURI
    - -string - -
    -

    SystemURI is the unique URI for the server resource in REDFISH API.

    -
    -power
    - - -Power - - -
    -(Optional) -

    Power specifies the desired power state of the server.

    -
    -indicatorLED
    - - -IndicatorLED - - -
    -(Optional) -

    IndicatorLED specifies the desired state of the server’s indicator LED.

    -
    -serverClaimRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    ServerClaimRef is a reference to a ServerClaim object that claims this server. -This field is optional and can be omitted if no claim is associated with this server.

    -
    -serverMaintenanceRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    ServerMaintenanceRef is a reference to a ServerMaintenance object that maintains this server.

    -
    -bmcRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    BMCRef is a reference to the BMC object associated with this server. -This field is optional and can be omitted if no BMC is associated with this server.

    -
    -bmc
    - - -BMCAccess - - -
    -(Optional) -

    BMC contains the access details for the BMC. -This field is optional and can be omitted if no BMC access is specified.

    -
    -bootConfigurationRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    BootConfigurationRef is a reference to a BootConfiguration object that specifies -the boot configuration for this server. This field is optional and can be omitted -if no boot configuration is specified.

    -
    -maintenanceBootConfigurationRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    MaintenanceBootConfigurationRef is a reference to a BootConfiguration object that specifies -the boot configuration for this server during maintenance. This field is optional and can be omitted

    -
    -bootOrder
    - - -[]BootOrder - - -
    -(Optional) -

    BootOrder specifies the boot order of the server.

    -
    -biosSettingsRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    BIOSSettingsRef is a reference to a biossettings object that specifies -the BIOS configuration for this server.

    -
    -
    -status
    - - -ServerStatus - - -
    -
    -

    ServerBootConfiguration -

    -
    -

    ServerBootConfiguration is the Schema for the serverbootconfigurations API

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -ServerBootConfigurationSpec - - -
    -
    -
    - - - - - - - - - - - - - -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    ServerRef is a reference to the server for which this boot configuration is intended.

    -
    -image
    - -string - -
    -(Optional) -

    Image specifies the boot image to be used for the server. -This field is optional and can be omitted if not specified.

    -
    -ignitionSecretRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    IgnitionSecretRef is a reference to the Kubernetes Secret object that contains -the ignition configuration for the server. This field is optional and can be omitted if not specified.

    -
    -
    -status
    - - -ServerBootConfigurationStatus - - -
    -
    -

    ServerBootConfigurationSpec -

    -

    -(Appears on:ServerBootConfiguration, ServerBootConfigurationTemplate) -

    -
    -

    ServerBootConfigurationSpec defines the desired state of ServerBootConfiguration.

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    ServerRef is a reference to the server for which this boot configuration is intended.

    -
    -image
    - -string - -
    -(Optional) -

    Image specifies the boot image to be used for the server. -This field is optional and can be omitted if not specified.

    -
    -ignitionSecretRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    IgnitionSecretRef is a reference to the Kubernetes Secret object that contains -the ignition configuration for the server. This field is optional and can be omitted if not specified.

    -
    -

    ServerBootConfigurationState -(string alias)

    -

    -(Appears on:ServerBootConfigurationStatus) -

    -
    -

    ServerBootConfigurationState defines the possible states of a ServerBootConfiguration.

    -
    - - - - - - - - - - - - - - -
    ValueDescription

    "Error"

    ServerBootConfigurationStateError indicates that there is an error with the boot configuration.

    -

    "Pending"

    ServerBootConfigurationStatePending indicates that the boot configuration is pending and not yet ready.

    -

    "Ready"

    ServerBootConfigurationStateReady indicates that the boot configuration is ready for use.

    -
    -

    ServerBootConfigurationStatus -

    -

    -(Appears on:ServerBootConfiguration) -

    -
    -

    ServerBootConfigurationStatus defines the observed state of ServerBootConfiguration.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -state
    - - -ServerBootConfigurationState - - -
    -(Optional) -

    State represents the current state of the boot configuration.

    -
    -conditions
    - - -[]Kubernetes meta/v1.Condition - - -
    -(Optional) -

    Conditions represents the latest available observations of the ServerBootConfig’s current state.

    -
    -

    ServerBootConfigurationTemplate -

    -

    -(Appears on:ServerMaintenanceSpec) -

    -
    -

    ServerBootConfigurationTemplate defines the parameters to be used for rendering a boot configuration.

    -
    - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    Name specifies the name of the boot configuration.

    -
    -spec
    - - -ServerBootConfigurationSpec - - -
    -

    Parameters specify the parameters to be used for rendering the boot configuration.

    -
    -
    - - - - - - - - - - - - - -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    ServerRef is a reference to the server for which this boot configuration is intended.

    -
    -image
    - -string - -
    -(Optional) -

    Image specifies the boot image to be used for the server. -This field is optional and can be omitted if not specified.

    -
    -ignitionSecretRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    IgnitionSecretRef is a reference to the Kubernetes Secret object that contains -the ignition configuration for the server. This field is optional and can be omitted if not specified.

    -
    -
    -

    ServerClaim -

    -
    -

    ServerClaim is the Schema for the serverclaims API

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -ServerClaimSpec - - -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - -
    -power
    - - -Power - - -
    -

    Power specifies the desired power state of the server.

    -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    ServerRef is a reference to a specific server to be claimed. -This field is optional and can be omitted if the server is to be selected using ServerSelector.

    -
    -serverSelector
    - - -Kubernetes meta/v1.LabelSelector - - -
    -(Optional) -

    ServerSelector specifies a label selector to identify the server to be claimed. -This field is optional and can be omitted if a specific server is referenced using ServerRef.

    -
    -ignitionSecretRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    IgnitionSecretRef is a reference to the Kubernetes Secret object that contains -the ignition configuration for the server. This field is optional and can be omitted if not specified.

    -
    -image
    - -string - -
    -

    Image specifies the boot image to be used for the server.

    -
    -
    -status
    - - -ServerClaimStatus - - -
    -
    -

    ServerClaimSpec -

    -

    -(Appears on:ServerClaim) -

    -
    -

    ServerClaimSpec defines the desired state of ServerClaim.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -power
    - - -Power - - -
    -

    Power specifies the desired power state of the server.

    -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    ServerRef is a reference to a specific server to be claimed. -This field is optional and can be omitted if the server is to be selected using ServerSelector.

    -
    -serverSelector
    - - -Kubernetes meta/v1.LabelSelector - - -
    -(Optional) -

    ServerSelector specifies a label selector to identify the server to be claimed. -This field is optional and can be omitted if a specific server is referenced using ServerRef.

    -
    -ignitionSecretRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    IgnitionSecretRef is a reference to the Kubernetes Secret object that contains -the ignition configuration for the server. This field is optional and can be omitted if not specified.

    -
    -image
    - -string - -
    -

    Image specifies the boot image to be used for the server.

    -
    -

    ServerClaimStatus -

    -

    -(Appears on:ServerClaim) -

    -
    -

    ServerClaimStatus defines the observed state of ServerClaim.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    -phase
    - - -Phase - - -
    -(Optional) -

    Phase represents the current phase of the server claim.

    -
    -

    ServerMaintenance -

    -
    -

    ServerMaintenance is the Schema for the ServerMaintenance API

    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -metadata
    - - -Kubernetes meta/v1.ObjectMeta - - -
    -Refer to the Kubernetes API documentation for the fields of the -metadata field. -
    -spec
    - - -ServerMaintenanceSpec - - -
    -
    -
    - - - - - - - - - - - - - - - - - -
    -policy
    - - -ServerMaintenancePolicy - - -
    -(Optional) -

    Policy specifies the maintenance policy to be enforced on the server.

    -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    ServerRef is a reference to the server that is to be maintained.

    -
    -serverPower
    - - -Power - - -
    -(Optional) -

    ServerPower specifies the power state of the server during maintenance.

    -
    -serverBootConfigurationTemplate
    - - -ServerBootConfigurationTemplate - - -
    -(Optional) -

    ServerBootConfigurationTemplate specifies the boot configuration to be applied to the server during maintenance.

    -
    -
    -status
    - - -ServerMaintenanceStatus - - -
    -
    -

    ServerMaintenancePolicy -(string alias)

    -

    -(Appears on:BIOSSettingsTemplate, BIOSVersionTemplate, BMCSettingsSpec, BMCVersionTemplate, ServerMaintenanceSpec) -

    -
    -

    ServerMaintenancePolicy specifies the maintenance policy to be enforced on the server.

    -
    - - - - - - - - - - - - -
    ValueDescription

    "Enforced"

    ServerMaintenancePolicyEnforced specifies that the maintenance policy is enforced.

    -

    "OwnerApproval"

    ServerMaintenancePolicyOwnerApproval specifies that the maintenance policy requires owner approval.

    -
    -

    ServerMaintenanceRefItem -

    -

    -(Appears on:BMCSettingsSpec, BMCVersionTemplate) -

    -
    -

    ServerMaintenanceRefItem is a reference to a ServerMaintenance object.

    -
    - - - - - - - - - - - - - -
    FieldDescription
    -serverMaintenanceRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    ServerMaintenanceRef is a reference to a ServerMaintenance object that the BMCSettings has requested for the referred server.

    -
    -

    ServerMaintenanceSpec -

    -

    -(Appears on:ServerMaintenance) -

    -
    -

    ServerMaintenanceSpec defines the desired state of a ServerMaintenance

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -policy
    - - -ServerMaintenancePolicy - - -
    -(Optional) -

    Policy specifies the maintenance policy to be enforced on the server.

    -
    -serverRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -

    ServerRef is a reference to the server that is to be maintained.

    -
    -serverPower
    - - -Power - - -
    -(Optional) -

    ServerPower specifies the power state of the server during maintenance.

    -
    -serverBootConfigurationTemplate
    - - -ServerBootConfigurationTemplate - - -
    -(Optional) -

    ServerBootConfigurationTemplate specifies the boot configuration to be applied to the server during maintenance.

    -
    -

    ServerMaintenanceState -(string alias)

    -

    -(Appears on:ServerMaintenanceStatus) -

    -
    -

    ServerMaintenanceState specifies the current state of the server maintenance.

    -
    - - - - - - - - - - - - - - -
    ValueDescription

    "Failed"

    ServerMaintenanceStateFailed specifies that the server maintenance has failed.

    -

    "InMaintenance"

    ServerMaintenanceStateInMaintenance specifies that the server is in maintenance.

    -

    "Pending"

    ServerMaintenanceStatePending specifies that the server maintenance is pending.

    -
    -

    ServerMaintenanceStatus -

    -

    -(Appears on:ServerMaintenance) -

    -
    -

    ServerMaintenanceStatus defines the observed state of a ServerMaintenance

    -
    - - - - - - - - - - - - - -
    FieldDescription
    -state
    - - -ServerMaintenanceState - - -
    -

    State specifies the current state of the server maintenance.

    -
    -

    ServerPowerState -(string alias)

    -

    -(Appears on:ServerStatus) -

    -
    -

    ServerPowerState defines the possible power states for a server.

    -
    - - - - - - - - - - - - - - - - - - -
    ValueDescription

    "Off"

    ServerOffPowerState indicates that the system is powered off, although some components may -continue to have auxiliary power such as the management controller.

    -

    "On"

    ServerOnPowerState indicates that the system is powered on.

    -

    "Paused"

    ServerPausedPowerState indicates that the system is paused.

    -

    "PoweringOff"

    ServerPoweringOffPowerState indicates a temporary state between On and Off. -The power off action can take time while the OS is in the shutdown process.

    -

    "PoweringOn"

    ServerPoweringOnPowerState indicates a temporary state between Off and On. -This temporary state can be very short.

    -
    -

    ServerSpec -

    -

    -(Appears on:Server) -

    -
    -

    ServerSpec defines the desired state of a Server.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -uuid
    - -string - -
    -

    UUID is the unique identifier for the server. -Deprecated in favor of systemUUID.

    -
    -systemUUID
    - -string - -
    -(Optional) -

    SystemUUID is the unique identifier for the server.

    -
    -systemURI
    - -string - -
    -

    SystemURI is the unique URI for the server resource in REDFISH API.

    -
    -power
    - - -Power - - -
    -(Optional) -

    Power specifies the desired power state of the server.

    -
    -indicatorLED
    - - -IndicatorLED - - -
    -(Optional) -

    IndicatorLED specifies the desired state of the server’s indicator LED.

    -
    -serverClaimRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    ServerClaimRef is a reference to a ServerClaim object that claims this server. -This field is optional and can be omitted if no claim is associated with this server.

    -
    -serverMaintenanceRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    ServerMaintenanceRef is a reference to a ServerMaintenance object that maintains this server.

    -
    -bmcRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    BMCRef is a reference to the BMC object associated with this server. -This field is optional and can be omitted if no BMC is associated with this server.

    -
    -bmc
    - - -BMCAccess - - -
    -(Optional) -

    BMC contains the access details for the BMC. -This field is optional and can be omitted if no BMC access is specified.

    -
    -bootConfigurationRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    BootConfigurationRef is a reference to a BootConfiguration object that specifies -the boot configuration for this server. This field is optional and can be omitted -if no boot configuration is specified.

    -
    -maintenanceBootConfigurationRef
    - - -Kubernetes core/v1.ObjectReference - - -
    -(Optional) -

    MaintenanceBootConfigurationRef is a reference to a BootConfiguration object that specifies -the boot configuration for this server during maintenance. This field is optional and can be omitted

    -
    -bootOrder
    - - -[]BootOrder - - -
    -(Optional) -

    BootOrder specifies the boot order of the server.

    -
    -biosSettingsRef
    - - -Kubernetes core/v1.LocalObjectReference - - -
    -(Optional) -

    BIOSSettingsRef is a reference to a biossettings object that specifies -the BIOS configuration for this server.

    -
    -

    ServerState -(string alias)

    -

    -(Appears on:ServerStatus) -

    -
    -

    ServerState defines the possible states of a server.

    -
    - - - - - - - - - - - - - - - - - - - - -
    ValueDescription

    "Available"

    ServerStateAvailable indicates that the server is available for use.

    -

    "Discovery"

    ServerStateDiscovery indicates that the server is in its discovery state.

    -

    "Error"

    ServerStateError indicates that there is an error with the server.

    -

    "Initial"

    ServerStateInitial indicates that the server is in its initial state.

    -

    "Maintenance"

    ServerStateMaintenance indicates that the server is in maintenance.

    -

    "Reserved"

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

    -
    -

    ServerStatus -

    -

    -(Appears on:Server) -

    -
    -

    ServerStatus defines the observed state of Server.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -manufacturer
    - -string - -
    -(Optional) -

    Manufacturer is the name of the server manufacturer.

    -
    -biosVersion
    - -string - -
    -

    BIOSVersion is the version of the server’s BIOS.

    -
    -model
    - -string - -
    -(Optional) -

    Model is the model of the server.

    -
    -sku
    - -string - -
    -(Optional) -

    SKU is the stock keeping unit identifier for the server.

    -
    -serialNumber
    - -string - -
    -(Optional) -

    SerialNumber is the serial number of the server.

    -
    -powerState
    - - -ServerPowerState - - -
    -(Optional) -

    PowerState represents the current power state of the server.

    -
    -indicatorLED
    - - -IndicatorLED - - -
    -(Optional) -

    IndicatorLED specifies the current state of the server’s indicator LED.

    -
    -state
    - - -ServerState - - -
    -(Optional) -

    State represents the current state of the server.

    -
    -networkInterfaces
    - - -[]NetworkInterface - - -
    -(Optional) -

    NetworkInterfaces is a list of network interfaces associated with the server.

    -
    -totalSystemMemory
    - - -k8s.io/apimachinery/pkg/api/resource.Quantity - - -
    -(Optional) -

    TotalSystemMemory is the total amount of memory in bytes available on the server.

    -
    -processors
    - - -[]Processor - - -
    -(Optional) -

    Processors is a list of Processors associated with the server.

    -
    -storages
    - - -[]Storage - - -
    -(Optional) -

    Storages is a list of storages associated with the server.

    -
    -conditions
    - - -[]Kubernetes meta/v1.Condition - - -
    -(Optional) -

    Conditions represents the latest available observations of the server’s current state.

    -
    -

    SettingsFlowItem -

    -

    -(Appears on:BIOSSettingsTemplate) -

    -
    -
    - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -

    Name identifies what this settings is doing

    -
    -settings
    - -map[string]string - -
    -(Optional) -

    Settings contains software (eg: BIOS, BMC) settings as map

    -
    -priority
    - -int32 - -
    -

    Priority defines the order of applying the settings -any int greater than 0. lower number have higher Priority (ie; lower number is applied first)

    -
    -

    Storage -

    -

    -(Appears on:ServerStatus) -

    -
    -

    Storage defines the details of one storage device

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -(Optional) -

    Name is the name of the storage interface.

    -
    -state
    - - -StorageState - - -
    -(Optional) -

    State specifies the state of the storage device.

    -
    -volumes
    - - -[]StorageVolume - - -
    -(Optional) -

    Volumes is a collection of volumes associated with this storage.

    -
    -drives
    - - -[]StorageDrive - - -
    -(Optional) -

    Drives is a collection of drives associated with this storage.

    -
    -

    StorageDrive -

    -

    -(Appears on:Storage) -

    -
    -

    StorageDrive defines the details of one storage drive

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -(Optional) -

    Name is the name of the storage interface.

    -
    -mediaType
    - -string - -
    -(Optional) -

    MediaType specifies the media type of the storage device.

    -
    -type
    - -string - -
    -(Optional) -

    Type specifies the type of the storage device.

    -
    -capacity
    - - -k8s.io/apimachinery/pkg/api/resource.Quantity - - -
    -(Optional) -

    Capacity specifies the size of the storage device in bytes.

    -
    -vendor
    - -string - -
    -(Optional) -

    Vendor specifies the vendor of the storage device.

    -
    -model
    - -string - -
    -(Optional) -

    Model specifies the model of the storage device.

    -
    -state
    - - -StorageState - - -
    -(Optional) -

    State specifies the state of the storage device.

    -
    -

    StorageState -(string alias)

    -

    -(Appears on:Storage, StorageDrive, StorageVolume) -

    -
    -

    StorageState represents Storage states

    -
    - - - - - - - - - - - - - - -
    ValueDescription

    "Absent"

    StorageStateAbsent indicates that the storage device is absent.

    -

    "Disabled"

    StorageStateDisabled indicates that the storage device is disabled.

    -

    "Enabled"

    StorageStateEnabled indicates that the storage device is enabled.

    -
    -

    StorageVolume -

    -

    -(Appears on:Storage) -

    -
    -

    StorageVolume defines the details of one storage volume

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -name
    - -string - -
    -(Optional) -

    Name is the name of the storage interface.

    -
    -capacity
    - - -k8s.io/apimachinery/pkg/api/resource.Quantity - - -
    -(Optional) -

    Capacity specifies the size of the storage device in bytes.

    -
    -state
    - - -StorageState - - -
    -(Optional) -

    Status specifies the status of the volume.

    -
    -raidType
    - -string - -
    -(Optional) -

    RAIDType specifies the RAID type of the associated Volume.

    -
    -volumeUsage
    - -string - -
    -(Optional) -

    VolumeUsage specifies the volume usage type for the Volume.

    -
    -

    Task -

    -

    -(Appears on:BIOSVersionStatus, BMCVersionStatus) -

    -
    -

    Task contains the status of the task created by the BMC for the BIOS upgrade.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldDescription
    -URI
    - -string - -
    -(Optional) -

    URI is the URI of the task created by the BMC for the BIOS upgrade.

    -
    -state
    - -github.com/stmcginnis/gofish/redfish.TaskState - -
    -(Optional) -

    State is the current state of the task.

    -
    -status
    - -github.com/stmcginnis/gofish/common.Health - -
    -(Optional) -

    Status is the current status of the task.

    -
    -percentageComplete
    - -int32 - -
    -(Optional) -

    PercentComplete is the percentage of completion of the task.

    -
    -

    UpdatePolicy -(string alias)

    -

    -(Appears on:BIOSVersionTemplate, BMCVersionTemplate) -

    -
    -
    - - - - - - - - - - -
    ValueDescription

    "Force"

    -
    -

    -Generated with gen-crd-api-reference-docs -

    # API Reference ## Packages @@ -5948,6 +590,8 @@ _Appears in:_ | `state` _[BMCState](#bmcstate)_ | State represents the current state of the BMC.
    kubebuilder:validation:Enum=Enabled;Error;Pending | Pending | | | `powerState` _[BMCPowerState](#bmcpowerstate)_ | PowerState represents the current power state of the BMC. | | | | `lastResetTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#time-v1-meta)_ | LastResetTime is the timestamp of the last reset operation performed on the BMC. | | | +| `metricsReportSubscriptionLink` _string_ | MetricsReportSubscriptionLink is the link to the metrics report subscription of the bmc. | | | +| `eventsSubscriptionLink` _string_ | EventsSubscriptionLink is the link to the events subscription of the bmc. | | | | `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#condition-v1-meta) array_ | Conditions represents the latest available observations of the BMC's current state. | | | diff --git a/internal/serverevents/subscription.go b/internal/serverevents/subscription.go index bd2d6e48..2a4d05c1 100644 --- a/internal/serverevents/subscription.go +++ b/internal/serverevents/subscription.go @@ -11,6 +11,7 @@ import ( "github.com/stmcginnis/gofish/redfish" ) +// SubscribeMetricsReport subscribes to Redfish metric reporting events for the given hostname and callback URL. func SubscribeMetricsReport(ctx context.Context, url, hostname string, bmcClient bmc.BMC) (string, error) { link, err := bmcClient.CreateEventSubscription( ctx, @@ -19,11 +20,12 @@ func SubscribeMetricsReport(ctx context.Context, url, hostname string, bmcClient redfish.TerminateAfterRetriesDeliveryRetryPolicy, ) if err != nil { - return link, fmt.Errorf("failed to create event subscription: %w", err) + return "", fmt.Errorf("failed to create event subscription: %w", err) } return link, nil } +// SubscribeEvents creates a Redfish event subscription for events. func SubscribeEvents(ctx context.Context, url, hostname string, bmcClient bmc.BMC) (string, error) { link, err := bmcClient.CreateEventSubscription( ctx, From 654d26f7a11636ea72dcde3aa277cb18c80b1e83 Mon Sep 17 00:00:00 2001 From: Stefan Hipfel Date: Mon, 29 Dec 2025 10:58:55 +0100 Subject: [PATCH 8/8] Remove redundant EventURL field from ServerReconciler --- cmd/manager/main.go | 2 +- internal/controller/server_controller.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 36593d7c..2777b3e2 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -346,6 +346,7 @@ func main() { // nolint: gocyclo BMCResetWaitTime: bmcResetWaitingInterval, BMCClientRetryInterval: bmcResetResyncInterval, ManagerNamespace: managerNamespace, + EventURL: eventURL, Conditions: conditionutils.NewAccessor(conditionutils.AccessorOptions{}), BMCOptions: bmc.Options{ BasicAuth: true, @@ -362,7 +363,6 @@ func main() { // nolint: gocyclo ProbeImage: probeImage, ProbeOSImage: probeOSImage, RegistryURL: registryURL, - EventURL: eventURL, RegistryResyncInterval: registryResyncInterval, ResyncInterval: serverResyncInterval, EnforceFirstBoot: enforceFirstBoot, diff --git a/internal/controller/server_controller.go b/internal/controller/server_controller.go index c89ed76b..236eb62a 100644 --- a/internal/controller/server_controller.go +++ b/internal/controller/server_controller.go @@ -83,7 +83,6 @@ type ServerReconciler struct { ManagerNamespace string ProbeImage string RegistryURL string - EventURL string ProbeOSImage string RegistryResyncInterval time.Duration EnforceFirstBoot bool