@@ -19,25 +19,20 @@ package controller
1919
2020import (
2121 "context"
22+ "errors"
2223 "fmt"
2324 "maps"
24- "strings"
2525
26- "github.com/gophercloud/gophercloud/v2"
27- "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/ports"
2826 corev1 "k8s.io/api/core/v1"
29- "k8s.io/apimachinery/pkg/api/errors"
27+ k8serrors "k8s.io/apimachinery/pkg/api/errors"
3028 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3129 "k8s.io/apimachinery/pkg/runtime"
3230 ctrl "sigs.k8s.io/controller-runtime"
33- "sigs.k8s.io/controller-runtime/pkg/client"
3431 k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
3532 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3633 logger "sigs.k8s.io/controller-runtime/pkg/log"
3734
3835 kvmv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
39- "github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/netbox"
40- "github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/openstack"
4136)
4237
4338const (
@@ -48,10 +43,8 @@ const (
4843)
4944
5045type NodeReconciler struct {
51- client.Client
52- Scheme * runtime.Scheme
53- serviceClient * gophercloud.ServiceClient
54- NetboxClient netbox.Client
46+ k8sclient.Client
47+ Scheme * runtime.Scheme
5548}
5649
5750// +kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch;patch
@@ -66,15 +59,11 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
6659 return ctrl.Result {}, k8sclient .IgnoreNotFound (err )
6760 }
6861
69- host , changed , err := r . normalizeName (ctx , node )
62+ host , err := normalizeName (node )
7063 if err != nil {
7164 return ctrl.Result {}, err
7265 }
7366
74- if changed {
75- return ctrl.Result {Requeue : true }, nil
76- }
77-
7867 name := fmt .Sprintf ("maintenance-required-%v" , host )
7968 eviction := kvmv1.Eviction {
8069 ObjectMeta : metav1.ObjectMeta {
@@ -88,8 +77,8 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
8877 }
8978
9079 // check for existing eviction, else create it
91- if err = r .Get (ctx , client .ObjectKeyFromObject (& eviction ), & eviction ); err != nil {
92- if errors .IsNotFound (err ) {
80+ if err = r .Get (ctx , k8sclient .ObjectKeyFromObject (& eviction ), & eviction ); err != nil {
81+ if k8serrors .IsNotFound (err ) {
9382 // attach ownerReference to the eviction, so we get notified about its changes
9483 if err = controllerutil .SetControllerReference (node , & eviction , r .Scheme ); err != nil {
9584 return ctrl.Result {}, err
@@ -106,110 +95,42 @@ func (r *NodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
10695 // check if the eviction is already succeeded
10796 switch eviction .Status .EvictionState {
10897 case "Succeeded" :
109- _ , err = r .setNodeLabels (ctx , node , map [string ]string {EVICTION_APPROVED_LABEL : "true" })
98+ return ctrl. Result {}, r .setNodeLabels (ctx , node , map [string ]string {EVICTION_APPROVED_LABEL : "true" })
11099 case "Failed" :
111- _ , err = r .setNodeLabels (ctx , node , map [string ]string {EVICTION_APPROVED_LABEL : "false" })
100+ return ctrl. Result {}, r .setNodeLabels (ctx , node , map [string ]string {EVICTION_APPROVED_LABEL : "false" })
112101 }
113102
114- return ctrl.Result {}, err
103+ return ctrl.Result {}, nil
115104}
116105
117- // normalizeName returns the host name of the node. If the host name is not set, it will be set to the node name.
118- // If the host is provisioned by Ironic, the host name will be retrieved from Netbox.
119- // Eventually ensure these labels are in Gardener
120- // kubernetes.metal.cloud.sap/role: kvm (rather set these in gardener, as it is fixed)
121- // kubernetes.metal.cloud.sap/bb
122- // kubernetes.metal.cloud.sap/host
123- // kubernetes.metal.cloud.sap/name
124- // kubernetes.metal.cloud.sap/node-ip
125- func (r * NodeReconciler ) normalizeName (ctx context.Context , node * corev1.Node ) (string , bool , error ) {
106+ // normalizeName returns the host name of the node.
107+ func normalizeName (node * corev1.Node ) (string , error ) {
126108 if name , found := node .Labels [NAME_LABEL ]; found {
127- return name , false , nil
109+ return name , nil
128110 }
129111
130112 if host , found := node .Labels [HOST_LABEL ]; found {
131- return host , false , nil
132- }
133-
134- providerId := node .Spec .ProviderID
135-
136- // openstack:/// is the prefix for Ironic nodes
137- if ! strings .HasPrefix (providerId , "openstack:///" ) {
138- // Assumption: The node name will be correct
139- changed := r .setHostLabel (ctx , node , node .Name )
140- return node .Name , changed , nil
141- }
142-
143- serverId := providerId [strings .LastIndex (providerId , "/" )+ 1 :]
144- listOpts := ports.ListOpts {
145- DeviceID : serverId ,
146- Limit : 1 ,
147- }
148-
149- pages , err := ports .List (r .serviceClient , listOpts ).AllPages (ctx )
150- if err != nil {
151- return "" , false , fmt .Errorf ("could not retrieve ports for %v (%v) due to %w" , node .Name , serverId , err )
152- }
153-
154- nodePorts , err := ports .ExtractPorts (pages )
155- // will raise error, if no nodePorts have been found (404)
156- if err != nil {
157- return "" , false , fmt .Errorf ("could not extract ports for %v (%v) due to %w" , node .Name , serverId , err )
158- }
159-
160- if len (nodePorts ) == 0 {
161- return "" , false , fmt .Errorf ("no Port found for %v (%v)" , node .Name , serverId )
113+ return host , nil
162114 }
163115
164- macAddress := nodePorts [0 ].MACAddress
165- host , err := r .NetboxClient .GetHostName (ctx , macAddress )
166-
167- if err != nil {
168- return host , false , err
169- }
170-
171- changed := r .setHostLabel (ctx , node , host )
172-
173- return host , changed , nil
174- }
175-
176- // setHostLabel sets the host label on the node.
177- func (r * NodeReconciler ) setHostLabel (ctx context.Context , node * corev1.Node , host string ) bool {
178- changed , err := r .setNodeLabels (ctx , node , map [string ]string {
179- HOST_LABEL : host ,
180- NAME_LABEL : host ,
181- })
182- if err != nil {
183- log := logger .FromContext (ctx )
184- log .Error (err , "cannot set host label on node" , "host" , host )
185- }
186- return changed
116+ return "" , errors .New ("could not find node name" )
187117}
188118
189- // setHostLabel sets the host label on the node.
190- func (r * NodeReconciler ) setNodeLabels (ctx context.Context , node * corev1.Node , labels map [string ]string ) ( bool , error ) {
119+ // setNodeLabels sets the labels on the node.
120+ func (r * NodeReconciler ) setNodeLabels (ctx context.Context , node * corev1.Node , labels map [string ]string ) error {
191121 newNode := node .DeepCopy ()
192122 maps .Copy (newNode .Labels , labels )
193123 if maps .Equal (node .Labels , newNode .Labels ) {
194- return false , nil
124+ return nil
195125 }
196126
197- return true , r .Patch (ctx , newNode , k8sclient .MergeFrom (node ))
127+ return r .Patch (ctx , newNode , k8sclient .MergeFrom (node ))
198128}
199129
200130// SetupWithManager sets up the controller with the Manager.
201131func (r * NodeReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
202132 _ = logger .FromContext (context .Background ())
203133
204- var err error
205- if r .serviceClient , err = openstack .GetServiceClient (context .Background (), "network" ); err != nil {
206- return err
207- }
208-
209- if ! strings .HasSuffix (r .serviceClient .Endpoint , "v2.0/" ) {
210- r .serviceClient .ResourceBase = r .serviceClient .Endpoint + "v2.0/"
211- }
212-
213134 return ctrl .NewControllerManagedBy (mgr ).
214135 For (& corev1.Node {}). // trigger the r.Reconcile whenever a node is created/updated/deleted
215136 Owns (& kvmv1.Eviction {}). // trigger the r.Reconcile whenever an Own-ed eviction is created/updated/deleted
0 commit comments