mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Ensure that StagingPath is supplied to blockVolume expansion
This commit is contained in:
parent
69613da0ae
commit
6342dad709
@ -107,9 +107,9 @@ func (m *csiBlockMapper) GetGlobalMapPath(spec *volume.Spec) (string, error) {
|
|||||||
return dir, nil
|
return dir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getStagingPath returns a staging path for a directory (on the node) that should be used on NodeStageVolume/NodeUnstageVolume
|
// GetStagingPath returns a staging path for a directory (on the node) that should be used on NodeStageVolume/NodeUnstageVolume
|
||||||
// Example: plugins/kubernetes.io/csi/volumeDevices/staging/{specName}
|
// Example: plugins/kubernetes.io/csi/volumeDevices/staging/{specName}
|
||||||
func (m *csiBlockMapper) getStagingPath() string {
|
func (m *csiBlockMapper) GetStagingPath() string {
|
||||||
return filepath.Join(m.plugin.host.GetVolumeDevicePluginDir(CSIPluginName), "staging", m.specName)
|
return filepath.Join(m.plugin.host.GetVolumeDevicePluginDir(CSIPluginName), "staging", m.specName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ func (m *csiBlockMapper) stageVolumeForBlock(
|
|||||||
) (string, error) {
|
) (string, error) {
|
||||||
klog.V(4).Infof(log("blockMapper.stageVolumeForBlock called"))
|
klog.V(4).Infof(log("blockMapper.stageVolumeForBlock called"))
|
||||||
|
|
||||||
stagingPath := m.getStagingPath()
|
stagingPath := m.GetStagingPath()
|
||||||
klog.V(4).Infof(log("blockMapper.stageVolumeForBlock stagingPath set [%s]", stagingPath))
|
klog.V(4).Infof(log("blockMapper.stageVolumeForBlock stagingPath set [%s]", stagingPath))
|
||||||
|
|
||||||
// Check whether "STAGE_UNSTAGE_VOLUME" is set
|
// Check whether "STAGE_UNSTAGE_VOLUME" is set
|
||||||
@ -237,7 +237,7 @@ func (m *csiBlockMapper) publishVolumeForBlock(
|
|||||||
ctx,
|
ctx,
|
||||||
m.volumeID,
|
m.volumeID,
|
||||||
m.readOnly,
|
m.readOnly,
|
||||||
m.getStagingPath(),
|
m.GetStagingPath(),
|
||||||
publishPath,
|
publishPath,
|
||||||
accessMode,
|
accessMode,
|
||||||
publishVolumeInfo,
|
publishVolumeInfo,
|
||||||
@ -435,7 +435,7 @@ func (m *csiBlockMapper) TearDownDevice(globalMapPath, devicePath string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call NodeUnstageVolume
|
// Call NodeUnstageVolume
|
||||||
stagingPath := m.getStagingPath()
|
stagingPath := m.GetStagingPath()
|
||||||
if _, err := os.Stat(stagingPath); err != nil {
|
if _, err := os.Stat(stagingPath); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
klog.V(4).Infof(log("blockMapper.TearDownDevice stagingPath(%s) has already been deleted, skip calling NodeUnstageVolume", stagingPath))
|
klog.V(4).Infof(log("blockMapper.TearDownDevice stagingPath(%s) has already been deleted, skip calling NodeUnstageVolume", stagingPath))
|
||||||
@ -471,7 +471,7 @@ func (m *csiBlockMapper) cleanupOrphanDeviceFiles() error {
|
|||||||
|
|
||||||
// Remove artifacts of NodeStage.
|
// Remove artifacts of NodeStage.
|
||||||
// stagingPath: xxx/plugins/kubernetes.io/csi/volumeDevices/staging/<volume name>
|
// stagingPath: xxx/plugins/kubernetes.io/csi/volumeDevices/staging/<volume name>
|
||||||
stagingPath := m.getStagingPath()
|
stagingPath := m.GetStagingPath()
|
||||||
if err := os.Remove(stagingPath); err != nil && !os.IsNotExist(err) {
|
if err := os.Remove(stagingPath); err != nil && !os.IsNotExist(err) {
|
||||||
return errors.New(log("failed to delete volume staging path [%s]: %v", stagingPath, err))
|
return errors.New(log("failed to delete volume staging path [%s]: %v", stagingPath, err))
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ func TestBlockMapperGetStagingPath(t *testing.T) {
|
|||||||
t.Fatalf("Failed to make a new Mapper: %v", err)
|
t.Fatalf("Failed to make a new Mapper: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
path := csiMapper.getStagingPath()
|
path := csiMapper.GetStagingPath()
|
||||||
|
|
||||||
if tc.path != path {
|
if tc.path != path {
|
||||||
t.Errorf("expecting path %s, got %s", tc.path, path)
|
t.Errorf("expecting path %s, got %s", tc.path, path)
|
||||||
|
@ -282,16 +282,22 @@ func (c *csiDriverClient) NodeExpandVolume(ctx context.Context, opts csiResizeOp
|
|||||||
defer closer.Close()
|
defer closer.Close()
|
||||||
|
|
||||||
req := &csipbv1.NodeExpandVolumeRequest{
|
req := &csipbv1.NodeExpandVolumeRequest{
|
||||||
VolumeId: opts.volumeID,
|
VolumeId: opts.volumeID,
|
||||||
VolumePath: opts.volumePath,
|
VolumePath: opts.volumePath,
|
||||||
StagingTargetPath: opts.stagingTargetPath,
|
CapacityRange: &csipbv1.CapacityRange{RequiredBytes: opts.newSize.Value()},
|
||||||
CapacityRange: &csipbv1.CapacityRange{RequiredBytes: opts.newSize.Value()},
|
|
||||||
VolumeCapability: &csipbv1.VolumeCapability{
|
VolumeCapability: &csipbv1.VolumeCapability{
|
||||||
AccessMode: &csipbv1.VolumeCapability_AccessMode{
|
AccessMode: &csipbv1.VolumeCapability_AccessMode{
|
||||||
Mode: asCSIAccessModeV1(opts.accessMode),
|
Mode: asCSIAccessModeV1(opts.accessMode),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// not all CSI drivers support NodeStageUnstage and hence the StagingTargetPath
|
||||||
|
// should only be set when available
|
||||||
|
if opts.stagingTargetPath != "" {
|
||||||
|
req.StagingTargetPath = opts.stagingTargetPath
|
||||||
|
}
|
||||||
|
|
||||||
if opts.fsType == fsTypeBlockName {
|
if opts.fsType == fsTypeBlockName {
|
||||||
req.VolumeCapability.AccessType = &csipbv1.VolumeCapability_Block{
|
req.VolumeCapability.AccessType = &csipbv1.VolumeCapability_Block{
|
||||||
Block: &csipbv1.VolumeCapability_BlockVolume{},
|
Block: &csipbv1.VolumeCapability_BlockVolume{},
|
||||||
|
@ -108,7 +108,11 @@ func (c *csiPlugin) nodeExpandWithClient(
|
|||||||
accessMode: api.ReadWriteOnce,
|
accessMode: api.ReadWriteOnce,
|
||||||
mountOptions: pv.Spec.MountOptions,
|
mountOptions: pv.Spec.MountOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !fsVolume {
|
if !fsVolume {
|
||||||
|
// for block volumes the volumePath in CSI NodeExpandvolumeRequest is
|
||||||
|
// basically same as DevicePath because block devices are not mounted and hence
|
||||||
|
// DeviceMountPath does not get populated in resizeOptions.DeviceMountPath
|
||||||
opts.volumePath = resizeOptions.DevicePath
|
opts.volumePath = resizeOptions.DevicePath
|
||||||
opts.fsType = fsTypeBlockName
|
opts.fsType = fsTypeBlockName
|
||||||
}
|
}
|
||||||
|
@ -621,6 +621,11 @@ func (m *localVolumeMapper) MapPodDevice() (string, error) {
|
|||||||
return globalPath, nil
|
return globalPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetStagingPath returns
|
||||||
|
func (m *localVolumeMapper) GetStagingPath() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// localVolumeUnmapper implements the BlockVolumeUnmapper interface for local volumes.
|
// localVolumeUnmapper implements the BlockVolumeUnmapper interface for local volumes.
|
||||||
type localVolumeUnmapper struct {
|
type localVolumeUnmapper struct {
|
||||||
*localVolume
|
*localVolume
|
||||||
|
@ -998,6 +998,10 @@ func (fv *FakeVolume) SetUpDevice() (string, error) {
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fv *FakeVolume) GetStagingPath() string {
|
||||||
|
return filepath.Join(fv.Plugin.Host.GetVolumeDevicePluginDir(utilstrings.EscapeQualifiedName(fv.Plugin.PluginName)), "staging", fv.VolName)
|
||||||
|
}
|
||||||
|
|
||||||
// Block volume support
|
// Block volume support
|
||||||
func (fv *FakeVolume) GetSetUpDeviceCallCount() int {
|
func (fv *FakeVolume) GetSetUpDeviceCallCount() int {
|
||||||
fv.RLock()
|
fv.RLock()
|
||||||
|
@ -1498,41 +1498,64 @@ func (og *operationGenerator) GenerateExpandInUseVolumeFunc(
|
|||||||
var simpleErr, detailedErr error
|
var simpleErr, detailedErr error
|
||||||
resizeOptions := volume.NodeResizeOptions{
|
resizeOptions := volume.NodeResizeOptions{
|
||||||
VolumeSpec: volumeToMount.VolumeSpec,
|
VolumeSpec: volumeToMount.VolumeSpec,
|
||||||
|
DevicePath: volumeToMount.DevicePath,
|
||||||
|
}
|
||||||
|
fsVolume, err := util.CheckVolumeModeFilesystem(volumeToMount.VolumeSpec)
|
||||||
|
if err != nil {
|
||||||
|
return volumeToMount.GenerateError("NodeExpandvolume.CheckVolumeModeFilesystem failed", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
attachableVolumePlugin, _ :=
|
if fsVolume {
|
||||||
og.volumePluginMgr.FindAttachablePluginBySpec(volumeToMount.VolumeSpec)
|
volumeMounter, newMounterErr := volumePlugin.NewMounter(
|
||||||
|
volumeToMount.VolumeSpec,
|
||||||
|
volumeToMount.Pod,
|
||||||
|
volume.VolumeOptions{})
|
||||||
|
if newMounterErr != nil {
|
||||||
|
return volumeToMount.GenerateError("NodeExpandVolume.NewMounter initialization failed", newMounterErr)
|
||||||
|
}
|
||||||
|
|
||||||
if attachableVolumePlugin != nil {
|
resizeOptions.DeviceMountPath = volumeMounter.GetPath()
|
||||||
volumeAttacher, _ := attachableVolumePlugin.NewAttacher()
|
|
||||||
if volumeAttacher != nil {
|
deviceMountableVolumePlugin, _ := og.volumePluginMgr.FindDeviceMountablePluginBySpec(volumeToMount.VolumeSpec)
|
||||||
resizeOptions.CSIVolumePhase = volume.CSIVolumeStaged
|
var volumeDeviceMounter volume.DeviceMounter
|
||||||
resizeOptions.DevicePath = volumeToMount.DevicePath
|
if deviceMountableVolumePlugin != nil {
|
||||||
dmp, err := volumeAttacher.GetDeviceMountPath(volumeToMount.VolumeSpec)
|
volumeDeviceMounter, _ = deviceMountableVolumePlugin.NewDeviceMounter()
|
||||||
|
}
|
||||||
|
|
||||||
|
if volumeDeviceMounter != nil {
|
||||||
|
deviceStagePath, err := volumeDeviceMounter.GetDeviceMountPath(volumeToMount.VolumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return volumeToMount.GenerateError("NodeExpandVolume.GetDeviceMountPath failed", err)
|
return volumeToMount.GenerateError("NodeExpandVolume.GetDeviceMountPath failed", err)
|
||||||
}
|
}
|
||||||
resizeOptions.DeviceMountPath = dmp
|
resizeOptions.DeviceStagePath = deviceStagePath
|
||||||
resizeOptions.DeviceStagePath = dmp
|
}
|
||||||
resizeDone, simpleErr, detailedErr = og.doOnlineExpansion(volumeToMount, actualStateOfWorld, resizeOptions)
|
} else {
|
||||||
if simpleErr != nil || detailedErr != nil {
|
// Get block volume mapper plugin
|
||||||
return simpleErr, detailedErr
|
blockVolumePlugin, err :=
|
||||||
}
|
og.volumePluginMgr.FindMapperPluginBySpec(volumeToMount.VolumeSpec)
|
||||||
if resizeDone {
|
if err != nil {
|
||||||
return nil, nil
|
return volumeToMount.GenerateError("MapVolume.FindMapperPluginBySpec failed", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if blockVolumePlugin == nil {
|
||||||
|
return volumeToMount.GenerateError("MapVolume.FindMapperPluginBySpec failed to find BlockVolumeMapper plugin. Volume plugin is nil.", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
blockVolumeMapper, newMapperErr := blockVolumePlugin.NewBlockVolumeMapper(
|
||||||
|
volumeToMount.VolumeSpec,
|
||||||
|
volumeToMount.Pod,
|
||||||
|
volume.VolumeOptions{})
|
||||||
|
if newMapperErr != nil {
|
||||||
|
return volumeToMount.GenerateError("MapVolume.NewBlockVolumeMapper initialization failed", newMapperErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if plugin supports custom mappers lets add DeviceStagePath
|
||||||
|
if customBlockVolumeMapper, ok := blockVolumeMapper.(volume.CustomBlockVolumeMapper); ok {
|
||||||
|
resizeOptions.DeviceStagePath = customBlockVolumeMapper.GetStagingPath()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if we are here that means volume plugin does not support attach interface
|
|
||||||
volumeMounter, newMounterErr := volumePlugin.NewMounter(
|
|
||||||
volumeToMount.VolumeSpec,
|
|
||||||
volumeToMount.Pod,
|
|
||||||
volume.VolumeOptions{})
|
|
||||||
if newMounterErr != nil {
|
|
||||||
return volumeToMount.GenerateError("NodeExpandVolume.NewMounter initialization failed", newMounterErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
resizeOptions.DeviceMountPath = volumeMounter.GetPath()
|
// if we are doing online expansion then volume is already published
|
||||||
resizeOptions.CSIVolumePhase = volume.CSIVolumePublished
|
resizeOptions.CSIVolumePhase = volume.CSIVolumePublished
|
||||||
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 {
|
||||||
|
@ -183,6 +183,10 @@ type CustomBlockVolumeMapper interface {
|
|||||||
// If empty string is returned, the path retuned by attacher.Attach() and
|
// If empty string is returned, the path retuned by attacher.Attach() and
|
||||||
// attacher.WaitForAttach() will be used.
|
// attacher.WaitForAttach() will be used.
|
||||||
MapPodDevice() (publishPath string, err error)
|
MapPodDevice() (publishPath string, err error)
|
||||||
|
|
||||||
|
// GetStagingPath returns path that was used for staging the volume
|
||||||
|
// it is mainly used by CSI plugins
|
||||||
|
GetStagingPath() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockVolumeUnmapper interface is an unmapper interface for block volume.
|
// BlockVolumeUnmapper interface is an unmapper interface for block volume.
|
||||||
|
Loading…
Reference in New Issue
Block a user