feat(master): hybrid cloud support cross zone when creating volume

Signed-off-by: true1064 <tangjingyu@oppo.com>
This commit is contained in:
true1064 2024-06-27 14:32:17 +08:00 committed by AmazingChi
parent 3b9ef65dbe
commit d7503fb7b5
4 changed files with 45 additions and 26 deletions

View File

@ -1553,7 +1553,7 @@ func (m *Server) createDataPartition(w http.ResponseWriter, r *http.Request) {
lastTotalDataPartitions = len(vol.dataPartitions.partitions)
clusterTotalDataPartitions = m.cluster.getDataPartitionCount()
// TODO:tangjingyu need to support requester to specify volStorageClass?
// TODO:tangjingyu to support assign mediaType
err = m.cluster.batchCreateDataPartition(vol, reqCreateCount, false, proto.GetMediaTypeByStorageClass(vol.volStorageClass))
rstMsg = fmt.Sprintf(" createDataPartition succeeeds. "+
"clusterLastTotalDataPartitions[%v],vol[%v] has %v data partitions previously and %v data partitions now",

View File

@ -2043,7 +2043,7 @@ func (c *Cluster) getSpecificZoneList(specifiedZone string) (zones []*Zone, err
func (c *Cluster) getHostFromNormalZone(nodeType uint32, excludeZones []string, excludeNodeSets []uint64,
excludeHosts []string, replicaNum int, zoneNumNeed int,
specifiedZoneName string, mediaType uint32) (hosts []string, peers []proto.Peer, err error,
specifiedZoneName string, dataMediaType uint32) (hosts []string, peers []proto.Peer, err error,
) {
var zonesQualified []*Zone
if replicaNum <= zoneNumNeed {
@ -2053,7 +2053,6 @@ func (c *Cluster) getHostFromNormalZone(nodeType uint32, excludeZones []string,
var specifiedZones []*Zone
var rsMgr *rsManager
if specifiedZoneName != "" {
// TODO:tangjngyu mediaType
if specifiedZones, err = c.getSpecificZoneList(specifiedZoneName); err != nil {
return
}
@ -2065,7 +2064,7 @@ func (c *Cluster) getHostFromNormalZone(nodeType uint32, excludeZones []string,
}
// get all zones that qualified
if zonesQualified, err = c.t.allocZonesForNode(rsMgr, zoneNumNeed, replicaNum, excludeZones, specifiedZones, mediaType); err != nil {
if zonesQualified, err = c.t.allocZonesForNode(rsMgr, zoneNumNeed, replicaNum, excludeZones, specifiedZones, dataMediaType); err != nil {
return
}

View File

@ -389,23 +389,21 @@ func TestCreateVolWithDpCount(t *testing.T) {
t.Run("dpCount != default count", func(t *testing.T) {
req := &createVolReq{
name: commonVolName + "001",
owner: "cfs",
dpSize: 11,
mpCount: 30,
dpCount: 30,
dpReplicaNum: 3,
capacity: 100,
followerRead: false,
authenticate: false,
// crossZone: true, //TODO: tangjingyu: hybrid cloud support crossZone
crossZone: false,
name: commonVolName + "001",
owner: "cfs",
dpSize: 11,
mpCount: 30,
dpCount: 30,
dpReplicaNum: 3,
capacity: 100,
followerRead: false,
authenticate: false,
crossZone: true,
normalZonesFirst: false,
// zoneName: testZone1 + "," + testZone2, //TODO: tangjingyu: hybrid cloud support crossZone
zoneName: testZone2,
description: "",
qosLimitArgs: &qosArgs{},
volStorageClass: defaultVolStorageClass,
zoneName: testZone1 + "," + testZone2,
description: "",
qosLimitArgs: &qosArgs{},
volStorageClass: defaultVolStorageClass,
}
// auto set allowedStorageClass[] in createVolReq

View File

@ -1379,6 +1379,24 @@ func calculateDemandWriteNodes(zoneNum int, replicaNum int, isSpecialZoneName bo
return
}
func (t *topology) pickUpZonesByMediaType(zones []*Zone, dataMediaType uint32) (zonesOfMediaType []*Zone) {
if dataMediaType == proto.MediaType_Unspecified {
log.LogDebugf("[pickUpZonesByMediaType] not require dataMediaType, zoneLen(%v)", len(zones))
zonesOfMediaType = zones
return
}
zonesOfMediaType = make([]*Zone, 0)
for _, zone := range zones {
if zone.dataMediaType == dataMediaType {
log.LogDebugf("[pickUpZonesByMediaType] pick up zone(%v), dataMediaType(%v)", zone.name, dataMediaType)
zonesOfMediaType = append(zonesOfMediaType, zone)
}
}
return zonesOfMediaType
}
// Choose the zone if it is writable and adapt to the rules for classifying zones
func (t *topology) allocZonesForNode(rsMgr *rsManager, zoneNumNeed, replicaNum int, excludeZone []string,
specialZones []*Zone, dataMediaType uint32) (zones []*Zone, err error) {
@ -1389,8 +1407,7 @@ func (t *topology) allocZonesForNode(rsMgr *rsManager, zoneNumNeed, replicaNum i
zones = t.getDomainExcludeZones()
log.LogInfof("action[allocZonesForNode] getDomainExcludeZones zones [%v]", t.domainExcludeZones)
} else if specialZones != nil && len(specialZones) > 0 {
// TODO:tangjingyu: mediaType
zones = specialZones
zones = t.pickUpZonesByMediaType(specialZones, dataMediaType)
zoneNumNeed = len(specialZones)
} else {
// if domain enable, will not enter here
@ -1421,9 +1438,15 @@ func (t *topology) allocZonesForNode(rsMgr *rsManager, zoneNumNeed, replicaNum i
// if across zone,candidateZones must be larger than or equal with 2,otherwise,must have a candidate zone
if (zoneNumNeed >= 2 && len(candidateZones) < 2) || len(candidateZones) < 1 {
log.LogError(fmt.Sprintf("action[allocZonesForNode],reqZoneNum[%v],candidateZones[%v],demandWriteNodes[%v],err:%v",
zoneNumNeed, len(candidateZones), demandWriteNodesCntPerZone, proto.ErrNoZoneToCreateMetaPartition))
return nil, proto.ErrNoZoneToCreateMetaPartition
if rsMgr.nodeType == DataNodeType {
err = proto.ErrNoZoneToCreateDataPartition
} else {
err = proto.ErrNoZoneToCreateMetaPartition
}
log.LogErrorf("action[allocZonesForNode],reqZoneNum[%v],candidateZones[%v],demandWriteNodes[%v],err:%v",
zoneNumNeed, len(candidateZones), demandWriteNodesCntPerZone, err.Error())
return nil, err
}
zones = candidateZones
err = nil
@ -1854,7 +1877,6 @@ func (zone *Zone) getDataNodeMaxTotal() (maxTotal uint64) {
return
}
// TODO:tangjingyu mediaType
func (zone *Zone) getAvailNodeHosts(nodeType uint32, excludeNodeSets []uint64, excludeHosts []string, replicaNum int) (newHosts []string, peers []proto.Peer, err error) {
if replicaNum == 0 {
return