aws_ebs_block.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // +build !providerless
  2. /*
  3. Copyright 2018 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. */
  14. package awsebs
  15. import (
  16. "fmt"
  17. "path/filepath"
  18. "strconv"
  19. "strings"
  20. "k8s.io/klog"
  21. "k8s.io/utils/mount"
  22. utilstrings "k8s.io/utils/strings"
  23. v1 "k8s.io/api/core/v1"
  24. "k8s.io/apimachinery/pkg/types"
  25. "k8s.io/kubernetes/pkg/volume"
  26. "k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
  27. "k8s.io/legacy-cloud-providers/aws"
  28. )
  29. var _ volume.BlockVolumePlugin = &awsElasticBlockStorePlugin{}
  30. func (plugin *awsElasticBlockStorePlugin) ConstructBlockVolumeSpec(podUID types.UID, volumeName, mapPath string) (*volume.Spec, error) {
  31. pluginDir := plugin.host.GetVolumeDevicePluginDir(awsElasticBlockStorePluginName)
  32. blkutil := volumepathhandler.NewBlockVolumePathHandler()
  33. globalMapPathUUID, err := blkutil.FindGlobalMapPathUUIDFromPod(pluginDir, mapPath, podUID)
  34. if err != nil {
  35. return nil, err
  36. }
  37. klog.V(5).Infof("globalMapPathUUID: %s", globalMapPathUUID)
  38. globalMapPath := filepath.Dir(globalMapPathUUID)
  39. if len(globalMapPath) <= 1 {
  40. return nil, fmt.Errorf("failed to get volume plugin information from globalMapPathUUID: %v", globalMapPathUUID)
  41. }
  42. return plugin.getVolumeSpecFromGlobalMapPath(volumeName, globalMapPath)
  43. }
  44. func (plugin *awsElasticBlockStorePlugin) getVolumeSpecFromGlobalMapPath(volumeName string, globalMapPath string) (*volume.Spec, error) {
  45. // Get volume spec information from globalMapPath
  46. // globalMapPath example:
  47. // plugins/kubernetes.io/{PluginName}/{DefaultKubeletVolumeDevicesDirName}/{volumeID}
  48. // plugins/kubernetes.io/aws-ebs/volumeDevices/vol-XXXXXX
  49. pluginDir := plugin.host.GetVolumeDevicePluginDir(awsElasticBlockStorePluginName)
  50. if !strings.HasPrefix(globalMapPath, pluginDir) {
  51. return nil, fmt.Errorf("volume symlink %s is not in global plugin directory", globalMapPath)
  52. }
  53. fullVolumeID := strings.TrimPrefix(globalMapPath, pluginDir) // /vol-XXXXXX
  54. fullVolumeID = strings.TrimLeft(fullVolumeID, "/") // vol-XXXXXX
  55. vID, err := formatVolumeID(fullVolumeID)
  56. if err != nil {
  57. return nil, fmt.Errorf("failed to get AWS volume id from map path %q: %v", globalMapPath, err)
  58. }
  59. block := v1.PersistentVolumeBlock
  60. return newAWSVolumeSpec(volumeName, vID, block), nil
  61. }
  62. // NewBlockVolumeMapper creates a new volume.BlockVolumeMapper from an API specification.
  63. func (plugin *awsElasticBlockStorePlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.BlockVolumeMapper, error) {
  64. // If this is called via GenerateUnmapDeviceFunc(), pod is nil.
  65. // Pass empty string as dummy uid since uid isn't used in the case.
  66. var uid types.UID
  67. if pod != nil {
  68. uid = pod.UID
  69. }
  70. return plugin.newBlockVolumeMapperInternal(spec, uid, &AWSDiskUtil{}, plugin.host.GetMounter(plugin.GetPluginName()))
  71. }
  72. func (plugin *awsElasticBlockStorePlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, manager ebsManager, mounter mount.Interface) (volume.BlockVolumeMapper, error) {
  73. ebs, readOnly, err := getVolumeSource(spec)
  74. if err != nil {
  75. return nil, err
  76. }
  77. volumeID := aws.KubernetesVolumeID(ebs.VolumeID)
  78. partition := ""
  79. if ebs.Partition != 0 {
  80. partition = strconv.Itoa(int(ebs.Partition))
  81. }
  82. return &awsElasticBlockStoreMapper{
  83. awsElasticBlockStore: &awsElasticBlockStore{
  84. podUID: podUID,
  85. volName: spec.Name(),
  86. volumeID: volumeID,
  87. partition: partition,
  88. manager: manager,
  89. mounter: mounter,
  90. plugin: plugin,
  91. },
  92. readOnly: readOnly}, nil
  93. }
  94. func (plugin *awsElasticBlockStorePlugin) NewBlockVolumeUnmapper(volName string, podUID types.UID) (volume.BlockVolumeUnmapper, error) {
  95. return plugin.newUnmapperInternal(volName, podUID, &AWSDiskUtil{}, plugin.host.GetMounter(plugin.GetPluginName()))
  96. }
  97. func (plugin *awsElasticBlockStorePlugin) newUnmapperInternal(volName string, podUID types.UID, manager ebsManager, mounter mount.Interface) (volume.BlockVolumeUnmapper, error) {
  98. return &awsElasticBlockStoreUnmapper{
  99. awsElasticBlockStore: &awsElasticBlockStore{
  100. podUID: podUID,
  101. volName: volName,
  102. manager: manager,
  103. mounter: mounter,
  104. plugin: plugin,
  105. }}, nil
  106. }
  107. type awsElasticBlockStoreUnmapper struct {
  108. *awsElasticBlockStore
  109. }
  110. var _ volume.BlockVolumeUnmapper = &awsElasticBlockStoreUnmapper{}
  111. type awsElasticBlockStoreMapper struct {
  112. *awsElasticBlockStore
  113. readOnly bool
  114. }
  115. var _ volume.BlockVolumeMapper = &awsElasticBlockStoreMapper{}
  116. // GetGlobalMapPath returns global map path and error
  117. // path: plugins/kubernetes.io/{PluginName}/volumeDevices/volumeID
  118. // plugins/kubernetes.io/aws-ebs/volumeDevices/vol-XXXXXX
  119. func (ebs *awsElasticBlockStore) GetGlobalMapPath(spec *volume.Spec) (string, error) {
  120. volumeSource, _, err := getVolumeSource(spec)
  121. if err != nil {
  122. return "", err
  123. }
  124. return filepath.Join(ebs.plugin.host.GetVolumeDevicePluginDir(awsElasticBlockStorePluginName), string(volumeSource.VolumeID)), nil
  125. }
  126. // GetPodDeviceMapPath returns pod device map path and volume name
  127. // path: pods/{podUid}/volumeDevices/kubernetes.io~aws
  128. func (ebs *awsElasticBlockStore) GetPodDeviceMapPath() (string, string) {
  129. name := awsElasticBlockStorePluginName
  130. return ebs.plugin.host.GetPodVolumeDeviceDir(ebs.podUID, utilstrings.EscapeQualifiedName(name)), ebs.volName
  131. }