k8s.io/kubernetes@v1.29.3/pkg/volume/rbd/disk_manager.go (about) 1 /* 2 Copyright 2014 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 // 18 // diskManager interface and diskSetup/TearDown functions abstract commonly used procedures to setup a block volume 19 // rbd volume implements diskManager, calls diskSetup when creating a volume, and calls diskTearDown inside volume unmounter. 20 // TODO: consolidate, refactor, and share diskManager among iSCSI, GCE PD, and RBD 21 // 22 23 package rbd 24 25 import ( 26 "fmt" 27 "os" 28 29 "k8s.io/klog/v2" 30 "k8s.io/mount-utils" 31 32 v1 "k8s.io/api/core/v1" 33 "k8s.io/apimachinery/pkg/api/resource" 34 "k8s.io/kubernetes/pkg/volume" 35 "k8s.io/kubernetes/pkg/volume/util" 36 ) 37 38 // Abstract interface to disk operations. 39 type diskManager interface { 40 // MakeGlobalPDName creates global persistent disk path. 41 MakeGlobalPDName(disk rbd) string 42 // MakeGlobalVDPDName creates global block disk path. 43 MakeGlobalVDPDName(disk rbd) string 44 // Attaches the disk to the kubelet's host machine. 45 // If it successfully attaches, the path to the device 46 // is returned. Otherwise, an error will be returned. 47 AttachDisk(disk rbdMounter) (string, error) 48 // Detaches the disk from the kubelet's host machine. 49 DetachDisk(plugin *rbdPlugin, deviceMountPath string, device string) error 50 // Detaches the block disk from the kubelet's host machine. 51 DetachBlockDisk(disk rbdDiskUnmapper, mntPath string) error 52 // Creates a rbd image. 53 CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDPersistentVolumeSource, volumeSizeGB int, err error) 54 // Deletes a rbd image. 55 DeleteImage(deleter *rbdVolumeDeleter) error 56 // Expands a rbd image 57 ExpandImage(expander *rbdVolumeExpander, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error) 58 } 59 60 // utility to mount a disk based filesystem 61 func diskSetUp(manager diskManager, b rbdMounter, volPath string, mounter mount.Interface, fsGroup *int64, fsGroupChangePolicy *v1.PodFSGroupChangePolicy) error { 62 globalPDPath := manager.MakeGlobalPDName(*b.rbd) 63 notMnt, err := mounter.IsLikelyNotMountPoint(globalPDPath) 64 if err != nil && !os.IsNotExist(err) { 65 klog.Errorf("cannot validate mountpoint: %s", globalPDPath) 66 return err 67 } 68 if notMnt { 69 return fmt.Errorf("no device is mounted at %s", globalPDPath) 70 } 71 72 notMnt, err = mounter.IsLikelyNotMountPoint(volPath) 73 if err != nil && !os.IsNotExist(err) { 74 klog.Errorf("cannot validate mountpoint: %s", volPath) 75 return err 76 } 77 if !notMnt { 78 return nil 79 } 80 81 if err := os.MkdirAll(volPath, 0750); err != nil { 82 klog.Errorf("failed to mkdir:%s", volPath) 83 return err 84 } 85 // Perform a bind mount to the full path to allow duplicate mounts of the same disk. 86 options := []string{"bind"} 87 if (&b).GetAttributes().ReadOnly { 88 options = append(options, "ro") 89 } 90 mountOptions := util.JoinMountOptions(b.mountOptions, options) 91 err = mounter.Mount(globalPDPath, volPath, "", mountOptions) 92 if err != nil { 93 klog.Errorf("failed to bind mount:%s", globalPDPath) 94 return err 95 } 96 klog.V(3).Infof("rbd: successfully bind mount %s to %s with options %v", globalPDPath, volPath, mountOptions) 97 98 if !b.ReadOnly { 99 volume.SetVolumeOwnership(&b, volPath, fsGroup, fsGroupChangePolicy, util.FSGroupCompleteHook(b.plugin, nil)) 100 } 101 102 return nil 103 } 104 105 // utility to tear down a disk based filesystem 106 func diskTearDown(manager diskManager, c rbdUnmounter, volPath string, mounter mount.Interface) error { 107 notMnt, err := mounter.IsLikelyNotMountPoint(volPath) 108 if err != nil && !os.IsNotExist(err) { 109 klog.Errorf("cannot validate mountpoint: %s", volPath) 110 return err 111 } 112 if notMnt { 113 klog.V(3).Infof("volume path %s is not a mountpoint, deleting", volPath) 114 return os.Remove(volPath) 115 } 116 117 // Unmount the bind-mount inside this pod. 118 if err := mounter.Unmount(volPath); err != nil { 119 klog.Errorf("failed to unmount %s", volPath) 120 return err 121 } 122 123 notMnt, mntErr := mounter.IsLikelyNotMountPoint(volPath) 124 if mntErr != nil && !os.IsNotExist(mntErr) { 125 klog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr) 126 return mntErr 127 } 128 if notMnt { 129 if err := os.Remove(volPath); err != nil { 130 klog.V(2).Infof("Error removing mountpoint %s: %v", volPath, err) 131 return err 132 } 133 } 134 return nil 135 }