mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
vendor updates
This commit is contained in:
6
vendor/k8s.io/kubernetes/pkg/volume/fc/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/volume/fc/BUILD
generated
vendored
@ -22,7 +22,7 @@ go_library(
|
||||
"//pkg/util/strings:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//pkg/volume/util/volumehelper:go_default_library",
|
||||
"//pkg/volume/util/volumepathhandler:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
@ -37,12 +37,12 @@ go_test(
|
||||
"fc_test.go",
|
||||
"fc_util_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/fc",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/testing:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
|
20
vendor/k8s.io/kubernetes/pkg/volume/fc/attacher.go
generated
vendored
20
vendor/k8s.io/kubernetes/pkg/volume/fc/attacher.go
generated
vendored
@ -31,7 +31,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumehelper"
|
||||
)
|
||||
|
||||
type fcAttacher struct {
|
||||
@ -113,7 +112,7 @@ func (attacher *fcAttacher) MountDevice(spec *volume.Spec, devicePath string, de
|
||||
}
|
||||
if notMnt {
|
||||
diskMounter := &mount.SafeFormatAndMount{Interface: mounter, Exec: attacher.host.GetExec(fcPluginName)}
|
||||
mountOptions := volume.MountOptionFromSpec(spec, options...)
|
||||
mountOptions := volumeutil.MountOptionFromSpec(spec, options...)
|
||||
err = diskMounter.FormatAndMount(devicePath, deviceMountPath, volumeSource.FSType, mountOptions)
|
||||
if err != nil {
|
||||
os.Remove(deviceMountPath)
|
||||
@ -189,7 +188,7 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost) (*fcDiskMoun
|
||||
}
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode, err := volumehelper.GetVolumeMode(spec)
|
||||
volumeMode, err := volumeutil.GetVolumeMode(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -199,14 +198,16 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost) (*fcDiskMoun
|
||||
fsType: fc.FSType,
|
||||
volumeMode: volumeMode,
|
||||
readOnly: readOnly,
|
||||
mounter: volumehelper.NewSafeFormatAndMountFromHost(fcPluginName, host),
|
||||
mounter: volumeutil.NewSafeFormatAndMountFromHost(fcPluginName, host),
|
||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
||||
}, nil
|
||||
}
|
||||
return &fcDiskMounter{
|
||||
fcDisk: fcDisk,
|
||||
fsType: fc.FSType,
|
||||
readOnly: readOnly,
|
||||
mounter: volumehelper.NewSafeFormatAndMountFromHost(fcPluginName, host),
|
||||
fcDisk: fcDisk,
|
||||
fsType: fc.FSType,
|
||||
readOnly: readOnly,
|
||||
mounter: volumeutil.NewSafeFormatAndMountFromHost(fcPluginName, host),
|
||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -215,6 +216,7 @@ func volumeSpecToUnmounter(mounter mount.Interface) *fcDiskUnmounter {
|
||||
fcDisk: &fcDisk{
|
||||
io: &osIOHandler{},
|
||||
},
|
||||
mounter: mounter,
|
||||
mounter: mounter,
|
||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
||||
}
|
||||
}
|
||||
|
4
vendor/k8s.io/kubernetes/pkg/volume/fc/disk_manager.go
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/volume/fc/disk_manager.go
generated
vendored
@ -31,7 +31,9 @@ type diskManager interface {
|
||||
// Attaches the disk to the kubelet's host machine.
|
||||
AttachDisk(b fcDiskMounter) (string, error)
|
||||
// Detaches the disk from the kubelet's host machine.
|
||||
DetachDisk(disk fcDiskUnmounter, devName string) error
|
||||
DetachDisk(disk fcDiskUnmounter, devicePath string) error
|
||||
// Detaches the block disk from the kubelet's host machine.
|
||||
DetachBlockFCDisk(disk fcDiskUnmapper, mntPath, devicePath string) error
|
||||
}
|
||||
|
||||
// utility to mount a disk based filesystem
|
||||
|
127
vendor/k8s.io/kubernetes/pkg/volume/fc/fc.go
generated
vendored
127
vendor/k8s.io/kubernetes/pkg/volume/fc/fc.go
generated
vendored
@ -18,6 +18,7 @@ package fc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -31,7 +32,7 @@ import (
|
||||
utilstrings "k8s.io/kubernetes/pkg/util/strings"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumehelper"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
||||
)
|
||||
|
||||
// This is the primary entrypoint for volume plugins.
|
||||
@ -81,11 +82,7 @@ func (plugin *fcPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
|
||||
}
|
||||
|
||||
func (plugin *fcPlugin) CanSupport(spec *volume.Spec) bool {
|
||||
if (spec.Volume != nil && spec.Volume.FC == nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.FC == nil) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return (spec.Volume != nil && spec.Volume.FC != nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.FC != nil)
|
||||
}
|
||||
|
||||
func (plugin *fcPlugin) RequiresRemount() bool {
|
||||
@ -136,7 +133,7 @@ func (plugin *fcPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID,
|
||||
}
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode, err := volumehelper.GetVolumeMode(spec)
|
||||
volumeMode, err := util.GetVolumeMode(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -147,13 +144,15 @@ func (plugin *fcPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID,
|
||||
volumeMode: volumeMode,
|
||||
readOnly: readOnly,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
}, nil
|
||||
}
|
||||
return &fcDiskMounter{
|
||||
fcDisk: fcDisk,
|
||||
fsType: fc.FSType,
|
||||
readOnly: readOnly,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
|
||||
fcDisk: fcDisk,
|
||||
fsType: fc.FSType,
|
||||
readOnly: readOnly,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
}, nil
|
||||
|
||||
}
|
||||
@ -189,8 +188,9 @@ func (plugin *fcPlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID t
|
||||
manager: manager,
|
||||
io: &osIOHandler{},
|
||||
plugin: plugin},
|
||||
readOnly: readOnly,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
|
||||
readOnly: readOnly,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -208,7 +208,8 @@ func (plugin *fcPlugin) newUnmounterInternal(volName string, podUID types.UID, m
|
||||
plugin: plugin,
|
||||
io: &osIOHandler{},
|
||||
},
|
||||
mounter: mounter,
|
||||
mounter: mounter,
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -225,42 +226,91 @@ func (plugin *fcPlugin) newUnmapperInternal(volName string, podUID types.UID, ma
|
||||
plugin: plugin,
|
||||
io: &osIOHandler{},
|
||||
},
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (plugin *fcPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) {
|
||||
fcVolume := &v1.Volume{
|
||||
Name: volumeName,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
FC: &v1.FCVolumeSource{},
|
||||
},
|
||||
// Find globalPDPath from pod volume directory(mountPath)
|
||||
// examples:
|
||||
// mountPath: pods/{podUid}/volumes/kubernetes.io~fc/{volumeName}
|
||||
// globalPDPath : plugins/kubernetes.io/fc/50060e801049cfd1-lun-0
|
||||
var globalPDPath string
|
||||
mounter := plugin.host.GetMounter(plugin.GetPluginName())
|
||||
paths, err := mount.GetMountRefs(mounter, mountPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, path := range paths {
|
||||
if strings.Contains(path, plugin.host.GetPluginDir(fcPluginName)) {
|
||||
globalPDPath = path
|
||||
break
|
||||
}
|
||||
}
|
||||
// Couldn't fetch globalPDPath
|
||||
if len(globalPDPath) == 0 {
|
||||
return nil, fmt.Errorf("couldn't fetch globalPDPath. failed to obtain volume spec")
|
||||
}
|
||||
arr := strings.Split(globalPDPath, "/")
|
||||
if len(arr) < 1 {
|
||||
return nil, fmt.Errorf("failed to retrieve volume plugin information from globalPDPath: %v", globalPDPath)
|
||||
}
|
||||
volumeInfo := arr[len(arr)-1]
|
||||
// Create volume from wwn+lun or wwid
|
||||
var fcVolume *v1.Volume
|
||||
if strings.Contains(volumeInfo, "-lun-") {
|
||||
wwnLun := strings.Split(volumeInfo, "-lun-")
|
||||
if len(wwnLun) < 2 {
|
||||
return nil, fmt.Errorf("failed to retrieve TargetWWN and Lun. volumeInfo is invalid: %v", volumeInfo)
|
||||
}
|
||||
lun, err := strconv.Atoi(wwnLun[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lun32 := int32(lun)
|
||||
fcVolume = &v1.Volume{
|
||||
Name: volumeName,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
FC: &v1.FCVolumeSource{TargetWWNs: []string{wwnLun[0]}, Lun: &lun32},
|
||||
},
|
||||
}
|
||||
glog.V(5).Infof("ConstructVolumeSpec: TargetWWNs: %v, Lun: %v",
|
||||
fcVolume.VolumeSource.FC.TargetWWNs, *fcVolume.VolumeSource.FC.Lun)
|
||||
} else {
|
||||
fcVolume = &v1.Volume{
|
||||
Name: volumeName,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
FC: &v1.FCVolumeSource{WWIDs: []string{volumeInfo}},
|
||||
},
|
||||
}
|
||||
glog.V(5).Infof("ConstructVolumeSpec: WWIDs: %v", fcVolume.VolumeSource.FC.WWIDs)
|
||||
}
|
||||
return volume.NewSpecFromVolume(fcVolume), nil
|
||||
}
|
||||
|
||||
// ConstructBlockVolumeSpec creates a new volume.Spec with following steps.
|
||||
// - Searchs a file whose name is {pod uuid} under volume plugin directory.
|
||||
// - Searches a file whose name is {pod uuid} under volume plugin directory.
|
||||
// - If a file is found, then retreives volumePluginDependentPath from globalMapPathUUID.
|
||||
// - Once volumePluginDependentPath is obtained, store volume information to VolumeSource
|
||||
// examples:
|
||||
// mapPath: pods/{podUid}}/{DefaultKubeletVolumeDevicesDirName}/{escapeQualifiedPluginName}/{volumeName}
|
||||
// mapPath: pods/{podUid}/{DefaultKubeletVolumeDevicesDirName}/{escapeQualifiedPluginName}/{volumeName}
|
||||
// globalMapPathUUID : plugins/kubernetes.io/{PluginName}/{DefaultKubeletVolumeDevicesDirName}/{volumePluginDependentPath}/{pod uuid}
|
||||
func (plugin *fcPlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, mapPath string) (*volume.Spec, error) {
|
||||
pluginDir := plugin.host.GetVolumeDevicePluginDir(fcPluginName)
|
||||
blkutil := util.NewBlockVolumePathHandler()
|
||||
blkutil := volumepathhandler.NewBlockVolumePathHandler()
|
||||
globalMapPathUUID, err := blkutil.FindGlobalMapPathUUIDFromPod(pluginDir, mapPath, podUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.V(5).Infof("globalMapPathUUID: %v, err: %v", globalMapPathUUID, err)
|
||||
|
||||
// Retreive volumePluginDependentPath from globalMapPathUUID
|
||||
// Retrieve volumePluginDependentPath from globalMapPathUUID
|
||||
// globalMapPathUUID examples:
|
||||
// wwn+lun: plugins/kubernetes.io/fc/volumeDevices/50060e801049cfd1-lun-0/{pod uuid}
|
||||
// wwid: plugins/kubernetes.io/fc/volumeDevices/3600508b400105e210000900000490000/{pod uuid}
|
||||
arr := strings.Split(globalMapPathUUID, "/")
|
||||
if len(arr) < 2 {
|
||||
return nil, fmt.Errorf("Fail to retreive volume plugin information from globalMapPathUUID: %v", globalMapPathUUID)
|
||||
return nil, fmt.Errorf("Fail to retrieve volume plugin information from globalMapPathUUID: %v", globalMapPathUUID)
|
||||
}
|
||||
l := len(arr) - 2
|
||||
volumeInfo := arr[l]
|
||||
@ -278,7 +328,7 @@ func (plugin *fcPlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, m
|
||||
v1.FCVolumeSource{TargetWWNs: []string{wwnLun[0]}, Lun: &lun32})
|
||||
glog.V(5).Infof("ConstructBlockVolumeSpec: TargetWWNs: %v, Lun: %v",
|
||||
fcPV.Spec.PersistentVolumeSource.FC.TargetWWNs,
|
||||
fcPV.Spec.PersistentVolumeSource.FC.Lun)
|
||||
*fcPV.Spec.PersistentVolumeSource.FC.Lun)
|
||||
} else {
|
||||
fcPV = createPersistentVolumeFromFCVolumeSource(volumeName,
|
||||
v1.FCVolumeSource{WWIDs: []string{volumeInfo}})
|
||||
@ -328,6 +378,7 @@ type fcDiskMounter struct {
|
||||
fsType string
|
||||
volumeMode v1.PersistentVolumeMode
|
||||
mounter *mount.SafeFormatAndMount
|
||||
deviceUtil util.DeviceUtil
|
||||
}
|
||||
|
||||
var _ volume.Mounter = &fcDiskMounter{}
|
||||
@ -362,7 +413,8 @@ func (b *fcDiskMounter) SetUpAt(dir string, fsGroup *int64) error {
|
||||
|
||||
type fcDiskUnmounter struct {
|
||||
*fcDisk
|
||||
mounter mount.Interface
|
||||
mounter mount.Interface
|
||||
deviceUtil util.DeviceUtil
|
||||
}
|
||||
|
||||
var _ volume.Unmounter = &fcDiskUnmounter{}
|
||||
@ -380,8 +432,9 @@ func (c *fcDiskUnmounter) TearDownAt(dir string) error {
|
||||
// Block Volumes Support
|
||||
type fcDiskMapper struct {
|
||||
*fcDisk
|
||||
readOnly bool
|
||||
mounter mount.Interface
|
||||
readOnly bool
|
||||
mounter mount.Interface
|
||||
deviceUtil util.DeviceUtil
|
||||
}
|
||||
|
||||
var _ volume.BlockVolumeMapper = &fcDiskMapper{}
|
||||
@ -392,18 +445,22 @@ func (b *fcDiskMapper) SetUpDevice() (string, error) {
|
||||
|
||||
type fcDiskUnmapper struct {
|
||||
*fcDisk
|
||||
deviceUtil util.DeviceUtil
|
||||
}
|
||||
|
||||
var _ volume.BlockVolumeUnmapper = &fcDiskUnmapper{}
|
||||
|
||||
func (c *fcDiskUnmapper) TearDownDevice(_, devicePath string) error {
|
||||
// Remove scsi device from the node.
|
||||
if !strings.HasPrefix(devicePath, "/dev/") {
|
||||
return fmt.Errorf("fc detach disk: invalid device name: %s", devicePath)
|
||||
func (c *fcDiskUnmapper) TearDownDevice(mapPath, devicePath string) error {
|
||||
err := c.manager.DetachBlockFCDisk(*c, mapPath, devicePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fc: failed to detach disk: %s\nError: %v", mapPath, err)
|
||||
}
|
||||
arr := strings.Split(devicePath, "/")
|
||||
dev := arr[len(arr)-1]
|
||||
removeFromScsiSubsystem(dev, c.io)
|
||||
glog.V(4).Infof("fc: %q is unmounted, deleting the directory", mapPath)
|
||||
err = os.RemoveAll(mapPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fc: failed to delete the directory: %s\nError: %v", mapPath, err)
|
||||
}
|
||||
glog.V(4).Infof("fc: successfully detached disk: %s", mapPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
105
vendor/k8s.io/kubernetes/pkg/volume/fc/fc_test.go
generated
vendored
105
vendor/k8s.io/kubernetes/pkg/volume/fc/fc_test.go
generated
vendored
@ -19,6 +19,8 @@ package fc
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
@ -48,9 +50,24 @@ func TestCanSupport(t *testing.T) {
|
||||
if plug.GetPluginName() != "kubernetes.io/fc" {
|
||||
t.Errorf("Wrong name: %s", plug.GetPluginName())
|
||||
}
|
||||
if plug.CanSupport(&volume.Spec{}) {
|
||||
t.Errorf("Expected false")
|
||||
}
|
||||
if plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) {
|
||||
t.Errorf("Expected false")
|
||||
}
|
||||
if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{FC: &v1.FCVolumeSource{}}}}) {
|
||||
t.Errorf("Expected true")
|
||||
}
|
||||
if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{}}}) {
|
||||
t.Errorf("Expected false")
|
||||
}
|
||||
if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) {
|
||||
t.Errorf("Expected false")
|
||||
}
|
||||
if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{FC: &v1.FCVolumeSource{}}}}}) {
|
||||
t.Errorf("Expected true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccessModes(t *testing.T) {
|
||||
@ -120,6 +137,15 @@ func (fake *fakeDiskManager) DetachDisk(c fcDiskUnmounter, mntPath string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fake *fakeDiskManager) DetachBlockFCDisk(c fcDiskUnmapper, mapPath, devicePath string) error {
|
||||
err := os.RemoveAll(mapPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fake.detachCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func doTestPlugin(t *testing.T, spec *volume.Spec) {
|
||||
tmpDir, err := utiltesting.MkTmpdir("fc_test")
|
||||
if err != nil {
|
||||
@ -162,13 +188,6 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) {
|
||||
t.Errorf("SetUp() failed: %v", err)
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
t.Errorf("SetUp() failed, volume path not created: %s", path)
|
||||
} else {
|
||||
t.Errorf("SetUp() failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
fakeManager2 := NewFakeDiskManager()
|
||||
defer fakeManager2.Cleanup()
|
||||
@ -403,3 +422,75 @@ func Test_getWwnsLunWwidsError(t *testing.T) {
|
||||
t.Errorf("unexpected fc disk found")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ConstructVolumeSpec(t *testing.T) {
|
||||
fm := &mount.FakeMounter{
|
||||
MountPoints: []mount.MountPoint{
|
||||
{Device: "/dev/sdb", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod1"},
|
||||
{Device: "/dev/sdb", Path: "/var/lib/kubelet/plugins/kubernetes.io/fc/50060e801049cfd1-lun-0"},
|
||||
{Device: "/dev/sdc", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod2"},
|
||||
{Device: "/dev/sdc", Path: "/var/lib/kubelet/plugins/kubernetes.io/fc/volumeDevices/3600508b400105e210000900000490000"},
|
||||
},
|
||||
}
|
||||
mountPaths := []string{
|
||||
"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod1",
|
||||
"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod2",
|
||||
}
|
||||
for _, path := range mountPaths {
|
||||
refs, _ := mount.GetMountRefs(fm, path)
|
||||
var globalPDPath string
|
||||
for _, ref := range refs {
|
||||
if strings.Contains(ref, "kubernetes.io/fc") {
|
||||
globalPDPath = ref
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(globalPDPath) == 0 {
|
||||
t.Errorf("couldn't fetch mountrefs")
|
||||
}
|
||||
arr := strings.Split(globalPDPath, "/")
|
||||
if len(arr) < 1 {
|
||||
t.Errorf("failed to retrieve volume plugin information from globalPDPath: %v", globalPDPath)
|
||||
}
|
||||
volumeInfo := arr[len(arr)-1]
|
||||
if strings.Contains(volumeInfo, "-lun-") {
|
||||
wwnLun := strings.Split(volumeInfo, "-lun-")
|
||||
if len(wwnLun) < 2 {
|
||||
t.Errorf("failed to retrieve TargetWWN and Lun. volumeInfo is invalid: %v", volumeInfo)
|
||||
}
|
||||
lun, _ := strconv.Atoi(wwnLun[1])
|
||||
lun32 := int32(lun)
|
||||
if wwnLun[0] != "50060e801049cfd1" || lun32 != 0 {
|
||||
t.Errorf("failed to retrieve TargetWWN and Lun")
|
||||
}
|
||||
} else {
|
||||
if volumeInfo != "3600508b400105e210000900000490000" {
|
||||
t.Errorf("failed to retrieve WWIDs")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ConstructVolumeSpecNoRefs(t *testing.T) {
|
||||
fm := &mount.FakeMounter{
|
||||
MountPoints: []mount.MountPoint{
|
||||
{Device: "/dev/sdd", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod1"},
|
||||
},
|
||||
}
|
||||
mountPaths := []string{
|
||||
"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~fc/fc-in-pod1",
|
||||
}
|
||||
for _, path := range mountPaths {
|
||||
refs, _ := mount.GetMountRefs(fm, path)
|
||||
var globalPDPath string
|
||||
for _, ref := range refs {
|
||||
if strings.Contains(ref, "kubernetes.io/fc") {
|
||||
globalPDPath = ref
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(globalPDPath) != 0 {
|
||||
t.Errorf("invalid globalPDPath")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
210
vendor/k8s.io/kubernetes/pkg/volume/fc/fc_util.go
generated
vendored
210
vendor/k8s.io/kubernetes/pkg/volume/fc/fc_util.go
generated
vendored
@ -29,6 +29,8 @@ import (
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
||||
)
|
||||
|
||||
type ioHandler interface {
|
||||
@ -40,6 +42,11 @@ type ioHandler interface {
|
||||
|
||||
type osIOHandler struct{}
|
||||
|
||||
const (
|
||||
byPath = "/dev/disk/by-path/"
|
||||
byID = "/dev/disk/by-id/"
|
||||
)
|
||||
|
||||
func (handler *osIOHandler) ReadDir(dirname string) ([]os.FileInfo, error) {
|
||||
return ioutil.ReadDir(dirname)
|
||||
}
|
||||
@ -53,37 +60,17 @@ func (handler *osIOHandler) WriteFile(filename string, data []byte, perm os.File
|
||||
return ioutil.WriteFile(filename, data, perm)
|
||||
}
|
||||
|
||||
// given a disk path like /dev/sdx, find the devicemapper parent
|
||||
// TODO #23192 Convert this code to use the generic code in ../util
|
||||
// which is used by the iSCSI implementation
|
||||
func findMultipathDeviceMapper(disk string, io ioHandler) string {
|
||||
sys_path := "/sys/block/"
|
||||
if dirs, err := io.ReadDir(sys_path); err == nil {
|
||||
for _, f := range dirs {
|
||||
name := f.Name()
|
||||
if strings.HasPrefix(name, "dm-") {
|
||||
if _, err1 := io.Lstat(sys_path + name + "/slaves/" + disk); err1 == nil {
|
||||
return "/dev/" + name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// given a wwn and lun, find the device and associated devicemapper parent
|
||||
func findDisk(wwn, lun string, io ioHandler) (string, string) {
|
||||
func findDisk(wwn, lun string, io ioHandler, deviceUtil volumeutil.DeviceUtil) (string, string) {
|
||||
fc_path := "-fc-0x" + wwn + "-lun-" + lun
|
||||
dev_path := "/dev/disk/by-path/"
|
||||
dev_path := byPath
|
||||
if dirs, err := io.ReadDir(dev_path); err == nil {
|
||||
for _, f := range dirs {
|
||||
name := f.Name()
|
||||
if strings.Contains(name, fc_path) {
|
||||
if disk, err1 := io.EvalSymlinks(dev_path + name); err1 == nil {
|
||||
arr := strings.Split(disk, "/")
|
||||
l := len(arr) - 1
|
||||
dev := arr[l]
|
||||
dm := findMultipathDeviceMapper(dev, io)
|
||||
dm := deviceUtil.FindMultipathDeviceForDevice(disk)
|
||||
glog.Infof("fc: find disk: %v, dm: %v", disk, dm)
|
||||
return disk, dm
|
||||
}
|
||||
}
|
||||
@ -93,7 +80,7 @@ func findDisk(wwn, lun string, io ioHandler) (string, string) {
|
||||
}
|
||||
|
||||
// given a wwid, find the device and associated devicemapper parent
|
||||
func findDiskWWIDs(wwid string, io ioHandler) (string, string) {
|
||||
func findDiskWWIDs(wwid string, io ioHandler, deviceUtil volumeutil.DeviceUtil) (string, string) {
|
||||
// Example wwid format:
|
||||
// 3600508b400105e210000900000490000
|
||||
// <VENDOR NAME> <IDENTIFIER NUMBER>
|
||||
@ -104,7 +91,7 @@ func findDiskWWIDs(wwid string, io ioHandler) (string, string) {
|
||||
// underscore when wwid is exposed under /dev/by-id.
|
||||
|
||||
fc_path := "scsi-" + wwid
|
||||
dev_id := "/dev/disk/by-id/"
|
||||
dev_id := byID
|
||||
if dirs, err := io.ReadDir(dev_id); err == nil {
|
||||
for _, f := range dirs {
|
||||
name := f.Name()
|
||||
@ -114,10 +101,8 @@ func findDiskWWIDs(wwid string, io ioHandler) (string, string) {
|
||||
glog.V(2).Infof("fc: failed to find a corresponding disk from symlink[%s], error %v", dev_id+name, err)
|
||||
return "", ""
|
||||
}
|
||||
arr := strings.Split(disk, "/")
|
||||
l := len(arr) - 1
|
||||
dev := arr[l]
|
||||
dm := findMultipathDeviceMapper(dev, io)
|
||||
dm := deviceUtil.FindMultipathDeviceForDevice(disk)
|
||||
glog.Infof("fc: find disk: %v, dm: %v", disk, dm)
|
||||
return disk, dm
|
||||
}
|
||||
}
|
||||
@ -197,9 +182,9 @@ func searchDisk(b fcDiskMounter) (string, error) {
|
||||
for true {
|
||||
for _, diskId := range diskIds {
|
||||
if len(wwns) != 0 {
|
||||
disk, dm = findDisk(diskId, lun, io)
|
||||
disk, dm = findDisk(diskId, lun, io, b.deviceUtil)
|
||||
} else {
|
||||
disk, dm = findDiskWWIDs(diskId, io)
|
||||
disk, dm = findDiskWWIDs(diskId, io, b.deviceUtil)
|
||||
}
|
||||
// if multipath device is found, break
|
||||
if dm != "" {
|
||||
@ -265,13 +250,160 @@ func (util *FCUtil) AttachDisk(b fcDiskMounter) (string, error) {
|
||||
return devicePath, err
|
||||
}
|
||||
|
||||
func (util *FCUtil) DetachDisk(c fcDiskUnmounter, devName string) error {
|
||||
// Remove scsi device from the node.
|
||||
if !strings.HasPrefix(devName, "/dev/") {
|
||||
return fmt.Errorf("fc detach disk: invalid device name: %s", devName)
|
||||
// DetachDisk removes scsi device file such as /dev/sdX from the node.
|
||||
func (util *FCUtil) DetachDisk(c fcDiskUnmounter, devicePath string) error {
|
||||
var devices []string
|
||||
// devicePath might be like /dev/mapper/mpathX. Find destination.
|
||||
dstPath, err := c.io.EvalSymlinks(devicePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Find slave
|
||||
if strings.HasPrefix(dstPath, "/dev/dm-") {
|
||||
devices = c.deviceUtil.FindSlaveDevicesOnMultipath(dstPath)
|
||||
} else {
|
||||
// Add single devicepath to devices
|
||||
devices = append(devices, dstPath)
|
||||
}
|
||||
glog.V(4).Infof("fc: DetachDisk devicePath: %v, dstPath: %v, devices: %v", devicePath, dstPath, devices)
|
||||
var lastErr error
|
||||
for _, device := range devices {
|
||||
err := util.detachFCDisk(c.io, device)
|
||||
if err != nil {
|
||||
glog.Errorf("fc: detachFCDisk failed. device: %v err: %v", device, err)
|
||||
lastErr = fmt.Errorf("fc: detachFCDisk failed. device: %v err: %v", device, err)
|
||||
}
|
||||
}
|
||||
if lastErr != nil {
|
||||
glog.Errorf("fc: last error occurred during detach disk:\n%v", lastErr)
|
||||
return lastErr
|
||||
}
|
||||
arr := strings.Split(devName, "/")
|
||||
dev := arr[len(arr)-1]
|
||||
removeFromScsiSubsystem(dev, c.io)
|
||||
return nil
|
||||
}
|
||||
|
||||
// detachFCDisk removes scsi device file such as /dev/sdX from the node.
|
||||
func (util *FCUtil) detachFCDisk(io ioHandler, devicePath string) error {
|
||||
// Remove scsi device from the node.
|
||||
if !strings.HasPrefix(devicePath, "/dev/") {
|
||||
return fmt.Errorf("fc detach disk: invalid device name: %s", devicePath)
|
||||
}
|
||||
arr := strings.Split(devicePath, "/")
|
||||
dev := arr[len(arr)-1]
|
||||
removeFromScsiSubsystem(dev, io)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DetachBlockFCDisk detaches a volume from kubelet node, removes scsi device file
|
||||
// such as /dev/sdX from the node, and then removes loopback for the scsi device.
|
||||
func (util *FCUtil) DetachBlockFCDisk(c fcDiskUnmapper, mapPath, devicePath string) error {
|
||||
// Check if devicePath is valid
|
||||
if len(devicePath) != 0 {
|
||||
if pathExists, pathErr := checkPathExists(devicePath); !pathExists || pathErr != nil {
|
||||
return pathErr
|
||||
}
|
||||
} else {
|
||||
// TODO: FC plugin can't obtain the devicePath from kubelet because devicePath
|
||||
// in volume object isn't updated when volume is attached to kubelet node.
|
||||
glog.Infof("fc: devicePath is empty. Try to retrieve FC configuration from global map path: %v", mapPath)
|
||||
}
|
||||
|
||||
// Check if global map path is valid
|
||||
// global map path examples:
|
||||
// wwn+lun: plugins/kubernetes.io/fc/volumeDevices/50060e801049cfd1-lun-0/
|
||||
// wwid: plugins/kubernetes.io/fc/volumeDevices/3600508b400105e210000900000490000/
|
||||
if pathExists, pathErr := checkPathExists(mapPath); !pathExists || pathErr != nil {
|
||||
return pathErr
|
||||
}
|
||||
|
||||
// Retrieve volume plugin dependent path like '50060e801049cfd1-lun-0' from global map path
|
||||
arr := strings.Split(mapPath, "/")
|
||||
if len(arr) < 1 {
|
||||
return fmt.Errorf("Fail to retrieve volume plugin information from global map path: %v", mapPath)
|
||||
}
|
||||
volumeInfo := arr[len(arr)-1]
|
||||
|
||||
// Search symbolick link which matches volumeInfo under /dev/disk/by-path or /dev/disk/by-id
|
||||
// then find destination device path from the link
|
||||
searchPath := byID
|
||||
if strings.Contains(volumeInfo, "-lun-") {
|
||||
searchPath = byPath
|
||||
}
|
||||
fis, err := ioutil.ReadDir(searchPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, fi := range fis {
|
||||
if strings.Contains(fi.Name(), volumeInfo) {
|
||||
devicePath = path.Join(searchPath, fi.Name())
|
||||
glog.V(5).Infof("fc: updated devicePath: %s", devicePath)
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(devicePath) == 0 {
|
||||
return fmt.Errorf("fc: failed to find corresponding device from searchPath: %v", searchPath)
|
||||
}
|
||||
dstPath, err := c.io.EvalSymlinks(devicePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
glog.V(4).Infof("fc: find destination device path from symlink: %v", dstPath)
|
||||
|
||||
// Get loopback device which takes fd lock for device beofore detaching a volume from node.
|
||||
// TODO: This is a workaround for issue #54108
|
||||
// Currently local attach plugins such as FC, iSCSI, RBD can't obtain devicePath during
|
||||
// GenerateUnmapDeviceFunc() in operation_generator. As a result, these plugins fail to get
|
||||
// and remove loopback device then it will be remained on kubelet node. To avoid the problem,
|
||||
// local attach plugins needs to remove loopback device during TearDownDevice().
|
||||
var devices []string
|
||||
blkUtil := volumepathhandler.NewBlockVolumePathHandler()
|
||||
dm := c.deviceUtil.FindMultipathDeviceForDevice(dstPath)
|
||||
if len(dm) != 0 {
|
||||
dstPath = dm
|
||||
}
|
||||
loop, err := volumepathhandler.BlockVolumePathHandler.GetLoopDevice(blkUtil, dstPath)
|
||||
if err != nil {
|
||||
if err.Error() != volumepathhandler.ErrDeviceNotFound {
|
||||
return fmt.Errorf("fc: failed to get loopback for destination path: %v, err: %v", dstPath, err)
|
||||
}
|
||||
glog.Warning("fc: loopback for destination path: %s not found", dstPath)
|
||||
}
|
||||
|
||||
// Detach volume from kubelet node
|
||||
if len(dm) != 0 {
|
||||
// Find all devices which are managed by multipath
|
||||
devices = c.deviceUtil.FindSlaveDevicesOnMultipath(dm)
|
||||
} else {
|
||||
// Add single device path to devices
|
||||
devices = append(devices, dstPath)
|
||||
}
|
||||
var lastErr error
|
||||
for _, device := range devices {
|
||||
err = util.detachFCDisk(c.io, device)
|
||||
if err != nil {
|
||||
glog.Errorf("fc: detachFCDisk failed. device: %v err: %v", device, err)
|
||||
lastErr = fmt.Errorf("fc: detachFCDisk failed. device: %v err: %v", device, err)
|
||||
}
|
||||
}
|
||||
if lastErr != nil {
|
||||
glog.Errorf("fc: last error occurred during detach disk:\n%v", lastErr)
|
||||
return lastErr
|
||||
}
|
||||
if len(loop) != 0 {
|
||||
// The volume was successfully detached from node. We can safely remove the loopback.
|
||||
err = volumepathhandler.BlockVolumePathHandler.RemoveLoopDevice(blkUtil, loop)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fc: failed to remove loopback :%v, err: %v", loop, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkPathExists(path string) (bool, error) {
|
||||
if pathExists, pathErr := volumeutil.PathExists(path); pathErr != nil {
|
||||
return pathExists, fmt.Errorf("Error checking if path exists: %v", pathErr)
|
||||
} else if !pathExists {
|
||||
glog.Warningf("Warning: Unmap skipped because path does not exist: %v", path)
|
||||
return pathExists, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
4
vendor/k8s.io/kubernetes/pkg/volume/fc/fc_util_test.go
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/volume/fc/fc_util_test.go
generated
vendored
@ -20,6 +20,8 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
type fakeFileInfo struct {
|
||||
@ -91,6 +93,7 @@ func TestSearchDisk(t *testing.T) {
|
||||
lun: "0",
|
||||
io: &fakeIOHandler{},
|
||||
},
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
}
|
||||
devicePath, error := searchDisk(fakeMounter)
|
||||
// if no disk matches input wwn and lun, exit
|
||||
@ -105,6 +108,7 @@ func TestSearchDiskWWID(t *testing.T) {
|
||||
wwids: []string{"3600508b400105e210000900000490000"},
|
||||
io: &fakeIOHandler{},
|
||||
},
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
}
|
||||
devicePath, error := searchDisk(fakeMounter)
|
||||
// if no disk matches input wwid, exit
|
||||
|
Reference in New Issue
Block a user