From b8877768807df0a9c1a80778f5a53b70a3ee5a2a Mon Sep 17 00:00:00 2001 From: Huamin Chen Date: Wed, 21 Jun 2017 20:20:14 +0000 Subject: [PATCH] add fc volume attacher Signed-off-by: Huamin Chen --- cmd/kube-controller-manager/app/BUILD | 1 + cmd/kube-controller-manager/app/plugins.go | 2 + pkg/volume/fc/BUILD | 1 + pkg/volume/fc/attacher.go | 170 +++++++++++++++++++++ pkg/volume/fc/disk_manager.go | 7 +- pkg/volume/fc/fc_test.go | 12 +- pkg/volume/fc/fc_util.go | 14 +- 7 files changed, 185 insertions(+), 22 deletions(-) create mode 100644 pkg/volume/fc/attacher.go diff --git a/cmd/kube-controller-manager/app/BUILD b/cmd/kube-controller-manager/app/BUILD index 4003b04fce..749a2e6bfd 100644 --- a/cmd/kube-controller-manager/app/BUILD +++ b/cmd/kube-controller-manager/app/BUILD @@ -75,6 +75,7 @@ go_library( "//pkg/volume/azure_dd:go_default_library", "//pkg/volume/azure_file:go_default_library", "//pkg/volume/cinder:go_default_library", + "//pkg/volume/fc:go_default_library", "//pkg/volume/flexvolume:go_default_library", "//pkg/volume/flocker:go_default_library", "//pkg/volume/gce_pd:go_default_library", diff --git a/cmd/kube-controller-manager/app/plugins.go b/cmd/kube-controller-manager/app/plugins.go index 33c724ee5c..2b036c8b7e 100644 --- a/cmd/kube-controller-manager/app/plugins.go +++ b/cmd/kube-controller-manager/app/plugins.go @@ -41,6 +41,7 @@ import ( "k8s.io/kubernetes/pkg/volume/azure_dd" "k8s.io/kubernetes/pkg/volume/azure_file" "k8s.io/kubernetes/pkg/volume/cinder" + "k8s.io/kubernetes/pkg/volume/fc" "k8s.io/kubernetes/pkg/volume/flexvolume" "k8s.io/kubernetes/pkg/volume/flocker" "k8s.io/kubernetes/pkg/volume/gce_pd" @@ -77,6 +78,7 @@ func ProbeAttachableVolumePlugins(config componentconfig.VolumeConfiguration) [] allPlugins = append(allPlugins, photon_pd.ProbeVolumePlugins()...) allPlugins = append(allPlugins, scaleio.ProbeVolumePlugins()...) allPlugins = append(allPlugins, storageos.ProbeVolumePlugins()...) + allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...) return allPlugins } diff --git a/pkg/volume/fc/BUILD b/pkg/volume/fc/BUILD index b329282789..9ac2857d74 100644 --- a/pkg/volume/fc/BUILD +++ b/pkg/volume/fc/BUILD @@ -11,6 +11,7 @@ load( go_library( name = "go_default_library", srcs = [ + "attacher.go", "disk_manager.go", "doc.go", "fc.go", diff --git a/pkg/volume/fc/attacher.go b/pkg/volume/fc/attacher.go new file mode 100644 index 0000000000..f3a506b01f --- /dev/null +++ b/pkg/volume/fc/attacher.go @@ -0,0 +1,170 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fc + +import ( + "fmt" + "os" + "strconv" + "time" + + "github.com/golang/glog" + "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/util/exec" + "k8s.io/kubernetes/pkg/util/mount" + "k8s.io/kubernetes/pkg/volume" + volumeutil "k8s.io/kubernetes/pkg/volume/util" +) + +type fcAttacher struct { + host volume.VolumeHost + manager diskManager + exe exec.Interface +} + +var _ volume.Attacher = &fcAttacher{} + +var _ volume.AttachableVolumePlugin = &fcPlugin{} + +func (plugin *fcPlugin) NewAttacher() (volume.Attacher, error) { + return &fcAttacher{ + host: plugin.host, + manager: &FCUtil{}, + exe: exec.New(), + }, nil +} + +func (plugin *fcPlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) { + mounter := plugin.host.GetMounter() + return mount.GetMountRefs(mounter, deviceMountPath) +} + +func (attacher *fcAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) { + return "", nil +} + +func (attacher *fcAttacher) VolumesAreAttached(specs []*volume.Spec, nodeName types.NodeName) (map[*volume.Spec]bool, error) { + volumesAttachedCheck := make(map[*volume.Spec]bool) + for _, spec := range specs { + volumesAttachedCheck[spec] = true + } + + return volumesAttachedCheck, nil +} + +func (attacher *fcAttacher) WaitForAttach(spec *volume.Spec, devicePath string, timeout time.Duration) (string, error) { + mounter, err := volumeSpecToMounter(spec, attacher.host) + if err != nil { + glog.Warningf("failed to get fc mounter: %v", err) + return "", err + } + return attacher.manager.AttachDisk(*mounter) +} + +func (attacher *fcAttacher) GetDeviceMountPath( + spec *volume.Spec) (string, error) { + mounter, err := volumeSpecToMounter(spec, attacher.host) + if err != nil { + glog.Warningf("failed to get fc mounter: %v", err) + return "", err + } + + return attacher.manager.MakeGlobalPDName(*mounter.fcDisk), nil +} + +func (attacher *fcAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string) error { + mounter := attacher.host.GetMounter() + notMnt, err := mounter.IsLikelyNotMountPoint(deviceMountPath) + if err != nil { + if os.IsNotExist(err) { + if err := os.MkdirAll(deviceMountPath, 0750); err != nil { + return err + } + notMnt = true + } else { + return err + } + } + + volumeSource, readOnly, err := getVolumeSource(spec) + if err != nil { + return err + } + + options := []string{} + if readOnly { + options = append(options, "ro") + } + if notMnt { + diskMounter := &mount.SafeFormatAndMount{Interface: mounter, Runner: exec.New()} + mountOptions := volume.MountOptionFromSpec(spec, options...) + err = diskMounter.FormatAndMount(devicePath, deviceMountPath, volumeSource.FSType, mountOptions) + if err != nil { + os.Remove(deviceMountPath) + return err + } + } + return nil +} + +type fcDetacher struct { + mounter mount.Interface + manager diskManager + exe exec.Interface +} + +var _ volume.Detacher = &fcDetacher{} + +func (plugin *fcPlugin) NewDetacher() (volume.Detacher, error) { + return &fcDetacher{ + mounter: plugin.host.GetMounter(), + manager: &FCUtil{}, + exe: exec.New(), + }, nil +} + +func (detacher *fcDetacher) Detach(deviceMountPath string, nodeName types.NodeName) error { + return nil +} + +func (detacher *fcDetacher) UnmountDevice(deviceMountPath string) error { + return volumeutil.UnmountPath(deviceMountPath, detacher.mounter) +} + +func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost) (*fcDiskMounter, error) { + fc, readOnly, err := getVolumeSource(spec) + if err != nil { + return nil, err + } + if fc.Lun == nil { + return nil, fmt.Errorf("empty lun") + } + lun := strconv.Itoa(int(*fc.Lun)) + return &fcDiskMounter{ + fcDisk: &fcDisk{ + plugin: &fcPlugin{ + host: host, + }, + wwns: fc.TargetWWNs, + lun: lun, + io: &osIOHandler{}, + }, + fsType: fc.FSType, + readOnly: readOnly, + mounter: &mount.SafeFormatAndMount{Interface: host.GetMounter(), Runner: exec.New()}, + }, nil +} diff --git a/pkg/volume/fc/disk_manager.go b/pkg/volume/fc/disk_manager.go index 7a0e210fb7..7602a9dc22 100644 --- a/pkg/volume/fc/disk_manager.go +++ b/pkg/volume/fc/disk_manager.go @@ -28,7 +28,7 @@ import ( type diskManager interface { MakeGlobalPDName(disk fcDisk) string // Attaches the disk to the kubelet's host machine. - AttachDisk(b fcDiskMounter) error + AttachDisk(b fcDiskMounter) (string, error) // Detaches the disk from the kubelet's host machine. DetachDisk(disk fcDiskUnmounter, mntPath string) error } @@ -46,11 +46,6 @@ func diskSetUp(manager diskManager, b fcDiskMounter, volPath string, mounter mou if !noMnt { return nil } - if err := manager.AttachDisk(b); err != nil { - glog.Errorf("failed to attach disk") - return err - } - if err := os.MkdirAll(volPath, 0750); err != nil { glog.Errorf("failed to mkdir:%s", volPath) return err diff --git a/pkg/volume/fc/fc_test.go b/pkg/volume/fc/fc_test.go index 3d6cb7bb92..6d4155fef8 100644 --- a/pkg/volume/fc/fc_test.go +++ b/pkg/volume/fc/fc_test.go @@ -100,18 +100,18 @@ func (fake *fakeDiskManager) Cleanup() { func (fake *fakeDiskManager) MakeGlobalPDName(disk fcDisk) string { return fake.tmpDir } -func (fake *fakeDiskManager) AttachDisk(b fcDiskMounter) error { +func (fake *fakeDiskManager) AttachDisk(b fcDiskMounter) (string, error) { globalPath := b.manager.MakeGlobalPDName(*b.fcDisk) err := os.MkdirAll(globalPath, 0750) if err != nil { - return err + return "", err } // Simulate the global mount so that the fakeMounter returns the // expected number of mounts for the attached disk. b.mounter.Mount(globalPath, globalPath, b.fsType, nil) fake.attachCalled = true - return nil + return "", nil } func (fake *fakeDiskManager) DetachDisk(c fcDiskUnmounter, mntPath string) error { @@ -172,9 +172,6 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) { t.Errorf("SetUp() failed: %v", err) } } - if !fakeManager.attachCalled { - t.Errorf("Attach was not called") - } fakeManager2 := NewFakeDiskManager() defer fakeManager2.Cleanup() @@ -194,9 +191,6 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) { } else if !os.IsNotExist(err) { t.Errorf("SetUp() failed: %v", err) } - if !fakeManager2.detachCalled { - t.Errorf("Detach was not called") - } } func TestPluginVolume(t *testing.T) { diff --git a/pkg/volume/fc/fc_util.go b/pkg/volume/fc/fc_util.go index 629c56cace..62e045fb82 100644 --- a/pkg/volume/fc/fc_util.go +++ b/pkg/volume/fc/fc_util.go @@ -140,7 +140,7 @@ func searchDisk(wwns []string, lun string, io ioHandler) (string, string) { return disk, dm } -func (util *FCUtil) AttachDisk(b fcDiskMounter) error { +func (util *FCUtil) AttachDisk(b fcDiskMounter) (string, error) { devicePath := "" wwns := b.wwns lun := b.lun @@ -148,7 +148,7 @@ func (util *FCUtil) AttachDisk(b fcDiskMounter) error { disk, dm := searchDisk(wwns, lun, io) // if no disk matches input wwn and lun, exit if disk == "" && dm == "" { - return fmt.Errorf("no fc disk found") + return "", fmt.Errorf("no fc disk found") } // if multipath devicemapper device is found, use it; otherwise use raw disk @@ -158,23 +158,23 @@ func (util *FCUtil) AttachDisk(b fcDiskMounter) error { devicePath = disk } // mount it - globalPDPath := b.manager.MakeGlobalPDName(*b.fcDisk) + globalPDPath := util.MakeGlobalPDName(*b.fcDisk) noMnt, err := b.mounter.IsLikelyNotMountPoint(globalPDPath) if !noMnt { glog.Infof("fc: %s already mounted", globalPDPath) - return nil + return devicePath, nil } if err := os.MkdirAll(globalPDPath, 0750); err != nil { - return fmt.Errorf("fc: failed to mkdir %s, error", globalPDPath) + return devicePath, fmt.Errorf("fc: failed to mkdir %s, error", globalPDPath) } err = b.mounter.FormatAndMount(devicePath, globalPDPath, b.fsType, nil) if err != nil { - return fmt.Errorf("fc: failed to mount fc volume %s [%s] to %s, error %v", devicePath, b.fsType, globalPDPath, err) + return devicePath, fmt.Errorf("fc: failed to mount fc volume %s [%s] to %s, error %v", devicePath, b.fsType, globalPDPath, err) } - return err + return devicePath, err } func (util *FCUtil) DetachDisk(c fcDiskUnmounter, mntPath string) error {