Fix/copy before delete replication (#6064)

* fix(shell): volume.fix.replication misplaced volumes unsatisfying replication factor

* fix(shell): simplify replication check

* fix(shell): add test for satisfyReplicaCurrentLocation
This commit is contained in:
Max Denushev 2024-09-26 18:34:13 +03:00 committed by GitHub
parent ae8c6d95a6
commit f1e700ce2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 109 additions and 1 deletions

View File

@ -99,7 +99,7 @@ func (c *commandVolumeFixReplication) Do(args []string, commandEnv *CommandEnv,
replica := replicas[0]
replicaPlacement, _ := super_block.NewReplicaPlacementFromByte(byte(replica.info.ReplicaPlacement))
switch {
case replicaPlacement.GetCopyCount() > len(replicas):
case replicaPlacement.GetCopyCount() > len(replicas) || !satisfyReplicaCurrentLocation(replicaPlacement, replicas):
underReplicatedVolumeIds = append(underReplicatedVolumeIds, vid)
case isMisplaced(replicas, replicaPlacement):
misplacedVolumeIds = append(misplacedVolumeIds, vid)
@ -377,6 +377,27 @@ func keepDataNodesSorted(dataNodes []location, diskType types.DiskType) {
})
}
func satisfyReplicaCurrentLocation(replicaPlacement *super_block.ReplicaPlacement, replicas []*VolumeReplica) bool {
existingDataCenters, existingRacks, _ := countReplicas(replicas)
if replicaPlacement.DiffDataCenterCount+1 > len(existingDataCenters) {
return false
}
if replicaPlacement.DiffRackCount+1 > len(existingRacks) {
return false
}
if replicaPlacement.SameRackCount > 0 {
foundSatisfyRack := false
for _, rackCount := range existingRacks {
if rackCount >= replicaPlacement.SameRackCount+1 {
foundSatisfyRack = true
}
}
return foundSatisfyRack
}
return true
}
/*
if on an existing data node {
return false

View File

@ -438,3 +438,90 @@ func TestPickingMisplacedVolumeToDelete(t *testing.T) {
}
}
func TestSatisfyReplicaCurrentLocation(t *testing.T) {
var tests = []testcase{
{
name: "test 001",
replication: "001",
replicas: []*VolumeReplica{
{
location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
},
{
location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
},
},
expected: false,
},
{
name: "test 010",
replication: "010",
replicas: []*VolumeReplica{
{
location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
},
{
location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
},
},
expected: true,
},
{
name: "test 011",
replication: "011",
replicas: []*VolumeReplica{
{
location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
},
{
location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn2"}},
},
{
location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn3"}},
},
},
expected: true,
},
{
name: "test 110",
replication: "110",
replicas: []*VolumeReplica{
{
location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
},
{
location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn2"}},
},
{
location: &location{"dc2", "r2", &master_pb.DataNodeInfo{Id: "dn3"}},
},
},
expected: true,
},
{
name: "test 100",
replication: "100",
replicas: []*VolumeReplica{
{
location: &location{"dc1", "r1", &master_pb.DataNodeInfo{Id: "dn1"}},
},
{
location: &location{"dc1", "r2", &master_pb.DataNodeInfo{Id: "dn2"}},
},
},
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
replicaPlacement, _ := super_block.NewReplicaPlacementFromString(tt.replication)
if satisfyReplicaCurrentLocation(replicaPlacement, tt.replicas) != tt.expected {
t.Errorf("%s: expect %v %v %+v",
tt.name, tt.expected, tt.replication, tt.replicas)
}
})
}
}