...

Source file src/k8s.io/kubernetes/pkg/volume/iscsi/attacher.go

Documentation: k8s.io/kubernetes/pkg/volume/iscsi

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package iscsi
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"time"
    23  
    24  	"k8s.io/klog/v2"
    25  	"k8s.io/mount-utils"
    26  	"k8s.io/utils/keymutex"
    27  
    28  	v1 "k8s.io/api/core/v1"
    29  	"k8s.io/apimachinery/pkg/types"
    30  	"k8s.io/kubernetes/pkg/volume"
    31  	volumeutil "k8s.io/kubernetes/pkg/volume/util"
    32  )
    33  
    34  type iscsiAttacher struct {
    35  	host        volume.VolumeHost
    36  	targetLocks keymutex.KeyMutex
    37  	manager     diskManager
    38  }
    39  
    40  var _ volume.Attacher = &iscsiAttacher{}
    41  
    42  var _ volume.DeviceMounter = &iscsiAttacher{}
    43  
    44  var _ volume.AttachableVolumePlugin = &iscsiPlugin{}
    45  
    46  var _ volume.DeviceMountableVolumePlugin = &iscsiPlugin{}
    47  
    48  func (plugin *iscsiPlugin) NewAttacher() (volume.Attacher, error) {
    49  	return &iscsiAttacher{
    50  		host:        plugin.host,
    51  		targetLocks: plugin.targetLocks,
    52  		manager:     &ISCSIUtil{},
    53  	}, nil
    54  }
    55  
    56  func (plugin *iscsiPlugin) NewDeviceMounter() (volume.DeviceMounter, error) {
    57  	return plugin.NewAttacher()
    58  }
    59  
    60  func (plugin *iscsiPlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, error) {
    61  	mounter := plugin.host.GetMounter(iscsiPluginName)
    62  	return mounter.GetMountRefs(deviceMountPath)
    63  }
    64  
    65  func (attacher *iscsiAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) {
    66  	return "", nil
    67  }
    68  
    69  func (attacher *iscsiAttacher) VolumesAreAttached(specs []*volume.Spec, nodeName types.NodeName) (map[*volume.Spec]bool, error) {
    70  	volumesAttachedCheck := make(map[*volume.Spec]bool)
    71  	for _, spec := range specs {
    72  		volumesAttachedCheck[spec] = true
    73  	}
    74  
    75  	return volumesAttachedCheck, nil
    76  }
    77  
    78  func (attacher *iscsiAttacher) WaitForAttach(spec *volume.Spec, devicePath string, pod *v1.Pod, timeout time.Duration) (string, error) {
    79  	mounter, err := volumeSpecToMounter(spec, attacher.host, attacher.targetLocks, pod)
    80  	if err != nil {
    81  		klog.Warningf("failed to get iscsi mounter: %v", err)
    82  		return "", err
    83  	}
    84  	return attacher.manager.AttachDisk(*mounter)
    85  }
    86  
    87  func (attacher *iscsiAttacher) GetDeviceMountPath(
    88  	spec *volume.Spec) (string, error) {
    89  	mounter, err := volumeSpecToMounter(spec, attacher.host, attacher.targetLocks, nil)
    90  	if err != nil {
    91  		klog.Warningf("failed to get iscsi mounter: %v", err)
    92  		return "", err
    93  	}
    94  	if mounter.InitiatorName != "" {
    95  		// new iface name is <target portal>:<volume name>
    96  		mounter.Iface = mounter.Portals[0] + ":" + mounter.VolName
    97  	}
    98  	return attacher.manager.MakeGlobalPDName(*mounter.iscsiDisk), nil
    99  }
   100  
   101  func (attacher *iscsiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string, mountArgs volume.DeviceMounterArgs) error {
   102  	mounter := attacher.host.GetMounter(iscsiPluginName)
   103  	notMnt, err := mounter.IsLikelyNotMountPoint(deviceMountPath)
   104  	if err != nil {
   105  		if os.IsNotExist(err) {
   106  			if err := os.MkdirAll(deviceMountPath, 0750); err != nil {
   107  				return err
   108  			}
   109  			notMnt = true
   110  		} else {
   111  			return err
   112  		}
   113  	}
   114  	readOnly, fsType, err := getISCSIVolumeInfo(spec)
   115  	if err != nil {
   116  		return err
   117  	}
   118  
   119  	options := []string{}
   120  	if readOnly {
   121  		options = append(options, "ro")
   122  	}
   123  	if mountArgs.SELinuxLabel != "" {
   124  		options = volumeutil.AddSELinuxMountOption(options, mountArgs.SELinuxLabel)
   125  	}
   126  	if notMnt {
   127  		diskMounter := &mount.SafeFormatAndMount{Interface: mounter, Exec: attacher.host.GetExec(iscsiPluginName)}
   128  		mountOptions := volumeutil.MountOptionFromSpec(spec, options...)
   129  		err = diskMounter.FormatAndMount(devicePath, deviceMountPath, fsType, mountOptions)
   130  		if err != nil {
   131  			os.Remove(deviceMountPath)
   132  			return err
   133  		}
   134  	}
   135  	return nil
   136  }
   137  
   138  type iscsiDetacher struct {
   139  	host    volume.VolumeHost
   140  	mounter mount.Interface
   141  	manager diskManager
   142  	plugin  *iscsiPlugin
   143  }
   144  
   145  var _ volume.Detacher = &iscsiDetacher{}
   146  
   147  var _ volume.DeviceUnmounter = &iscsiDetacher{}
   148  
   149  func (plugin *iscsiPlugin) NewDetacher() (volume.Detacher, error) {
   150  	return &iscsiDetacher{
   151  		host:    plugin.host,
   152  		mounter: plugin.host.GetMounter(iscsiPluginName),
   153  		manager: &ISCSIUtil{},
   154  		plugin:  plugin,
   155  	}, nil
   156  }
   157  
   158  func (plugin *iscsiPlugin) NewDeviceUnmounter() (volume.DeviceUnmounter, error) {
   159  	return plugin.NewDetacher()
   160  }
   161  
   162  func (detacher *iscsiDetacher) Detach(volumeName string, nodeName types.NodeName) error {
   163  	return nil
   164  }
   165  
   166  func (detacher *iscsiDetacher) UnmountDevice(deviceMountPath string) error {
   167  	unMounter := volumeSpecToUnmounter(detacher.mounter, detacher.host, detacher.plugin)
   168  	err := detacher.manager.DetachDisk(*unMounter, deviceMountPath)
   169  	if err != nil {
   170  		return fmt.Errorf("iscsi: failed to detach disk: %s\nError: %v", deviceMountPath, err)
   171  	}
   172  	klog.V(4).Infof("iscsi: %q is unmounted, deleting the directory", deviceMountPath)
   173  	err = os.RemoveAll(deviceMountPath)
   174  	if err != nil {
   175  		return fmt.Errorf("iscsi: failed to delete the directory: %s\nError: %v", deviceMountPath, err)
   176  	}
   177  	klog.V(4).Infof("iscsi: successfully detached disk: %s", deviceMountPath)
   178  	return nil
   179  }
   180  
   181  func (plugin *iscsiPlugin) CanAttach(spec *volume.Spec) (bool, error) {
   182  	return true, nil
   183  }
   184  
   185  func (plugin *iscsiPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
   186  	return true, nil
   187  }
   188  
   189  func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost, targetLocks keymutex.KeyMutex, pod *v1.Pod) (*iscsiDiskMounter, error) {
   190  	var secret map[string]string
   191  	readOnly, fsType, err := getISCSIVolumeInfo(spec)
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  	var podUID types.UID
   196  	if pod != nil {
   197  		secret, err = createSecretMap(spec, &iscsiPlugin{host: host, targetLocks: targetLocks}, pod.Namespace)
   198  		if err != nil {
   199  			return nil, err
   200  		}
   201  		podUID = pod.UID
   202  	}
   203  	iscsiDisk, err := createISCSIDisk(spec,
   204  		podUID,
   205  		&iscsiPlugin{host: host, targetLocks: targetLocks},
   206  		&ISCSIUtil{},
   207  		secret,
   208  	)
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  	exec := host.GetExec(iscsiPluginName)
   213  
   214  	volumeMode, err := volumeutil.GetVolumeMode(spec)
   215  	if err != nil {
   216  		return nil, err
   217  	}
   218  
   219  	klog.V(5).Infof("iscsi: VolumeSpecToMounter volumeMode %s", volumeMode)
   220  	return &iscsiDiskMounter{
   221  		iscsiDisk:  iscsiDisk,
   222  		fsType:     fsType,
   223  		volumeMode: volumeMode,
   224  		readOnly:   readOnly,
   225  		mounter:    &mount.SafeFormatAndMount{Interface: host.GetMounter(iscsiPluginName), Exec: exec},
   226  		exec:       exec,
   227  		deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
   228  	}, nil
   229  }
   230  
   231  func volumeSpecToUnmounter(mounter mount.Interface, host volume.VolumeHost, plugin *iscsiPlugin) *iscsiDiskUnmounter {
   232  	exec := host.GetExec(iscsiPluginName)
   233  	return &iscsiDiskUnmounter{
   234  		iscsiDisk: &iscsiDisk{
   235  			plugin: plugin,
   236  		},
   237  		mounter:    mounter,
   238  		exec:       exec,
   239  		deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
   240  	}
   241  }
   242  

View as plain text