feat(dp): set dpCount when create volume

Signed-off-by: lily-lee <lilylee88756@gmail.com>
This commit is contained in:
lily-lee 2024-01-04 15:11:16 +08:00 committed by leonrayang
parent 5a4727d7a4
commit f45b4cd606
13 changed files with 103 additions and 18 deletions

View File

@ -69,6 +69,7 @@ const (
CliFlagCapacity = "capacity"
CliFlagBusiness = "description"
CliFlagMPCount = "mp-count"
CliFlagDPCount = "dp-count"
CliFlagReplicaNum = "replica-num"
CliFlagSize = "size"
CliFlagVolType = "vol-type"

View File

@ -87,6 +87,7 @@ const (
cmdVolCreateUse = "create [VOLUME NAME] [USER ID]"
cmdVolCreateShort = "Create a new volume"
cmdVolDefaultMPCount = 3
cmdVolDefaultDPCount = 10
cmdVolDefaultDPSize = 120
cmdVolDefaultCapacity = 10 // 100GB
cmdVolDefaultZoneName = ""
@ -111,6 +112,7 @@ func newVolCreateCmd(client *master.MasterClient) *cobra.Command {
var optNormalZonesFirst string
var optBusiness string
var optMPCount int
var optDPCount int
var optReplicaNum string
var optDPSize int
var optVolType int
@ -176,6 +178,7 @@ func newVolCreateCmd(client *master.MasterClient) *cobra.Command {
stdout(" DefaultPriority : %v\n", normalZonesFirst)
stdout(" description : %v\n", optBusiness)
stdout(" mpCount : %v\n", optMPCount)
stdout(" dpCount : %v\n", optDPCount)
stdout(" replicaNum : %v\n", optReplicaNum)
stdout(" dpSize : %v G\n", optDPSize)
stdout(" volType : %v\n", optVolType)
@ -206,7 +209,7 @@ func newVolCreateCmd(client *master.MasterClient) *cobra.Command {
err = client.AdminAPI().CreateVolName(
volumeName, userID, optCapacity, optDeleteLockTime, crossZone, normalZonesFirst, optBusiness,
optMPCount, int(replicaNum), optDPSize, optVolType, followerRead,
optMPCount, optDPCount, int(replicaNum), optDPSize, optVolType, followerRead,
optZoneName, optCacheRuleKey, optEbsBlkSize, optCacheCap,
optCacheAction, optCacheThreshold, optCacheTTL, optCacheHighWater,
optCacheLowWater, optCacheLRUInterval, dpReadOnlyWhenVolFull,
@ -223,6 +226,7 @@ func newVolCreateCmd(client *master.MasterClient) *cobra.Command {
cmd.Flags().StringVar(&optNormalZonesFirst, CliNormalZonesFirst, cmdVolDefaultCrossZone, "Write to normal zone first")
cmd.Flags().StringVar(&optBusiness, CliFlagBusiness, cmdVolDefaultBusiness, "Description")
cmd.Flags().IntVar(&optMPCount, CliFlagMPCount, cmdVolDefaultMPCount, "Specify init meta partition count")
cmd.Flags().IntVar(&optDPCount, CliFlagDPCount, cmdVolDefaultDPCount, "Specify init data partition count")
cmd.Flags().StringVar(&optReplicaNum, CliFlagReplicaNum, "", "Specify data partition replicas number(default 3 for normal volume,1 for low volume)")
cmd.Flags().IntVar(&optDPSize, CliFlagDataPartitionSize, cmdVolDefaultDPSize, "Specify data partition size[Unit: GB]")
cmd.Flags().IntVar(&optVolType, CliFlagVolType, cmdVolDefaultVolType, "Type of volume (default 0)")

View File

@ -24,6 +24,7 @@ CubeFS以 **Owner**参数作为用户ID。
| capacity | int | 卷的配额,单位是GB | 是 | 无 |
| owner | string | 卷的所有者同时也是用户ID | 是 | 无 |
| mpCount | int | 初始化元数据分片个数 | 否 | 3 |
| dpCount | int | 初始化数据分片个数 | 否 | 默认10 最大值200 |
| replicaNum | int | 副本数 | 否 | 副本卷默认3支持1,3纠删码卷默认1支持1-16个 |
| dpSize | int | 数据分片大小上限单位GB | 否 | 120 |
| enablePosixAcl | bool | 是否配置posix权限限制 | 否 | false |

View File

@ -23,8 +23,9 @@ Parameter List
| capacity | int | Volume quota, in GB | Yes | None |
| owner | string | Volume owner, also the user ID | Yes | None |
| mpCount | int | Number of initialized metadata shards | No | 3 |
| dpCount | int | Number of initialized data shards | No | default 10, maximum limit 200 |
| replicaNum | int | Number of replicas | No | 3 for replica volume (supports 1, 3), 1 for erasure-coded volume (supports 1-16) |
| dpSize | int | Maximum data shard size, in GB | No | 120 |
| dpSize | int | Maximum data shard size, in GB | No | 120 |
| enablePosixAcl | bool | Whether to configure POSIX permission restrictions | No | false |
| followerRead | bool | Whether to allow reading data from followers, true by default for erasure-coded volume | No | false |
| crossZone | bool | Whether to cross regions. If set to true, the zoneName parameter cannot be set | No | false |
@ -56,7 +57,7 @@ When deleting a volume, all permission information related to the volume will be
Parameter List
| Parameter | Type | Description |
| Parameter | Type | Description |
|-----------|--------|----------------------------------------------------------------------------------------|
| name | string | Volume name |
| authKey | string | Calculate the 32-bit MD5 value of the owner field of vol as authentication information |
@ -325,9 +326,9 @@ Enable/Disable trash feature for the specified volume.
Parameter List
| Parameter | Type | Description | Required |
|----------|--------|---------------------------|-----|
| name | string | Volume name | Yes |
| Parameter | Type | Description | Required |
|-----------|--------|----------------------------------------------------------------------------------------|----------|
| name | string | Volume name | Yes |
| authKey | string | Calculate the 32-bit MD5 value of the owner field of vol as authentication information | Yes |
| trashInterval | int | The time interval for cleaning expired data in the trash is specified in minutes. A value of 0 indicates that the trash is disabled, while any other positive value indicates that the trash is enabled. | Yes

View File

@ -654,6 +654,7 @@ type createVolReq struct {
owner string
dpSize int
mpCount int
dpCount int
dpReplicaNum uint8
capacity int
deleteLockTime int64
@ -747,6 +748,10 @@ func parseRequestToCreateVol(r *http.Request, req *createVolReq) (err error) {
return
}
if req.dpCount, err = extractUintWithDefault(r, dataPartitionCountKey, defaultInitDataPartitionCnt); err != nil {
return
}
var parsedDpReplicaNum int
if parsedDpReplicaNum, err = extractUint(r, replicaNumKey); err != nil {
return

View File

@ -2228,6 +2228,10 @@ func (m *Server) checkCreateReq(req *createVolReq) (err error) {
return fmt.Errorf("datapartition dpSize must be bigger than 10 G")
}
if req.dpCount > maxInitDataPartitionCnt {
return fmt.Errorf("dpCount[%d] exceeds maximum limit[%d]", req.dpCount, maxInitDataPartitionCnt)
}
if proto.IsHot(req.volType) {
if req.dpReplicaNum == 0 {
req.dpReplicaNum = defaultReplicaNum

View File

@ -1491,7 +1491,6 @@ func (c *Cluster) createDataPartition(volName string, preload *DataPartitionPreL
if partitionID, err = c.idAlloc.allocateDataPartitionID(); err != nil {
goto errHandler
}
dp = newDataPartition(partitionID, dpReplicaNum, volName, vol.ID, proto.GetDpType(vol.VolType, isPreload), partitionTTL)
dp.Hosts = targetHosts
dp.Peers = targetPeers
@ -3186,8 +3185,13 @@ func (c *Cluster) createVol(req *createVolReq) (vol *Vol, err error) {
}
if vol.CacheCapacity > 0 || (proto.IsHot(vol.VolType) && vol.Capacity > 0) {
if req.dpCount > maxInitDataPartitionCnt {
err = fmt.Errorf("action[createVol] initDataPartitions failed, vol[%v], dpCount[%d] exceeds maximum limit[%d]",
req.name, req.dpCount, maxInitDataPartitionCnt)
goto errHandler
}
for retryCount := 0; readWriteDataPartitions < defaultInitMetaPartitionCount && retryCount < 3; retryCount++ {
err = vol.initDataPartitions(c)
err = vol.initDataPartitions(c, req.dpCount)
if err != nil {
log.LogError("action[createVol] init dataPartition error ",
err.Error(), retryCount, len(vol.dataPartitions.partitionMap))

View File

@ -362,3 +362,56 @@ func TestBalanceMetaPartition(t *testing.T) {
sortNodes.balanceLeader()
}
func TestCreateVolWithDpCount(t *testing.T) {
// create volume and metaNode will create mp,sleep some time to wait cluster get latest meteNode info
// cluster normal volume has 3 mps , total 3*3 =9 mp in metaNode
t.Run("dpCount != default count", func(t *testing.T) {
req := &createVolReq{
name: commonVolName + "001",
owner: "cfs",
dpSize: 3,
mpCount: 30,
dpCount: 30,
dpReplicaNum: 3,
capacity: 100,
followerRead: false,
authenticate: false,
crossZone: true,
normalZonesFirst: false,
zoneName: testZone1 + "," + testZone2,
description: "",
qosLimitArgs: &qosArgs{},
}
_, err := server.cluster.createVol(req)
require.NoError(t, err)
vol, err := server.cluster.getVol(req.name)
require.NoError(t, err)
dpCount := len(vol.dataPartitions.partitions)
require.Equal(t, req.dpCount, dpCount)
})
t.Run("dpCount > max count", func(t *testing.T) {
req := &createVolReq{
name: commonVolName + "002",
owner: "cfs",
dpSize: 3,
mpCount: 30,
dpCount: 300,
dpReplicaNum: 3,
capacity: 100,
followerRead: false,
authenticate: false,
crossZone: true,
normalZonesFirst: false,
zoneName: testZone1 + "," + testZone2,
description: "",
qosLimitArgs: &qosArgs{},
}
_, err := server.cluster.createVol(req)
require.Error(t, err)
})
}

View File

@ -35,6 +35,7 @@ const (
dirLimitKey = "dirSizeLimit"
dataPartitionSizeKey = "dpSize"
metaPartitionCountKey = "mpCount"
dataPartitionCountKey = "dpCount"
volCapacityKey = "capacity"
volDeleteLockTimeKey = "deleteLockTime"
volTypeKey = "volType"
@ -182,6 +183,7 @@ const (
intervalToWarnDataPartition = 600
intervalToLoadDataPartition = 12 * 60 * 60
defaultInitDataPartitionCnt = 10
maxInitDataPartitionCnt = 200
volExpansionRatio = 0.1
maxNumberOfDataPartitionsForExpansion = 100
EmptyCrcValue uint32 = 4045511210

View File

@ -174,10 +174,10 @@ func (s *VolumeService) volPermission(ctx context.Context, args struct {
}
func (s *VolumeService) createVolume(ctx context.Context, args struct {
Name, Owner, ZoneName, Description string
Capacity, DataPartitionSize, MpCount, DpReplicaNum uint64
FollowerRead, Authenticate, CrossZone, DefaultPriority bool
iopsRLimit, iopsWLimit, flowRlimit, flowWlimit uint64
Name, Owner, ZoneName, Description string
Capacity, DataPartitionSize, MpCount, DpCount, DpReplicaNum uint64
FollowerRead, Authenticate, CrossZone, DefaultPriority bool
iopsRLimit, iopsWLimit, flowRlimit, flowWlimit uint64
}) (*Vol, error) {
uid, per, err := permissions(ctx, ADMIN|USER)
if err != nil {
@ -196,11 +196,16 @@ func (s *VolumeService) createVolume(ctx context.Context, args struct {
return nil, fmt.Errorf("invalid arg dpReplicaNum: %v", args.DpReplicaNum)
}
if args.DpCount > maxInitDataPartitionCnt {
return nil, fmt.Errorf("invalid arg dpCount[%v], exceeds maximum limit[%d]", args.DpCount, maxInitDataPartitionCnt)
}
req := &createVolReq{
name: args.Name,
owner: args.Owner,
dpSize: int(args.DataPartitionSize),
mpCount: int(args.MpCount),
dpCount: int(args.DpCount),
dpReplicaNum: uint8(args.DpReplicaNum),
capacity: int(args.Capacity),
followerRead: args.FollowerRead,

View File

@ -494,9 +494,12 @@ func (vol *Vol) initMetaPartitions(c *Cluster, count int) (err error) {
return
}
func (vol *Vol) initDataPartitions(c *Cluster) (err error) {
func (vol *Vol) initDataPartitions(c *Cluster, dpCount int) (err error) {
if dpCount == 0 {
dpCount = defaultInitDataPartitionCnt
}
// initialize k data partitionMap at a time
err = c.batchCreateDataPartition(vol, defaultInitDataPartitionCnt, true)
err = c.batchCreateDataPartition(vol, dpCount, true)
return
}

View File

@ -74,10 +74,10 @@ type SimpleVolView struct {
}
//function begin .....
func (c *VolumeClient) CreateVolume(ctx context.Context, authenticate bool, capacity uint64, crossZone bool, dataPartitionSize uint64, description string, dpReplicaNum uint64, enableToken bool, followerRead bool, mpCount uint64, name string, owner string, zoneName string) (*Vol, error) {
func (c *VolumeClient) CreateVolume(ctx context.Context, authenticate bool, capacity uint64, crossZone bool, dataPartitionSize uint64, description string, dpReplicaNum uint64, enableToken bool, followerRead bool, mpCount uint64, dpCount uint64, name string, owner string, zoneName string) (*Vol, error) {
req := client.NewRequest(ctx, `mutation($authenticate: bool, $capacity: uint64, $crossZone: bool, $dataPartitionSize: uint64, $description: string, $dpReplicaNum: uint64, $enableToken: bool, $followerRead: bool, $mpCount: uint64, $name: string, $owner: string, $zoneName: string){
createVolume(authenticate: $authenticate, capacity: $capacity, crossZone: $crossZone, dataPartitionSize: $dataPartitionSize, description: $description, dpReplicaNum: $dpReplicaNum, enableToken: $enableToken, followerRead: $followerRead, mpCount: $mpCount, name: $name, owner: $owner, zoneName: $zoneName){
req := client.NewRequest(ctx, `mutation($authenticate: bool, $capacity: uint64, $crossZone: bool, $dataPartitionSize: uint64, $description: string, $dpReplicaNum: uint64, $enableToken: bool, $followerRead: bool, $mpCount: uint64, $dpCount: uint64, $name: string, $owner: string, $zoneName: string){
createVolume(authenticate: $authenticate, capacity: $capacity, crossZone: $crossZone, dataPartitionSize: $dataPartitionSize, description: $description, dpReplicaNum: $dpReplicaNum, enableToken: $enableToken, followerRead: $followerRead, mpCount: $mpCount, dpCount: $dpCount, name: $name, owner: $owner, zoneName: $zoneName){
capacity
createTime
dpReplicaNum
@ -130,6 +130,7 @@ func (c *VolumeClient) CreateVolume(ctx context.Context, authenticate bool, capa
req.Var("enableToken", enableToken)
req.Var("followerRead", followerRead)
req.Var("mpCount", mpCount)
req.Var("dpCount", dpCount)
req.Var("name", name)
req.Var("owner", owner)
req.Var("zoneName", zoneName)

View File

@ -429,7 +429,7 @@ func (api *AdminAPI) VolExpand(volName string, capacity uint64, authKey, clientI
}
func (api *AdminAPI) CreateVolName(volName, owner string, capacity uint64, deleteLockTime int64, crossZone, normalZonesFirst bool, business string,
mpCount, replicaNum, dpSize, volType int, followerRead bool, zoneName, cacheRuleKey string, ebsBlkSize,
mpCount, dpCount, replicaNum, dpSize, volType int, followerRead bool, zoneName, cacheRuleKey string, ebsBlkSize,
cacheCapacity, cacheAction, cacheThreshold, cacheTTL, cacheHighWater, cacheLowWater, cacheLRUInterval int,
dpReadOnlyWhenVolFull bool, txMask string, txTimeout uint32, txConflictRetryNum int64, txConflictRetryInterval int64, optEnableQuota string,
clientIDKey string) (err error) {
@ -442,6 +442,7 @@ func (api *AdminAPI) CreateVolName(volName, owner string, capacity uint64, delet
request.addParam("normalZonesFirst", strconv.FormatBool(normalZonesFirst))
request.addParam("description", business)
request.addParam("mpCount", strconv.Itoa(mpCount))
request.addParam("dpCount", strconv.Itoa(dpCount))
request.addParam("replicaNum", strconv.Itoa(replicaNum))
request.addParam("dpSize", strconv.Itoa(dpSize))
request.addParam("volType", strconv.Itoa(volType))