This is an automated email from the ASF dual-hosted git repository.
szetszwo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ratis.git
The following commit(s) were added to refs/heads/master by this push:
new ba7b24b RATIS-1428. Add ratis-shell elect command (#531)
ba7b24b is described below
commit ba7b24b71c0df104f98f40f2b75c4daca7b9cf67
Author: maobaolong <[email protected]>
AuthorDate: Fri Nov 12 19:34:00 2021 +0800
RATIS-1428. Add ratis-shell elect command (#531)
---
.../shell/cli/sh/command/AbstractRatisCommand.java | 22 ++--
.../ratis/shell/cli/sh/command/ElectCommand.java | 130 +++++++++++++++++++++
.../ratis/shell/cli/sh/command/InfoCommand.java | 4 +-
3 files changed, 141 insertions(+), 15 deletions(-)
diff --git
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java
index 07e76cf..6c8c8b6 100644
---
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java
+++
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java
@@ -17,6 +17,7 @@
*/
package org.apache.ratis.shell.cli.sh.command;
+import org.apache.commons.cli.Option;
import org.apache.ratis.protocol.*;
import org.apache.ratis.protocol.exceptions.RaftException;
import org.apache.ratis.shell.cli.Command;
@@ -80,10 +81,7 @@ public abstract class AbstractRatisCommand implements
Command {
@Override
public int run(CommandLine cl) throws IOException {
List<InetSocketAddress> addresses = new ArrayList<>();
- String peersStr = "";
- if (cl.hasOption(PEER_OPTION_NAME)) {
- peersStr = cl.getOptionValue(PEER_OPTION_NAME);
- }
+ String peersStr = cl.getOptionValue(PEER_OPTION_NAME);
String[] peersArray = peersStr.split(",");
for (int i = 0; i < peersArray.length; i++) {
String[] hostPortPair = peersArray[i].split(":");
@@ -131,17 +129,15 @@ public abstract class AbstractRatisCommand implements
Command {
}
@Override
- public void validateArgs(CommandLine cl) throws IllegalArgumentException {
- if (!cl.hasOption(PEER_OPTION_NAME)) {
- throw new IllegalArgumentException(String.format(
- "should provide [%s]", PEER_OPTION_NAME));
- }
- }
-
- @Override
public Options getOptions() {
return new Options()
- .addOption(PEER_OPTION_NAME, true, "Peer addresses seperated by
comma")
+ .addOption(
+ Option.builder()
+ .option(PEER_OPTION_NAME)
+ .hasArg()
+ .required()
+ .desc("Peer addresses seperated by comma")
+ .build())
.addOption(GROUPID_OPTION_NAME, true, "Raft group id");
}
diff --git
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/ElectCommand.java
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/ElectCommand.java
new file mode 100644
index 0000000..6b7eb0e
--- /dev/null
+++
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/ElectCommand.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ratis.shell.cli.sh.command;
+
+import org.apache.commons.cli.Option;
+import org.apache.ratis.shell.cli.RaftUtils;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Options;
+import org.apache.ratis.client.RaftClient;
+import org.apache.ratis.protocol.RaftClientReply;
+import org.apache.ratis.protocol.RaftPeer;
+import org.apache.ratis.protocol.RaftPeerId;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Command for transferring the leadership to another peer.
+ */
+public class ElectCommand extends AbstractRatisCommand {
+ public static final String ADDRESS_OPTION_NAME = "address";
+
+ /**
+ * @param context command context
+ */
+ public ElectCommand(Context context) {
+ super(context);
+ }
+
+ @Override
+ public String getCommandName() {
+ return "elect";
+ }
+
+ @Override
+ public int run(CommandLine cl) throws IOException {
+ super.run(cl);
+
+ String strAddr = cl.getOptionValue(ADDRESS_OPTION_NAME);
+
+ RaftPeerId newLeaderId = null;
+ // update priorities to enable transfer
+ List<RaftPeer> peersWithNewPriorities = new ArrayList<>();
+ for (RaftPeer peer : getRaftGroup().getPeers()) {
+ peersWithNewPriorities.add(
+ RaftPeer.newBuilder(peer)
+ .setPriority(peer.getAddress().equals(strAddr) ? 2 : 1)
+ .build()
+ );
+ if (peer.getAddress().equals(strAddr)) {
+ newLeaderId = peer.getId();
+ }
+ }
+ if (newLeaderId == null) {
+ return -2;
+ }
+ try (RaftClient client = RaftUtils.createClient(getRaftGroup())) {
+ String stringPeers = "[" +
peersWithNewPriorities.stream().map(RaftPeer::toString)
+ .collect(Collectors.joining(", ")) + "]";
+ printf("Applying new peer state before transferring leadership: %n%s%n",
stringPeers);
+ RaftClientReply setConfigurationReply =
+ client.admin().setConfiguration(peersWithNewPriorities);
+ processReply(setConfigurationReply,
+ () -> "failed to set priorities before initiating election");
+ // transfer leadership
+ printf("Transferring leadership to server with address <%s> %n",
strAddr);
+ try {
+ Thread.sleep(3_000);
+ RaftClientReply transferLeadershipReply =
+ client.admin().transferLeadership(newLeaderId, 60_000);
+ processReply(transferLeadershipReply, () -> "election failed");
+ } catch (Throwable t) {
+ printf("caught an error when executing transfer: %s%n",
t.getMessage());
+ return -1;
+ }
+ println("Transferring leadership initiated");
+ }
+ return 0;
+ }
+
+ @Override
+ public String getUsage() {
+ return String.format("%s -%s <HOSTNAME:PORT>"
+ + " -%s
<PEER0_HOST:PEER0_PORT,PEER1_HOST:PEER1_PORT,PEER2_HOST:PEER2_PORT>"
+ + " [-%s <RAFT_GROUP_ID>]",
+ getCommandName(), ADDRESS_OPTION_NAME, PEER_OPTION_NAME,
+ GROUPID_OPTION_NAME);
+ }
+
+ @Override
+ public String getDescription() {
+ return description();
+ }
+
+ @Override
+ public Options getOptions() {
+ return super.getOptions().addOption(
+ Option.builder()
+ .option(ADDRESS_OPTION_NAME)
+ .hasArg()
+ .required()
+ .desc("Server address that will take over as leader")
+ .build()
+ );
+ }
+
+ /**
+ * @return command's description
+ */
+ public static String description() {
+ return "Transfers leadership to the <hostname>:<port>";
+ }
+}
diff --git
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/InfoCommand.java
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/InfoCommand.java
index 6e05a65..d9ab19c 100644
---
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/InfoCommand.java
+++
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/InfoCommand.java
@@ -59,8 +59,8 @@ public class InfoCommand extends AbstractRatisCommand {
@Override
public String getUsage() {
return String.format("%s"
- + " [-%s
PEER0_HOST:PEER0_PORT,PEER1_HOST:PEER1_PORT,PEER2_HOST:PEER2_PORT]"
- + " [-%s RAFT_GROUP_ID]",
+ + " -%s
<PEER0_HOST:PEER0_PORT,PEER1_HOST:PEER1_PORT,PEER2_HOST:PEER2_PORT>"
+ + " [-%s <RAFT_GROUP_ID>]",
getCommandName(), PEER_OPTION_NAME, GROUPID_OPTION_NAME);
}