...

Source file src/k8s.io/kubernetes/pkg/volume/rbd/disk_manager.go

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

     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  }
   136  

View as plain text