k8s.io/kubernetes@v1.29.3/pkg/volume/vsphere_volume/vsphere_volume_block.go (about)

     1  //go:build !providerless
     2  // +build !providerless
     3  
     4  /*
     5  Copyright 2018 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package vsphere_volume
    21  
    22  import (
    23  	"fmt"
    24  	"path/filepath"
    25  	"strings"
    26  
    27  	"k8s.io/klog/v2"
    28  	"k8s.io/mount-utils"
    29  	utilstrings "k8s.io/utils/strings"
    30  
    31  	v1 "k8s.io/api/core/v1"
    32  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    33  	"k8s.io/apimachinery/pkg/types"
    34  	"k8s.io/kubernetes/pkg/volume"
    35  	"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
    36  )
    37  
    38  var _ volume.BlockVolumePlugin = &vsphereVolumePlugin{}
    39  
    40  func (plugin *vsphereVolumePlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, mapPath string) (*volume.Spec, error) {
    41  
    42  	pluginDir := plugin.host.GetPluginDir(plugin.GetPluginName())
    43  	blkUtil := volumepathhandler.NewBlockVolumePathHandler()
    44  	globalMapPathUUID, err := blkUtil.FindGlobalMapPathUUIDFromPod(pluginDir, mapPath, podUID)
    45  	if err != nil {
    46  		klog.Errorf("Failed to find GlobalMapPathUUID from Pod: %s with error: %+v", podUID, err)
    47  		return nil, err
    48  	}
    49  	klog.V(5).Infof("globalMapPathUUID: %v", globalMapPathUUID)
    50  	globalMapPath := filepath.Dir(globalMapPathUUID)
    51  	if len(globalMapPath) <= 1 {
    52  		return nil, fmt.Errorf("failed to get volume plugin information from globalMapPathUUID: %v", globalMapPathUUID)
    53  	}
    54  	return getVolumeSpecFromGlobalMapPath(volumeName, globalMapPath)
    55  }
    56  
    57  func getVolumeSpecFromGlobalMapPath(volumeName, globalMapPath string) (*volume.Spec, error) {
    58  	// Construct volume spec from globalMapPath
    59  	// globalMapPath example:
    60  	//   plugins/kubernetes.io/{PluginName}/{DefaultKubeletVolumeDevicesDirName}/{volumeID}
    61  	//   plugins/kubernetes.io/vsphere-volume/volumeDevices/[datastore1]\\040volumes/myDisk
    62  	volPath := filepath.Base(globalMapPath)
    63  	volPath = strings.Replace(volPath, "\\040", "", -1)
    64  	if len(volPath) <= 1 {
    65  		return nil, fmt.Errorf("failed to get volume path from global path=%s", globalMapPath)
    66  	}
    67  	block := v1.PersistentVolumeBlock
    68  	vsphereVolume := &v1.PersistentVolume{
    69  		ObjectMeta: metav1.ObjectMeta{
    70  			Name: volumeName,
    71  		},
    72  		Spec: v1.PersistentVolumeSpec{
    73  			PersistentVolumeSource: v1.PersistentVolumeSource{
    74  				VsphereVolume: &v1.VsphereVirtualDiskVolumeSource{
    75  					VolumePath: volPath,
    76  				},
    77  			},
    78  			VolumeMode: &block,
    79  		},
    80  	}
    81  	return volume.NewSpecFromPersistentVolume(vsphereVolume, true), nil
    82  }
    83  
    84  func (plugin *vsphereVolumePlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.BlockVolumeMapper, error) {
    85  	// If this called via GenerateUnmapDeviceFunc(), pod is nil.
    86  	// Pass empty string as dummy uid since uid isn't used in the case.
    87  	var uid types.UID
    88  	if pod != nil {
    89  		uid = pod.UID
    90  	}
    91  	return plugin.newBlockVolumeMapperInternal(spec, uid, &VsphereDiskUtil{}, plugin.host.GetMounter(plugin.GetPluginName()))
    92  }
    93  
    94  func (plugin *vsphereVolumePlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, manager vdManager, mounter mount.Interface) (volume.BlockVolumeMapper, error) {
    95  	volumeSource, _, err := getVolumeSource(spec)
    96  	if err != nil {
    97  		klog.Errorf("Failed to get Volume source from volume Spec: %+v with error: %+v", *spec, err)
    98  		return nil, err
    99  	}
   100  	volPath := volumeSource.VolumePath
   101  	mapper := &vsphereBlockVolumeMapper{
   102  		vsphereVolume: &vsphereVolume{
   103  			volName:         spec.Name(),
   104  			podUID:          podUID,
   105  			volPath:         volPath,
   106  			manager:         manager,
   107  			mounter:         mounter,
   108  			plugin:          plugin,
   109  			MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
   110  		},
   111  	}
   112  
   113  	blockPath, err := mapper.GetGlobalMapPath(spec)
   114  	if err != nil {
   115  		return nil, fmt.Errorf("failed to get device path: %v", err)
   116  	}
   117  	mapper.MetricsProvider = volume.NewMetricsBlock(filepath.Join(blockPath, string(podUID)))
   118  
   119  	return mapper, nil
   120  }
   121  
   122  func (plugin *vsphereVolumePlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (volume.BlockVolumeUnmapper, error) {
   123  	return plugin.newUnmapperInternal(volName, podUID, &VsphereDiskUtil{})
   124  }
   125  
   126  func (plugin *vsphereVolumePlugin) newUnmapperInternal(volName string, podUID types.UID, manager vdManager) (volume.BlockVolumeUnmapper, error) {
   127  	return &vsphereBlockVolumeUnmapper{
   128  		vsphereVolume: &vsphereVolume{
   129  			volName: volName,
   130  			podUID:  podUID,
   131  			volPath: volName,
   132  			manager: manager,
   133  			plugin:  plugin,
   134  		},
   135  	}, nil
   136  }
   137  
   138  var _ volume.BlockVolumeMapper = &vsphereBlockVolumeMapper{}
   139  
   140  type vsphereBlockVolumeMapper struct {
   141  	*vsphereVolume
   142  }
   143  
   144  var _ volume.BlockVolumeUnmapper = &vsphereBlockVolumeUnmapper{}
   145  
   146  type vsphereBlockVolumeUnmapper struct {
   147  	*vsphereVolume
   148  	volume.MetricsNil
   149  }
   150  
   151  // GetGlobalMapPath returns global map path and error
   152  // path: plugins/kubernetes.io/{PluginName}/volumeDevices/volumePath
   153  func (v *vsphereVolume) GetGlobalMapPath(spec *volume.Spec) (string, error) {
   154  	volumeSource, _, err := getVolumeSource(spec)
   155  	if err != nil {
   156  		return "", err
   157  	}
   158  	return filepath.Join(v.plugin.host.GetVolumeDevicePluginDir(vsphereVolumePluginName), string(volumeSource.VolumePath)), nil
   159  }
   160  
   161  func (v *vsphereVolume) GetPodDeviceMapPath() (string, string) {
   162  	return v.plugin.host.GetPodVolumeDeviceDir(v.podUID, utilstrings.EscapeQualifiedName(vsphereVolumePluginName)), v.volName
   163  }
   164  
   165  // SupportsMetrics returns true for vsphereBlockVolumeMapper as it initializes the
   166  // MetricsProvider.
   167  func (vbvm *vsphereBlockVolumeMapper) SupportsMetrics() bool {
   168  	return true
   169  }