mirror of
https://github.com/cubefs/cubefs.git
synced 2026-08-02 02:00:56 +00:00
feat(mastercli): add API to add storageClass to volume's allowedStorageClass list
Signed-off-by: true1064 <tangjingyu@oppo.com>
This commit is contained in:
parent
5bcc78bb43
commit
9d2bf3b483
@ -16,6 +16,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -55,6 +56,7 @@ func newVolCmd(client *master.MasterClient) *cobra.Command {
|
||||
newVolSetAuditLogCmd(client),
|
||||
newVolSetTrashIntervalCmd(client),
|
||||
newVolSetDpRepairBlockSize(client),
|
||||
newVolAddAllowedStorageClassCmd(client),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
@ -1236,3 +1238,54 @@ func newVolSetTrashIntervalCmd(client *master.MasterClient) *cobra.Command {
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
var (
|
||||
cmdVolAddAllowedStorageClassUse = "addAllowedStorageClass [VOLUME] [STORAGE_CLASS_TO_ADD] [flags]"
|
||||
cmdVolAddAllowedStorageClassShort = "add a storageClass to volume's allowedStorageClass list"
|
||||
)
|
||||
|
||||
func newVolAddAllowedStorageClassCmd(client *master.MasterClient) *cobra.Command {
|
||||
var clientIDKey string
|
||||
var addAllowedStorageClass uint32
|
||||
var ascUint64 uint64
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: cmdVolAddAllowedStorageClassUse,
|
||||
Short: cmdVolAddAllowedStorageClassShort,
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
volName := args[0]
|
||||
addAllowedStorageClassStr := args[1]
|
||||
var err error
|
||||
defer func() {
|
||||
errout(err)
|
||||
}()
|
||||
|
||||
ascUint64, err = strconv.ParseUint(addAllowedStorageClassStr, 10, 32)
|
||||
if err != nil || ascUint64 > math.MaxUint32 {
|
||||
err = fmt.Errorf("parse param[addAllowedStorageClass] is not valid uint32[%d], err %v", ascUint64, err)
|
||||
return
|
||||
}
|
||||
addAllowedStorageClass = uint32(ascUint64)
|
||||
|
||||
if !proto.IsValidStorageClass(addAllowedStorageClass) {
|
||||
err = fmt.Errorf("param[addAllowedStorageClass] is not valid storageClass: %v", addAllowedStorageClass)
|
||||
return
|
||||
}
|
||||
|
||||
var vv *proto.SimpleVolView
|
||||
if vv, err = client.AdminAPI().GetVolumeSimpleInfo(volName); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = client.AdminAPI().VolAddAllowedStorageClass(volName, addAllowedStorageClass, util.CalcAuthKey(vv.Owner), clientIDKey); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
stdout("Volume add allowedStorageClass successfully\n")
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&clientIDKey, CliFlagClientIDKey, client.ClientIDKey(), CliUsageClientIDKey)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -338,8 +338,8 @@ func extractUint32WithDefault(r *http.Request, key string, def uint32) (val uint
|
||||
}
|
||||
|
||||
var valUint64 uint64
|
||||
if valUint64, err = strconv.ParseUint(str, 10, 32); err != nil || valUint64 < 0 || valUint64 > math.MaxUint32 {
|
||||
return 0, fmt.Errorf("parse [%s] is not valid uint64 [%d], err %v", key, val, err)
|
||||
if valUint64, err = strconv.ParseUint(str, 10, 32); err != nil || valUint64 > math.MaxUint32 {
|
||||
return 0, fmt.Errorf("parse [%s] is not valid uint32 [%d], err %v", key, val, err)
|
||||
}
|
||||
|
||||
val = uint32(valUint64)
|
||||
@ -1755,12 +1755,13 @@ func extractUint32(r *http.Request, key string) (val uint32, err error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var tmp uint64
|
||||
if tmp, err = strconv.ParseUint(str, 10, 32); err != nil {
|
||||
return 0, fmt.Errorf("args [%s] is not legal, val %s", key, str)
|
||||
var valUint64 uint64
|
||||
if valUint64, err = strconv.ParseUint(str, 10, 32); err != nil || valUint64 > math.MaxUint32 {
|
||||
return 0, fmt.Errorf("parse [%s] is not valid uint32 [%d], err %v", key, val, err)
|
||||
}
|
||||
|
||||
return uint32(tmp), nil
|
||||
val = uint32(valUint64)
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func extractPositiveUint64(r *http.Request, key string) (val uint64, err error) {
|
||||
|
||||
@ -7692,3 +7692,82 @@ func (m *Server) resetDecommissionDataNodeStatus(w http.ResponseWriter, r *http.
|
||||
msg := fmt.Sprintf("reset decommission status for datanode %v success", dn.Addr)
|
||||
sendOkReply(w, r, newSuccessHTTPReply(msg))
|
||||
}
|
||||
|
||||
func (m *Server) volAddAllowedStorageClass(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
name string
|
||||
authKey string
|
||||
err error
|
||||
msg string
|
||||
addAllowedStorageClass uint32
|
||||
vol *Vol
|
||||
)
|
||||
|
||||
metric := exporter.NewTPCnt(apiToMetricsName(proto.AdminVolAddAllowedStorageClass))
|
||||
defer func() {
|
||||
doStatAndMetric(proto.AdminVolAddAllowedStorageClass, metric, err, map[string]string{exporter.Vol: name})
|
||||
}()
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
sendErrReply(w, r, &proto.HTTPReply{Code: proto.ErrCodeParamError, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if name, err = extractName(r); err != nil {
|
||||
sendErrReply(w, r, &proto.HTTPReply{Code: proto.ErrCodeParamError, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if authKey, err = extractAuthKey(r); err != nil {
|
||||
sendErrReply(w, r, &proto.HTTPReply{Code: proto.ErrCodeParamError, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if addAllowedStorageClass, err = extractUint32(r, allowedStorageClassKey); err != nil {
|
||||
sendErrReply(w, r, &proto.HTTPReply{Code: proto.ErrCodeParamError, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if !proto.IsValidStorageClass(addAllowedStorageClass) {
|
||||
err = fmt.Errorf("invalid storageClass(%v)", addAllowedStorageClass)
|
||||
sendErrReply(w, r, &proto.HTTPReply{Code: proto.ErrCodeParamError, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if vol, err = m.cluster.getVol(name); err != nil {
|
||||
sendErrReply(w, r, &proto.HTTPReply{Code: proto.ErrCodeVolNotExists, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if in := vol.isStorageClassInAllowed(addAllowedStorageClass); in {
|
||||
err = fmt.Errorf("storageClass(%v) already in vol allowedStorageClass(%v)",
|
||||
addAllowedStorageClass, vol.allowedStorageClass)
|
||||
sendErrReply(w, r, &proto.HTTPReply{Code: proto.ErrCodeParamError, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
resourceChecker := NewStorageClassResourceChecker(m.cluster)
|
||||
if !resourceChecker.HasResourceOfStorageClass(addAllowedStorageClass) {
|
||||
err = fmt.Errorf("cluster has no resoure to support storageClass(%v)",
|
||||
proto.StorageClassString(addAllowedStorageClass))
|
||||
sendErrReply(w, r, &proto.HTTPReply{Code: proto.ErrCodeParamError, Msg: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
newArgs := getVolVarargs(vol)
|
||||
newArgs.allowedStorageClass = append(newArgs.allowedStorageClass, addAllowedStorageClass)
|
||||
sort.Slice(newArgs.allowedStorageClass, func(i, j int) bool {
|
||||
return newArgs.allowedStorageClass[i] < newArgs.allowedStorageClass[j]
|
||||
})
|
||||
|
||||
log.LogInfof("to add vol(%v) allowedStorageClass, old(%v), add(%v)",
|
||||
name, vol.allowedStorageClass, addAllowedStorageClass)
|
||||
|
||||
if err = m.cluster.updateVol(name, authKey, newArgs); err != nil {
|
||||
sendErrReply(w, r, newErrHTTPReply(err))
|
||||
return
|
||||
}
|
||||
|
||||
msg = fmt.Sprintf("add vol(%v) allowedStorageClass successfully", name)
|
||||
log.LogInfof("%v, added(%v), current(%v)", msg, addAllowedStorageClass, vol.allowedStorageClass)
|
||||
}
|
||||
|
||||
@ -1669,7 +1669,7 @@ func (c *Cluster) batchCreateDataPartition(vol *Vol, reqCount int, init bool, me
|
||||
}
|
||||
|
||||
if _, err = c.createDataPartition(vol.Name, nil, mediaType); err != nil {
|
||||
log.LogErrorf("action[batchCreateDataPartition] after create [%v] data partition,occurred error,err[%v]", i, err)
|
||||
log.LogErrorf("action[batchCreateDataPartition] after create [%v] data partition, occurred error,err[%v]", i, err)
|
||||
break
|
||||
}
|
||||
createdCnt++
|
||||
@ -3707,7 +3707,6 @@ func (c *Cluster) createVol(req *createVolReq) (vol *Vol, err error) {
|
||||
req.name, readWriteDataPartitions, proto.MediaTypeString(chosenMediaType))
|
||||
}
|
||||
|
||||
vol.dataPartitions.updateResponseCache(true, 0, vol.VolType)
|
||||
vol.updateViewCache(c)
|
||||
// NOTE: update dp view cache
|
||||
vol.dataPartitions.updateResponseCache(true, 0, vol)
|
||||
|
||||
@ -58,7 +58,7 @@ const (
|
||||
|
||||
cfgHttpReversePoolSize = "httpReversePoolSize"
|
||||
|
||||
cfgDefaultDataMediaType = "defaultDataMediaType" //for hybrid cloud
|
||||
cfgDefaultDataMediaType = "defaultDataMediaType" // for hybrid cloud
|
||||
)
|
||||
|
||||
// default value
|
||||
|
||||
@ -170,11 +170,12 @@ var AuthenticationUri2MsgTypeMap = map[string]proto.MsgType{
|
||||
proto.AdminSetNodeRdOnly: proto.MsgMasterSetNodeRdOnlyReq,
|
||||
|
||||
// Master API volume management
|
||||
proto.AdminCreateVol: proto.MsgMasterCreateVolReq,
|
||||
proto.AdminDeleteVol: proto.MsgMasterDeleteVolReq,
|
||||
proto.AdminUpdateVol: proto.MsgMasterUpdateVolReq,
|
||||
proto.AdminVolShrink: proto.MsgMasterVolShrinkReq,
|
||||
proto.AdminVolExpand: proto.MsgMasterVolExpandReq,
|
||||
proto.AdminCreateVol: proto.MsgMasterCreateVolReq,
|
||||
proto.AdminDeleteVol: proto.MsgMasterDeleteVolReq,
|
||||
proto.AdminUpdateVol: proto.MsgMasterUpdateVolReq,
|
||||
proto.AdminVolShrink: proto.MsgMasterVolShrinkReq,
|
||||
proto.AdminVolExpand: proto.MsgMasterVolExpandReq,
|
||||
proto.AdminVolAddAllowedStorageClass: proto.MsgMasterVolAddAllowedStorageClass,
|
||||
|
||||
// Master API meta partition management
|
||||
proto.AdminLoadMetaPartition: proto.MsgMasterLoadMetaPartitionReq,
|
||||
@ -430,6 +431,9 @@ func (m *Server) registerAPIRoutes(router *mux.Router) {
|
||||
router.NewRoute().Methods(http.MethodGet, http.MethodPost).
|
||||
Path(proto.AdminAbortDecommissionDisk).
|
||||
HandlerFunc(m.abortDecommissionDisk)
|
||||
router.NewRoute().Methods(http.MethodGet, http.MethodPost).
|
||||
Path(proto.AdminVolAddAllowedStorageClass).
|
||||
HandlerFunc(m.volAddAllowedStorageClass)
|
||||
|
||||
// multi version snapshot APIs
|
||||
router.NewRoute().Methods(http.MethodGet).
|
||||
|
||||
@ -58,6 +58,7 @@ type VolVarargs struct {
|
||||
accessTimeValidInterval int64
|
||||
enablePersistAccessTime bool
|
||||
volStorageClass uint32
|
||||
allowedStorageClass []uint32
|
||||
}
|
||||
|
||||
type CacheSubItem struct {
|
||||
@ -1701,6 +1702,7 @@ func setVolFromArgs(args *VolVarargs, vol *Vol) {
|
||||
vol.EnableAutoMetaRepair.Store(args.enableAutoDpMetaRepair)
|
||||
vol.EnablePersistAccessTime = args.enablePersistAccessTime
|
||||
vol.volStorageClass = args.volStorageClass
|
||||
vol.allowedStorageClass = append([]uint32{}, args.allowedStorageClass...)
|
||||
}
|
||||
|
||||
func getVolVarargs(vol *Vol) *VolVarargs {
|
||||
@ -1744,6 +1746,7 @@ func getVolVarargs(vol *Vol) *VolVarargs {
|
||||
enablePersistAccessTime: vol.EnablePersistAccessTime,
|
||||
enableAutoDpMetaRepair: vol.EnableAutoMetaRepair.Load(),
|
||||
volStorageClass: vol.volStorageClass,
|
||||
allowedStorageClass: append([]uint32{}, vol.allowedStorageClass...),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1814,3 +1817,16 @@ func (vol *Vol) checkDataReplicaMeta(c *Cluster) (cnt int) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (vol *Vol) isStorageClassInAllowed(storageClass uint32) (in bool) {
|
||||
vol.volLock.Lock()
|
||||
defer vol.volLock.Unlock()
|
||||
|
||||
for _, asc := range vol.allowedStorageClass {
|
||||
if asc == storageClass {
|
||||
in = true
|
||||
}
|
||||
}
|
||||
|
||||
return in
|
||||
}
|
||||
|
||||
@ -265,6 +265,8 @@ const (
|
||||
S3QoSGet = "/s3/qos/get"
|
||||
S3QoSDelete = "/s3/qos/delete"
|
||||
AdminEnablePersistAccessTime = "/vol/enablePersistAccessTime"
|
||||
|
||||
AdminVolAddAllowedStorageClass = "/vol/addAllowedStorageClass"
|
||||
)
|
||||
|
||||
var GApiInfo map[string]string = map[string]string{
|
||||
@ -284,6 +286,7 @@ var GApiInfo map[string]string = map[string]string{
|
||||
"adminupdatevol": AdminUpdateVol,
|
||||
"adminvolshrink": AdminVolShrink,
|
||||
"adminvolexpand": AdminVolExpand,
|
||||
"adminvoladdallowedstorageclass": AdminVolAddAllowedStorageClass,
|
||||
"admincreatevol": AdminCreateVol,
|
||||
"admingetvol": AdminGetVol,
|
||||
"adminclusterfreeze": AdminClusterFreeze,
|
||||
|
||||
@ -208,11 +208,12 @@ const (
|
||||
MsgMasterAutoDecommissionReq MsgType = MsgMasterAPIAccessReq + 0x20600
|
||||
|
||||
// Master API volume management
|
||||
MsgMasterCreateVolReq MsgType = MsgMasterAPIAccessReq + 0x30100
|
||||
MsgMasterDeleteVolReq MsgType = MsgMasterAPIAccessReq + 0x30200
|
||||
MsgMasterUpdateVolReq MsgType = MsgMasterAPIAccessReq + 0x30300
|
||||
MsgMasterVolShrinkReq MsgType = MsgMasterAPIAccessReq + 0x30400
|
||||
MsgMasterVolExpandReq MsgType = MsgMasterAPIAccessReq + 0x30500
|
||||
MsgMasterCreateVolReq MsgType = MsgMasterAPIAccessReq + 0x30100
|
||||
MsgMasterDeleteVolReq MsgType = MsgMasterAPIAccessReq + 0x30200
|
||||
MsgMasterUpdateVolReq MsgType = MsgMasterAPIAccessReq + 0x30300
|
||||
MsgMasterVolShrinkReq MsgType = MsgMasterAPIAccessReq + 0x30400
|
||||
MsgMasterVolExpandReq MsgType = MsgMasterAPIAccessReq + 0x30500
|
||||
MsgMasterVolAddAllowedStorageClass MsgType = MsgMasterAPIAccessReq + 0x30501
|
||||
|
||||
// Master API meta partition management
|
||||
MsgMasterLoadMetaPartitionReq MsgType = MsgMasterAPIAccessReq + 0x40100
|
||||
@ -296,11 +297,12 @@ var MsgType2ResourceMap = map[MsgType]string{
|
||||
MsgMasterAutoDecommissionReq: "master:autodecommission",
|
||||
|
||||
// Master API volume management
|
||||
MsgMasterCreateVolReq: "master:createvol",
|
||||
MsgMasterDeleteVolReq: "master:deletevol",
|
||||
MsgMasterUpdateVolReq: "master:updatevol",
|
||||
MsgMasterVolShrinkReq: "master:volshrink",
|
||||
MsgMasterVolExpandReq: "master:volexpand",
|
||||
MsgMasterCreateVolReq: "master:createvol",
|
||||
MsgMasterDeleteVolReq: "master:deletevol",
|
||||
MsgMasterUpdateVolReq: "master:updatevol",
|
||||
MsgMasterVolShrinkReq: "master:volshrink",
|
||||
MsgMasterVolExpandReq: "master:volexpand",
|
||||
MsgMasterVolAddAllowedStorageClass: "master:voladdallowedStorageClass",
|
||||
|
||||
// Master API meta partition management
|
||||
MsgMasterLoadMetaPartitionReq: "master:loadmetapartition",
|
||||
|
||||
@ -350,6 +350,18 @@ func (api *AdminAPI) VolExpand(volName string, capacity uint64, authKey, clientI
|
||||
return
|
||||
}
|
||||
|
||||
func (api *AdminAPI) VolAddAllowedStorageClass(volName string, addAllowedStorageClass uint32, authKey, clientIDKey string) (err error) {
|
||||
request := newRequest(http.MethodGet, proto.AdminVolAddAllowedStorageClass)
|
||||
request.addParam("name", volName).Header(api.h)
|
||||
request.addParam("allowedStorageClass", strconv.FormatUint(uint64(addAllowedStorageClass), 10))
|
||||
request.addParam("authKey", authKey)
|
||||
request.addParam("clientIDKey", clientIDKey)
|
||||
if _, err = api.mc.serveRequest(request); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (api *AdminAPI) CreateVolName(volName, owner string, capacity uint64, deleteLockTime int64, crossZone, normalZonesFirst bool,
|
||||
business string, mpCount, dpCount, replicaNum, dpSize int, followerRead bool, zoneName, cacheRuleKey string, ebsBlkSize,
|
||||
cacheCapacity, cacheAction, cacheThreshold, cacheTTL, cacheHighWater, cacheLowWater, cacheLRUInterval int,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user