Skip to content

Commit daaf0f6

Browse files
committed
setting node annotation with 'sriovnetwork.openshift.io/use-external-drainer=true' in case exteranl drainer is enabled
The motivation is for external drainer verification, that SRIOV operator is set with external drainer Signed-off-by: Ido Heyvi <[email protected]>
1 parent cd01dcf commit daaf0f6

File tree

3 files changed

+98
-2
lines changed

3 files changed

+98
-2
lines changed

pkg/consts/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ const (
7676
SriovDevicePluginLabelEnabled = "Enabled"
7777
SriovDevicePluginLabelDisabled = "Disabled"
7878

79+
NodeExternalDrainerAnnotation = "sriovnetwork.openshift.io/use-external-drainer"
7980
NodeDrainAnnotation = "sriovnetwork.openshift.io/state"
8081
NodeStateDrainAnnotation = "sriovnetwork.openshift.io/desired-state"
8182
NodeStateDrainAnnotationCurrent = "sriovnetwork.openshift.io/current-state"

pkg/daemon/daemon.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,17 @@ func (dn *NodeReconciler) apply(ctx context.Context, desiredNodeState *sriovnetw
408408
return ctrl.Result{}, err
409409
}
410410

411+
// remove external drainer annotation
412+
if err := utils.AnnotateNode(ctx,
413+
desiredNodeState.Name,
414+
consts.NodeExternalDrainerAnnotation,
415+
"", dn.client); err != nil {
416+
if !errors.IsNotFound(err) {
417+
reqLogger.Error(err, "failed to remove node external drainer annotation")
418+
return ctrl.Result{}, err
419+
}
420+
}
421+
411422
reqLogger.Info("sync succeeded")
412423
syncStatus := consts.SyncStatusSucceeded
413424
lastSyncError := ""
@@ -532,6 +543,17 @@ func (dn *NodeReconciler) handleDrain(ctx context.Context, desiredNodeState *sri
532543
return false, nil
533544
}
534545

546+
// add external drainer annotation if enabled
547+
if vars.UseExternalDrainer {
548+
if err := utils.AnnotateNode(ctx,
549+
desiredNodeState.Name,
550+
consts.NodeExternalDrainerAnnotation,
551+
"true", dn.client); err != nil {
552+
funcLog.Error(err, "failed to add node external drainer annotation")
553+
return false, err
554+
}
555+
}
556+
535557
// annotate both node and node state with drain or reboot
536558
annotation := consts.DrainRequired
537559
if reqReboot {

pkg/daemon/daemon_test.go

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ var (
5151
)
5252

5353
const (
54-
waitTime = 30 * time.Minute
54+
waitTime = 10 * time.Second
5555
retryTime = 5 * time.Second
56+
nodeName = "node1"
5657
)
5758

5859
var _ = Describe("Daemon Controller", Ordered, func() {
@@ -151,7 +152,7 @@ var _ = Describe("Daemon Controller", Ordered, func() {
151152
daemonReconciler = createDaemon(hostHelper, platformHelper, featureGates, []string{})
152153
startDaemon(daemonReconciler)
153154

154-
_, nodeState = createNode("node1")
155+
_, nodeState = createNode(nodeName)
155156
})
156157

157158
AfterAll(func() {
@@ -253,6 +254,11 @@ var _ = Describe("Daemon Controller", Ordered, func() {
253254
ToNot(HaveOccurred())
254255

255256
g.Expect(nodeState.Annotations[constants.NodeStateDrainAnnotation]).To(Equal(constants.DrainRequired))
257+
// verify that external drainer annotation doesn't exist
258+
node := &corev1.Node{}
259+
g.Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: nodeName}, node)).
260+
ToNot(HaveOccurred())
261+
g.Expect(node.Annotations).NotTo(ContainElement(constants.NodeExternalDrainerAnnotation))
256262
}, waitTime, retryTime).Should(Succeed())
257263

258264
patchAnnotation(nodeState, constants.NodeStateDrainAnnotationCurrent, constants.DrainComplete)
@@ -334,6 +340,73 @@ var _ = Describe("Daemon Controller", Ordered, func() {
334340
eventuallySyncStatusEqual(nodeState, constants.SyncStatusSucceeded)
335341
assertLastStatusTransitionsContains(nodeState, 2, constants.SyncStatusInProgress)
336342
})
343+
344+
It("Should apply external drainer annotation when useExternalDrainer is true", func(ctx context.Context) {
345+
DeferCleanup(func(x bool) { vars.UseExternalDrainer = x }, vars.UseExternalDrainer)
346+
vars.UseExternalDrainer = true
347+
348+
discoverSriovReturn.Store(&[]sriovnetworkv1.InterfaceExt{
349+
{
350+
Name: "eno1",
351+
Driver: "ice",
352+
PciAddress: "0000:16:00.0",
353+
DeviceID: "1593",
354+
Vendor: "8086",
355+
EswitchMode: "legacy",
356+
LinkAdminState: "up",
357+
LinkSpeed: "10000 Mb/s",
358+
LinkType: "ETH",
359+
Mac: "aa:bb:cc:dd:ee:ff",
360+
Mtu: 1500,
361+
TotalVfs: 2,
362+
NumVfs: 0,
363+
},
364+
})
365+
366+
By("waiting for state to be in progress")
367+
eventuallySyncStatusEqual(nodeState, constants.SyncStatusInProgress)
368+
369+
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: nodeState.Namespace, Name: nodeState.Name}, nodeState)
370+
Expect(err).ToNot(HaveOccurred())
371+
372+
By("waiting to require drain")
373+
err = k8sClient.Get(ctx, types.NamespacedName{Namespace: nodeState.Namespace, Name: nodeState.Name}, nodeState)
374+
Expect(err).ToNot(HaveOccurred())
375+
nodeState.Spec.Interfaces = []sriovnetworkv1.Interface{}
376+
err = k8sClient.Update(ctx, nodeState)
377+
Expect(err).ToNot(HaveOccurred())
378+
379+
EventuallyWithOffset(1, func(g Gomega) {
380+
g.Expect(k8sClient.Get(context.Background(), types.NamespacedName{Namespace: nodeState.Namespace, Name: nodeState.Name}, nodeState)).
381+
ToNot(HaveOccurred())
382+
383+
g.Expect(nodeState.Annotations[constants.NodeStateDrainAnnotation]).To(Equal(constants.DrainRequired))
384+
}, waitTime, retryTime).Should(Succeed())
385+
386+
// Validate status
387+
EventuallyWithOffset(1, func(g Gomega) {
388+
// get node by name
389+
node := &corev1.Node{}
390+
g.Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: nodeName}, node)).
391+
ToNot(HaveOccurred())
392+
g.Expect(node.Annotations[constants.NodeExternalDrainerAnnotation]).To(Equal("true"))
393+
}, waitTime, retryTime).Should(Succeed())
394+
395+
patchAnnotation(nodeState, constants.NodeStateDrainAnnotationCurrent, constants.DrainComplete)
396+
// Validate status
397+
EventuallyWithOffset(1, func(g Gomega) {
398+
g.Expect(k8sClient.Get(context.Background(), types.NamespacedName{Namespace: nodeState.Namespace, Name: nodeState.Name}, nodeState)).
399+
ToNot(HaveOccurred())
400+
401+
g.Expect(nodeState.Status.SyncStatus).To(Equal(constants.SyncStatusInProgress))
402+
node := &corev1.Node{}
403+
g.Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: nodeName}, node)).
404+
ToNot(HaveOccurred())
405+
// verify that external drainer annotation is removed
406+
g.Expect(node.Annotations).NotTo(ContainElement(constants.NodeExternalDrainerAnnotation))
407+
}, waitTime, retryTime).Should(Succeed())
408+
409+
})
337410
})
338411
})
339412

0 commit comments

Comments
 (0)