Skip to content

Commit 22fe861

Browse files
authored
Fix kubevirt failover
Fixes an auto-failover issue with kubevirt.
1 parent e765034 commit 22fe861

File tree

13 files changed

+583
-196
lines changed

13 files changed

+583
-196
lines changed

frontend/crd/controller/crd_controller.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,10 @@ func NewTridentCrdController(
228228

229229
indexers := indexers.NewIndexers(clients.KubeClient)
230230
indexers.Activate()
231-
remediationUtils := NewNodeRemediationUtils(clients.KubeClient, orchestrator, indexers)
231+
232+
pvcGetter := getPVCGetter(ctx, orchestrator)
233+
234+
remediationUtils := NewNodeRemediationUtils(clients.KubeClient, orchestrator, indexers, pvcGetter)
232235

233236
return newTridentCrdControllerImpl(orchestrator, clients.Namespace, clients.KubeClient,
234237
clients.SnapshotClient, clients.TridentClient, indexers, remediationUtils)
@@ -1249,13 +1252,16 @@ func (c *TridentCrdController) SetForceDetach(enableForceDetach bool) {
12491252

12501253
// getPVCGetter returns the Kubernetes helper frontend from the orchestrator (by name) for cache-first
12511254
// PVC lookup, or nil if not available (e.g. plain CSI helper or not yet registered).
1252-
func (c *TridentCrdController) getPVCGetter(ctx context.Context) k8shelper.K8SControllerHelperPlugin {
1253-
frontend, err := c.orchestrator.GetFrontend(ctx, controllerhelpers.KubernetesHelper)
1255+
func getPVCGetter(ctx context.Context, orchestrator core.Orchestrator) k8shelper.K8SControllerHelperPlugin {
1256+
if orchestrator == nil {
1257+
return nil
1258+
}
1259+
frontend, err := orchestrator.GetFrontend(ctx, controllerhelpers.KubernetesHelper)
12541260
if err != nil {
12551261
return nil
12561262
}
1257-
if k8s, ok := frontend.(k8shelper.K8SControllerHelperPlugin); ok {
1258-
return k8s
1263+
if helper, ok := frontend.(k8shelper.K8SControllerHelperPlugin); ok {
1264+
return helper
12591265
}
12601266
return nil
12611267
}

frontend/crd/controller/crd_controller_test.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -678,20 +678,14 @@ func TestDeleteCRHandler(t *testing.T) {
678678
// TestGetPVCGetter exercises getPVCGetter: GetFrontend(KubernetesHelper) success, error, and wrong type.
679679
func TestGetPVCGetter(t *testing.T) {
680680
ctx := context.Background()
681-
tridentNamespace := "trident"
682-
kubeClient := GetTestKubernetesClientset()
683-
snapClient := GetTestSnapshotClientset()
684-
crdClient := GetTestCrdClientset()
685681

686682
t.Run("returns_K8s_helper_when_GetFrontend_returns_it", func(t *testing.T) {
687683
mockCtrl := gomock.NewController(t)
688684
defer mockCtrl.Finish()
689685
orchestrator := mockcore.NewMockOrchestrator(mockCtrl)
690686
mockK8s := mockk8s.NewMockK8SControllerHelperPlugin(mockCtrl)
691687
orchestrator.EXPECT().GetFrontend(gomock.Any(), controllerhelpers.KubernetesHelper).Return(mockK8s, nil)
692-
controller, err := newTridentCrdControllerImpl(orchestrator, tridentNamespace, kubeClient, snapClient, crdClient, nil, nil)
693-
require.NoError(t, err)
694-
got := controller.getPVCGetter(ctx)
688+
got := getPVCGetter(ctx, orchestrator)
695689
assert.Same(t, mockK8s, got)
696690
})
697691

@@ -700,9 +694,7 @@ func TestGetPVCGetter(t *testing.T) {
700694
defer mockCtrl.Finish()
701695
orchestrator := mockcore.NewMockOrchestrator(mockCtrl)
702696
orchestrator.EXPECT().GetFrontend(gomock.Any(), controllerhelpers.KubernetesHelper).Return(nil, fmt.Errorf("not found"))
703-
controller, err := newTridentCrdControllerImpl(orchestrator, tridentNamespace, kubeClient, snapClient, crdClient, nil, nil)
704-
require.NoError(t, err)
705-
got := controller.getPVCGetter(ctx)
697+
got := getPVCGetter(ctx, orchestrator)
706698
assert.Nil(t, got)
707699
})
708700

@@ -712,9 +704,7 @@ func TestGetPVCGetter(t *testing.T) {
712704
orchestrator := mockcore.NewMockOrchestrator(mockCtrl)
713705
// Frontend is nil (e.g. not yet registered); type assertion in getPVCGetter yields nil.
714706
orchestrator.EXPECT().GetFrontend(gomock.Any(), controllerhelpers.KubernetesHelper).Return(nil, nil)
715-
controller, err := newTridentCrdControllerImpl(orchestrator, tridentNamespace, kubeClient, snapClient, crdClient, nil, nil)
716-
require.NoError(t, err)
717-
got := controller.getPVCGetter(ctx)
707+
got := getPVCGetter(ctx, orchestrator)
718708
assert.Nil(t, got)
719709
})
720710
}

frontend/crd/controller/indexers/indexers.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,27 @@ type VolumeAttachmentIndexer interface {
3434
GetCachedVolumeAttachmentsByNode(ctx context.Context, nodeName string) ([]*k8sstoragev1.VolumeAttachment, error)
3535
}
3636

37-
type k8sIndexers struct {
37+
type K8sIndexers struct {
3838
Indexer
3939
vaIndexer VolumeAttachmentIndexer
4040
}
4141

42-
func NewIndexers(kubeClient kubernetes.Interface) *k8sIndexers {
43-
indexers := &k8sIndexers{}
42+
func NewIndexers(kubeClient kubernetes.Interface) *K8sIndexers {
43+
indexers := &K8sIndexers{}
4444
indexers.vaIndexer = vaindexer.NewVolumeAttachmentIndexer(kubeClient)
4545
return indexers
4646
}
4747

4848
// Activate starts all the indexers
49-
func (k *k8sIndexers) Activate() {
49+
func (k *K8sIndexers) Activate() {
5050
k.vaIndexer.Activate()
5151
}
5252

5353
// Deactivate stops all the indexers
54-
func (k *k8sIndexers) Deactivate() {
54+
func (k *K8sIndexers) Deactivate() {
5555
k.vaIndexer.Deactivate()
5656
}
5757

58-
func (k *k8sIndexers) VolumeAttachmentIndexer() VolumeAttachmentIndexer {
58+
func (k *K8sIndexers) VolumeAttachmentIndexer() VolumeAttachmentIndexer {
5959
return k.vaIndexer
6060
}

frontend/crd/controller/indexers/indexers_test.go

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,22 @@ import (
1313
mock_indexer "github.com/netapp/trident/mocks/mock_frontend/crd/controller/indexers/indexer"
1414
)
1515

16+
func GetMockK8sIndexer(ctrl *gomock.Controller) (
17+
*K8sIndexers, *mock_indexer.MockVolumeAttachmentIndexer,
18+
) {
19+
// Create mock VolumeAttachmentIndexer
20+
mockVAIndexer := mock_indexer.NewMockVolumeAttachmentIndexer(ctrl)
21+
22+
// Create k8sIndexers with mock
23+
indexers := &K8sIndexers{
24+
vaIndexer: mockVAIndexer,
25+
}
26+
return indexers, mockVAIndexer
27+
}
28+
1629
func TestNewIndexers(t *testing.T) {
1730
// Create a fake Kubernetes client
18-
kubeClient := fake.NewSimpleClientset()
31+
kubeClient := fake.NewClientset()
1932

2033
// Test creating new indexers
2134
indexers := NewIndexers(kubeClient)
@@ -36,13 +49,8 @@ func TestK8sIndexers_Activate(t *testing.T) {
3649
ctrl := gomock.NewController(t)
3750
defer ctrl.Finish()
3851

39-
// Create mock VolumeAttachmentIndexer
40-
mockVAIndexer := mock_indexer.NewMockVolumeAttachmentIndexer(ctrl)
41-
42-
// Create k8sIndexers with mock
43-
indexers := &k8sIndexers{
44-
vaIndexer: mockVAIndexer,
45-
}
52+
// Create mock indexers
53+
indexers, mockVAIndexer := GetMockK8sIndexer(ctrl)
4654

4755
// Set expectation for Activate call
4856
mockVAIndexer.EXPECT().Activate().Times(1)
@@ -55,13 +63,8 @@ func TestK8sIndexers_Deactivate(t *testing.T) {
5563
ctrl := gomock.NewController(t)
5664
defer ctrl.Finish()
5765

58-
// Create mock VolumeAttachmentIndexer
59-
mockVAIndexer := mock_indexer.NewMockVolumeAttachmentIndexer(ctrl)
60-
61-
// Create k8sIndexers with mock
62-
indexers := &k8sIndexers{
63-
vaIndexer: mockVAIndexer,
64-
}
66+
// Create mock indexers
67+
indexers, mockVAIndexer := GetMockK8sIndexer(ctrl)
6568

6669
// Set expectation for Deactivate call
6770
mockVAIndexer.EXPECT().Deactivate().Times(1)
@@ -74,13 +77,8 @@ func TestK8sIndexers_VolumeAttachmentIndexer(t *testing.T) {
7477
ctrl := gomock.NewController(t)
7578
defer ctrl.Finish()
7679

77-
// Create mock VolumeAttachmentIndexer
78-
mockVAIndexer := mock_indexer.NewMockVolumeAttachmentIndexer(ctrl)
79-
80-
// Create k8sIndexers with mock
81-
indexers := &k8sIndexers{
82-
vaIndexer: mockVAIndexer,
83-
}
80+
// Create mock indexers
81+
indexers, mockVAIndexer := GetMockK8sIndexer(ctrl)
8482

8583
// Test VolumeAttachmentIndexer returns correct indexer
8684
result := indexers.VolumeAttachmentIndexer()

frontend/crd/controller/indexers/vaindexer/vaindexer.go

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
// Indexer keys
1818
const vaByNodeIndex = "vaByNode"
1919

20-
type vaIndexer struct {
20+
type VaIndexer struct {
2121
// Volume Attachment Indexer
2222
vaIndexer cache.Indexer
2323
vaController cache.SharedIndexInformer
@@ -26,8 +26,8 @@ type vaIndexer struct {
2626
vaSynced cache.InformerSynced
2727
}
2828

29-
func NewVolumeAttachmentIndexer(kubeClient kubernetes.Interface) *vaIndexer {
30-
va := &vaIndexer{}
29+
func NewVolumeAttachmentIndexer(kubeClient kubernetes.Interface) *VaIndexer {
30+
va := &VaIndexer{}
3131

3232
// Init stop channels
3333
va.vaControllerStopChan = make(chan struct{})
@@ -40,7 +40,7 @@ func NewVolumeAttachmentIndexer(kubeClient kubernetes.Interface) *vaIndexer {
4040
fields.Everything(),
4141
)
4242

43-
// Set cachSyncPeriod to 0 to disable resync. This is to avoid scaling concens with large number of VAs.
43+
// Set cacheSyncPeriod to 0 to disable resync. This is to avoid scaling concerns with large number of VAs.
4444
const cacheSyncPeriod = 0
4545

4646
// Set up the VolumeAttachments indexing controller
@@ -55,21 +55,21 @@ func NewVolumeAttachmentIndexer(kubeClient kubernetes.Interface) *vaIndexer {
5555
return va
5656
}
5757

58-
func (v *vaIndexer) Activate() {
58+
func (v *VaIndexer) Activate() {
5959
go v.vaController.Run(v.vaControllerStopChan)
6060
}
6161

62-
func (v *vaIndexer) Deactivate() {
62+
func (v *VaIndexer) Deactivate() {
6363
close(v.vaControllerStopChan)
6464
}
6565

66-
// getCachedVolumeAttachmentsByNode returns a VA list from the client's cache, or an error if not found.
67-
func (v *vaIndexer) GetCachedVolumeAttachmentsByNode(
66+
// GetCachedVolumeAttachmentsByNode returns a VA list for a node from the client's cache.
67+
func (v *VaIndexer) GetCachedVolumeAttachmentsByNode(
6868
ctx context.Context, nodeName string,
6969
) ([]*k8sstoragev1.VolumeAttachment, error) {
7070
logFields := LogFields{"nodeName": nodeName}
71-
Logc(ctx).WithFields(logFields).Trace(">>>> getCachedVolumeAttachmentsByNode")
72-
defer Logc(ctx).Trace("<<<< getCachedVolumeAttachmentsByNode")
71+
Logc(ctx).WithFields(logFields).Trace(">>>> GetCachedVolumeAttachmentsByNode")
72+
defer Logc(ctx).Trace("<<<< GetCachedVolumeAttachmentsByNode")
7373

7474
items, err := v.vaIndexer.ByIndex(vaByNodeIndex, nodeName)
7575
if err != nil {
@@ -94,14 +94,12 @@ func (v *vaIndexer) GetCachedVolumeAttachmentsByNode(
9494
return attachments, nil
9595
}
9696

97-
func (v *vaIndexer) WaitForCacheSync(ctx context.Context) bool {
98-
successful := true
99-
if ok := cache.WaitForCacheSync(v.vaControllerStopChan, v.vaSynced); !ok {
100-
successful = false
101-
err := fmt.Errorf("failed to wait for vaController cache to sync")
102-
Logc(ctx).Errorf("Error: %v", err)
97+
func (v *VaIndexer) WaitForCacheSync(ctx context.Context) bool {
98+
var ok bool
99+
if ok = cache.WaitForCacheSync(v.vaControllerStopChan, v.vaSynced); !ok {
100+
Logc(ctx).Errorf("failed to wait for vaController cache to sync")
103101
}
104-
return successful
102+
return ok
105103
}
106104

107105
// volumeAttachmentsByNodeKeyFunc is a indexer KeyFunc which knows how to make keys for VolumeAttachment by node.

frontend/crd/controller/trident_autogrow_request_internal.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ func (c *TridentCrdController) getPVCForVolume(ctx context.Context, volExternal
907907
return nil, fmt.Errorf("invalid volume name")
908908
}
909909

910-
getter := c.getPVCGetter(ctx)
910+
getter := getPVCGetter(ctx, c.orchestrator)
911911
if getter != nil {
912912
pvc, err := getter.GetPVCForPV(ctx, volumeName)
913913
if err == nil {

frontend/crd/controller/trident_node_remediation.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,8 @@ func (c *TridentCrdController) failoverDetach(
313313
return err
314314
}
315315

316-
pvcToTvolMap, err := c.nodeRemediationUtils.GetPvcToTvolMap(ctx, nodeName)
317-
if err != nil {
318-
Logc(ctx).WithError(err).Error("Failed to get PVC to Tvol map.")
319-
return err
320-
}
316+
nodePvcs := c.nodeRemediationUtils.GetPvcsForPods(ctx, nodePods)
317+
pvcToTvolMap := c.nodeRemediationUtils.GetPvcToTvolMap(ctx, nodePvcs)
321318

322319
// Get pods to delete
323320
Logc(ctx).WithField("node", nodeName).Info("Finding pods to remove from failed node.")

0 commit comments

Comments
 (0)