From 5d85a424c5aeab9cee98375755befa177a248a1b Mon Sep 17 00:00:00 2001 From: chrislusf Date: Tue, 2 Dec 2025 22:18:33 -0800 Subject: [PATCH] volumeServer.evacuate: evacuate EC volumes from all disk types Remove -diskType flag from volumeServer.evacuate since evacuation should move all EC volumes regardless of disk type. The command now iterates over all disk types (HDD, SSD) and evacuates EC shards from each, moving them to destination nodes with matching disk types. --- weed/shell/command_volume_server_evacuate.go | 41 ++++++++++---------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/weed/shell/command_volume_server_evacuate.go b/weed/shell/command_volume_server_evacuate.go index 610de6c73..470a97a3d 100644 --- a/weed/shell/command_volume_server_evacuate.go +++ b/weed/shell/command_volume_server_evacuate.go @@ -23,7 +23,6 @@ type commandVolumeServerEvacuate struct { topologyInfo *master_pb.TopologyInfo targetServer *string volumeRack *string - diskType types.DiskType } func (c *commandVolumeServerEvacuate) Name() string { @@ -33,7 +32,7 @@ func (c *commandVolumeServerEvacuate) Name() string { func (c *commandVolumeServerEvacuate) Help() string { return `move out all data on a volume server - volumeServer.evacuate -node [-diskType=] + volumeServer.evacuate -node This command moves all data away from the volume server. The volumes on the volume servers will be redistributed. @@ -45,9 +44,6 @@ func (c *commandVolumeServerEvacuate) Help() string { E.g. a volume replication 001 in a cluster with 2 volume servers can not be moved. You can use "-skipNonMoveable" to move the rest volumes. - Options: - -diskType: disk type for EC shards (hdd, ssd, or empty for default hdd) - ` } @@ -63,7 +59,6 @@ func (c *commandVolumeServerEvacuate) Do(args []string, commandEnv *CommandEnv, c.targetServer = vsEvacuateCommand.String("target", "", ": of target volume") skipNonMoveable := vsEvacuateCommand.Bool("skipNonMoveable", false, "skip volumes that can not be moved") applyChange := vsEvacuateCommand.Bool("apply", false, "actually apply the changes") - diskTypeStr := vsEvacuateCommand.String("diskType", "", "disk type for EC shards (hdd, ssd, or empty for default hdd)") // TODO: remove this alias applyChangeAlias := vsEvacuateCommand.Bool("force", false, "actually apply the changes (alias for -apply)") retryCount := vsEvacuateCommand.Int("retry", 0, "how many times to retry") @@ -74,8 +69,6 @@ func (c *commandVolumeServerEvacuate) Do(args []string, commandEnv *CommandEnv, handleDeprecatedForceFlag(writer, vsEvacuateCommand, applyChangeAlias, applyChange) infoAboutSimulationMode(writer, *applyChange, "-apply") - c.diskType = types.ToDiskType(*diskTypeStr) - if err = commandEnv.confirmIsLocked(args); err != nil && *applyChange { return } @@ -164,18 +157,26 @@ func (c *commandVolumeServerEvacuate) evacuateNormalVolumes(commandEnv *CommandE } func (c *commandVolumeServerEvacuate) evacuateEcVolumes(commandEnv *CommandEnv, volumeServer string, skipNonMoveable, applyChange bool, writer io.Writer) error { - // find this ec volume server - ecNodes, _ := collectEcVolumeServersByDc(c.topologyInfo, "", c.diskType) - thisNodes, otherNodes := c.ecNodesOtherThan(ecNodes, volumeServer) - if len(thisNodes) == 0 { - return fmt.Errorf("%s is not found in this cluster\n", volumeServer) - } + // Evacuate EC volumes for all disk types + // We need to handle each disk type separately because shards should be moved to nodes with the same disk type + diskTypes := []types.DiskType{types.HardDriveType, types.SsdType} + + for _, diskType := range diskTypes { + ecNodes, _ := collectEcVolumeServersByDc(c.topologyInfo, "", diskType) + thisNodes, otherNodes := c.ecNodesOtherThan(ecNodes, volumeServer) + if len(thisNodes) == 0 { + // This server doesn't have EC shards for this disk type, skip + continue + } - // move away ec volumes - for _, thisNode := range thisNodes { - for _, diskInfo := range thisNode.info.DiskInfos { + // move away ec volumes for this disk type + for _, thisNode := range thisNodes { + diskInfo, found := thisNode.info.DiskInfos[string(diskType)] + if !found { + continue + } for _, ecShardInfo := range diskInfo.EcShardInfos { - hasMoved, err := c.moveAwayOneEcVolume(commandEnv, ecShardInfo, thisNode, otherNodes, applyChange) + hasMoved, err := c.moveAwayOneEcVolume(commandEnv, ecShardInfo, thisNode, otherNodes, applyChange, diskType) if err != nil { fmt.Fprintf(writer, "move away volume %d from %s: %v", ecShardInfo.Id, volumeServer, err) } @@ -192,7 +193,7 @@ func (c *commandVolumeServerEvacuate) evacuateEcVolumes(commandEnv *CommandEnv, return nil } -func (c *commandVolumeServerEvacuate) moveAwayOneEcVolume(commandEnv *CommandEnv, ecShardInfo *master_pb.VolumeEcShardInformationMessage, thisNode *EcNode, otherNodes []*EcNode, applyChange bool) (hasMoved bool, err error) { +func (c *commandVolumeServerEvacuate) moveAwayOneEcVolume(commandEnv *CommandEnv, ecShardInfo *master_pb.VolumeEcShardInformationMessage, thisNode *EcNode, otherNodes []*EcNode, applyChange bool, diskType types.DiskType) (hasMoved bool, err error) { for _, shardId := range erasure_coding.ShardBits(ecShardInfo.EcIndexBits).ShardIds() { slices.SortFunc(otherNodes, func(a, b *EcNode) int { @@ -211,7 +212,7 @@ func (c *commandVolumeServerEvacuate) moveAwayOneEcVolume(commandEnv *CommandEnv } else { fmt.Fprintf(os.Stdout, "moving ec volume %s%d.%d %s => %s\n", collectionPrefix, ecShardInfo.Id, shardId, thisNode.info.Id, emptyNode.info.Id) } - err = moveMountedShardToEcNode(commandEnv, thisNode, ecShardInfo.Collection, vid, shardId, emptyNode, destDiskId, applyChange, c.diskType) + err = moveMountedShardToEcNode(commandEnv, thisNode, ecShardInfo.Collection, vid, shardId, emptyNode, destDiskId, applyChange, diskType) if err != nil { return } else {