fix(admin): use gRPC address for current server in RaftListClusterServers
The old Raft implementation was returning the HTTP address
(ms.option.Master) for the current server, while peers used gRPC
addresses (peer.ConnectionString). The Admin UI's GetClusterMasters()
converts all addresses from gRPC to HTTP via GrpcAddressToServerAddress
(port - 10000), which produced a negative port (-667) for the current
server since its address was already in HTTP format (port 9333).
Use ToGrpcAddress() for consistency with both HashicorpRaft (which
stores gRPC addresses) and old Raft peers.
Fixes#8921
* proto: add RaftLeadershipTransfer RPC for forced leader change
Add new gRPC RPC and messages for leadership transfer:
- RaftLeadershipTransferRequest: optional target_id and target_address
- RaftLeadershipTransferResponse: previous_leader and new_leader
This enables graceful leadership transfer before master maintenance,
reducing errors in filers during planned maintenance windows.
Ref: https://github.com/seaweedfs/seaweedfs/issues/7527
* proto: regenerate Go files for RaftLeadershipTransfer
Generated from master.proto changes.
* master: implement RaftLeadershipTransfer gRPC handler
Add gRPC handler for leadership transfer with support for:
- Transfer to any eligible follower (when target_id is empty)
- Transfer to a specific server (when target_id and target_address are provided)
Uses hashicorp/raft LeadershipTransfer() and LeadershipTransferToServer() APIs.
Returns the previous and new leader in the response.
* shell: add cluster.raft.leader.transfer command
Add weed shell command for graceful leadership transfer:
- Displays current cluster status before transfer
- Supports auto-selection of target (any eligible follower)
- Supports targeted transfer with -id and -address flags
- Provides clear feedback on success/failure with troubleshooting tips
Usage:
cluster.raft.leader.transfer
cluster.raft.leader.transfer -id <server_id> -address <grpc_address>
* master: add unit tests for raft gRPC handlers
Add tests covering:
- RaftLeadershipTransfer with no raft initialized
- RaftLeadershipTransfer with target_id but no address
- RaftListClusterServers with no raft initialized
- RaftAddServer with no raft initialized
- RaftRemoveServer with no raft initialized
These tests verify error handling when raft is not configured.
* shell: add tests for cluster.raft.leader.transfer command
Add tests covering:
- Command name and help text validation
- HasTag returns false for ResourceHeavy
- Validation of -id without -address
- Argument parsing with unknown flags
* master: clarify that leadership transfer requires -raftHashicorp
The default raft implementation (seaweedfs/raft, a goraft fork) does not
support graceful leadership transfer. This feature is only available when
using hashicorp raft (-raftHashicorp=true).
Update error messages and help text to make this requirement clear:
- gRPC handler returns specific error for goraft users
- Shell command help text notes the requirement
- Added test for goraft case
* test: use strings.Contains instead of custom helper
Replace custom contains/containsHelper functions with the standard
library strings.Contains for better maintainability.
* shell: return flag parsing errors instead of swallowing them
- Return the error from flag.Parse() instead of returning nil
- Update test to explicitly assert error for unknown flags
* test: document integration test scenarios for Raft leadership transfer
Add comments explaining:
- Why these unit tests only cover 'Raft not initialized' scenarios
- What integration tests should cover (with multi-master cluster)
- hashicorp/raft uses concrete types that cannot be easily mocked
* fix: address reviewer feedback on tests and leader routing
- Remove misleading tests that couldn't properly validate their
documented behavior without a real Raft cluster:
- TestRaftLeadershipTransfer_GoraftNotSupported
- TestRaftLeadershipTransfer_ValidationTargetIdWithoutAddress
- Change WithClient(false) to WithClient(true) for RaftLeadershipTransfer
RPC to ensure the request is routed to the current leader
* Improve cluster.raft.transferLeader command
- Rename command from cluster.raft.leader.transfer to cluster.raft.transferLeader
- Add symmetric validation: -id and -address must be specified together
- Handle case where same leader is re-elected after transfer
- Add test for -address without -id validation
- Add docker compose file for 5-master raft cluster testing