@@ -16,6 +16,7 @@ import (
16
16
"k8s.io/apimachinery/pkg/runtime"
17
17
ctrl "sigs.k8s.io/controller-runtime"
18
18
"sigs.k8s.io/controller-runtime/pkg/client"
19
+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
19
20
20
21
multinicv1 "github.com/foundation-model-stack/multi-nic-cni/api/v1"
21
22
"github.com/foundation-model-stack/multi-nic-cni/controllers/vars"
@@ -31,28 +32,20 @@ import (
31
32
"os"
32
33
)
33
34
34
- const (
35
- SERVICE_ACCOUNT_NAME = "multi-nic-cni-operator-controller-manager"
36
- DEFAULT_OPERATOR_NAMESPACE = "multi-nic-cni-operator-system"
37
-
38
- // NetworkAttachmentDefinition watching queue size
39
- MAX_QSIZE = 100
40
- )
35
+ const configFinalizer = "finalizers.config.multinic.fms.io"
41
36
42
37
var (
43
38
OPERATOR_NAMESPACE string = getOperatorNamespace ()
44
39
ConfigReady bool = false
45
40
// referred by daemon watcher
46
- DAEMON_LABEL_NAME = "app"
47
- DAEMON_LABEL_VALUE = "multi-nicd"
48
- DaemonName string = DAEMON_LABEL_VALUE
41
+ DaemonName string = vars .DaemonLabelValue
49
42
)
50
43
51
44
func getOperatorNamespace () string {
52
45
key := "OPERATOR_NAMESPACE"
53
46
val , found := os .LookupEnv (key )
54
47
if ! found {
55
- return DEFAULT_OPERATOR_NAMESPACE
48
+ return vars . DefaultOperatorNamespace
56
49
}
57
50
return val
58
51
}
@@ -74,13 +67,10 @@ type ConfigReconciler struct {
74
67
//+kubebuilder:rbac:groups=multinic.fms.io,resources=configs,verbs=get;list;watch;create;update;patch;delete
75
68
//+kubebuilder:rbac:groups=multinic.fms.io,resources=configs/status,verbs=get;update;patch
76
69
77
- func (r * ConfigReconciler ) CreateDefaultDaemonConfig () error {
78
- objMeta := metav1.ObjectMeta {
79
- Name : DaemonName ,
80
- }
70
+ func (r * ConfigReconciler ) getDefaultConfigSpec () multinicv1.ConfigSpec {
81
71
daemonEnv := corev1.EnvVar {
82
72
Name : "DAEMON_PORT" ,
83
- Value : "11000" ,
73
+ Value : fmt . Sprintf ( "%d" , vars . DefaultDaemonPort ) ,
84
74
}
85
75
routeEnv := corev1.EnvVar {
86
76
Name : "RT_TABLE_PATH" ,
@@ -90,7 +80,7 @@ func (r *ConfigReconciler) CreateDefaultDaemonConfig() error {
90
80
binMnt := multinicv1.HostPathMount {
91
81
Name : "cnibin" ,
92
82
PodCNIPath : "/host/opt/cni/bin" ,
93
- HostCNIPath : "/var/lib/cni/bin" ,
83
+ HostCNIPath : r . getCNIHostPath () ,
94
84
}
95
85
devPluginMnt := multinicv1.HostPathMount {
96
86
Name : "device-plugin" ,
@@ -114,25 +104,33 @@ func (r *ConfigReconciler) CreateDefaultDaemonConfig() error {
114
104
Privileged : & privileged ,
115
105
}
116
106
daemonSpec := multinicv1.DaemonSpec {
117
- Image : "ghcr.io/foundation-model-stack/multi-nic-cni-daemon:v1.0.4" ,
107
+ Image : vars . DefaultDaemonImage ,
118
108
Env : env ,
119
109
HostPathMounts : hostPathMounts ,
120
110
Resources : resources ,
121
111
SecurityContext : securityContext ,
122
- DaemonPort : 11000 ,
112
+ DaemonPort : vars . DefaultDaemonPort ,
123
113
}
124
114
spec := multinicv1.ConfigSpec {
125
- CNIType : "multi-nic" ,
126
- IPAMType : "multi-nic-ipam" ,
115
+ CNIType : vars . DefaultCNIType ,
116
+ IPAMType : vars . DefaultIPAMType ,
127
117
Daemon : daemonSpec ,
128
- JoinPath : "/join" ,
129
- InterfacePath : "/interface" ,
130
- AddRoutePath : "/addl3" ,
131
- DeleteRoutePath : "/deletel3" ,
118
+ JoinPath : vars . DefaultJoinPath ,
119
+ InterfacePath : vars . DefaultInterfacePath ,
120
+ AddRoutePath : vars . DefaultAddRoutePath ,
121
+ DeleteRoutePath : vars . DefaultDeleteRoutePath ,
132
122
}
123
+ return spec
124
+ }
125
+
126
+ func (r * ConfigReconciler ) CreateDefaultDaemonConfig () error {
127
+ objMeta := metav1.ObjectMeta {
128
+ Name : DaemonName ,
129
+ }
130
+
133
131
cfg := & multinicv1.Config {
134
132
ObjectMeta : objMeta ,
135
- Spec : spec ,
133
+ Spec : r . getDefaultConfigSpec () ,
136
134
}
137
135
err := r .Client .Create (context .TODO (), cfg )
138
136
return err
@@ -148,16 +146,39 @@ func (r *ConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
148
146
if errors .IsNotFound (err ) {
149
147
// Request object not found, could have been deleted after reconcile request.
150
148
// Return and don't requeue
151
- err = r .callFinalizer (vars .ConfigLog , req .NamespacedName .Name )
152
- if err != nil {
153
- vars .ConfigLog .V (1 ).Info (fmt .Sprintf ("Failed to finalize %s: %v " , req .NamespacedName .Name , err ))
154
- }
155
149
return ctrl.Result {}, nil
156
150
}
157
151
vars .ConfigLog .V (7 ).Info (fmt .Sprintf ("Cannot get #%v " , err ))
158
152
// Error reading the object - requeue the request.
159
153
return ctrl.Result {RequeueAfter : vars .LongReconcileTime }, nil
160
154
}
155
+
156
+ // Add finalizer to instance
157
+ if ! controllerutil .ContainsFinalizer (instance , configFinalizer ) {
158
+ controllerutil .AddFinalizer (instance , configFinalizer )
159
+ err = r .Update (ctx , instance )
160
+ if err != nil {
161
+ return ctrl.Result {}, err
162
+ }
163
+ }
164
+
165
+ // If config is deleted, delete corresponding daemonset
166
+ is_deleted := instance .GetDeletionTimestamp () != nil
167
+ if is_deleted {
168
+ if controllerutil .ContainsFinalizer (instance , configFinalizer ) {
169
+ if err = r .callFinalizer (vars .ConfigLog , req .NamespacedName .Name ); err != nil {
170
+ return ctrl.Result {}, err
171
+ }
172
+
173
+ controllerutil .RemoveFinalizer (instance , configFinalizer )
174
+ err := r .Client .Update (ctx , instance )
175
+ if err != nil {
176
+ return ctrl.Result {}, err
177
+ }
178
+ }
179
+ return ctrl.Result {}, nil
180
+ }
181
+
161
182
r .UpdateConfigBySpec (& instance .Spec )
162
183
163
184
if ! ConfigReady {
@@ -172,17 +193,17 @@ func (r *ConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
172
193
_ , err = r .Clientset .AppsV1 ().DaemonSets (OPERATOR_NAMESPACE ).Get (context .TODO (), dsName , metav1.GetOptions {})
173
194
daemonset := r .newCNIDaemonSet (r .Clientset , dsName , instance .Spec .Daemon )
174
195
if err != nil {
175
- // - create CNI daemonset, and NetworkAttachmentDefinition watcher if not exist
196
+ // - create CNI daemonset
176
197
if errors .IsNotFound (err ) {
177
- r . newNetAttachDefWatcher (instance )
198
+ SetDaemonConnector (instance . Spec )
178
199
_ , err = r .Clientset .AppsV1 ().DaemonSets (OPERATOR_NAMESPACE ).Create (context .TODO (), daemonset , metav1.CreateOptions {})
179
200
vars .ConfigLog .V (7 ).Info (fmt .Sprintf ("Create new multi-nic daemonset #%s (cni=%s,ipam=%s), err=%v " , dsName , instance .Spec .CNIType , instance .Spec .IPAMType , err ))
180
201
} else {
181
202
vars .ConfigLog .Info (fmt .Sprintf ("Cannot get daemonset #%v " , err ))
182
203
}
183
204
} else {
184
- // - otherwise, update the existing daemonset and restart NetworkAttachmentDefinition watcher
185
- r . newNetAttachDefWatcher (instance )
205
+ // - otherwise, update the existing daemonset
206
+ SetDaemonConnector (instance . Spec )
186
207
_ , err = r .Clientset .AppsV1 ().DaemonSets (OPERATOR_NAMESPACE ).Update (context .TODO (), daemonset , metav1.UpdateOptions {})
187
208
vars .ConfigLog .V (7 ).Info (fmt .Sprintf ("Update multi-nic daemonset #%s, err=%v " , dsName , err ))
188
209
}
@@ -224,19 +245,13 @@ func (r *ConfigReconciler) UpdateConfigBySpec(spec *multinicv1.ConfigSpec) {
224
245
vars .SetLog ()
225
246
}
226
247
}
227
- }
228
-
229
- // newNetAttachDefWatcher restarts NetworkAttachmentDefinition watcher
230
- func (r * ConfigReconciler ) newNetAttachDefWatcher (instance * multinicv1.Config ) {
231
- vars .DaemonPort = instance .Spec .Daemon .DaemonPort
232
- vars .TargetCNI = instance .Spec .CNIType
233
- DaemonName = instance .GetName ()
234
- SetDaemon (instance .Spec )
248
+ vars .DaemonPort = spec .Daemon .DaemonPort
249
+ vars .TargetCNI = spec .CNIType
235
250
}
236
251
237
252
// newCNIDaemonSet creates new CNI daemonset
238
253
func (r * ConfigReconciler ) newCNIDaemonSet (client * kubernetes.Clientset , name string , daemonSpec multinicv1.DaemonSpec ) * appsv1.DaemonSet {
239
- labels := map [string ]string {DAEMON_LABEL_NAME : DAEMON_LABEL_VALUE }
254
+ labels := map [string ]string {vars . DeamonLabelKey : vars . DaemonLabelValue }
240
255
241
256
// prepare container port
242
257
containerPort := corev1.ContainerPort {ContainerPort : int32 (daemonSpec .DaemonPort )}
@@ -306,7 +321,7 @@ func (r *ConfigReconciler) newCNIDaemonSet(client *kubernetes.Clientset, name st
306
321
ObjectMeta : metav1.ObjectMeta {Labels : labels },
307
322
Spec : corev1.PodSpec {
308
323
HostNetwork : true ,
309
- ServiceAccountName : SERVICE_ACCOUNT_NAME ,
324
+ ServiceAccountName : vars . ServiceAccountName ,
310
325
NodeSelector : daemonSpec .NodeSelector ,
311
326
Tolerations : daemonSpec .Tolerations ,
312
327
Containers : []corev1.Container {
@@ -320,12 +335,40 @@ func (r *ConfigReconciler) newCNIDaemonSet(client *kubernetes.Clientset, name st
320
335
}
321
336
}
322
337
338
+ func (r * ConfigReconciler ) getCNIHostPath () string {
339
+ ctx , cancel := context .WithTimeout (context .Background (), vars .ContextTimeout )
340
+ defer cancel ()
341
+ // find multus pod
342
+ labels := fmt .Sprintf ("%s=%s" , vars .MultusLabelKey , vars .MultusLabelValue )
343
+ listOptions := metav1.ListOptions {
344
+ LabelSelector : labels ,
345
+ Limit : 1 ,
346
+ }
347
+ multusPods , err := r .Clientset .CoreV1 ().Pods (metav1 .NamespaceAll ).List (ctx , listOptions )
348
+ if err != nil {
349
+ return vars .DefaultCNIHostPath
350
+ }
351
+ for _ , multusPod := range multusPods .Items {
352
+ volumes := multusPod .Spec .Volumes
353
+ for _ , volume := range volumes {
354
+ if volume .Name == vars .CNIBinVolumeName {
355
+ if volume .HostPath != nil {
356
+ cniPath := volume .HostPath .Path
357
+ vars .ConfigLog .Info (fmt .Sprintf ("Find Multus CNI path: %s" , cniPath ))
358
+ return cniPath
359
+ } else {
360
+ // hostpath is not defined
361
+ return vars .DefaultCNIHostPath
362
+ }
363
+ }
364
+ }
365
+ }
366
+ return vars .DefaultCNIHostPath
367
+ }
368
+
323
369
// callFinalizer deletes all CIDRs, waits for all ippools deleted, deletes CNI deamonset, and stops NetworkAttachmentDefinition watcher
324
370
func (r * ConfigReconciler ) callFinalizer (reqLogger logr.Logger , dsName string ) error {
325
- // reset default name
326
- DaemonName = DAEMON_LABEL_VALUE
327
371
reqLogger .Info (fmt .Sprintf ("Finalize %s" , dsName ))
328
-
329
372
// delete all CIDRs
330
373
cidrMap , err := r .CIDRHandler .ListCIDR ()
331
374
if err == nil {
0 commit comments