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 package volume 18 19 import ( 20 "time" 21 22 v1 "k8s.io/api/core/v1" 23 "k8s.io/apimachinery/pkg/api/resource" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/types" 26 ) 27 28 // Volume represents a directory used by pods or hosts on a node. All method 29 // implementations of methods in the volume interface must be idempotent. 30 type Volume interface { 31 // GetPath returns the path to which the volume should be mounted for the 32 // pod. 33 GetPath() string 34 35 // MetricsProvider embeds methods for exposing metrics (e.g. 36 // used, available space). 37 MetricsProvider 38 } 39 40 // BlockVolume interface provides methods to generate global map path 41 // and pod device map path. 42 type BlockVolume interface { 43 // GetGlobalMapPath returns a global map path which contains 44 // bind mount associated to a block device. 45 // ex. plugins/kubernetes.io/{PluginName}/{DefaultKubeletVolumeDevicesDirName}/{volumePluginDependentPath}/{pod uuid} 46 GetGlobalMapPath(spec *Spec) (string, error) 47 // GetPodDeviceMapPath returns a pod device map path 48 // and name of a symbolic link associated to a block device. 49 // ex. pods/{podUid}/{DefaultKubeletVolumeDevicesDirName}/{escapeQualifiedPluginName}/, {volumeName} 50 GetPodDeviceMapPath() (string, string) 51 52 // SupportsMetrics should return true if the MetricsProvider is 53 // initialized 54 SupportsMetrics() bool 55 56 // MetricsProvider embeds methods for exposing metrics (e.g. 57 // used, available space). 58 MetricsProvider 59 } 60 61 // MetricsProvider exposes metrics (e.g. used,available space) related to a 62 // Volume. 63 type MetricsProvider interface { 64 // GetMetrics returns the Metrics for the Volume. Maybe expensive for 65 // some implementations. 66 GetMetrics() (*Metrics, error) 67 } 68 69 // Metrics represents the used and available bytes of the Volume. 70 type Metrics struct { 71 // The time at which these stats were updated. 72 Time metav1.Time 73 74 // Used represents the total bytes used by the Volume. 75 // Note: For block devices this maybe more than the total size of the files. 76 Used *resource.Quantity 77 78 // Capacity represents the total capacity (bytes) of the volume's 79 // underlying storage. For Volumes that share a filesystem with the host 80 // (e.g. emptydir, hostpath) this is the size of the underlying storage, 81 // and will not equal Used + Available as the fs is shared. 82 Capacity *resource.Quantity 83 84 // Available represents the storage space available (bytes) for the 85 // Volume. For Volumes that share a filesystem with the host (e.g. 86 // emptydir, hostpath), this is the available space on the underlying 87 // storage, and is shared with host processes and other Volumes. 88 Available *resource.Quantity 89 90 // InodesUsed represents the total inodes used by the Volume. 91 InodesUsed *resource.Quantity 92 93 // Inodes represents the total number of inodes available in the volume. 94 // For volumes that share a filesystem with the host (e.g. emptydir, hostpath), 95 // this is the inodes available in the underlying storage, 96 // and will not equal InodesUsed + InodesFree as the fs is shared. 97 Inodes *resource.Quantity 98 99 // InodesFree represent the inodes available for the volume. For Volumes that share 100 // a filesystem with the host (e.g. emptydir, hostpath), this is the free inodes 101 // on the underlying storage, and is shared with host processes and other volumes 102 InodesFree *resource.Quantity 103 104 // Normal volumes are available for use and operating optimally. 105 // An abnormal volume does not meet these criteria. 106 // This field is OPTIONAL. Only some csi drivers which support NodeServiceCapability_RPC_VOLUME_CONDITION 107 // need to fill it. 108 Abnormal *bool 109 110 // The message describing the condition of the volume. 111 // This field is OPTIONAL. Only some csi drivers which support capability_RPC_VOLUME_CONDITION 112 // need to fill it. 113 Message *string 114 } 115 116 // Attributes represents the attributes of this mounter. 117 type Attributes struct { 118 ReadOnly bool 119 Managed bool 120 SELinuxRelabel bool 121 } 122 123 // MounterArgs provides more easily extensible arguments to Mounter 124 type MounterArgs struct { 125 // When FsUser is set, the ownership of the volume will be modified to be 126 // owned and writable by FsUser. Otherwise, there is no side effects. 127 // Currently only supported with projected service account tokens. 128 FsUser *int64 129 FsGroup *int64 130 FSGroupChangePolicy *v1.PodFSGroupChangePolicy 131 DesiredSize *resource.Quantity 132 SELinuxLabel string 133 } 134 135 // Mounter interface provides methods to set up/mount the volume. 136 type Mounter interface { 137 // Uses Interface to provide the path for Docker binds. 138 Volume 139 140 // SetUp prepares and mounts/unpacks the volume to a 141 // self-determined directory path. The mount point and its 142 // content should be owned by `fsUser` or 'fsGroup' so that it can be 143 // accessed by the pod. This may be called more than once, so 144 // implementations must be idempotent. 145 // It could return following types of errors: 146 // - TransientOperationFailure 147 // - UncertainProgressError 148 // - Error of any other type should be considered a final error 149 SetUp(mounterArgs MounterArgs) error 150 151 // SetUpAt prepares and mounts/unpacks the volume to the 152 // specified directory path, which may or may not exist yet. 153 // The mount point and its content should be owned by `fsUser` 154 // 'fsGroup' so that it can be accessed by the pod. This may 155 // be called more than once, so implementations must be 156 // idempotent. 157 SetUpAt(dir string, mounterArgs MounterArgs) error 158 // GetAttributes returns the attributes of the mounter. 159 // This function is called after SetUp()/SetUpAt(). 160 GetAttributes() Attributes 161 } 162 163 // Unmounter interface provides methods to cleanup/unmount the volumes. 164 type Unmounter interface { 165 Volume 166 // TearDown unmounts the volume from a self-determined directory and 167 // removes traces of the SetUp procedure. 168 TearDown() error 169 // TearDown unmounts the volume from the specified directory and 170 // removes traces of the SetUp procedure. 171 TearDownAt(dir string) error 172 } 173 174 // BlockVolumeMapper interface is a mapper interface for block volume. 175 type BlockVolumeMapper interface { 176 BlockVolume 177 } 178 179 // CustomBlockVolumeMapper interface provides custom methods to set up/map the volume. 180 type CustomBlockVolumeMapper interface { 181 BlockVolumeMapper 182 // SetUpDevice prepares the volume to the node by the plugin specific way. 183 // For most in-tree plugins, attacher.Attach() and attacher.WaitForAttach() 184 // will do necessary works. 185 // This may be called more than once, so implementations must be idempotent. 186 // SetUpDevice returns stagingPath if device setup was successful 187 SetUpDevice() (stagingPath string, err error) 188 189 // MapPodDevice maps the block device to a path and return the path. 190 // Unique device path across kubelet node reboot is required to avoid 191 // unexpected block volume destruction. 192 // If empty string is returned, the path returned by attacher.Attach() and 193 // attacher.WaitForAttach() will be used. 194 MapPodDevice() (publishPath string, err error) 195 196 // GetStagingPath returns path that was used for staging the volume 197 // it is mainly used by CSI plugins 198 GetStagingPath() string 199 } 200 201 // BlockVolumeUnmapper interface is an unmapper interface for block volume. 202 type BlockVolumeUnmapper interface { 203 BlockVolume 204 } 205 206 // CustomBlockVolumeUnmapper interface provides custom methods to cleanup/unmap the volumes. 207 type CustomBlockVolumeUnmapper interface { 208 BlockVolumeUnmapper 209 // TearDownDevice removes traces of the SetUpDevice procedure. 210 // If the plugin is non-attachable, this method detaches the volume 211 // from a node. 212 TearDownDevice(mapPath string, devicePath string) error 213 214 // UnmapPodDevice removes traces of the MapPodDevice procedure. 215 UnmapPodDevice() error 216 } 217 218 // Provisioner is an interface that creates templates for PersistentVolumes 219 // and can create the volume as a new resource in the infrastructure provider. 220 type Provisioner interface { 221 // Provision creates the resource by allocating the underlying volume in a 222 // storage system. This method should block until completion and returns 223 // PersistentVolume representing the created storage resource. 224 Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) 225 } 226 227 // Deleter removes the resource from the underlying storage provider. Calls 228 // to this method should block until the deletion is complete. Any error 229 // returned indicates the volume has failed to be reclaimed. A nil return 230 // indicates success. 231 type Deleter interface { 232 Volume 233 // This method should block until completion. 234 // deletedVolumeInUseError returned from this function will not be reported 235 // as error and it will be sent as "Info" event to the PV being deleted. The 236 // volume controller will retry deleting the volume in the next periodic 237 // sync. This can be used to postpone deletion of a volume that is being 238 // detached from a node. Deletion of such volume would fail anyway and such 239 // error would confuse users. 240 Delete() error 241 } 242 243 // Attacher can attach a volume to a node. 244 type Attacher interface { 245 DeviceMounter 246 247 // Attaches the volume specified by the given spec to the node with the given Name. 248 // On success, returns the device path where the device was attached on the 249 // node. 250 Attach(spec *Spec, nodeName types.NodeName) (string, error) 251 252 // VolumesAreAttached checks whether the list of volumes still attached to the specified 253 // node. It returns a map which maps from the volume spec to the checking result. 254 // If an error is occurred during checking, the error will be returned 255 VolumesAreAttached(specs []*Spec, nodeName types.NodeName) (map[*Spec]bool, error) 256 257 // WaitForAttach blocks until the device is attached to this 258 // node. If it successfully attaches, the path to the device 259 // is returned. Otherwise, if the device does not attach after 260 // the given timeout period, an error will be returned. 261 WaitForAttach(spec *Spec, devicePath string, pod *v1.Pod, timeout time.Duration) (string, error) 262 } 263 264 // DeviceMounterArgs provides auxiliary, optional arguments to DeviceMounter. 265 type DeviceMounterArgs struct { 266 FsGroup *int64 267 SELinuxLabel string 268 } 269 270 // DeviceMounter can mount a block volume to a global path. 271 type DeviceMounter interface { 272 // GetDeviceMountPath returns a path where the device should 273 // be mounted after it is attached. This is a global mount 274 // point which should be bind mounted for individual volumes. 275 GetDeviceMountPath(spec *Spec) (string, error) 276 277 // MountDevice mounts the disk to a global path which 278 // individual pods can then bind mount 279 // Note that devicePath can be empty if the volume plugin does not implement any of Attach and WaitForAttach methods. 280 // It could return following types of errors: 281 // - TransientOperationFailure 282 // - UncertainProgressError 283 // - Error of any other type should be considered a final error 284 MountDevice(spec *Spec, devicePath string, deviceMountPath string, deviceMounterArgs DeviceMounterArgs) error 285 } 286 287 type BulkVolumeVerifier interface { 288 // BulkVerifyVolumes checks whether the list of volumes still attached to the 289 // clusters in the node. It returns a map which maps from the volume spec to the checking result. 290 // If an error occurs during check - error should be returned and volume on nodes 291 // should be assumed as still attached. 292 BulkVerifyVolumes(volumesByNode map[types.NodeName][]*Spec) (map[types.NodeName]map[*Spec]bool, error) 293 } 294 295 // Detacher can detach a volume from a node. 296 type Detacher interface { 297 DeviceUnmounter 298 // Detach the given volume from the node with the given Name. 299 // volumeName is name of the volume as returned from plugin's 300 // GetVolumeName(). 301 Detach(volumeName string, nodeName types.NodeName) error 302 } 303 304 // DeviceUnmounter can unmount a block volume from the global path. 305 type DeviceUnmounter interface { 306 // UnmountDevice unmounts the global mount of the disk. This 307 // should only be called once all bind mounts have been 308 // unmounted. 309 UnmountDevice(deviceMountPath string) error 310 } 311