mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +00:00
Add extra fields in node expansion CSI call
This commit is contained in:
parent
c53ce48d48
commit
7d6959ce2c
@ -54,7 +54,7 @@ type csiClient interface {
|
|||||||
fsType string,
|
fsType string,
|
||||||
mountOptions []string,
|
mountOptions []string,
|
||||||
) error
|
) error
|
||||||
NodeExpandVolume(ctx context.Context, volumeid, volumePath string, newSize resource.Quantity) (resource.Quantity, error)
|
NodeExpandVolume(ctx context.Context, rsOpts csiResizeOptions) (resource.Quantity, error)
|
||||||
NodeUnpublishVolume(
|
NodeUnpublishVolume(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
volID string,
|
volID string,
|
||||||
@ -95,6 +95,16 @@ type csiDriverClient struct {
|
|||||||
nodeV1ClientCreator nodeV1ClientCreator
|
nodeV1ClientCreator nodeV1ClientCreator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type csiResizeOptions struct {
|
||||||
|
volumeid string
|
||||||
|
volumePath string
|
||||||
|
stagingTargetPath string
|
||||||
|
fsType string
|
||||||
|
accessMode api.PersistentVolumeAccessMode
|
||||||
|
newSize resource.Quantity
|
||||||
|
mountOptions []string
|
||||||
|
}
|
||||||
|
|
||||||
var _ csiClient = &csiDriverClient{}
|
var _ csiClient = &csiDriverClient{}
|
||||||
|
|
||||||
type nodeV1ClientCreator func(addr csiAddr) (
|
type nodeV1ClientCreator func(addr csiAddr) (
|
||||||
@ -245,36 +255,55 @@ func (c *csiDriverClient) NodePublishVolume(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *csiDriverClient) NodeExpandVolume(ctx context.Context, volumeID, volumePath string, newSize resource.Quantity) (resource.Quantity, error) {
|
func (c *csiDriverClient) NodeExpandVolume(ctx context.Context, opts csiResizeOptions) (resource.Quantity, error) {
|
||||||
if c.nodeV1ClientCreator == nil {
|
if c.nodeV1ClientCreator == nil {
|
||||||
return newSize, fmt.Errorf("version of CSI driver does not support volume expansion")
|
return opts.newSize, fmt.Errorf("version of CSI driver does not support volume expansion")
|
||||||
}
|
}
|
||||||
|
|
||||||
if volumeID == "" {
|
if opts.volumeid == "" {
|
||||||
return newSize, errors.New("missing volume id")
|
return opts.newSize, errors.New("missing volume id")
|
||||||
}
|
}
|
||||||
if volumePath == "" {
|
if opts.volumeid == "" {
|
||||||
return newSize, errors.New("missing volume path")
|
return opts.newSize, errors.New("missing volume path")
|
||||||
}
|
}
|
||||||
|
|
||||||
if newSize.Value() < 0 {
|
if opts.newSize.Value() < 0 {
|
||||||
return newSize, errors.New("size can not be less than 0")
|
return opts.newSize, errors.New("size can not be less than 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeClient, closer, err := c.nodeV1ClientCreator(c.addr)
|
nodeClient, closer, err := c.nodeV1ClientCreator(c.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newSize, err
|
return opts.newSize, err
|
||||||
}
|
}
|
||||||
defer closer.Close()
|
defer closer.Close()
|
||||||
|
|
||||||
req := &csipbv1.NodeExpandVolumeRequest{
|
req := &csipbv1.NodeExpandVolumeRequest{
|
||||||
VolumeId: volumeID,
|
VolumeId: opts.volumeid,
|
||||||
VolumePath: volumePath,
|
VolumePath: opts.volumePath,
|
||||||
CapacityRange: &csipbv1.CapacityRange{RequiredBytes: newSize.Value()},
|
StagingTargetPath: opts.stagingTargetPath,
|
||||||
|
CapacityRange: &csipbv1.CapacityRange{RequiredBytes: opts.newSize.Value()},
|
||||||
|
VolumeCapability: &csipbv1.VolumeCapability{
|
||||||
|
AccessMode: &csipbv1.VolumeCapability_AccessMode{
|
||||||
|
Mode: asCSIAccessModeV1(opts.accessMode),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
if opts.fsType == fsTypeBlockName {
|
||||||
|
req.VolumeCapability.AccessType = &csipbv1.VolumeCapability_Block{
|
||||||
|
Block: &csipbv1.VolumeCapability_BlockVolume{},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
req.VolumeCapability.AccessType = &csipbv1.VolumeCapability_Mount{
|
||||||
|
Mount: &csipbv1.VolumeCapability_MountVolume{
|
||||||
|
FsType: opts.fsType,
|
||||||
|
MountFlags: opts.mountOptions,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := nodeClient.NodeExpandVolume(ctx, req)
|
resp, err := nodeClient.NodeExpandVolume(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newSize, err
|
return opts.newSize, err
|
||||||
}
|
}
|
||||||
updatedQuantity := resource.NewQuantity(resp.CapacityBytes, resource.BinarySI)
|
updatedQuantity := resource.NewQuantity(resp.CapacityBytes, resource.BinarySI)
|
||||||
return *updatedQuantity, nil
|
return *updatedQuantity, nil
|
||||||
|
@ -284,16 +284,34 @@ func (c *fakeCsiDriverClient) NodeSupportsStageUnstage(ctx context.Context) (boo
|
|||||||
return stageUnstageSet, nil
|
return stageUnstageSet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeCsiDriverClient) NodeExpandVolume(ctx context.Context, volumeid, volumePath string, newSize resource.Quantity) (resource.Quantity, error) {
|
func (c *fakeCsiDriverClient) NodeExpandVolume(ctx context.Context, opts csiResizeOptions) (resource.Quantity, error) {
|
||||||
c.t.Log("calling fake.NodeExpandVolume")
|
c.t.Log("calling fake.NodeExpandVolume")
|
||||||
req := &csipbv1.NodeExpandVolumeRequest{
|
req := &csipbv1.NodeExpandVolumeRequest{
|
||||||
VolumeId: volumeid,
|
VolumeId: opts.volumeid,
|
||||||
VolumePath: volumePath,
|
VolumePath: opts.volumePath,
|
||||||
CapacityRange: &csipbv1.CapacityRange{RequiredBytes: newSize.Value()},
|
StagingTargetPath: opts.stagingTargetPath,
|
||||||
|
CapacityRange: &csipbv1.CapacityRange{RequiredBytes: opts.newSize.Value()},
|
||||||
|
VolumeCapability: &csipbv1.VolumeCapability{
|
||||||
|
AccessMode: &csipbv1.VolumeCapability_AccessMode{
|
||||||
|
Mode: asCSIAccessModeV1(opts.accessMode),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if opts.fsType == fsTypeBlockName {
|
||||||
|
req.VolumeCapability.AccessType = &csipbv1.VolumeCapability_Block{
|
||||||
|
Block: &csipbv1.VolumeCapability_BlockVolume{},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
req.VolumeCapability.AccessType = &csipbv1.VolumeCapability_Mount{
|
||||||
|
Mount: &csipbv1.VolumeCapability_MountVolume{
|
||||||
|
FsType: opts.fsType,
|
||||||
|
MountFlags: opts.mountOptions,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resp, err := c.nodeClient.NodeExpandVolume(ctx, req)
|
resp, err := c.nodeClient.NodeExpandVolume(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newSize, err
|
return opts.newSize, err
|
||||||
}
|
}
|
||||||
updatedQuantity := resource.NewQuantity(resp.CapacityBytes, resource.BinarySI)
|
updatedQuantity := resource.NewQuantity(resp.CapacityBytes, resource.BinarySI)
|
||||||
return *updatedQuantity, nil
|
return *updatedQuantity, nil
|
||||||
@ -635,7 +653,8 @@ func TestNodeExpandVolume(t *testing.T) {
|
|||||||
return nodeClient, fakeCloser, nil
|
return nodeClient, fakeCloser, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := client.NodeExpandVolume(context.Background(), tc.volID, tc.volumePath, tc.newSize)
|
opts := csiResizeOptions{volumeid: tc.volID, volumePath: tc.volumePath, newSize: tc.newSize}
|
||||||
|
_, err := client.NodeExpandVolume(context.Background(), opts)
|
||||||
checkErr(t, tc.mustFail, err)
|
checkErr(t, tc.mustFail, err)
|
||||||
if !tc.mustFail {
|
if !tc.mustFail {
|
||||||
fakeCloser.Check()
|
fakeCloser.Check()
|
||||||
|
@ -94,12 +94,30 @@ func (c *csiPlugin) nodeExpandWithClient(
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
volumeTargetPath := resizeOptions.DeviceMountPath
|
pv := resizeOptions.VolumeSpec.PersistentVolume
|
||||||
if !fsVolume {
|
if pv == nil {
|
||||||
volumeTargetPath = resizeOptions.DevicePath
|
return false, fmt.Errorf("Expander.NodeExpand failed to find associated PersistentVolume for plugin %s", c.GetPluginName())
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = csClient.NodeExpandVolume(ctx, csiSource.VolumeHandle, volumeTargetPath, resizeOptions.NewSize)
|
opts := csiResizeOptions{
|
||||||
|
volumePath: resizeOptions.DeviceMountPath,
|
||||||
|
stagingTargetPath: resizeOptions.DeviceStagePath,
|
||||||
|
volumeid: csiSource.VolumeHandle,
|
||||||
|
newSize: resizeOptions.NewSize,
|
||||||
|
fsType: csiSource.FSType,
|
||||||
|
accessMode: api.ReadWriteOnce,
|
||||||
|
mountOptions: pv.Spec.MountOptions,
|
||||||
|
}
|
||||||
|
if !fsVolume {
|
||||||
|
opts.volumePath = resizeOptions.DevicePath
|
||||||
|
opts.fsType = fsTypeBlockName
|
||||||
|
}
|
||||||
|
|
||||||
|
if pv.Spec.AccessModes != nil {
|
||||||
|
opts.accessMode = pv.Spec.AccessModes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = csClient.NodeExpandVolume(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("Expander.NodeExpand failed to expand the volume : %v", err)
|
return false, fmt.Errorf("Expander.NodeExpand failed to expand the volume : %v", err)
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ func TestNodeExpand(t *testing.T) {
|
|||||||
volumePhase volume.CSIVolumePhaseType
|
volumePhase volume.CSIVolumePhaseType
|
||||||
success bool
|
success bool
|
||||||
fsVolume bool
|
fsVolume bool
|
||||||
|
deviceStagePath string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "when node expansion is not set",
|
name: "when node expansion is not set",
|
||||||
@ -44,6 +45,7 @@ func TestNodeExpand(t *testing.T) {
|
|||||||
volumePhase: volume.CSIVolumeStaged,
|
volumePhase: volume.CSIVolumeStaged,
|
||||||
success: true,
|
success: true,
|
||||||
fsVolume: true,
|
fsVolume: true,
|
||||||
|
deviceStagePath: "/foo/bar",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "when nodeExpansion=on, nodeStage=off, volumePhase=staged",
|
name: "when nodeExpansion=on, nodeStage=off, volumePhase=staged",
|
||||||
@ -88,21 +90,42 @@ func TestNodeExpand(t *testing.T) {
|
|||||||
VolumeSpec: spec,
|
VolumeSpec: spec,
|
||||||
NewSize: newSize,
|
NewSize: newSize,
|
||||||
DeviceMountPath: "/foo/bar",
|
DeviceMountPath: "/foo/bar",
|
||||||
|
DeviceStagePath: "/foo/bar",
|
||||||
DevicePath: "/mnt/foobar",
|
DevicePath: "/mnt/foobar",
|
||||||
CSIVolumePhase: tc.volumePhase,
|
CSIVolumePhase: tc.volumePhase,
|
||||||
}
|
}
|
||||||
csiSource, _ := getCSISourceFromSpec(resizeOptions.VolumeSpec)
|
csiSource, _ := getCSISourceFromSpec(resizeOptions.VolumeSpec)
|
||||||
|
|
||||||
csClient := setupClientWithExpansion(t, tc.nodeStageSet, tc.nodeExpansion)
|
csClient := setupClientWithExpansion(t, tc.nodeStageSet, tc.nodeExpansion)
|
||||||
|
|
||||||
|
fakeCSIClient, _ := csClient.(*fakeCsiDriverClient)
|
||||||
|
fakeNodeClient := fakeCSIClient.nodeClient
|
||||||
ok, err := plug.nodeExpandWithClient(resizeOptions, csiSource, csClient, tc.fsVolume)
|
ok, err := plug.nodeExpandWithClient(resizeOptions, csiSource, csClient, tc.fsVolume)
|
||||||
|
|
||||||
|
// verify device staging targer path
|
||||||
|
stagingTargetPath := fakeNodeClient.FakeNodeExpansionRequest.GetStagingTargetPath()
|
||||||
|
if tc.deviceStagePath != "" && tc.deviceStagePath != stagingTargetPath {
|
||||||
|
t.Errorf("For %s: expected staging path %s got %s", tc.name, tc.deviceStagePath, stagingTargetPath)
|
||||||
|
}
|
||||||
|
|
||||||
if ok != tc.success {
|
if ok != tc.success {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("For %s : expected %v got %v with %v", tc.name, tc.success, ok, err)
|
t.Errorf("For %s : expected %v got %v with %v", tc.name, tc.success, ok, err)
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("For %s : expected %v got %v", tc.name, tc.success, ok)
|
t.Errorf("For %s : expected %v got %v", tc.name, tc.success, ok)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// verify volume capability received by node expansion request
|
||||||
|
if tc.success {
|
||||||
|
capability := fakeNodeClient.FakeNodeExpansionRequest.GetVolumeCapability()
|
||||||
|
if tc.fsVolume {
|
||||||
|
if capability.GetMount() == nil {
|
||||||
|
t.Errorf("For %s: expected mount accesstype got: %v", tc.name, capability)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if capability.GetBlock() == nil {
|
||||||
|
t.Errorf("For %s: expected block accesstype got: %v", tc.name, capability)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,7 @@ type NodeClient struct {
|
|||||||
volumeStatsSet bool
|
volumeStatsSet bool
|
||||||
nodeGetInfoResp *csipb.NodeGetInfoResponse
|
nodeGetInfoResp *csipb.NodeGetInfoResponse
|
||||||
nodeVolumeStatsResp *csipb.NodeGetVolumeStatsResponse
|
nodeVolumeStatsResp *csipb.NodeGetVolumeStatsResponse
|
||||||
|
FakeNodeExpansionRequest *csipb.NodeExpandVolumeRequest
|
||||||
nextErr error
|
nextErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,6 +297,8 @@ func (f *NodeClient) NodeExpandVolume(ctx context.Context, req *csipb.NodeExpand
|
|||||||
return nil, errors.New("required bytes should be greater than 0")
|
return nil, errors.New("required bytes should be greater than 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.FakeNodeExpansionRequest = req
|
||||||
|
|
||||||
resp := &csipb.NodeExpandVolumeResponse{
|
resp := &csipb.NodeExpandVolumeResponse{
|
||||||
CapacityBytes: req.GetCapacityRange().RequiredBytes,
|
CapacityBytes: req.GetCapacityRange().RequiredBytes,
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,9 @@ type NodeResizeOptions struct {
|
|||||||
// it would be location where volume was mounted for the pod
|
// it would be location where volume was mounted for the pod
|
||||||
DeviceMountPath string
|
DeviceMountPath string
|
||||||
|
|
||||||
|
// DeviceStagingPath stores location where the volume is staged
|
||||||
|
DeviceStagePath string
|
||||||
|
|
||||||
NewSize resource.Quantity
|
NewSize resource.Quantity
|
||||||
OldSize resource.Quantity
|
OldSize resource.Quantity
|
||||||
|
|
||||||
|
@ -604,6 +604,7 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
resizeOptions.DeviceMountPath = deviceMountPath
|
resizeOptions.DeviceMountPath = deviceMountPath
|
||||||
|
resizeOptions.DeviceStagePath = deviceMountPath
|
||||||
resizeOptions.CSIVolumePhase = volume.CSIVolumeStaged
|
resizeOptions.CSIVolumePhase = volume.CSIVolumeStaged
|
||||||
|
|
||||||
// NodeExpandVolume will resize the file system if user has requested a resize of
|
// NodeExpandVolume will resize the file system if user has requested a resize of
|
||||||
@ -1505,6 +1506,7 @@ func (og *operationGenerator) GenerateExpandInUseVolumeFunc(
|
|||||||
return volumeToMount.GenerateError("NodeExpandVolume.GetDeviceMountPath failed", err)
|
return volumeToMount.GenerateError("NodeExpandVolume.GetDeviceMountPath failed", err)
|
||||||
}
|
}
|
||||||
resizeOptions.DeviceMountPath = dmp
|
resizeOptions.DeviceMountPath = dmp
|
||||||
|
resizeOptions.DeviceStagePath = dmp
|
||||||
resizeDone, simpleErr, detailedErr = og.doOnlineExpansion(volumeToMount, actualStateOfWorld, resizeOptions)
|
resizeDone, simpleErr, detailedErr = og.doOnlineExpansion(volumeToMount, actualStateOfWorld, resizeOptions)
|
||||||
if simpleErr != nil || detailedErr != nil {
|
if simpleErr != nil || detailedErr != nil {
|
||||||
return simpleErr, detailedErr
|
return simpleErr, detailedErr
|
||||||
|
Loading…
Reference in New Issue
Block a user