mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 02:09:56 +00:00
check usage when VolumeCondition is not supported
The Usage and VolumeCondition are both optional in the response and kubelet need to consider returning metrics if either one is set.
This commit is contained in:
parent
de6db3ffb0
commit
d644860cfb
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user