Skip to content

Commit

Permalink
Merge pull request kubernetes#48940 from rootfs/fc-fencing
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue (batch tested with PRs 48377, 48940, 49144, 49062, 49148)

support fc volume attach and detach

**What this PR does / why we need it**:
Support FC volume attach and detach to enforce RWO access

**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes kubernetes#48953

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```
  • Loading branch information
Kubernetes Submit Queue authored Jul 20, 2017
2 parents 8d26afa + b887776 commit 25d3523
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 22 deletions.
1 change: 1 addition & 0 deletions cmd/kube-controller-manager/app/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,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",
Expand Down
2 changes: 2 additions & 0 deletions cmd/kube-controller-manager/app/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}

Expand Down
1 change: 1 addition & 0 deletions pkg/volume/fc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ load(
go_library(
name = "go_default_library",
srcs = [
"attacher.go",
"disk_manager.go",
"doc.go",
"fc.go",
Expand Down
170 changes: 170 additions & 0 deletions pkg/volume/fc/attacher.go
Original file line number Diff line number Diff line change
@@ -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
}
7 changes: 1 addition & 6 deletions pkg/volume/fc/disk_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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
Expand Down
12 changes: 3 additions & 9 deletions pkg/volume/fc/fc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
Expand All @@ -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) {
Expand Down
14 changes: 7 additions & 7 deletions pkg/volume/fc/fc_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,15 @@ 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
io := b.io
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
Expand All @@ -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 {
Expand Down

0 comments on commit 25d3523

Please sign in to comment.