• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

k8snetworkplumbingwg / sriov-network-operator / 11723997336

07 Nov 2024 01:29PM UTC coverage: 45.623% (+0.2%) from 45.458%
11723997336

Pull #799

github

web-flow
Merge 02c6b009c into 2b02ba1fe
Pull Request #799: Rdma subsytem mode

158 of 293 new or added lines in 12 files covered. (53.92%)

3 existing lines in 2 files now uncovered.

6880 of 15080 relevant lines covered (45.62%)

0.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

11.75
/controllers/sriovnetworknodepolicy_controller.go
1
/*
2
Copyright 2021.
3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
    http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16

17
package controllers
18

19
import (
20
        "context"
21
        "encoding/json"
22
        "fmt"
23
        "reflect"
24
        "sort"
25
        "strings"
26
        "time"
27

28
        corev1 "k8s.io/api/core/v1"
29
        "k8s.io/apimachinery/pkg/api/equality"
30
        "k8s.io/apimachinery/pkg/api/errors"
31
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
32
        "k8s.io/apimachinery/pkg/runtime"
33
        "k8s.io/apimachinery/pkg/types"
34
        "k8s.io/client-go/util/workqueue"
35
        ctrl "sigs.k8s.io/controller-runtime"
36
        "sigs.k8s.io/controller-runtime/pkg/client"
37
        "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
38
        "sigs.k8s.io/controller-runtime/pkg/event"
39
        "sigs.k8s.io/controller-runtime/pkg/handler"
40
        "sigs.k8s.io/controller-runtime/pkg/log"
41
        "sigs.k8s.io/controller-runtime/pkg/reconcile"
42
        "sigs.k8s.io/controller-runtime/pkg/source"
43

44
        dptypes "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types"
45

46
        sriovnetworkv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1"
47
        constants "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts"
48
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/featuregate"
49
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars"
50
)
51

52
const nodePolicySyncEventName = "node-policy-sync-event"
53

54
// SriovNetworkNodePolicyReconciler reconciles a SriovNetworkNodePolicy object
55
type SriovNetworkNodePolicyReconciler struct {
56
        client.Client
57
        Scheme      *runtime.Scheme
58
        FeatureGate featuregate.FeatureGate
59
}
60

61
//+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworknodepolicies,verbs=get;list;watch;create;update;patch;delete
62
//+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworknodepolicies/status,verbs=get;update;patch
63
//+kubebuilder:rbac:groups=sriovnetwork.openshift.io,resources=sriovnetworknodepolicies/finalizers,verbs=update
64

65
// Reconcile is part of the main kubernetes reconciliation loop which aims to
66
// move the current state of the cluster closer to the desired state.
67
// TODO(user): Modify the Reconcile function to compare the state specified by
68
// the SriovNetworkNodePolicy object against the actual cluster state, and then
69
// perform operations to make the cluster state reflect the state specified by
70
// the user.
71
//
72
// For more details, check Reconcile and its Result here:
73
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.8.3/pkg/reconcile
74
func (r *SriovNetworkNodePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
×
75
        // Only handle node-policy-sync-event
×
76
        if req.Name != nodePolicySyncEventName || req.Namespace != "" {
×
77
                return reconcile.Result{}, nil
×
78
        }
×
79

80
        reqLogger := log.FromContext(ctx)
×
81
        reqLogger.Info("Reconciling")
×
82

×
83
        // Fetch the default SriovOperatorConfig
×
84
        defaultOpConf := &sriovnetworkv1.SriovOperatorConfig{}
×
85
        if err := r.Get(ctx, types.NamespacedName{Namespace: vars.Namespace, Name: constants.DefaultConfigName}, defaultOpConf); err != nil {
×
86
                if errors.IsNotFound(err) {
×
87
                        reqLogger.Info("default SriovOperatorConfig object not found, cannot reconcile SriovNetworkNodePolicies. Requeue.")
×
88
                        return reconcile.Result{RequeueAfter: 5 * time.Second}, nil
×
89
                }
×
90
                return reconcile.Result{}, err
×
91
        }
92

93
        // Fetch the SriovNetworkNodePolicyList
94
        policyList := &sriovnetworkv1.SriovNetworkNodePolicyList{}
×
95
        err := r.List(ctx, policyList, &client.ListOptions{})
×
96
        if err != nil {
×
97
                if errors.IsNotFound(err) {
×
98
                        // Request object not found, could have been deleted after reconcile request.
×
99
                        // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
×
100
                        // Return and don't requeue
×
101
                        return reconcile.Result{}, nil
×
102
                }
×
103
                // Error reading the object - requeue the request.
104
                return reconcile.Result{}, err
×
105
        }
106
        // Fetch the Nodes
107
        nodeList := &corev1.NodeList{}
×
108
        lo := &client.MatchingLabels{
×
109
                "node-role.kubernetes.io/worker": "",
×
110
                "kubernetes.io/os":               "linux",
×
111
        }
×
112
        if len(defaultOpConf.Spec.ConfigDaemonNodeSelector) > 0 {
×
113
                labels := client.MatchingLabels(defaultOpConf.Spec.ConfigDaemonNodeSelector)
×
114
                lo = &labels
×
115
        }
×
116
        err = r.List(ctx, nodeList, lo)
×
117
        if err != nil {
×
118
                // Error reading the object - requeue the request.
×
119
                reqLogger.Error(err, "Fail to list nodes")
×
120
                return reconcile.Result{}, err
×
121
        }
×
122

123
        // Sort the policies with priority, higher priority ones is applied later
124
        // We need to use the sort so we always get the policies in the same order
125
        // That is needed so when we create the node Affinity for the sriov-device plugin
126
        // it will remain in the same order and not trigger a pod recreation
127
        sort.Sort(sriovnetworkv1.ByPriority(policyList.Items))
×
128
        // Sync SriovNetworkNodeState objects
×
129
        if err = r.syncAllSriovNetworkNodeStates(ctx, defaultOpConf, policyList, nodeList); err != nil {
×
130
                return reconcile.Result{}, err
×
131
        }
×
132
        // Sync Sriov device plugin ConfigMap object
133
        if err = r.syncDevicePluginConfigMap(ctx, defaultOpConf, policyList, nodeList); err != nil {
×
134
                return reconcile.Result{}, err
×
135
        }
×
136
        // Render and sync Daemon objects
137
        if err = syncPluginDaemonObjs(ctx, r.Client, r.Scheme, defaultOpConf, policyList); err != nil {
×
138
                return reconcile.Result{}, err
×
139
        }
×
140

141
        // All was successful. Request that this be re-triggered after ResyncPeriod,
142
        // so we can reconcile state again.
143
        return reconcile.Result{RequeueAfter: constants.ResyncPeriod}, nil
×
144
}
145

146
// SetupWithManager sets up the controller with the Manager.
147
func (r *SriovNetworkNodePolicyReconciler) SetupWithManager(mgr ctrl.Manager) error {
×
148
        qHandler := func(q workqueue.RateLimitingInterface) {
×
149
                q.AddAfter(reconcile.Request{NamespacedName: types.NamespacedName{
×
150
                        Namespace: "",
×
151
                        Name:      nodePolicySyncEventName,
×
152
                }}, time.Second)
×
153
        }
×
154

155
        delayedEventHandler := handler.Funcs{
×
156
                CreateFunc: func(ctx context.Context, e event.CreateEvent, q workqueue.RateLimitingInterface) {
×
157
                        log.Log.WithName("SriovNetworkNodePolicy").
×
NEW
158
                                Info("Enqueuing sync for create event", "resource", e.Object.GetName(), "type", e.Object.GetObjectKind().GroupVersionKind().String())
×
159
                        qHandler(q)
×
160
                },
×
161
                UpdateFunc: func(ctx context.Context, e event.UpdateEvent, q workqueue.RateLimitingInterface) {
×
162
                        log.Log.WithName("SriovNetworkNodePolicy").
×
NEW
163
                                Info("Enqueuing sync for update event", "resource", e.ObjectNew.GetName(), "type", e.ObjectNew.GetObjectKind().GroupVersionKind().String())
×
164
                        qHandler(q)
×
165
                },
×
166
                DeleteFunc: func(ctx context.Context, e event.DeleteEvent, q workqueue.RateLimitingInterface) {
×
167
                        log.Log.WithName("SriovNetworkNodePolicy").
×
NEW
168
                                Info("Enqueuing sync for delete event", "resource", e.Object.GetName(), "type", e.Object.GetObjectKind().GroupVersionKind().String())
×
169
                        qHandler(q)
×
170
                },
×
171
                GenericFunc: func(ctx context.Context, e event.GenericEvent, q workqueue.RateLimitingInterface) {
×
172
                        log.Log.WithName("SriovNetworkNodePolicy").
×
NEW
173
                                Info("Enqueuing sync for generic event", "resource", e.Object.GetName(), "type", e.Object.GetObjectKind().GroupVersionKind().String())
×
174
                        qHandler(q)
×
175
                },
×
176
        }
177

178
        // we want to act fast on new or deleted nodes
179
        nodeEvenHandler := handler.Funcs{
×
180
                CreateFunc: func(ctx context.Context, e event.CreateEvent, q workqueue.RateLimitingInterface) {
×
181
                        log.Log.WithName("SriovNetworkNodePolicy").
×
182
                                Info("Enqueuing sync for create event", "resource", e.Object.GetName())
×
183
                        qHandler(q)
×
184
                },
×
185
                DeleteFunc: func(ctx context.Context, e event.DeleteEvent, q workqueue.RateLimitingInterface) {
×
186
                        log.Log.WithName("SriovNetworkNodePolicy").
×
187
                                Info("Enqueuing sync for delete event", "resource", e.Object.GetName())
×
188
                        qHandler(q)
×
189
                },
×
190
        }
191

192
        // send initial sync event to trigger reconcile when controller is started
193
        var eventChan = make(chan event.GenericEvent, 1)
×
194
        eventChan <- event.GenericEvent{Object: &sriovnetworkv1.SriovNetworkNodePolicy{
×
195
                ObjectMeta: metav1.ObjectMeta{Name: nodePolicySyncEventName, Namespace: ""}}}
×
196
        close(eventChan)
×
197

×
198
        return ctrl.NewControllerManagedBy(mgr).
×
199
                For(&sriovnetworkv1.SriovNetworkNodePolicy{}).
×
200
                Watches(&corev1.Node{}, nodeEvenHandler).
×
201
                Watches(&sriovnetworkv1.SriovNetworkNodePolicy{}, delayedEventHandler).
×
NEW
202
                Watches(&sriovnetworkv1.SriovNetworkPoolConfig{}, delayedEventHandler).
×
203
                WatchesRawSource(&source.Channel{Source: eventChan}, delayedEventHandler).
×
204
                Complete(r)
×
205
}
206

207
func (r *SriovNetworkNodePolicyReconciler) syncDevicePluginConfigMap(ctx context.Context, dc *sriovnetworkv1.SriovOperatorConfig,
208
        pl *sriovnetworkv1.SriovNetworkNodePolicyList, nl *corev1.NodeList) error {
×
209
        logger := log.Log.WithName("syncDevicePluginConfigMap")
×
210
        logger.V(1).Info("Start to sync device plugin ConfigMap")
×
211

×
212
        configData := make(map[string]string)
×
213
        for _, node := range nl.Items {
×
214
                data, err := r.renderDevicePluginConfigData(ctx, pl, &node)
×
215
                if err != nil {
×
216
                        return err
×
217
                }
×
218
                config, err := json.Marshal(data)
×
219
                if err != nil {
×
220
                        return err
×
221
                }
×
222
                configData[node.Name] = string(config)
×
223
        }
224

225
        cm := &corev1.ConfigMap{
×
226
                TypeMeta: metav1.TypeMeta{
×
227
                        APIVersion: "v1",
×
228
                        Kind:       "ConfigMap",
×
229
                },
×
230
                ObjectMeta: metav1.ObjectMeta{
×
231
                        Name:      constants.ConfigMapName,
×
232
                        Namespace: vars.Namespace,
×
233
                },
×
234
                Data: configData,
×
235
        }
×
236

×
237
        if err := controllerutil.SetControllerReference(dc, cm, r.Scheme); err != nil {
×
238
                return err
×
239
        }
×
240

241
        found := &corev1.ConfigMap{}
×
242
        err := r.Get(ctx, types.NamespacedName{Namespace: cm.Namespace, Name: cm.Name}, found)
×
243
        if err != nil {
×
244
                if errors.IsNotFound(err) {
×
245
                        err = r.Create(ctx, cm)
×
246
                        if err != nil {
×
247
                                return fmt.Errorf("couldn't create ConfigMap: %v", err)
×
248
                        }
×
249
                        logger.V(1).Info("Created ConfigMap for", cm.Namespace, cm.Name)
×
250
                } else {
×
251
                        return fmt.Errorf("failed to get ConfigMap: %v", err)
×
252
                }
×
253
        } else {
×
254
                logger.V(1).Info("ConfigMap already exists, updating")
×
255
                err = r.Update(ctx, cm)
×
256
                if err != nil {
×
257
                        return fmt.Errorf("couldn't update ConfigMap: %v", err)
×
258
                }
×
259
        }
260
        return nil
×
261
}
262

263
func (r *SriovNetworkNodePolicyReconciler) syncAllSriovNetworkNodeStates(ctx context.Context, dc *sriovnetworkv1.SriovOperatorConfig, npl *sriovnetworkv1.SriovNetworkNodePolicyList, nl *corev1.NodeList) error {
×
264
        logger := log.Log.WithName("syncAllSriovNetworkNodeStates")
×
265
        logger.V(1).Info("Start to sync all SriovNetworkNodeState custom resource")
×
266
        found := &corev1.ConfigMap{}
×
267
        if err := r.Get(ctx, types.NamespacedName{Namespace: vars.Namespace, Name: constants.ConfigMapName}, found); err != nil {
×
268
                logger.V(1).Info("Fail to get", "ConfigMap", constants.ConfigMapName)
×
269
        }
×
270
        for _, node := range nl.Items {
×
271
                logger.V(1).Info("Sync SriovNetworkNodeState CR", "name", node.Name)
×
272
                ns := &sriovnetworkv1.SriovNetworkNodeState{}
×
273
                ns.Name = node.Name
×
274
                ns.Namespace = vars.Namespace
×
NEW
275
                netPoolConfig, _, err := findNodePoolConfig(ctx, &node, r.Client)
×
NEW
276
                if err != nil {
×
NEW
277
                        logger.Error(err, "failed to get SriovNetworkPoolConfig for the current node")
×
NEW
278
                }
×
NEW
279
                if netPoolConfig != nil {
×
NEW
280
                        ns.Spec.System.RdmaMode = netPoolConfig.Spec.RdmaMode
×
NEW
281
                }
×
282
                j, _ := json.Marshal(ns)
×
283
                logger.V(2).Info("SriovNetworkNodeState CR", "content", j)
×
284
                if err := r.syncSriovNetworkNodeState(ctx, dc, npl, ns, &node); err != nil {
×
285
                        logger.Error(err, "Fail to sync", "SriovNetworkNodeState", ns.Name)
×
286
                        return err
×
287
                }
×
288
        }
289
        logger.V(1).Info("Remove SriovNetworkNodeState custom resource for unselected node")
×
290
        nsList := &sriovnetworkv1.SriovNetworkNodeStateList{}
×
291
        err := r.List(ctx, nsList, &client.ListOptions{})
×
292
        if err != nil {
×
293
                if !errors.IsNotFound(err) {
×
294
                        logger.Error(err, "Fail to list SriovNetworkNodeState CRs")
×
295
                        return err
×
296
                }
×
297
        } else {
×
298
                for _, ns := range nsList.Items {
×
299
                        found := false
×
300
                        for _, node := range nl.Items {
×
301
                                if ns.GetName() == node.GetName() {
×
302
                                        found = true
×
303
                                        break
×
304
                                }
305
                        }
306
                        if !found {
×
307
                                logger.Info("Deleting SriovNetworkNodeState as node with that name doesn't exist", "nodeStateName", ns.Name)
×
308
                                err := r.Delete(ctx, &ns, &client.DeleteOptions{})
×
309
                                if err != nil {
×
310
                                        logger.Error(err, "Fail to Delete", "SriovNetworkNodeState CR:", ns.GetName())
×
311
                                        return err
×
312
                                }
×
313
                        }
314
                }
315
        }
316
        return nil
×
317
}
318

319
func (r *SriovNetworkNodePolicyReconciler) syncSriovNetworkNodeState(ctx context.Context,
320
        dc *sriovnetworkv1.SriovOperatorConfig,
321
        npl *sriovnetworkv1.SriovNetworkNodePolicyList,
322
        ns *sriovnetworkv1.SriovNetworkNodeState,
323
        node *corev1.Node) error {
×
324
        logger := log.Log.WithName("syncSriovNetworkNodeState")
×
325
        logger.V(1).Info("Start to sync SriovNetworkNodeState", "Name", ns.Name)
×
326

×
327
        if err := controllerutil.SetControllerReference(dc, ns, r.Scheme); err != nil {
×
328
                return err
×
329
        }
×
330
        found := &sriovnetworkv1.SriovNetworkNodeState{}
×
331
        err := r.Get(ctx, types.NamespacedName{Namespace: ns.Namespace, Name: ns.Name}, found)
×
332
        if err != nil {
×
333
                logger.Error(err, "Fail to get SriovNetworkNodeState", "namespace", ns.Namespace, "name", ns.Name)
×
334
                if errors.IsNotFound(err) {
×
335
                        err = r.Create(ctx, ns)
×
336
                        if err != nil {
×
337
                                return fmt.Errorf("couldn't create SriovNetworkNodeState: %v", err)
×
338
                        }
×
339
                        logger.Info("Created SriovNetworkNodeState for", ns.Namespace, ns.Name)
×
340
                } else {
×
341
                        return fmt.Errorf("failed to get SriovNetworkNodeState: %v", err)
×
342
                }
×
343
        } else {
×
344
                if len(found.Status.Interfaces) == 0 {
×
345
                        logger.Info("SriovNetworkNodeState Status Interfaces are empty. Skip update of policies in spec",
×
346
                                "namespace", ns.Namespace, "name", ns.Name)
×
347
                        return nil
×
348
                }
×
349

350
                logger.V(1).Info("SriovNetworkNodeState already exists, updating")
×
351
                newVersion := found.DeepCopy()
×
352
                newVersion.Spec = ns.Spec
×
353
                newVersion.OwnerReferences = ns.OwnerReferences
×
354

×
355
                // Previous Policy Priority(ppp) records the priority of previous evaluated policy in node policy list.
×
356
                // Since node policy list is already sorted with priority number, comparing current priority with ppp shall
×
357
                // be sufficient.
×
358
                // ppp is set to 100 as initial value to avoid matching with the first policy in policy list, although
×
359
                // it should not matter since the flag used in p.Apply() will only be applied when VF partition is detected.
×
360
                ppp := 100
×
361
                for _, p := range npl.Items {
×
362
                        // Note(adrianc): default policy is deprecated and ignored.
×
363
                        if p.Name == constants.DefaultPolicyName {
×
364
                                continue
×
365
                        }
366
                        if p.Selected(node) {
×
367
                                logger.Info("apply", "policy", p.Name, "node", node.Name)
×
368
                                // Merging only for policies with the same priority (ppp == p.Spec.Priority)
×
369
                                // This boolean flag controls merging of PF configuration (e.g. mtu, numvfs etc)
×
370
                                // when VF partition is configured.
×
371
                                err = p.Apply(newVersion, ppp == p.Spec.Priority)
×
372
                                if err != nil {
×
373
                                        return err
×
374
                                }
×
375
                                if r.FeatureGate.IsEnabled(constants.ManageSoftwareBridgesFeatureGate) {
×
376
                                        err = p.ApplyBridgeConfig(newVersion)
×
377
                                        if err != nil {
×
378
                                                return err
×
379
                                        }
×
380
                                }
381
                                // record the evaluated policy priority for next loop
382
                                ppp = p.Spec.Priority
×
383
                        }
384
                }
385

386
                // Note(adrianc): we check same ownerReferences since SriovNetworkNodeState
387
                // was owned by a default SriovNetworkNodePolicy. if we encounter a descripancy
388
                // we need to update.
389
                if reflect.DeepEqual(newVersion.OwnerReferences, found.OwnerReferences) &&
×
390
                        equality.Semantic.DeepEqual(newVersion.Spec, found.Spec) {
×
391
                        logger.V(1).Info("SriovNetworkNodeState did not change, not updating")
×
392
                        return nil
×
393
                }
×
394
                err = r.Update(ctx, newVersion)
×
395
                if err != nil {
×
396
                        return fmt.Errorf("couldn't update SriovNetworkNodeState: %v", err)
×
397
                }
×
398
        }
399
        return nil
×
400
}
401

402
func (r *SriovNetworkNodePolicyReconciler) renderDevicePluginConfigData(ctx context.Context, pl *sriovnetworkv1.SriovNetworkNodePolicyList, node *corev1.Node) (dptypes.ResourceConfList, error) {
1✔
403
        logger := log.Log.WithName("renderDevicePluginConfigData")
1✔
404
        logger.V(1).Info("Start to render device plugin config data", "node", node.Name)
1✔
405
        rcl := dptypes.ResourceConfList{}
1✔
406
        for _, p := range pl.Items {
2✔
407
                // Note(adrianc): default policy is deprecated and ignored.
1✔
408
                if p.Name == constants.DefaultPolicyName {
1✔
409
                        continue
×
410
                }
411

412
                // render node specific data for device plugin config
413
                if !p.Selected(node) {
1✔
414
                        continue
×
415
                }
416

417
                nodeState := &sriovnetworkv1.SriovNetworkNodeState{}
1✔
418
                err := r.Get(ctx, types.NamespacedName{Namespace: vars.Namespace, Name: node.Name}, nodeState)
1✔
419
                if err != nil {
1✔
420
                        return rcl, err
×
421
                }
×
422

423
                found, i := resourceNameInList(p.Spec.ResourceName, &rcl)
1✔
424

1✔
425
                if found {
1✔
426
                        err := updateDevicePluginResource(ctx, &rcl.ResourceList[i], &p, nodeState)
×
427
                        if err != nil {
×
428
                                return rcl, err
×
429
                        }
×
430
                        logger.V(1).Info("Update resource", "Resource", rcl.ResourceList[i])
×
431
                } else {
1✔
432
                        rc, err := createDevicePluginResource(ctx, &p, nodeState)
1✔
433
                        if err != nil {
1✔
434
                                return rcl, err
×
435
                        }
×
436
                        rcl.ResourceList = append(rcl.ResourceList, *rc)
1✔
437
                        logger.V(1).Info("Add resource", "Resource", *rc)
1✔
438
                }
439
        }
440
        return rcl, nil
1✔
441
}
442

443
func resourceNameInList(name string, rcl *dptypes.ResourceConfList) (bool, int) {
1✔
444
        for i, rc := range rcl.ResourceList {
1✔
445
                if rc.ResourceName == name {
×
446
                        return true, i
×
447
                }
×
448
        }
449
        return false, 0
1✔
450
}
451

452
func createDevicePluginResource(
453
        ctx context.Context,
454
        p *sriovnetworkv1.SriovNetworkNodePolicy,
455
        nodeState *sriovnetworkv1.SriovNetworkNodeState) (*dptypes.ResourceConfig, error) {
1✔
456
        netDeviceSelectors := dptypes.NetDeviceSelectors{}
1✔
457

1✔
458
        rc := &dptypes.ResourceConfig{
1✔
459
                ResourceName: p.Spec.ResourceName,
1✔
460
        }
1✔
461
        netDeviceSelectors.IsRdma = p.Spec.IsRdma
1✔
462
        netDeviceSelectors.NeedVhostNet = p.Spec.NeedVhostNet
1✔
463
        netDeviceSelectors.VdpaType = dptypes.VdpaType(p.Spec.VdpaType)
1✔
464

1✔
465
        if p.Spec.NicSelector.Vendor != "" {
1✔
466
                netDeviceSelectors.Vendors = append(netDeviceSelectors.Vendors, p.Spec.NicSelector.Vendor)
×
467
        }
×
468
        if p.Spec.NicSelector.DeviceID != "" {
1✔
469
                var deviceID string
×
470
                if p.Spec.NumVfs == 0 {
×
471
                        deviceID = p.Spec.NicSelector.DeviceID
×
472
                } else {
×
473
                        deviceID = sriovnetworkv1.GetVfDeviceID(p.Spec.NicSelector.DeviceID)
×
474
                }
×
475

476
                if !sriovnetworkv1.StringInArray(deviceID, netDeviceSelectors.Devices) && deviceID != "" {
×
477
                        netDeviceSelectors.Devices = append(netDeviceSelectors.Devices, deviceID)
×
478
                }
×
479
        }
480
        if len(p.Spec.NicSelector.PfNames) > 0 {
1✔
481
                netDeviceSelectors.PfNames = append(netDeviceSelectors.PfNames, p.Spec.NicSelector.PfNames...)
×
482
        }
×
483
        // vfio-pci device link type is not detectable
484
        if p.Spec.DeviceType != constants.DeviceTypeVfioPci {
2✔
485
                if p.Spec.LinkType != "" {
1✔
486
                        linkType := constants.LinkTypeEthernet
×
487
                        if strings.EqualFold(p.Spec.LinkType, constants.LinkTypeIB) {
×
488
                                linkType = constants.LinkTypeInfiniband
×
489
                        }
×
490
                        netDeviceSelectors.LinkTypes = sriovnetworkv1.UniqueAppend(netDeviceSelectors.LinkTypes, linkType)
×
491
                }
492
        }
493
        if len(p.Spec.NicSelector.RootDevices) > 0 {
1✔
494
                netDeviceSelectors.RootDevices = append(netDeviceSelectors.RootDevices, p.Spec.NicSelector.RootDevices...)
×
495
        }
×
496
        // Removed driver constraint for "netdevice" DeviceType
497
        if p.Spec.DeviceType == constants.DeviceTypeVfioPci {
1✔
498
                netDeviceSelectors.Drivers = append(netDeviceSelectors.Drivers, p.Spec.DeviceType)
×
499
        }
×
500
        // Enable the selection of devices using NetFilter
501
        if p.Spec.NicSelector.NetFilter != "" {
1✔
502
                // Loop through interfaces status to find a match for NetworkID or NetworkTag
×
503
                if len(nodeState.Status.Interfaces) == 0 {
×
504
                        return nil, fmt.Errorf("node state %s doesn't contain interfaces data", nodeState.Name)
×
505
                }
×
506
                for _, intf := range nodeState.Status.Interfaces {
×
507
                        if sriovnetworkv1.NetFilterMatch(p.Spec.NicSelector.NetFilter, intf.NetFilter) {
×
508
                                // Found a match add the Interfaces PciAddress
×
509
                                netDeviceSelectors.PciAddresses = sriovnetworkv1.UniqueAppend(netDeviceSelectors.PciAddresses, intf.PciAddress)
×
510
                        }
×
511
                }
512
        }
513

514
        netDeviceSelectorsMarshal, err := json.Marshal(netDeviceSelectors)
1✔
515
        if err != nil {
1✔
516
                return nil, err
×
517
        }
×
518
        rawNetDeviceSelectors := json.RawMessage(netDeviceSelectorsMarshal)
1✔
519
        rc.Selectors = &rawNetDeviceSelectors
1✔
520

1✔
521
        rc.ExcludeTopology = p.Spec.ExcludeTopology
1✔
522

1✔
523
        return rc, nil
1✔
524
}
525

526
func updateDevicePluginResource(
527
        ctx context.Context,
528
        rc *dptypes.ResourceConfig,
529
        p *sriovnetworkv1.SriovNetworkNodePolicy,
530
        nodeState *sriovnetworkv1.SriovNetworkNodeState) error {
×
531
        netDeviceSelectors := dptypes.NetDeviceSelectors{}
×
532

×
533
        if err := json.Unmarshal(*rc.Selectors, &netDeviceSelectors); err != nil {
×
534
                return err
×
535
        }
×
536

537
        if p.Spec.NicSelector.Vendor != "" && !sriovnetworkv1.StringInArray(p.Spec.NicSelector.Vendor, netDeviceSelectors.Vendors) {
×
538
                netDeviceSelectors.Vendors = append(netDeviceSelectors.Vendors, p.Spec.NicSelector.Vendor)
×
539
        }
×
540
        if p.Spec.NicSelector.DeviceID != "" {
×
541
                var deviceID string
×
542
                if p.Spec.NumVfs == 0 {
×
543
                        deviceID = p.Spec.NicSelector.DeviceID
×
544
                } else {
×
545
                        deviceID = sriovnetworkv1.GetVfDeviceID(p.Spec.NicSelector.DeviceID)
×
546
                }
×
547

548
                if !sriovnetworkv1.StringInArray(deviceID, netDeviceSelectors.Devices) && deviceID != "" {
×
549
                        netDeviceSelectors.Devices = append(netDeviceSelectors.Devices, deviceID)
×
550
                }
×
551
        }
552
        if len(p.Spec.NicSelector.PfNames) > 0 {
×
553
                netDeviceSelectors.PfNames = sriovnetworkv1.UniqueAppend(netDeviceSelectors.PfNames, p.Spec.NicSelector.PfNames...)
×
554
        }
×
555
        // vfio-pci device link type is not detectable
556
        if p.Spec.DeviceType != constants.DeviceTypeVfioPci {
×
557
                if p.Spec.LinkType != "" {
×
558
                        linkType := constants.LinkTypeEthernet
×
559
                        if strings.EqualFold(p.Spec.LinkType, constants.LinkTypeIB) {
×
560
                                linkType = constants.LinkTypeInfiniband
×
561
                        }
×
562
                        if !sriovnetworkv1.StringInArray(linkType, netDeviceSelectors.LinkTypes) {
×
563
                                netDeviceSelectors.LinkTypes = sriovnetworkv1.UniqueAppend(netDeviceSelectors.LinkTypes, linkType)
×
564
                        }
×
565
                }
566
        }
567
        if len(p.Spec.NicSelector.RootDevices) > 0 {
×
568
                netDeviceSelectors.RootDevices = sriovnetworkv1.UniqueAppend(netDeviceSelectors.RootDevices, p.Spec.NicSelector.RootDevices...)
×
569
        }
×
570
        // Removed driver constraint for "netdevice" DeviceType
571
        if p.Spec.DeviceType == constants.DeviceTypeVfioPci {
×
572
                netDeviceSelectors.Drivers = sriovnetworkv1.UniqueAppend(netDeviceSelectors.Drivers, p.Spec.DeviceType)
×
573
        }
×
574
        // Enable the selection of devices using NetFilter
575
        if p.Spec.NicSelector.NetFilter != "" {
×
576
                // Loop through interfaces status to find a match for NetworkID or NetworkTag
×
577
                for _, intf := range nodeState.Status.Interfaces {
×
578
                        if sriovnetworkv1.NetFilterMatch(p.Spec.NicSelector.NetFilter, intf.NetFilter) {
×
579
                                // Found a match add the Interfaces PciAddress
×
580
                                netDeviceSelectors.PciAddresses = sriovnetworkv1.UniqueAppend(netDeviceSelectors.PciAddresses, intf.PciAddress)
×
581
                        }
×
582
                }
583
        }
584

585
        netDeviceSelectorsMarshal, err := json.Marshal(netDeviceSelectors)
×
586
        if err != nil {
×
587
                return err
×
588
        }
×
589
        rawNetDeviceSelectors := json.RawMessage(netDeviceSelectorsMarshal)
×
590
        rc.Selectors = &rawNetDeviceSelectors
×
591

×
592
        rc.ExcludeTopology = p.Spec.ExcludeTopology
×
593

×
594
        return nil
×
595
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc