Merge pull request #14055 from rook/mergify/bp/release-1.14/pr-14036

subvolumegroup: add support for size and datapool (backport #14036)
This commit is contained in:
Travis Nielsen authored and GitHub committed 2024-04-11 15:49:57 -06:00
commit cfe61733e2
11 files changed
+168 -8

No files matched your search

@@ -32,6 +32,10 @@ spec:
distributed: 1 # distributed=<0, 1> (disabled=0)
# export: # export=<0-256> (disabled=-1)
# random: # random=[0.0, 1.0](disabled=0.0)
# Quota size of the subvolume group.
#quota: 10G
# data pool name for the subvolume group layout instead of the default data pool.
#dataPoolName: myfs-replicated
```
## Settings
@@ -48,7 +52,11 @@ If any setting is unspecified, a suitable default will be used automatically.
* `filesystemName`: The metadata name of the CephFilesystem CR where the subvolume group will be created.
* `pinning`: To distribute load across MDS ranks in predictable and stable ways. Reference: https://docs.ceph.com/en/latest/cephfs/fs-volumes/#pinning-subvolumes-and-subvolume-groups.
* `quota`: Quota size of the Ceph Filesystem subvolume group.
* `dataPoolName`: The data pool name for the subvolume group layout instead of the default data pool.
* `pinning`: To distribute load across MDS ranks in predictable and stable ways. See the Ceph doc for [Pinning subvolume groups](https://docs.ceph.com/en/latest/cephfs/fs-volumes/#pinning-subvolumes-and-subvolume-groups).
* `distributed`: Range: <0, 1>, for disabling it set to 0
* `export`: Range: <0-256>, for disabling it set to -1
* `random`: Range: [0.0, 1.0], for disabling it set to 0.0
+48
View File
@@ -1576,6 +1576,30 @@ reference <a href="https://docs.ceph.com/en/latest/cephfs/fs-volumes/#pinning-su
only one out of (export, distributed, random) can be set at a time</p>
</td>
</tr>
<tr>
<td>
<code>quota</code><br/>
<em>
k8s.io/apimachinery/pkg/api/resource.Quantity
</em>
</td>
<td>
<em>(Optional)</em>
<p>Quota size of the Ceph Filesystem subvolume group.</p>
</td>
</tr>
<tr>
<td>
<code>dataPoolName</code><br/>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>The data pool name for the Ceph Filesystem subvolume group layout, if the default CephFS pool is not desired.</p>
</td>
</tr>
</table>
</td>
</tr>
@@ -3716,6 +3740,30 @@ reference <a href="https://docs.ceph.com/en/latest/cephfs/fs-volumes/#pinning-su
only one out of (export, distributed, random) can be set at a time</p>
</td>
</tr>
<tr>
<td>
<code>quota</code><br/>
<em>
k8s.io/apimachinery/pkg/api/resource.Quantity
</em>
</td>
<td>
<em>(Optional)</em>
<p>Quota size of the Ceph Filesystem subvolume group.</p>
</td>
</tr>
<tr>
<td>
<code>dataPoolName</code><br/>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>The data pool name for the Ceph Filesystem subvolume group layout, if the default CephFS pool is not desired.</p>
</td>
</tr>
</tbody>
</table>
<h3 id="ceph.rook.io/v1.CephFilesystemSubVolumeGroupSpecPinning">CephFilesystemSubVolumeGroupSpecPinning
@@ -7983,6 +7983,9 @@ spec:
spec:
description: Spec represents the specification of a Ceph Filesystem SubVolumeGroup
properties:
dataPoolName:
description: The data pool name for the Ceph Filesystem subvolume group layout, if the default CephFS pool is not desired.
type: string
filesystemName:
description: |-
FilesystemName is the name of Ceph Filesystem SubVolumeGroup volume name. Typically it's the name of
@@ -8024,6 +8027,13 @@ spec:
x-kubernetes-validations:
- message: only one pinning type should be set
rule: (has(self.export) && !has(self.distributed) && !has(self.random)) || (!has(self.export) && has(self.distributed) && !has(self.random)) || (!has(self.export) && !has(self.distributed) && has(self.random)) || (!has(self.export) && !has(self.distributed) && !has(self.random))
quota:
anyOf:
- type: integer
- type: string
description: Quota size of the Ceph Filesystem subvolume group.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
required:
- filesystemName
type: object
+10
View File
@@ -7977,6 +7977,9 @@ spec:
spec:
description: Spec represents the specification of a Ceph Filesystem SubVolumeGroup
properties:
dataPoolName:
description: The data pool name for the Ceph Filesystem subvolume group layout, if the default CephFS pool is not desired.
type: string
filesystemName:
description: |-
FilesystemName is the name of Ceph Filesystem SubVolumeGroup volume name. Typically it's the name of
@@ -8018,6 +8021,13 @@ spec:
x-kubernetes-validations:
- message: only one pinning type should be set
rule: (has(self.export) && !has(self.distributed) && !has(self.random)) || (!has(self.export) && has(self.distributed) && !has(self.random)) || (!has(self.export) && !has(self.distributed) && has(self.random)) || (!has(self.export) && !has(self.distributed) && !has(self.random))
quota:
anyOf:
- type: integer
- type: string
description: Quota size of the Ceph Filesystem subvolume group.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
required:
- filesystemName
type: object
+4
View File
@@ -17,3 +17,7 @@ spec:
distributed: 1 # distributed=<0, 1> (disabled=0)
# export: # export=<0-256> (disabled=-1)
# random: # random=[0.0, 1.0](disabled=0.0)
# Quota size of the subvolume group.
#quota: 10G
# data pool name for the subvolume group layout instead of the default data pool.
#dataPoolName: myfs-replicated
+6
View File
@@ -3022,6 +3022,12 @@ type CephFilesystemSubVolumeGroupSpec struct {
// only one out of (export, distributed, random) can be set at a time
// +optional
Pinning CephFilesystemSubVolumeGroupSpecPinning `json:"pinning,omitempty"`
// Quota size of the Ceph Filesystem subvolume group.
// +optional
Quota *resource.Quantity `json:"quota,omitempty"`
// The data pool name for the Ceph Filesystem subvolume group layout, if the default CephFS pool is not desired.
// +optional
DataPoolName string `json:"dataPoolName"`
}
// CephFilesystemSubVolumeGroupSpecPinning represents the pinning configuration of SubVolumeGroup
+74 -4
View File
@@ -17,9 +17,11 @@ limitations under the License.
package client
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"syscall"
"github.com/pkg/errors"
cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
@@ -30,21 +32,89 @@ import (
// CreateCephFSSubVolumeGroup create a CephFS subvolume group.
// volName is the name of the Ceph FS volume, the same as the CephFilesystem CR name.
func CreateCephFSSubVolumeGroup(context *clusterd.Context, clusterInfo *ClusterInfo, volName, groupName string) error {
func CreateCephFSSubVolumeGroup(context *clusterd.Context, clusterInfo *ClusterInfo, volName, groupName string, svgSpec *cephv1.CephFilesystemSubVolumeGroupSpec) error {
logger.Infof("creating cephfs %q subvolume group %q", volName, groupName)
// [--pool_layout <data_pool_name>] [--uid <uid>] [--gid <gid>] [--mode <octal_mode>]
// [<size:int>] [--pool_layout <data_pool_name>] [--uid <uid>] [--gid <gid>] [--mode <octal_mode>]
args := []string{"fs", "subvolumegroup", "create", volName, groupName}
if svgSpec != nil {
if svgSpec.Quota != nil {
// convert the size to bytes as ceph expect the size in bytes
args = append(args, fmt.Sprintf("--size=%d", svgSpec.Quota.Value()))
}
if svgSpec.DataPoolName != "" {
args = append(args, fmt.Sprintf("--pool_layout=%s", svgSpec.DataPoolName))
}
}
svgInfo, err := getCephFSSubVolumeGroupInfo(context, clusterInfo, volName, groupName)
if err != nil {
// return error other than not found.
if code, ok := exec.ExitStatus(err); ok && code != int(syscall.ENOENT) {
return errors.Wrapf(err, "failed to create subvolume group %q in filesystem %q", groupName, volName)
}
}
// if the subvolumegroup exists, resize the subvolumegroup
if err == nil && svgSpec != nil && svgSpec.Quota != nil && svgSpec.Quota.CmpInt64(svgInfo.BytesQuota) != 0 {
err = resizeCephFSSubVolumeGroup(context, clusterInfo, volName, groupName, svgSpec)
if err != nil {
return errors.Wrapf(err, "failed to create subvolume group %q in filesystem %q", groupName, volName)
}
}
cmd := NewCephCommand(context, clusterInfo, args)
cmd.JsonOutput = false
output, err := cmd.Run()
if err != nil {
return errors.Wrapf(err, "failed to create subvolume group %q. %s", volName, output)
return errors.Wrapf(err, "failed to create subvolume group %q in filesystem %q. %s", groupName, volName, output)
}
logger.Infof("successfully created cephfs %q subvolume group %q", volName, groupName)
logger.Infof("successfully created subvolume group %q in filesystem %q", groupName, volName)
return nil
}
// resizeCephFSSubVolumeGroup resize a CephFS subvolume group.
// volName is the name of the Ceph FS volume, the same as the CephFilesystem CR name.
func resizeCephFSSubVolumeGroup(context *clusterd.Context, clusterInfo *ClusterInfo, volName, groupName string, svgSpec *cephv1.CephFilesystemSubVolumeGroupSpec) error {
logger.Infof("resizing cephfs %q subvolume group %q", volName, groupName)
// <vol_name> <group_name> <new_size> [--no-shrink]
args := []string{"fs", "subvolumegroup", "resize", volName, groupName, "--no-shrink", fmt.Sprintf("%d", svgSpec.Quota.Value())}
cmd := NewCephCommand(context, clusterInfo, args)
cmd.JsonOutput = false
output, err := cmd.Run()
if err != nil {
return errors.Wrapf(err, "failed to resize subvolume group %q in filesystem %q. %s", groupName, volName, output)
}
logger.Infof("successfully resized subvolume group %q in filesystem %q to %s", groupName, volName, svgSpec.Quota)
return nil
}
type subvolumeGroupInfo struct {
BytesQuota int64 `json:"bytes_quota"`
BytesUsed int64 `json:"bytes_used"`
DataPool string `json:"data_pool"`
}
// getCephFSSubVolumeGroupInfo get subvolumegroup info of the group name.
// volName is the name of the Ceph FS volume, the same as the CephFilesystem CR name.
func getCephFSSubVolumeGroupInfo(context *clusterd.Context, clusterInfo *ClusterInfo, volName, groupName string) (*subvolumeGroupInfo, error) {
args := []string{"fs", "subvolumegroup", "info", volName, groupName}
cmd := NewCephCommand(context, clusterInfo, args)
cmd.JsonOutput = true
output, err := cmd.Run()
if err != nil {
return nil, errors.Wrapf(err, "failed to get subvolume group %q in filesystem %q. %s", groupName, volName, output)
}
svgInfo := subvolumeGroupInfo{}
err = json.Unmarshal(output, &svgInfo)
if err != nil {
return nil, errors.Wrapf(err, "failed to unmarshal into subvolumeGroupInfo")
}
return &svgInfo, nil
}
// DeleteCephFSSubVolumeGroup delete a CephFS subvolume group.
func DeleteCephFSSubVolumeGroup(context *clusterd.Context, clusterInfo *ClusterInfo, volName, groupName string) error {
logger.Infof("deleting cephfs %q subvolume group %q", volName, groupName)
+1 -1
View File
@@ -74,7 +74,7 @@ func createFilesystem(
}
}
err := cephclient.CreateCephFSSubVolumeGroup(context, clusterInfo, fs.Name, defaultCSISubvolumeGroup)
err := cephclient.CreateCephFSSubVolumeGroup(context, clusterInfo, fs.Name, defaultCSISubvolumeGroup, nil)
if err != nil {
return errors.Wrapf(err, "failed to create subvolume group %q", defaultCSISubvolumeGroup)
}
@@ -233,6 +233,8 @@ func fsExecutor(t *testing.T, fsName, configDir string, multiFS bool, createData
return `{"standbys":[], "filesystems":[]}`, nil
} else if reflect.DeepEqual(args[0:5], []string{"fs", "subvolumegroup", "create", fsName, defaultCSISubvolumeGroup}) {
return "", nil
} else if reflect.DeepEqual(args[0:5], []string{"fs", "subvolumegroup", "info", fsName, defaultCSISubvolumeGroup}) {
return "", nil
} else if contains(args, "osd") && contains(args, "lspools") {
return "[]", nil
} else if contains(args, "mds") && contains(args, "fail") {
@@ -318,7 +318,7 @@ func (r *ReconcileCephFilesystemSubVolumeGroup) updateClusterConfig(cephFilesyst
func (r *ReconcileCephFilesystemSubVolumeGroup) createOrUpdateSubVolumeGroup(cephFilesystemSubVolumeGroup *cephv1.CephFilesystemSubVolumeGroup) error {
logger.Infof("creating ceph filesystem subvolume group %s in namespace %s", cephFilesystemSubVolumeGroup.Name, cephFilesystemSubVolumeGroup.Namespace)
err := cephclient.CreateCephFSSubVolumeGroup(r.context, r.clusterInfo, cephFilesystemSubVolumeGroup.Spec.FilesystemName, getSubvolumeGroupName(cephFilesystemSubVolumeGroup))
err := cephclient.CreateCephFSSubVolumeGroup(r.context, r.clusterInfo, cephFilesystemSubVolumeGroup.Spec.FilesystemName, getSubvolumeGroupName(cephFilesystemSubVolumeGroup), &cephFilesystemSubVolumeGroup.Spec)
if err != nil {
return errors.Wrapf(err, "failed to create ceph filesystem subvolume group %q", cephFilesystemSubVolumeGroup.Name)
}
+3 -1
View File
@@ -652,7 +652,9 @@ metadata:
name: ` + groupName + `
namespace: ` + m.settings.Namespace + `
spec:
filesystemName: ` + fsName
filesystemName: ` + fsName + `
quota: 10G
dataPoolName: ` + fsName + "-data0"
}
func (m *CephManifestsMaster) GetCOSIDriver() string {