storage.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Copyright 2019 Yunion
  2. //
  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. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package storage
  15. import (
  16. "fmt"
  17. "strings"
  18. "yunion.io/x/log"
  19. "yunion.io/x/pkg/errors"
  20. "yunion.io/x/onecloud/pkg/util/mountutils"
  21. "yunion.io/x/onecloud/pkg/util/procutils"
  22. )
  23. var (
  24. drivers = make(map[StorageType]IContainerStorage)
  25. )
  26. type StorageType string
  27. const (
  28. STORAGE_TYPE_LOCAL_RAW StorageType = "local_raw"
  29. STORAGE_TYPE_LOCAL_QCOW2 StorageType = "local_qcow2"
  30. STORAGE_TYPE_RBD StorageType = "rbd"
  31. )
  32. type IContainerStorage interface {
  33. GetType() StorageType
  34. CheckConnect(diskPath string) (string, bool, error)
  35. ConnectDisk(diskPath string) (string, error)
  36. DisconnectDisk(diskPath string, mountPoint string) error
  37. }
  38. func GetDriver(t StorageType) IContainerStorage {
  39. return drivers[t]
  40. }
  41. func RegisterDriver(drv IContainerStorage) {
  42. _, ok := drivers[drv.GetType()]
  43. if ok {
  44. panic(fmt.Sprintf("driver %s already registered", drv.GetType()))
  45. }
  46. drivers[drv.GetType()] = drv
  47. }
  48. func Mount(devPath string, mountPoint string, fsType string) error {
  49. return mountutils.Mount(devPath, mountPoint, fsType)
  50. }
  51. func MountWithResId(devPath string, mountPoint string, fsType string, resUid int, resGid int) error {
  52. opts := []string{}
  53. if resUid > 0 {
  54. opts = append(opts, fmt.Sprintf("resuid=%d", resUid))
  55. }
  56. if resGid > 0 {
  57. opts = append(opts, fmt.Sprintf("resgid=%d", resGid))
  58. }
  59. optStr := strings.Join(opts, ",")
  60. params := []string{}
  61. if len(optStr) > 0 {
  62. params = []string{"-o", optStr}
  63. }
  64. return mountutils.MountWithParams(devPath, mountPoint, fsType, params)
  65. }
  66. func Unmount(devPath string) error {
  67. return mountutils.Unmount(devPath, false)
  68. }
  69. func UnmountWithSubDirs(devPath string) error {
  70. err := mountutils.Unmount(devPath, false)
  71. if err == nil {
  72. return nil
  73. }
  74. if !strings.Contains(err.Error(), "target is busy") {
  75. return err
  76. }
  77. // found mountpoints starts with devPath
  78. out, err2 := procutils.NewRemoteCommandAsFarAsPossible("sh", "-c", fmt.Sprintf("mount | grep ' %s/' | awk '{print $3}' | tac", devPath)).Output()
  79. if err2 == nil && len(out) != 0 {
  80. mntPoints := strings.Split(string(out), "\n")
  81. for _, mntPoint := range mntPoints {
  82. if mntPoint != "" {
  83. if err := mountutils.Unmount(mntPoint, false); err != nil {
  84. return errors.Wrapf(err, "umount subdir %s", mntPoint)
  85. }
  86. log.Infof("unmount subdir %q", mntPoint)
  87. }
  88. }
  89. }
  90. if err := Unmount(devPath); err != nil {
  91. return errors.Wrapf(err, "unmount %q again", devPath)
  92. }
  93. return nil
  94. }