disk_manager.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. //
  14. // diskManager interface and diskSetup/TearDown functions abstract commonly used procedures to setup a block volume
  15. // rbd volume implements diskManager, calls diskSetup when creating a volume, and calls diskTearDown inside volume unmounter.
  16. // TODO: consolidate, refactor, and share diskManager among iSCSI, GCE PD, and RBD
  17. //
  18. package rbd
  19. import (
  20. "fmt"
  21. "os"
  22. "k8s.io/api/core/v1"
  23. "k8s.io/apimachinery/pkg/api/resource"
  24. "k8s.io/klog"
  25. "k8s.io/kubernetes/pkg/util/mount"
  26. "k8s.io/kubernetes/pkg/volume"
  27. "k8s.io/kubernetes/pkg/volume/util"
  28. )
  29. // Abstract interface to disk operations.
  30. type diskManager interface {
  31. // MakeGlobalPDName creates global persistent disk path.
  32. MakeGlobalPDName(disk rbd) string
  33. // MakeGlobalVDPDName creates global block disk path.
  34. MakeGlobalVDPDName(disk rbd) string
  35. // Attaches the disk to the kubelet's host machine.
  36. // If it successfully attaches, the path to the device
  37. // is returned. Otherwise, an error will be returned.
  38. AttachDisk(disk rbdMounter) (string, error)
  39. // Detaches the disk from the kubelet's host machine.
  40. DetachDisk(plugin *rbdPlugin, deviceMountPath string, device string) error
  41. // Detaches the block disk from the kubelet's host machine.
  42. DetachBlockDisk(disk rbdDiskUnmapper, mntPath string) error
  43. // Creates a rbd image.
  44. CreateImage(provisioner *rbdVolumeProvisioner) (r *v1.RBDPersistentVolumeSource, volumeSizeGB int, err error)
  45. // Deletes a rbd image.
  46. DeleteImage(deleter *rbdVolumeDeleter) error
  47. // Expands a rbd image
  48. ExpandImage(expander *rbdVolumeExpander, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error)
  49. }
  50. // utility to mount a disk based filesystem
  51. func diskSetUp(manager diskManager, b rbdMounter, volPath string, mounter mount.Interface, fsGroup *int64) error {
  52. globalPDPath := manager.MakeGlobalPDName(*b.rbd)
  53. notMnt, err := mounter.IsLikelyNotMountPoint(globalPDPath)
  54. if err != nil && !os.IsNotExist(err) {
  55. klog.Errorf("cannot validate mountpoint: %s", globalPDPath)
  56. return err
  57. }
  58. if notMnt {
  59. return fmt.Errorf("no device is mounted at %s", globalPDPath)
  60. }
  61. notMnt, err = mounter.IsLikelyNotMountPoint(volPath)
  62. if err != nil && !os.IsNotExist(err) {
  63. klog.Errorf("cannot validate mountpoint: %s", volPath)
  64. return err
  65. }
  66. if !notMnt {
  67. return nil
  68. }
  69. if err := os.MkdirAll(volPath, 0750); err != nil {
  70. klog.Errorf("failed to mkdir:%s", volPath)
  71. return err
  72. }
  73. // Perform a bind mount to the full path to allow duplicate mounts of the same disk.
  74. options := []string{"bind"}
  75. if (&b).GetAttributes().ReadOnly {
  76. options = append(options, "ro")
  77. }
  78. mountOptions := util.JoinMountOptions(b.mountOptions, options)
  79. err = mounter.Mount(globalPDPath, volPath, "", mountOptions)
  80. if err != nil {
  81. klog.Errorf("failed to bind mount:%s", globalPDPath)
  82. return err
  83. }
  84. klog.V(3).Infof("rbd: successfully bind mount %s to %s with options %v", globalPDPath, volPath, mountOptions)
  85. if !b.ReadOnly {
  86. volume.SetVolumeOwnership(&b, fsGroup)
  87. }
  88. return nil
  89. }
  90. // utility to tear down a disk based filesystem
  91. func diskTearDown(manager diskManager, c rbdUnmounter, volPath string, mounter mount.Interface) error {
  92. notMnt, err := mounter.IsLikelyNotMountPoint(volPath)
  93. if err != nil && !os.IsNotExist(err) {
  94. klog.Errorf("cannot validate mountpoint: %s", volPath)
  95. return err
  96. }
  97. if notMnt {
  98. klog.V(3).Infof("volume path %s is not a mountpoint, deleting", volPath)
  99. return os.Remove(volPath)
  100. }
  101. // Unmount the bind-mount inside this pod.
  102. if err := mounter.Unmount(volPath); err != nil {
  103. klog.Errorf("failed to umount %s", volPath)
  104. return err
  105. }
  106. notMnt, mntErr := mounter.IsLikelyNotMountPoint(volPath)
  107. if mntErr != nil && !os.IsNotExist(mntErr) {
  108. klog.Errorf("IsLikelyNotMountPoint check failed: %v", mntErr)
  109. return mntErr
  110. }
  111. if notMnt {
  112. if err := os.Remove(volPath); err != nil {
  113. klog.V(2).Infof("Error removing mountpoint %s: %v", volPath, err)
  114. return err
  115. }
  116. }
  117. return nil
  118. }