subvolumegroup.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. Copyright 2021 The Rook Authors. All rights reserved.
  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. package client
  14. import (
  15. "fmt"
  16. "strconv"
  17. "github.com/pkg/errors"
  18. cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
  19. "github.com/rook/rook/pkg/clusterd"
  20. "k8s.io/apimachinery/pkg/types"
  21. )
  22. // CreateCephFSSubVolumeGroup create a CephFS subvolume group.
  23. // volName is the name of the Ceph FS volume, the same as the CephFilesystem CR name.
  24. func CreateCephFSSubVolumeGroup(context *clusterd.Context, clusterInfo *ClusterInfo, volName, groupName string) error {
  25. logger.Infof("creating cephfs %q subvolume group %q", volName, groupName)
  26. // [--pool_layout <data_pool_name>] [--uid <uid>] [--gid <gid>] [--mode <octal_mode>]
  27. args := []string{"fs", "subvolumegroup", "create", volName, groupName}
  28. cmd := NewCephCommand(context, clusterInfo, args)
  29. cmd.JsonOutput = false
  30. output, err := cmd.Run()
  31. if err != nil {
  32. return errors.Wrapf(err, "failed to create subvolume group %q. %s", volName, output)
  33. }
  34. logger.Infof("successfully created cephfs %q subvolume group %q", volName, groupName)
  35. return nil
  36. }
  37. // DeleteCephFSSubVolumeGroup delete a CephFS subvolume group.
  38. func DeleteCephFSSubVolumeGroup(context *clusterd.Context, clusterInfo *ClusterInfo, volName, groupName string) error {
  39. logger.Infof("deleting cephfs %q subvolume group %q", volName, groupName)
  40. args := []string{"fs", "subvolumegroup", "rm", volName, groupName}
  41. cmd := NewCephCommand(context, clusterInfo, args)
  42. cmd.JsonOutput = false
  43. output, err := cmd.Run()
  44. if err != nil {
  45. logger.Debugf("failed to delete subvolume group %q. %s. %v", volName, output, err)
  46. // Intentionally don't wrap the error so the caller can inspect the return code
  47. return err
  48. }
  49. logger.Infof("successfully deleted cephfs %q subvolume group %q", volName, groupName)
  50. return nil
  51. }
  52. // PinCephFSSubVolumeGroup pin the cephfs subvolume group
  53. func PinCephFSSubVolumeGroup(context *clusterd.Context, clusterInfo *ClusterInfo, volName string, cephFilesystemSubVolumeGroup *cephv1.CephFilesystemSubVolumeGroup, cephFilesystemSubVolumeGroupName string) error {
  54. // namespace is the namespace of the svg CR, name is the svg name spec otherwise svg CR name
  55. namespaceName := types.NamespacedName{Namespace: cephFilesystemSubVolumeGroup.Namespace, Name: cephFilesystemSubVolumeGroupName}
  56. logger.Infof("validating pinning configuration of cephfs subvolume group %v of filesystem %q", namespaceName, volName)
  57. err := validatePinningValues(cephFilesystemSubVolumeGroup.Spec.Pinning)
  58. if err != nil {
  59. return errors.Wrapf(err, "failed to pin subvolume group %q", cephFilesystemSubVolumeGroupName)
  60. }
  61. logger.Infof("pinning cephfs subvolume group %v of filesystem %q", namespaceName, volName)
  62. args := []string{"fs", "subvolumegroup", "pin", volName, cephFilesystemSubVolumeGroupName}
  63. if cephFilesystemSubVolumeGroup.Spec.Pinning.Distributed != nil {
  64. setting := strconv.Itoa(*cephFilesystemSubVolumeGroup.Spec.Pinning.Distributed)
  65. args = append(args, "distributed", setting)
  66. } else if cephFilesystemSubVolumeGroup.Spec.Pinning.Export != nil {
  67. setting := strconv.Itoa(*cephFilesystemSubVolumeGroup.Spec.Pinning.Export)
  68. args = append(args, "export", setting)
  69. } else if cephFilesystemSubVolumeGroup.Spec.Pinning.Random != nil {
  70. setting := strconv.FormatFloat(*cephFilesystemSubVolumeGroup.Spec.Pinning.Random, 'f', -1, 64)
  71. args = append(args, "random", setting)
  72. } else {
  73. // set by default value
  74. args = append(args, "distributed", "1")
  75. }
  76. logger.Infof("subvolume group pinning args %v", args)
  77. cmd := NewCephCommand(context, clusterInfo, args)
  78. cmd.JsonOutput = false
  79. output, err := cmd.Run()
  80. if err != nil {
  81. return errors.Wrapf(err, "failed to pin subvolume group %q. %s", cephFilesystemSubVolumeGroupName, output)
  82. }
  83. logger.Infof("successfully pinned cephfs subvolume group %v", namespaceName)
  84. return nil
  85. }
  86. func validatePinningValues(pinning cephv1.CephFilesystemSubVolumeGroupSpecPinning) error {
  87. numNils := 0
  88. var err error
  89. if pinning.Export != nil {
  90. numNils++
  91. if *pinning.Export > 256 {
  92. err = errors.Errorf("validate pinning type failed, Export: value too big %d", *pinning.Export)
  93. } else if *pinning.Export < -1 {
  94. err = errors.Errorf("validate pinning type failed, Export: negative value %d not allowed except -1", *pinning.Export)
  95. }
  96. }
  97. if pinning.Distributed != nil {
  98. numNils++
  99. if !(*pinning.Distributed == 1) && !(*pinning.Distributed == 0) {
  100. err = errors.Errorf("validate pinning type failed, Distributed: unknown value %d", *pinning.Distributed)
  101. }
  102. }
  103. if pinning.Random != nil {
  104. numNils++
  105. if (*pinning.Random < 0) || (*pinning.Random > 1.0) {
  106. err = errors.Errorf("validate pinning type failed, Random: value %.2f is not between 0.0 and 1.1 (inclusive)", *pinning.Random)
  107. }
  108. }
  109. if numNils > 1 {
  110. return fmt.Errorf("only one can be set")
  111. }
  112. if numNils == 0 {
  113. return nil // pinning disabled
  114. }
  115. return err
  116. }