Skip to content

Commit

Permalink
naive bios management job implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Artem Bortnikov <artem.bortnikov@telekom.com>
  • Loading branch information
aobort committed Nov 4, 2024
1 parent be6443c commit 1c3946d
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 25 deletions.
77 changes: 77 additions & 0 deletions cmd/jobbios/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package main

import (
"flag"
"os"

metalv1alpha1 "github.com/ironcore-dev/metal-operator/api/v1alpha1"
"github.com/ironcore-dev/metal-operator/internal/job"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)

var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)

func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(metalv1alpha1.AddToScheme(scheme))
// +kubebuilder:scaffold:scheme
}

func main() {
var (
jobTypeString string
serverBIOSRef string
insecure bool
)

pflag.StringVar(&jobTypeString, "job-type", "", "job type")
pflag.StringVar(&serverBIOSRef, "server-bios-ref", "", "server bios ref")
pflag.BoolVar(&insecure, "insecure", true, "use insecure connection to BMC")

opts := zap.Options{
Development: true,
}
opts.BindFlags(flag.CommandLine)
flag.Parse()

ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

if jobTypeString == "" {
setupLog.Error(nil, "job type is required")
os.Exit(1)
}

if serverBIOSRef == "" {
setupLog.Error(nil, "server bios ref is required")
os.Exit(1)
}

config, err := rest.InClusterConfig()
if err != nil {
setupLog.Error(err, "unable to get in cluster config")
os.Exit(1)
}
kubeClient, err := client.New(config, client.Options{
Scheme: scheme,
})
if err != nil {
setupLog.Error(err, "unable to create kubernetes client")
os.Exit(1)
}

executor := job.New(kubeClient)
ctx := ctrl.SetupSignalHandler()
if err = executor.Run(ctx, jobTypeString, serverBIOSRef); err != nil {
os.Exit(1)
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: Apache-2.0

package controller
package bmcutils

import (
"context"
"fmt"

metalv1alpha1 "github.com/ironcore-dev/metal-operator/api/v1alpha1"
"github.com/ironcore-dev/metal-operator/bmc"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const DefaultKubeNamespace = "default"

func GetBMCClientForServer(ctx context.Context, c client.Client, server *metalv1alpha1.Server, insecure bool) (bmc.BMC, error) {
if server.Spec.BMCRef != nil {
b := &metalv1alpha1.BMC{}
Expand Down Expand Up @@ -102,7 +101,7 @@ func CreateBMCClient(ctx context.Context, c client.Client, insecure bool, bmcPro
if err != nil {
return nil, fmt.Errorf("failed to get credentials from BMC secret: %w", err)
}
bmcClient, err = bmc.NewRedfishKubeBMCClient(ctx, bmcAddress, username, password, true, c, DefaultKubeNamespace)
bmcClient, err = bmc.NewRedfishKubeBMCClient(ctx, bmcAddress, username, password, true, c, metav1.NamespaceDefault)
if err != nil {
return nil, fmt.Errorf("failed to create Redfish client: %w", err)
}
Expand Down
17 changes: 9 additions & 8 deletions internal/controller/bmc_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"strings"

"github.com/ironcore-dev/metal-operator/internal/bmcutils"
"k8s.io/apimachinery/pkg/api/errors"

"github.com/go-logr/logr"
Expand All @@ -30,11 +31,11 @@ type BMCReconciler struct {
Insecure bool
}

//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints,verbs=get;list;watch
//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcsecrets,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs/finalizers,verbs=update
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints,verbs=get;list;watch
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcsecrets,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs/finalizers,verbs=update

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down Expand Up @@ -117,7 +118,7 @@ func (r *BMCReconciler) updateBMCStatusDetails(ctx context.Context, log logr.Log
return fmt.Errorf("failed to patch IP and MAC address status: %w", err)
}

bmcClient, err := GetBMCClientFromBMC(ctx, r.Client, bmcObj, r.Insecure)
bmcClient, err := bmcutils.GetBMCClientFromBMC(ctx, r.Client, bmcObj, r.Insecure)
if err != nil {
return fmt.Errorf("failed to create BMC client: %w", err)
}
Expand Down Expand Up @@ -147,7 +148,7 @@ func (r *BMCReconciler) updateBMCStatusDetails(ctx context.Context, log logr.Log
}

func (r *BMCReconciler) discoverServers(ctx context.Context, log logr.Logger, bmcObj *metalv1alpha1.BMC) error {
bmcClient, err := GetBMCClientFromBMC(ctx, r.Client, bmcObj, r.Insecure)
bmcClient, err := bmcutils.GetBMCClientFromBMC(ctx, r.Client, bmcObj, r.Insecure)
if err != nil {
return fmt.Errorf("failed to create BMC client: %w", err)
}
Expand All @@ -164,7 +165,7 @@ func (r *BMCReconciler) discoverServers(ctx context.Context, log logr.Logger, bm
Kind: "Server",
},
ObjectMeta: metav1.ObjectMeta{
Name: GetServerNameFromBMCandIndex(i, bmcObj),
Name: bmcutils.GetServerNameFromBMCandIndex(i, bmcObj),
},
Spec: metalv1alpha1.ServerSpec{
UUID: strings.ToLower(s.UUID), // always use lower-case uuids
Expand Down
5 changes: 3 additions & 2 deletions internal/controller/bmc_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package controller

import (
metalv1alpha1 "github.com/ironcore-dev/metal-operator/api/v1alpha1"
"github.com/ironcore-dev/metal-operator/internal/bmcutils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -52,7 +53,7 @@ var _ = Describe("BMC Controller", func() {
By("Ensuring that the Server resource will be removed")
server := &metalv1alpha1.Server{
ObjectMeta: metav1.ObjectMeta{
Name: GetServerNameFromBMCandIndex(0, bmc),
Name: bmcutils.GetServerNameFromBMCandIndex(0, bmc),
},
}
DeferCleanup(k8sClient.Delete, server)
Expand Down Expand Up @@ -85,7 +86,7 @@ var _ = Describe("BMC Controller", func() {
By("Ensuring that the Server resource has been created")
server := &metalv1alpha1.Server{
ObjectMeta: metav1.ObjectMeta{
Name: GetServerNameFromBMCandIndex(0, bmc),
Name: bmcutils.GetServerNameFromBMCandIndex(0, bmc),
},
}
Eventually(Object(server)).Should(SatisfyAll(
Expand Down
12 changes: 6 additions & 6 deletions internal/controller/endpoint_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ type EndpointReconciler struct {
Insecure bool
}

//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcsecrets,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints/finalizers,verbs=update
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcs,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=bmcsecrets,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=metal.ironcore.dev,resources=endpoints/finalizers,verbs=update

func (r *EndpointReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := ctrl.LoggerFrom(ctx)
Expand Down Expand Up @@ -124,7 +124,7 @@ func (r *EndpointReconciler) reconcile(ctx context.Context, log logr.Logger, end
case metalv1alpha1.ProtocolRedfishKube:
log.V(1).Info("Creating client for a kube test BMC")
bmcAddress := fmt.Sprintf("%s://%s:%d", r.getProtocol(), endpoint.Spec.IP, m.Port)
bmcClient, err := bmc.NewRedfishKubeBMCClient(ctx, bmcAddress, m.DefaultCredentials[0].Username, m.DefaultCredentials[0].Password, true, r.Client, DefaultKubeNamespace)
bmcClient, err := bmc.NewRedfishKubeBMCClient(ctx, bmcAddress, m.DefaultCredentials[0].Username, m.DefaultCredentials[0].Password, true, r.Client, metav1.NamespaceDefault)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to create BMC client: %w", err)
}
Expand Down
11 changes: 6 additions & 5 deletions internal/controller/server_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

"github.com/ironcore-dev/metal-operator/bmc"
"github.com/ironcore-dev/metal-operator/internal/bmcutils"
"k8s.io/apimachinery/pkg/util/wait"

"github.com/go-logr/logr"
Expand Down Expand Up @@ -394,7 +395,7 @@ func (r *ServerReconciler) updateServerStatus(ctx context.Context, log logr.Logg
log.V(1).Info("Server has no BMC connection configured")
return nil
}
bmcClient, err := GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
if err != nil {
return fmt.Errorf("failed to create BMC client: %w", err)
}
Expand Down Expand Up @@ -571,7 +572,7 @@ func (r *ServerReconciler) pxeBootServer(ctx context.Context, log logr.Logger, s
return fmt.Errorf("can only PXE boot server with valid BMC ref or inline BMC configuration")
}

bmcClient, err := GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
defer func() {
if bmcClient != nil {
bmcClient.Logout()
Expand Down Expand Up @@ -662,7 +663,7 @@ func (r *ServerReconciler) ensureServerPowerState(ctx context.Context, log logr.
return nil
}

bmcClient, err := GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
defer func() {
if bmcClient != nil {
bmcClient.Logout()
Expand Down Expand Up @@ -784,7 +785,7 @@ func (r *ServerReconciler) applyBootOrder(ctx context.Context, log logr.Logger,
log.V(1).Info("Server has no BMC connection configured")
return nil
}
bmcClient, err := GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
if err != nil {
return fmt.Errorf("failed to create BMC client: %w", err)
}
Expand Down Expand Up @@ -818,7 +819,7 @@ func (r *ServerReconciler) handleAnnotionOperations(ctx context.Context, log log
if !ok {
return false, nil
}
bmcClient, err := GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
bmcClient, err := bmcutils.GetBMCClientForServer(ctx, r.Client, server, r.Insecure)
if err != nil {
return false, fmt.Errorf("failed to create BMC client: %w", err)
}
Expand Down
6 changes: 6 additions & 0 deletions internal/controller/serverbios_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package controller
import (
"context"
"fmt"
"strconv"
"time"

"github.com/go-logr/logr"
Expand All @@ -29,6 +30,7 @@ type ServerBIOSReconciler struct {
client.Client
Scheme *runtime.Scheme

Insecure bool
// todo: need to decide how to provide jobs' configuration to controller
JobNamespace string
JobImage string
Expand Down Expand Up @@ -283,6 +285,10 @@ func (r *ServerBIOSReconciler) createJob(
Name: "SERVER_BIOS_REF",
Value: serverBIOS.Name,
},
{
Name: "INSECURE",
Value: strconv.FormatBool(r.Insecure),
},
},
},
},
Expand Down
Loading

0 comments on commit 1c3946d

Please sign in to comment.