From 3081a3016882c7bb6f97efedc692a88c73dd296e Mon Sep 17 00:00:00 2001 From: true1064 Date: Thu, 2 Nov 2023 05:25:48 +0800 Subject: [PATCH] feat(master): hybrid cloud add mediaType property to zone (1) zone mediaType is set as the first add-in datanode's mediaType (2) once zone mediaType is set, all datanodes in the zone must be the same mediaType. (3) the cmd 'cfs-cli zone info' shows zone mediaType. Signed-off-by: true1064 --- cli/cmd/fmt.go | 1 + datanode/server.go | 15 +++------ master/api_service.go | 2 ++ master/cluster.go | 66 +++++++++++++++++++++++++++++++++++---- master/cluster_task.go | 4 +-- master/config.go | 8 ++--- master/metadata_fsm_op.go | 61 ++++++++++++++++++------------------ master/topology.go | 20 ++++++++++-- master/topology_test.go | 8 ++--- proto/admin_proto.go | 37 ++++++++++++++++++++++ 10 files changed, 164 insertions(+), 58 deletions(-) diff --git a/cli/cmd/fmt.go b/cli/cmd/fmt.go index 7c0a7e5c1..bbb8ed903 100644 --- a/cli/cmd/fmt.go +++ b/cli/cmd/fmt.go @@ -875,6 +875,7 @@ func formatZoneView(zv *proto.ZoneView) string { sb := strings.Builder{} sb.WriteString(fmt.Sprintf("Zone Name: %v\n", zv.Name)) sb.WriteString(fmt.Sprintf("Status: %v\n", zv.Status)) + sb.WriteString(fmt.Sprintf("MediaType: %v\n", zv.MediaType)) sb.WriteString("Nodeset Selector:\n") sb.WriteString(fmt.Sprintf(" Data:%v\n", zv.DataNodesetSelector)) sb.WriteString(fmt.Sprintf(" Meta:%v\n", zv.MetaNodesetSelector)) diff --git a/datanode/server.go b/datanode/server.go index 3e9860196..48a26dfe7 100644 --- a/datanode/server.go +++ b/datanode/server.go @@ -18,6 +18,8 @@ import ( "bytes" "errors" "fmt" + syslog "log" + "math" "net" "net/http" "os" @@ -31,8 +33,6 @@ import ( "syscall" "time" - syslog "log" - "github.com/cubefs/cubefs/cmd/common" "github.com/cubefs/cubefs/proto" "github.com/cubefs/cubefs/raftstore" @@ -418,14 +418,9 @@ func (s *DataNode) parseConfig(cfg *config.Config) (err error) { s.diskUnavailablePartitionErrorCount = uint64(diskUnavailablePartitionErrorCount) log.LogDebugf("action[parseConfig] load diskUnavailablePartitionErrorCount(%v)", s.diskUnavailablePartitionErrorCount) - mediaType := cfg.GetInt64(ConfigMediaType) - switch uint32(mediaType) { - case proto.MediaType_SSD: - s.mediaType = proto.MediaType_SSD - case proto.MediaType_HDD: - s.mediaType = proto.MediaType_HDD - default: - s.mediaType = proto.MediaType_Unspecified + var mediaType uint32 + mediaTypeInt64 := cfg.GetInt64(ConfigMediaType) + if mediaTypeInt64 < 0 || mediaTypeInt64 > math.MaxUint32 { err = fmt.Errorf("parseConfig: invalid mediaType[%v]", mediaType) return err } diff --git a/master/api_service.go b/master/api_service.go index 76e8dfb54..a3ae59bf7 100644 --- a/master/api_service.go +++ b/master/api_service.go @@ -103,6 +103,7 @@ type ZoneView struct { DataNodesetSelector string MetaNodesetSelector string NodeSet map[uint64]*NodeSetView + MediaType string } func newZoneView(name string) *ZoneView { @@ -360,6 +361,7 @@ func (m *Server) getTopology(w http.ResponseWriter, r *http.Request) { cv.Status = zone.getStatusToString() cv.DataNodesetSelector = zone.GetDataNodesetSelector() cv.MetaNodesetSelector = zone.GetMetaNodesetSelector() + cv.MediaType = zone.GetMediaTypeString() tv.Zones = append(tv.Zones, cv) nsc := zone.getAllNodeSet() for _, ns := range nsc { diff --git a/master/cluster.go b/master/cluster.go index b3a33b283..aa41e6b26 100644 --- a/master/cluster.go +++ b/master/cluster.go @@ -461,8 +461,8 @@ func (c *Cluster) scheduleToUpdateStatInfo() { func (c *Cluster) addNodeSetGrp(ns *nodeSet, load bool) (err error) { log.LogWarnf("addNodeSetGrp nodeSet id[%v] zonename[%v] load[%v] grpManager init[%v]", - ns.ID, ns.zoneName, load, c.domainManager.init) + if c.domainManager.init { err = c.domainManager.putNodeSet(ns, load) c.putZoneDomain(false) @@ -1135,7 +1135,7 @@ func (c *Cluster) addMetaNode(nodeAddr, zoneName string, nodesetId uint64) (id u metaNode.MpCntLimit = newLimitCounter(&c.cfg.MaxMpCntLimit, defaultMaxMpCntLimit) zone, err := c.t.getZone(zoneName) if err != nil { - zone = c.t.putZoneIfAbsent(newZone(zoneName)) + zone = c.t.putZoneIfAbsent(newZone(zoneName, proto.MediaType_Unspecified)) } var ns *nodeSet @@ -1187,23 +1187,77 @@ func (c *Cluster) addDataNode(nodeAddr, zoneName string, nodesetId uint64, media c.dnMutex.Lock() defer c.dnMutex.Unlock() var dataNode *DataNode + var needPersistZone bool + log.LogInfof("[addDataNode] to add: datanode(%v) zone(%v) nodesetId(%v) mediaType(%v)", + nodeAddr, zoneName, nodesetId, mediaType) + if node, ok := c.dataNodes.Load(nodeAddr); ok { dataNode = node.(*DataNode) if nodesetId > 0 && nodesetId != dataNode.NodeSetID { - return dataNode.ID, fmt.Errorf("addr already in nodeset [%v]", nodeAddr) + msg := fmt.Sprintf("datanode(%v) already in cluster, but nodesetId not match, existNodeSetID(%v) toAdd(%v)", + nodeAddr, dataNode.NodeSetID, nodesetId) + log.LogErrorf("[addDataNode] %v", msg) + return dataNode.ID, fmt.Errorf(msg) } + + if dataNode.MediaType != mediaType { + msg := fmt.Sprintf("datanode(%v) already in cluster, but datanode mediaType not match, existMediaType(%v) toAdd(%v)", + nodeAddr, proto.MediaTypeString(dataNode.MediaType), proto.MediaTypeString(mediaType)) + log.LogErrorf("[addDataNode] %v", msg) + return dataNode.ID, fmt.Errorf(msg) + } + + log.LogInfof("[addDataNode] already exist: datanode(%v) zone(%v) nodesetId(%v) mediaType(%v)", + nodeAddr, zoneName, nodesetId, mediaType) return dataNode.ID, nil } + if !proto.IsValidMediaType(mediaType) { + msg := fmt.Sprintf("invalid mediaType(%v) when adding datanode(%v)", mediaType, nodeAddr) + log.LogErrorf("[addDataNode] %v", msg) + return dataNode.ID, fmt.Errorf(msg) + } + dataNode = newDataNode(nodeAddr, zoneName, c.Name, mediaType) dataNode.DpCntLimit = newLimitCounter(&c.cfg.MaxDpCntLimit, defaultMaxDpCntLimit) zone, err := c.t.getZone(zoneName) if err != nil { - zone = c.t.putZoneIfAbsent(newZone(zoneName)) + log.LogInfof("[addDataNode] create zone(%v) by datanode(%v)", zoneName, nodeAddr) + zone = newZone(zoneName, mediaType) + needPersistZone = true } + + zoneMediaType := zone.GetMediaType() + if zoneMediaType != mediaType { + if zoneMediaType != proto.MediaType_Unspecified { + // if zone.mediaType is proto.MediaType_Unspecified, means has no datanode added into the zone yet + + msg := fmt.Sprintf("datanode(%v) already in zone(%v) mediaType not match, existMediaType(%v) toAdd(%v)", + nodeAddr, zoneName, proto.MediaTypeString(zoneMediaType), proto.MediaTypeString(mediaType)) + log.LogErrorf("[addDataNode] %v", msg) + return dataNode.ID, fmt.Errorf(msg) + } else { + zone.SetMediaType(mediaType) + log.LogInfof("[addDataNode] set zone(%v) mediaType(%v) by datanode(%v)", + zoneName, proto.MediaTypeString(mediaType), nodeAddr) + needPersistZone = true + } + } + + if needPersistZone { + persistErr := c.sycnPutZoneInfo(zone) + if persistErr != nil { + msg := fmt.Sprintf("persist zone(%v) failed when adding datanode(%v)", zoneName, nodeAddr) + log.LogErrorf("[addDataNode] %v", msg) + return dataNode.ID, fmt.Errorf(msg) + } + } + c.t.putZoneIfAbsent(zone) // put if the above code creates zone + var ns *nodeSet if nodesetId > 0 { if ns, err = zone.getNodeSet(nodesetId); err != nil { + log.LogErrorf("[addDataNode] %v", err.Error()) return nodesetId, err } } else { @@ -1237,11 +1291,11 @@ func (c *Cluster) addDataNode(nodeAddr, zoneName string, nodesetId uint64, media c.addNodeSetGrp(ns, false) c.dataNodes.Store(nodeAddr, dataNode) - log.LogInfof("action[addDataNode],clusterID[%v] dataNodeAddr:%v,nodeSetId[%v],capacity[%v]", + log.LogInfof("action[addDataNode] clusterID[%v] dataNodeAddr:%v, nodeSetId[%v], capacity[%v]", c.Name, nodeAddr, ns.ID, ns.Capacity) return errHandler: - err = fmt.Errorf("action[addDataNode],clusterID[%v] dataNodeAddr:%v err:%v ", c.Name, nodeAddr, err.Error()) + err = fmt.Errorf("action[addDataNode] clusterID[%v] dataNodeAddr:%v err:%v", c.Name, nodeAddr, err.Error()) log.LogError(errors.Stack(err)) Warn(c.Name, err.Error()) return diff --git a/master/cluster_task.go b/master/cluster_task.go index c4703de5b..c09b8e6a5 100644 --- a/master/cluster_task.go +++ b/master/cluster_task.go @@ -863,7 +863,7 @@ func (c *Cluster) adjustMetaNode(metaNode *MetaNode) { var zone *Zone zone, err = c.t.getZone(metaNode.ZoneName) if err != nil { - zone = newZone(metaNode.ZoneName) + zone = newZone(metaNode.ZoneName, proto.MediaType_Unspecified) c.t.putZone(zone) } c.nsMutex.Lock() @@ -1045,7 +1045,7 @@ func (c *Cluster) adjustDataNode(dataNode *DataNode) { var zone *Zone zone, err = c.t.getZone(dataNode.ZoneName) if err != nil { - zone = newZone(dataNode.ZoneName) + zone = newZone(dataNode.ZoneName, dataNode.MediaType) c.t.putZone(zone) } diff --git a/master/config.go b/master/config.go index 64262040d..171cc99c0 100644 --- a/master/config.go +++ b/master/config.go @@ -64,14 +64,14 @@ const ( // default value const ( defaultTobeFreedDataPartitionCount = 1000 - defaultSecondsToFreeDataPartitionAfterLoad = 5 * 60 // a data partition can only be freed after loading 5 mins - defaultIntervalToFreeDataPartition = 10 // in terms of seconds + defaultSecondsToFreeDataPartitionAfterLoad = 5 * 60 // a data partition can only be freed after loading 5 mins + defaultIntervalToFreeDataPartition = 10 // in terms of seconds defaultIntervalToCheck = 60 defaultIntervalToCheckHeartbeat = 6 defaultIntervalToCheckDataPartition = 5 defaultIntervalToCheckQos = 1 - defaultIntervalToCheckCrc = 20 * defaultIntervalToCheck // in terms of seconds - noHeartBeatTimes = 3 // number of times that no heartbeat reported + defaultIntervalToCheckCrc = 20 * defaultIntervalToCheck // in terms of seconds + noHeartBeatTimes = 3 // number of times that no heartbeat reported defaultNodeTimeOutSec = noHeartBeatTimes * defaultIntervalToCheckHeartbeat defaultDataPartitionTimeOutSec = 200 * defaultIntervalToCheckHeartbeat // datanode with massive amount of dp may cost 10-min defaultMissingDataPartitionInterval = 24 * 3600 diff --git a/master/metadata_fsm_op.go b/master/metadata_fsm_op.go index 63b0eb142..f73a8729d 100644 --- a/master/metadata_fsm_op.go +++ b/master/metadata_fsm_op.go @@ -24,8 +24,8 @@ import ( "golang.org/x/time/rate" - "github.com/cubefs/cubefs/depends/tiglabs/raft/proto" - bsProto "github.com/cubefs/cubefs/proto" + raftProto "github.com/cubefs/cubefs/depends/tiglabs/raft/proto" + "github.com/cubefs/cubefs/proto" "github.com/cubefs/cubefs/util/errors" "github.com/cubefs/cubefs/util/log" ) @@ -121,7 +121,7 @@ type metaPartitionValue struct { VolName string Hosts string OfflinePeerID uint64 - Peers []bsProto.Peer + Peers []proto.Peer IsRecover bool } @@ -146,7 +146,7 @@ type dataPartitionValue struct { PartitionID uint64 ReplicaNum uint8 Hosts string - Peers []bsProto.Peer + Peers []proto.Peer Status int8 VolID uint64 VolName string @@ -309,7 +309,7 @@ type volValue struct { EnablePosixAcl bool EnableQuota bool - EnableTransaction bsProto.TxOpMask + EnableTransaction proto.TxOpMask TxTimeout int64 TxConflictRetryNum int64 TxConflictRetryInterval int64 @@ -377,14 +377,14 @@ func newVolValue(vol *Vol) (vv *volValue) { CacheLRUInterval: vol.CacheLRUInterval, CacheRule: vol.CacheRule, VolQosEnable: vol.qosManager.qosEnable, - IopsRLimit: vol.qosManager.getQosLimit(bsProto.IopsReadType), - IopsWLimit: vol.qosManager.getQosLimit(bsProto.IopsWriteType), - FlowRlimit: vol.qosManager.getQosLimit(bsProto.FlowReadType), - FlowWlimit: vol.qosManager.getQosLimit(bsProto.FlowWriteType), - IopsRMagnify: vol.qosManager.getQosMagnify(bsProto.IopsReadType), - IopsWMagnify: vol.qosManager.getQosMagnify(bsProto.IopsWriteType), - FlowRMagnify: vol.qosManager.getQosMagnify(bsProto.FlowReadType), - FlowWMagnify: vol.qosManager.getQosMagnify(bsProto.FlowWriteType), + IopsRLimit: vol.qosManager.getQosLimit(proto.IopsReadType), + IopsWLimit: vol.qosManager.getQosLimit(proto.IopsWriteType), + FlowRlimit: vol.qosManager.getQosLimit(proto.FlowReadType), + FlowWlimit: vol.qosManager.getQosLimit(proto.FlowWriteType), + IopsRMagnify: vol.qosManager.getQosMagnify(proto.IopsReadType), + IopsWMagnify: vol.qosManager.getQosMagnify(proto.IopsWriteType), + FlowRMagnify: vol.qosManager.getQosMagnify(proto.FlowReadType), + FlowWMagnify: vol.qosManager.getQosMagnify(proto.FlowWriteType), ClientReqPeriod: vol.qosManager.ClientReqPeriod, ClientHitTriggerCnt: vol.qosManager.ClientHitTriggerCnt, @@ -994,8 +994,8 @@ func (c *Cluster) syncPutDataNode(opType uint32, dataNode *DataNode) (err error) func (c *Cluster) addRaftNode(nodeID uint64, addr string) (err error) { log.LogInfof("action[addRaftNode] nodeID: %v, addr: %v:", nodeID, addr) - peer := proto.Peer{ID: nodeID} - _, err = c.partition.ChangeMember(proto.ConfAddNode, peer, []byte(addr)) + peer := raftProto.Peer{ID: nodeID} + _, err = c.partition.ChangeMember(raftProto.ConfAddNode, peer, []byte(addr)) if err != nil { return errors.New("action[addRaftNode] error: " + err.Error()) } @@ -1005,8 +1005,8 @@ func (c *Cluster) addRaftNode(nodeID uint64, addr string) (err error) { func (c *Cluster) removeRaftNode(nodeID uint64, addr string) (err error) { log.LogInfof("action[removeRaftNode] nodeID: %v, addr: %v:", nodeID, addr) - peer := proto.Peer{ID: nodeID} - _, err = c.partition.ChangeMember(proto.ConfRemoveNode, peer, []byte(addr)) + peer := raftProto.Peer{ID: nodeID} + _, err = c.partition.ChangeMember(raftProto.ConfRemoveNode, peer, []byte(addr)) if err != nil { return errors.New("action[removeRaftNode] error: " + err.Error()) } @@ -1014,8 +1014,8 @@ func (c *Cluster) removeRaftNode(nodeID uint64, addr string) (err error) { } func (c *Cluster) updateDirChildrenNumLimit(val uint32) { - if val < bsProto.MinDirChildrenNumLimit { - val = bsProto.DefaultDirChildrenNumLimit + if val < proto.MinDirChildrenNumLimit { + val = proto.DefaultDirChildrenNumLimit } atomic.StoreUint32(&c.cfg.DirChildrenNumLimit, val) } @@ -1119,9 +1119,10 @@ func (c *Cluster) loadZoneValue() (err error) { if zone.GetMetaNodesetSelector() != cv.MetaNodesetSelector { zone.metaNodesetSelector = NewNodesetSelector(cv.MetaNodesetSelector, MetaNodeType) } - log.LogInfof("action[loadZoneValue] load zonename[%v] with limit [%v,%v,%v,%v]", - zone.name, cv.QosFlowRLimit, cv.QosIopsWLimit, cv.QosFlowWLimit, cv.QosIopsRLimit) + log.LogInfof("action[loadZoneValue] load zoneName[%v] with limit [%v,%v,%v,%v], mediaType:%v", + zone.name, cv.QosFlowRLimit, cv.QosIopsWLimit, cv.QosFlowWLimit, cv.QosIopsRLimit, proto.MediaTypeString(cv.MediaType)) zone.loadDataNodeQosLimit() + zone.SetMediaType(cv.MediaType) } return @@ -1278,7 +1279,7 @@ func (c *Cluster) loadNodeSets() (err error) { zone, err := c.t.getZone(nsv.ZoneName) if err != nil { log.LogErrorf("action[loadNodeSets], getZone err:%v", err) - zone = newZone(nsv.ZoneName) + zone = newZone(nsv.ZoneName, proto.MediaType_Unspecified) c.t.putZoneIfAbsent(zone) } ns.UpdateMaxParallel(int32(c.DecommissionLimit)) @@ -1579,7 +1580,7 @@ func (c *Cluster) loadVols() (err error) { } log.LogInfof("action[loadVols],vol[%v]", vol.Name) - if vol.Forbidden && vol.Status == bsProto.VolStatusMarkDelete { + if vol.Forbidden && vol.Status == proto.VolStatusMarkDelete { c.delayDeleteVolsInfo = append(c.delayDeleteVolsInfo, &delayDeleteVolInfo{volName: vol.Name, authKey: vol.authKey, execTime: vol.DeleteExecTime, user: vol.user}) log.LogInfof("action[loadDelayDeleteVols],vol[%v]", vol.Name) } @@ -1746,8 +1747,8 @@ type decommissionDiskValue struct { Type uint32 DecommissionCompleteTime int64 DecommissionLimit int - IgnoreDecommissionDps []bsProto.IgnoreDecommissionDP - ResidualDecommissionDps []bsProto.IgnoreDecommissionDP + IgnoreDecommissionDps []proto.IgnoreDecommissionDP + ResidualDecommissionDps []proto.IgnoreDecommissionDP DiskDisable bool } @@ -1878,19 +1879,19 @@ func (c *Cluster) loadLcNodes() (err error) { return } -func (c *Cluster) syncAddLcConf(lcConf *bsProto.LcConfiguration) (err error) { +func (c *Cluster) syncAddLcConf(lcConf *proto.LcConfiguration) (err error) { return c.syncPutLcConfInfo(opSyncAddLcConf, lcConf) } -func (c *Cluster) syncDeleteLcConf(lcConf *bsProto.LcConfiguration) (err error) { +func (c *Cluster) syncDeleteLcConf(lcConf *proto.LcConfiguration) (err error) { return c.syncPutLcConfInfo(opSyncDeleteLcConf, lcConf) } -func (c *Cluster) syncUpdateLcConf(lcConf *bsProto.LcConfiguration) (err error) { +func (c *Cluster) syncUpdateLcConf(lcConf *proto.LcConfiguration) (err error) { return c.syncPutLcConfInfo(opSyncUpdateLcConf, lcConf) } -func (c *Cluster) syncPutLcConfInfo(opType uint32, lcConf *bsProto.LcConfiguration) (err error) { +func (c *Cluster) syncPutLcConfInfo(opType uint32, lcConf *proto.LcConfiguration) (err error) { metadata := new(RaftCmd) metadata.Op = opType metadata.K = lcConfPrefix + lcConf.VolName @@ -1909,7 +1910,7 @@ func (c *Cluster) loadLcConfs() (err error) { } for _, value := range result { - lcConf := &bsProto.LcConfiguration{} + lcConf := &proto.LcConfiguration{} if err = json.Unmarshal(value, lcConf); err != nil { err = fmt.Errorf("action[loadLcConfs],value:%v,unmarshal err:%v", string(value), err) return diff --git a/master/topology.go b/master/topology.go index 736c75dad..5e45ecaa6 100644 --- a/master/topology.go +++ b/master/topology.go @@ -1390,6 +1390,7 @@ type Zone struct { QosIopsWLimit uint64 QosFlowRLimit uint64 QosFlowWLimit uint64 + mediaType uint32 sync.RWMutex } @@ -1401,9 +1402,10 @@ type zoneValue struct { QosFlowWLimit uint64 DataNodesetSelector string MetaNodesetSelector string + MediaType uint32 } -func newZone(name string) (zone *Zone) { +func newZone(name string, mediaType uint32) (zone *Zone) { zone = &Zone{name: name} zone.setStatus(normalZone) zone.dataNodes = new(sync.Map) @@ -1411,6 +1413,7 @@ func newZone(name string) (zone *Zone) { zone.nodeSetMap = make(map[uint64]*nodeSet) zone.dataNodesetSelector = NewNodesetSelector(DefaultNodesetSelectorName, DataNodeType) zone.metaNodesetSelector = NewNodesetSelector(DefaultNodesetSelectorName, MetaNodeType) + zone.SetMediaType(mediaType) return } @@ -1460,6 +1463,7 @@ func (zone *Zone) getFsmValue() *zoneValue { QosFlowWLimit: zone.QosFlowWLimit, DataNodesetSelector: zone.GetDataNodesetSelector(), MetaNodesetSelector: zone.GetMetaNodesetSelector(), + MediaType: zone.GetMediaType(), } } @@ -1484,7 +1488,7 @@ func (zone *Zone) getNodeSet(setID uint64) (ns *nodeSet, err error) { defer zone.nsLock.RUnlock() ns, ok := zone.nodeSetMap[setID] if !ok { - return nil, errors.NewErrorf("set %v not found", setID) + return nil, errors.NewErrorf("nodeset %v not found", setID) } return } @@ -1944,6 +1948,18 @@ func (zone *Zone) startDecommissionListTraverse(c *Cluster) (err error) { return } +func (zone *Zone) GetMediaType() uint32 { + return atomic.LoadUint32(&zone.mediaType) +} + +func (zone *Zone) GetMediaTypeString() string { + return proto.MediaTypeString(atomic.LoadUint32(&zone.mediaType)) +} + +func (zone *Zone) SetMediaType(newMediaType uint32) { + atomic.StoreUint32(&zone.mediaType, newMediaType) +} + type DecommissionDataPartitionList struct { mu sync.Mutex cacheMap map[uint64]*list.Element diff --git a/master/topology_test.go b/master/topology_test.go index 00b665aef..a2b7540ee 100644 --- a/master/topology_test.go +++ b/master/topology_test.go @@ -25,7 +25,7 @@ func createDataNodeForTopo(addr, zoneName string, ns *nodeSet) (dn *DataNode) { func TestSingleZone(t *testing.T) { topo := newTopology() zoneName := "test" - zone := newZone(zoneName) + zone := newZone(zoneName, proto.MediaType_Unspecified) topo.putZone(zone) c := new(Cluster) nodeSet := newNodeSet(c, 1, 6, zoneName) @@ -93,7 +93,7 @@ func TestAllocZones(t *testing.T) { // add three zones zoneName1 := testZone1 - zone1 := newZone(zoneName1) + zone1 := newZone(zoneName1, proto.MediaType_Unspecified) nodeSet1 := newNodeSet(c, 1, 6, zoneName1) zone1.putNodeSet(nodeSet1) @@ -102,7 +102,7 @@ func TestAllocZones(t *testing.T) { topo.putDataNode(createDataNodeForTopo(mds2Addr, zoneName1, nodeSet1)) zoneName2 := testZone2 - zone2 := newZone(zoneName2) + zone2 := newZone(zoneName2, proto.MediaType_Unspecified) nodeSet2 := newNodeSet(c, 2, 6, zoneName2) zone2.putNodeSet(nodeSet2) @@ -111,7 +111,7 @@ func TestAllocZones(t *testing.T) { topo.putDataNode(createDataNodeForTopo(mds4Addr, zoneName2, nodeSet2)) zoneName3 := "zone3" - zone3 := newZone(zoneName3) + zone3 := newZone(zoneName3, proto.MediaType_Unspecified) nodeSet3 := newNodeSet(c, 3, 6, zoneName3) zone3.putNodeSet(nodeSet3) diff --git a/proto/admin_proto.go b/proto/admin_proto.go index f344351b0..9359c755f 100644 --- a/proto/admin_proto.go +++ b/proto/admin_proto.go @@ -1280,6 +1280,7 @@ type ZoneView struct { DataNodesetSelector string MetaNodesetSelector string NodeSet map[uint64]*NodeSetView + MediaType string } type NodeSetView struct { @@ -1404,3 +1405,39 @@ func MediaTypeString(mediaType uint32) (value string) { } const ForbiddenMigrationRenewalPeriod = 2 * time.Minute + +func IsValidMediaType(mediaType uint32) bool { + if mediaType >= MediaType_SSD && mediaType <= MediaType_HDD { + return true + } + + return false +} + +type StorageClass uint32 + +const ( + StorageClass_Unspecified uint32 = 0 + StorageClass_Replica_SSD uint32 = 1 + StorageClass_Replica_HDD uint32 = 2 + StorageClass_Blobtore uint32 = 3 + + //Types may be added later: + //StorageClass_S3 + //StorageClass_ARCHIV + //StorageClass_HDFS +) + +var storageClassStringMap = map[uint32]string{ + StorageClass_Unspecified: "Unspecified", + StorageClass_Replica_SSD: "ReplicaSSD", + StorageClass_Replica_HDD: "ReplicaHDD", +} + +func StorageClassStringMap(storageClass uint32) (value string) { + value, ok := storageClassStringMap[storageClass] + if !ok { + value = "InvalidValue" + } + return +}