Move MapBlockVolume call to operation_generator and add UnmapBlockVolume

This commit is contained in:
Masaki Kimura 2019-11-01 19:32:23 +00:00
parent 68be3947b8
commit 8a159d7253
13 changed files with 69 additions and 110 deletions

View File

@ -29,7 +29,6 @@ import (
"k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
"k8s.io/legacy-cloud-providers/aws"
utilstrings "k8s.io/utils/strings"
@ -148,7 +147,7 @@ func (b *awsElasticBlockStoreMapper) SetUpDevice() (string, error) {
}
func (b *awsElasticBlockStoreMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
// GetGlobalMapPath returns global map path and error

View File

@ -28,7 +28,6 @@ import (
"k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
utilstrings "k8s.io/utils/strings"
)
@ -141,7 +140,7 @@ func (b *azureDataDiskMapper) SetUpDevice() (string, error) {
}
func (b *azureDataDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
// GetGlobalMapPath returns global map path and error

View File

@ -28,7 +28,6 @@ import (
"k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
utilstrings "k8s.io/utils/strings"
)
@ -151,7 +150,7 @@ func (b *cinderVolumeMapper) SetUpDevice() (string, error) {
}
func (b *cinderVolumeMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
// GetGlobalMapPath returns global map path and error

View File

@ -31,7 +31,6 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/volume"
ioutil "k8s.io/kubernetes/pkg/volume/util"
utilstrings "k8s.io/utils/strings"
)
@ -267,7 +266,7 @@ func (m *csiBlockMapper) SetUpDevice() (string, error) {
}
func (m *csiBlockMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return ioutil.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
var _ volume.BlockVolumeUnmapper = &csiBlockMapper{}

View File

@ -315,44 +315,12 @@ func TestBlockMapperMapDevice(t *testing.T) {
t.Fatalf("mapper failed to GetGlobalMapPath: %v", err)
}
// Actual SetupDevice should create a symlink to or a bind mout of device in devicePath.
// Create dummy file there before calling MapDevice to test it properly.
fd, err := os.Create(devicePath)
if err != nil {
t.Fatalf("mapper failed to create dummy file in devicePath: %v", err)
}
if err := fd.Close(); err != nil {
t.Fatalf("mapper failed to close dummy file in devicePath: %v", err)
}
// Map device to global and pod device map path
volumeMapPath, volName := csiMapper.GetPodDeviceMapPath()
err = csiMapper.MapDevice(devicePath, globalMapPath, volumeMapPath, volName, csiMapper.podUID)
if err != nil {
t.Fatalf("mapper failed to GetGlobalMapPath: %v", err)
}
// Check if symlink {globalMapPath}/{podUID} exists
globalMapFilePath := filepath.Join(globalMapPath, string(csiMapper.podUID))
if _, err := os.Stat(globalMapFilePath); err != nil {
if os.IsNotExist(err) {
t.Errorf("mapper.MapDevice failed, symlink in globalMapPath not created: %v", err)
t.Errorf("mapper.MapDevice devicePath:%v, globalMapPath: %v, globalMapFilePath: %v",
devicePath, globalMapPath, globalMapFilePath)
} else {
t.Errorf("mapper.MapDevice failed: %v", err)
}
}
// Check if symlink {volumeMapPath}/{volName} exists
volumeMapFilePath := filepath.Join(volumeMapPath, volName)
if _, err := os.Stat(volumeMapFilePath); err != nil {
if os.IsNotExist(err) {
t.Errorf("mapper.MapDevice failed, symlink in volumeMapPath not created: %v", err)
} else {
t.Errorf("mapper.MapDevice failed: %v", err)
}
}
}
func TestBlockMapperMapDeviceNotSupportAttach(t *testing.T) {
@ -402,44 +370,12 @@ func TestBlockMapperMapDeviceNotSupportAttach(t *testing.T) {
t.Fatalf("mapper failed to GetGlobalMapPath: %v", err)
}
// Actual SetupDevice should create a symlink to or a bind mout of device in devicePath.
// Create dummy file there before calling MapDevice to test it properly.
fd, err := os.Create(devicePath)
if err != nil {
t.Fatalf("mapper failed to create dummy file in devicePath: %v", err)
}
if err := fd.Close(); err != nil {
t.Fatalf("mapper failed to close dummy file in devicePath: %v", err)
}
// Map device to global and pod device map path
volumeMapPath, volName := csiMapper.GetPodDeviceMapPath()
err = csiMapper.MapDevice(devicePath, globalMapPath, volumeMapPath, volName, csiMapper.podUID)
if err != nil {
t.Fatalf("mapper failed to GetGlobalMapPath: %v", err)
}
// Check if symlink {globalMapPath}/{podUID} exists
globalMapFilePath := filepath.Join(globalMapPath, string(csiMapper.podUID))
if _, err := os.Stat(globalMapFilePath); err != nil {
if os.IsNotExist(err) {
t.Errorf("mapper.MapDevice failed, symlink in globalMapPath not created: %v", err)
t.Errorf("mapper.MapDevice devicePath:%v, globalMapPath: %v, globalMapFilePath: %v",
devicePath, globalMapPath, globalMapFilePath)
} else {
t.Errorf("mapper.MapDevice failed: %v", err)
}
}
// Check if symlink {volumeMapPath}/{volName} exists
volumeMapFilePath := filepath.Join(volumeMapPath, volName)
if _, err := os.Stat(volumeMapFilePath); err != nil {
if os.IsNotExist(err) {
t.Errorf("mapper.MapDevice failed, symlink in volumeMapPath not created: %v", err)
} else {
t.Errorf("mapper.MapDevice failed: %v", err)
}
}
}
func TestBlockMapperTearDownDevice(t *testing.T) {

View File

@ -419,7 +419,7 @@ func (b *fcDiskMapper) SetUpDevice() (string, error) {
}
func (b *fcDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
type fcDiskUnmapper struct {

View File

@ -29,7 +29,6 @@ import (
"k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
utilstrings "k8s.io/utils/strings"
)
@ -158,7 +157,7 @@ func (b *gcePersistentDiskMapper) SetUpDevice() (string, error) {
}
func (b *gcePersistentDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
// GetGlobalMapPath returns global map path and error

View File

@ -389,7 +389,7 @@ func (b *iscsiDiskMapper) SetUpDevice() (string, error) {
}
func (b *iscsiDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return ioutil.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
type iscsiDiskUnmapper struct {

View File

@ -621,7 +621,7 @@ func (m *localVolumeMapper) SetUpDevice() (string, error) {
}
func (m *localVolumeMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
// localVolumeUnmapper implements the BlockVolumeUnmapper interface for local volumes.

View File

@ -917,7 +917,7 @@ func (rbd *rbdDiskMapper) SetUpDevice() (string, error) {
}
func (rbd *rbdDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return volutil.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
func (rbd *rbd) rbdGlobalMapPath(spec *volume.Spec) (string, error) {

View File

@ -39,6 +39,7 @@ import (
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/csi"
"k8s.io/kubernetes/pkg/volume/util"
ioutil "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/hostutil"
volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
@ -1084,21 +1085,19 @@ func (og *operationGenerator) GenerateMapVolumeFunc(
return volumeToMount.GenerateError("MapVolume.EvalHostSymlinks failed", err)
}
// Map device to global and pod device map path
// Execute driver specific map
volumeMapPath, volName := blockVolumeMapper.GetPodDeviceMapPath()
mapErr = blockVolumeMapper.MapDevice(devicePath, globalMapPath, volumeMapPath, volName, volumeToMount.Pod.UID)
if mapErr != nil {
// On failure, return error. Caller will log and retry.
return volumeToMount.GenerateError("MapVolume.MapDevice failed", mapErr)
return volumeToMount.GenerateError("MapVolume.MapPodDevice failed", mapErr)
}
// Take filedescriptor lock to keep a block device opened. Otherwise, there is a case
// that the block device is silently removed and attached another device with same name.
// Container runtime can't handler this problem. To avoid unexpected condition fd lock
// for the block device is required.
_, err = og.blkUtil.AttachFileDevice(filepath.Join(globalMapPath, string(volumeToMount.Pod.UID)))
if err != nil {
return volumeToMount.GenerateError("MapVolume.AttachFileDevice failed", err)
// Execute common map
mapErr = ioutil.MapBlockVolume(og.blkUtil, devicePath, globalMapPath, volumeMapPath, volName, volumeToMount.Pod.UID)
if mapErr != nil {
// On failure, return error. Caller will log and retry.
return volumeToMount.GenerateError("MapVolume.MapDevice failed", mapErr)
}
// Update actual state of world to reflect volume is globally mounted
@ -1207,28 +1206,16 @@ func (og *operationGenerator) GenerateUnmapVolumeFunc(
}
unmapVolumeFunc := func() (error, error) {
globalUnmapPath := volumeToUnmount.DeviceMountPath
// Release file descriptor lock.
err := og.blkUtil.DetachFileDevice(filepath.Join(globalUnmapPath, string(volumeToUnmount.PodUID)))
if err != nil {
return volumeToUnmount.GenerateError("UnmapVolume.UnmapDevice Detaching descriptor lock failed", err)
}
// Try to unmap volumeName symlink under pod device map path dir
// pods/{podUid}/volumeDevices/{escapeQualifiedPluginName}/{volumeName}
podDeviceUnmapPath, volName := blockVolumeUnmapper.GetPodDeviceMapPath()
unmapDeviceErr := og.blkUtil.UnmapDevice(podDeviceUnmapPath, volName, false /* bindMount */)
if unmapDeviceErr != nil {
// On failure, return error. Caller will log and retry.
return volumeToUnmount.GenerateError("UnmapVolume.UnmapDevice on pod device map path failed", unmapDeviceErr)
}
// Try to unmap podUID symlink under global map path dir
// plugins/kubernetes.io/{PluginName}/volumeDevices/{volumePluginDependentPath}/{podUID}
unmapDeviceErr = og.blkUtil.UnmapDevice(globalUnmapPath, string(volumeToUnmount.PodUID), true /* bindMount */)
if unmapDeviceErr != nil {
globalUnmapPath := volumeToUnmount.DeviceMountPath
// Execute common unmap
unmapErr := ioutil.UnmapBlockVolume(og.blkUtil, globalUnmapPath, podDeviceUnmapPath, volName, volumeToUnmount.PodUID)
if unmapErr != nil {
// On failure, return error. Caller will log and retry.
return volumeToUnmount.GenerateError("UnmapVolume.UnmapDevice on global map path failed", unmapDeviceErr)
return volumeToUnmount.GenerateError("UnmapVolume.UnmapBlockVolume failed", unmapErr)
}
klog.Infof(

View File

@ -503,18 +503,17 @@ func MakeAbsolutePath(goos, path string) string {
return "c:\\" + path
}
// MapBlockVolume is a utility function to provide a common way of mounting
// MapBlockVolume is a utility function to provide a common way of mapping
// block device path for a specified volume and pod. This function should be
// called by volume plugins that implements volume.BlockVolumeMapper.Map() method.
func MapBlockVolume(
blkUtil volumepathhandler.BlockVolumePathHandler,
devicePath,
globalMapPath,
podVolumeMapPath,
volumeMapName string,
podUID utypes.UID,
) error {
blkUtil := volumepathhandler.NewBlockVolumePathHandler()
// map devicePath to global node path as bind mount
mapErr := blkUtil.MapDevice(devicePath, globalMapPath, string(podUID), true /* bindMount */)
if mapErr != nil {
@ -529,6 +528,49 @@ func MapBlockVolume(
devicePath, podVolumeMapPath, volumeMapName, false, mapErr)
}
// Take file descriptor lock to keep a block device opened. Otherwise, there is a case
// that the block device is silently removed and attached another device with the same name.
// Container runtime can't handle this problem. To avoid unexpected condition fd lock
// for the block device is required.
_, mapErr = blkUtil.AttachFileDevice(filepath.Join(globalMapPath, string(podUID)))
if mapErr != nil {
return fmt.Errorf("blkUtil.AttachFileDevice failed. globalMapPath:%s, podUID: %s: %v",
globalMapPath, string(podUID), mapErr)
}
return nil
}
// UnmapBlockVolume is a utility function to provide a common way of unmapping
// block device path for a specified volume and pod. This function should be
// called by volume plugins that implements volume.BlockVolumeMapper.Map() method.
func UnmapBlockVolume(
blkUtil volumepathhandler.BlockVolumePathHandler,
globalUnmapPath,
podDeviceUnmapPath,
volumeMapName string,
podUID utypes.UID,
) error {
// Release file descriptor lock.
err := blkUtil.DetachFileDevice(filepath.Join(globalUnmapPath, string(podUID)))
if err != nil {
return fmt.Errorf("blkUtil.DetachFileDevice failed. globalUnmapPath:%s, podUID: %s: %v",
globalUnmapPath, string(podUID), err)
}
// unmap devicePath from pod volume path
unmapDeviceErr := blkUtil.UnmapDevice(podDeviceUnmapPath, volumeMapName, false /* bindMount */)
if unmapDeviceErr != nil {
return fmt.Errorf("blkUtil.DetachFileDevice failed. podDeviceUnmapPath:%s, volumeMapName: %s, bindMount: %v: %v",
podDeviceUnmapPath, volumeMapName, false, unmapDeviceErr)
}
// unmap devicePath from global node path
unmapDeviceErr = blkUtil.UnmapDevice(globalUnmapPath, string(podUID), true /* bindMount */)
if unmapDeviceErr != nil {
return fmt.Errorf("blkUtil.DetachFileDevice failed. globalUnmapPath:%s, podUID: %s, bindMount: %v: %v",
globalUnmapPath, string(podUID), true, unmapDeviceErr)
}
return nil
}

View File

@ -29,7 +29,6 @@ import (
"k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util"
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
utilstrings "k8s.io/utils/strings"
)
@ -138,7 +137,7 @@ func (v vsphereBlockVolumeMapper) SetUpDevice() (string, error) {
}
func (v vsphereBlockVolumeMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, volumeMapName string, podUID types.UID) error {
return util.MapBlockVolume(devicePath, globalMapPath, volumeMapPath, volumeMapName, podUID)
return nil
}
var _ volume.BlockVolumeUnmapper = &vsphereBlockVolumeUnmapper{}