Merge pull request #127021 from Madhu-1/fix-volume-abnormal

check for usage when volume is normal
This commit is contained in:
Kubernetes Prow Robot 2024-09-03 16:55:16 +01:00 committed by GitHub
commit 49ccfaf1ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 80 additions and 32 deletions

View File

@ -612,10 +612,7 @@ func (c *csiDriverClient) NodeGetVolumeStats(ctx context.Context, volID string,
if err != nil { if err != nil {
return nil, err return nil, err
} }
usages := resp.GetUsage()
if usages == nil {
return nil, fmt.Errorf("failed to get usage from response. usage is nil")
}
metrics := &volume.Metrics{ metrics := &volume.Metrics{
Used: resource.NewQuantity(int64(0), resource.BinarySI), Used: resource.NewQuantity(int64(0), resource.BinarySI),
Capacity: resource.NewQuantity(int64(0), resource.BinarySI), Capacity: resource.NewQuantity(int64(0), resource.BinarySI),
@ -625,8 +622,9 @@ func (c *csiDriverClient) NodeGetVolumeStats(ctx context.Context, volID string,
InodesFree: resource.NewQuantity(int64(0), resource.BinarySI), InodesFree: resource.NewQuantity(int64(0), resource.BinarySI),
} }
var isSupportNodeVolumeCondition bool
if utilfeature.DefaultFeatureGate.Enabled(features.CSIVolumeHealth) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIVolumeHealth) {
isSupportNodeVolumeCondition, err := c.nodeSupportsVolumeCondition(ctx) isSupportNodeVolumeCondition, err = c.nodeSupportsVolumeCondition(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -637,6 +635,12 @@ func (c *csiDriverClient) NodeGetVolumeStats(ctx context.Context, volID string,
} }
} }
usages := resp.GetUsage()
// If the driver does not support volume condition and usages is nil, return an error
if !isSupportNodeVolumeCondition && usages == nil {
return nil, fmt.Errorf("failed to get usage from response. usage is nil")
}
for _, usage := range usages { for _, usage := range usages {
if usage == nil { if usage == nil {
continue continue

View File

@ -66,10 +66,10 @@ func newFakeCsiDriverClientWithVolumeStats(t *testing.T, volumeStatsSet bool) *f
} }
} }
func newFakeCsiDriverClientWithVolumeStatsAndCondition(t *testing.T, volumeStatsSet, volumeConditionSet bool) *fakeCsiDriverClient { func newFakeCsiDriverClientWithVolumeStatsAndCondition(t *testing.T, volumeStatsSet, volumeConditionSet, setVolumeStat, setVolumeCondition bool) *fakeCsiDriverClient {
return &fakeCsiDriverClient{ return &fakeCsiDriverClient{
t: t, t: t,
nodeClient: fake.NewNodeClientWithVolumeStatsAndCondition(volumeStatsSet, volumeConditionSet), nodeClient: fake.NewNodeClientWithVolumeStatsAndCondition(volumeStatsSet, volumeConditionSet, setVolumeStat, setVolumeCondition),
} }
} }
@ -100,18 +100,23 @@ func (c *fakeCsiDriverClient) NodeGetVolumeStats(ctx context.Context, volID stri
VolumeId: volID, VolumeId: volID,
VolumePath: targetPath, VolumePath: targetPath,
} }
fakeResp := &csipbv1.NodeGetVolumeStatsResponse{}
if c.nodeClient.SetVolumeStats {
fakeResp = getRawVolumeInfo()
}
if c.nodeClient.SetVolumecondition {
fakeResp.VolumeCondition = &csipbv1.VolumeCondition{
Abnormal: true,
Message: "Volume is abnormal",
}
}
c.nodeClient.SetNodeVolumeStatsResp(fakeResp)
c.nodeClient.SetNodeVolumeStatsResp(getRawVolumeInfo())
resp, err := c.nodeClient.NodeGetVolumeStats(ctx, req) resp, err := c.nodeClient.NodeGetVolumeStats(ctx, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
usages := resp.GetUsage()
if usages == nil {
return nil, nil
}
metrics := &volume.Metrics{} metrics := &volume.Metrics{}
isSupportNodeVolumeCondition, err := c.nodeSupportsVolumeCondition(ctx) isSupportNodeVolumeCondition, err := c.nodeSupportsVolumeCondition(ctx)
@ -124,6 +129,10 @@ func (c *fakeCsiDriverClient) NodeGetVolumeStats(ctx context.Context, volID stri
metrics.Abnormal, metrics.Message = &abnormal, &message metrics.Abnormal, metrics.Message = &abnormal, &message
} }
usages := resp.GetUsage()
if !isSupportNodeVolumeCondition && usages == nil {
return nil, errors.New("volume usage is nil")
}
for _, usage := range usages { for _, usage := range usages {
if usage == nil { if usage == nil {
continue continue
@ -377,8 +386,8 @@ func setupClientWithExpansion(t *testing.T, stageUnstageSet bool, expansionSet b
return newFakeCsiDriverClientWithExpansion(t, stageUnstageSet, expansionSet) return newFakeCsiDriverClientWithExpansion(t, stageUnstageSet, expansionSet)
} }
func setupClientWithVolumeStatsAndCondition(t *testing.T, volumeStatsSet, volumeConditionSet bool) csiClient { func setupClientWithVolumeStatsAndCondition(t *testing.T, volumeStatsSet, volumeConditionSet, setVolumeStat, setVolumecondition bool) csiClient {
return newFakeCsiDriverClientWithVolumeStatsAndCondition(t, volumeStatsSet, volumeConditionSet) return newFakeCsiDriverClientWithVolumeStatsAndCondition(t, volumeStatsSet, volumeConditionSet, setVolumeStat, setVolumecondition)
} }
func setupClientWithVolumeStats(t *testing.T, volumeStatsSet bool) csiClient { func setupClientWithVolumeStats(t *testing.T, volumeStatsSet bool) csiClient {
@ -839,13 +848,17 @@ func TestVolumeHealthEnable(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
volumeStatsSet bool volumeStatsSet bool
setVolumeStat bool
setVolumecondition bool
volumeConditionSet bool volumeConditionSet bool
volumeData VolumeStatsOptions volumeData VolumeStatsOptions
success bool success bool
}{ }{
{ {
name: "when nodeVolumeStats=on, VolumeID=on, DeviceMountPath=on, VolumeCondition=on", name: "when nodeVolumeStats=on, volumeStatsSet=on, setVolumeStat=on, volumeCondition=on, setVolumecondition=on",
volumeStatsSet: true, volumeStatsSet: true,
setVolumeStat: true,
setVolumecondition: true,
volumeConditionSet: true, volumeConditionSet: true,
volumeData: VolumeStatsOptions{ volumeData: VolumeStatsOptions{
VolumeSpec: spec, VolumeSpec: spec,
@ -855,8 +868,10 @@ func TestVolumeHealthEnable(t *testing.T) {
success: true, success: true,
}, },
{ {
name: "when nodeVolumeStats=on, VolumeID=on, DeviceMountPath=on, VolumeCondition=off", name: "when nodeVolumeStats=on, volumeStatsSet=on, setVolumeStat=on, volumeCondition=off, setVolumecondition=off",
volumeStatsSet: true, volumeStatsSet: true,
setVolumeStat: true,
setVolumecondition: false,
volumeConditionSet: false, volumeConditionSet: false,
volumeData: VolumeStatsOptions{ volumeData: VolumeStatsOptions{
VolumeSpec: spec, VolumeSpec: spec,
@ -865,6 +880,30 @@ func TestVolumeHealthEnable(t *testing.T) {
}, },
success: true, success: true,
}, },
{
name: "when nodeVolumeStats=on, volumeStatsSet=off, setVolumeStat=off, volumeCondition=on, setVolumecondition=on",
volumeStatsSet: false,
setVolumeStat: false,
setVolumecondition: true,
volumeConditionSet: true,
volumeData: VolumeStatsOptions{
VolumeSpec: spec,
VolumeID: "volume1",
DeviceMountPath: "/foo/bar",
},
success: true,
},
{
name: "when nodeVolumeStats=on, volumeStatsSet=off, setVolumeStat=off, volumeCondition=off, setVolumecondition=off",
setVolumeStat: false,
volumeConditionSet: false,
volumeData: VolumeStatsOptions{
VolumeSpec: spec,
VolumeID: "volume1",
DeviceMountPath: "/foo/bar",
},
success: false,
},
} }
for _, tc := range tests { for _, tc := range tests {
@ -872,24 +911,24 @@ func TestVolumeHealthEnable(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) ctx, cancel := context.WithTimeout(context.Background(), csiTimeout)
defer cancel() defer cancel()
csiSource, _ := getCSISourceFromSpec(tc.volumeData.VolumeSpec) csiSource, _ := getCSISourceFromSpec(tc.volumeData.VolumeSpec)
csClient := setupClientWithVolumeStatsAndCondition(t, tc.volumeStatsSet, tc.volumeConditionSet) csClient := setupClientWithVolumeStatsAndCondition(t, tc.volumeStatsSet, tc.volumeConditionSet, tc.setVolumeStat, tc.setVolumecondition)
metrics, err := csClient.NodeGetVolumeStats(ctx, csiSource.VolumeHandle, tc.volumeData.DeviceMountPath) metrics, err := csClient.NodeGetVolumeStats(ctx, csiSource.VolumeHandle, tc.volumeData.DeviceMountPath)
if tc.success { if err != nil && tc.success {
assert.Nil(t, err) t.Errorf("For %s : expected %v got %v", tc.name, tc.success, err)
} }
if tc.success {
if metrics == nil { if metrics == nil {
t.Errorf("csi.NodeGetVolumeStats returned nil metrics for volume %s", tc.volumeData.VolumeID) t.Errorf("csi.NodeGetVolumeStats returned nil metrics for volume %s", tc.volumeData.VolumeID)
} else {
if tc.volumeConditionSet {
assert.NotNil(t, metrics.Abnormal)
assert.NotNil(t, metrics.Message)
} else { } else {
assert.Nil(t, metrics.Abnormal) if tc.volumeConditionSet {
assert.Nil(t, metrics.Message) assert.NotNil(t, metrics.Abnormal)
assert.NotNil(t, metrics.Message)
} else {
assert.Nil(t, metrics.Abnormal)
assert.Nil(t, metrics.Message)
}
} }
} }
}) })
} }
} }
@ -919,7 +958,7 @@ func TestVolumeHealthDisable(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), csiTimeout) ctx, cancel := context.WithTimeout(context.Background(), csiTimeout)
defer cancel() defer cancel()
csiSource, _ := getCSISourceFromSpec(tc.volumeData.VolumeSpec) csiSource, _ := getCSISourceFromSpec(tc.volumeData.VolumeSpec)
csClient := setupClientWithVolumeStatsAndCondition(t, tc.volumeStatsSet, false) csClient := setupClientWithVolumeStatsAndCondition(t, tc.volumeStatsSet, false, true, false)
metrics, err := csClient.NodeGetVolumeStats(ctx, csiSource.VolumeHandle, tc.volumeData.DeviceMountPath) metrics, err := csClient.NodeGetVolumeStats(ctx, csiSource.VolumeHandle, tc.volumeData.DeviceMountPath)
if tc.success { if tc.success {
assert.Nil(t, err) assert.Nil(t, err)

View File

@ -80,6 +80,8 @@ type NodeClient struct {
expansionSet bool expansionSet bool
volumeStatsSet bool volumeStatsSet bool
volumeConditionSet bool volumeConditionSet bool
SetVolumeStats bool
SetVolumecondition bool
singleNodeMultiWriterSet bool singleNodeMultiWriterSet bool
volumeMountGroupSet bool volumeMountGroupSet bool
nodeGetInfoResp *csipb.NodeGetInfoResponse nodeGetInfoResp *csipb.NodeGetInfoResponse
@ -110,13 +112,16 @@ func NewNodeClientWithExpansion(stageUnstageSet bool, expansionSet bool) *NodeCl
func NewNodeClientWithVolumeStats(volumeStatsSet bool) *NodeClient { func NewNodeClientWithVolumeStats(volumeStatsSet bool) *NodeClient {
return &NodeClient{ return &NodeClient{
volumeStatsSet: volumeStatsSet, volumeStatsSet: volumeStatsSet,
SetVolumeStats: true,
} }
} }
func NewNodeClientWithVolumeStatsAndCondition(volumeStatsSet, volumeConditionSet bool) *NodeClient { func NewNodeClientWithVolumeStatsAndCondition(volumeStatsSet, volumeConditionSet, setVolumeStats, setVolumeCondition bool) *NodeClient {
return &NodeClient{ return &NodeClient{
volumeStatsSet: volumeStatsSet, volumeStatsSet: volumeStatsSet,
volumeConditionSet: volumeConditionSet, volumeConditionSet: volumeConditionSet,
SetVolumeStats: setVolumeStats,
SetVolumecondition: setVolumeCondition,
} }
} }