You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by sz...@apache.org on 2023/02/14 08:04:28 UTC
[ozone] branch master updated: HDDS-7687. Support OM transfer Ratis leadership (#4265)
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/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 469c034423 HDDS-7687. Support OM transfer Ratis leadership (#4265)
469c034423 is described below
commit 469c034423bc079a4a9c5eb993f2c706dbe1d0a7
Author: Nibiru <ax...@qq.com>
AuthorDate: Tue Feb 14 16:04:22 2023 +0800
HDDS-7687. Support OM transfer Ratis leadership (#4265)
---
.../org/apache/hadoop/hdds/ratis/RatisHelper.java | 59 ++++++++++++
.../interface-client/src/main/proto/hdds.proto | 7 ++
.../main/java/org/apache/hadoop/ozone/OmUtils.java | 1 +
.../org/apache/hadoop/ozone/audit/OMAction.java | 1 +
.../ozone/om/protocol/OzoneManagerProtocol.java | 8 ++
...OzoneManagerProtocolClientSideTranslatorPB.java | 14 +++
.../dist/src/main/smoketest/omha/testOMHA.robot | 46 +++++++++
.../ozone/shell/TestTransferLeadershipShell.java | 105 +++++++++++++++++++++
.../src/main/proto/OmClientProtocol.proto | 6 ++
.../org/apache/hadoop/ozone/om/OzoneManager.java | 48 ++++++++++
.../protocolPB/OzoneManagerRequestHandler.java | 14 +++
.../org/apache/hadoop/ozone/admin/om/OMAdmin.java | 3 +-
.../ozone/admin/om/TransferOmLeaderSubCommand.java | 73 ++++++++++++++
13 files changed, 384 insertions(+), 1 deletion(-)
diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/ratis/RatisHelper.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/ratis/RatisHelper.java
index 84a882560b..b24ffddeec 100644
--- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/ratis/RatisHelper.java
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/ratis/RatisHelper.java
@@ -52,6 +52,7 @@ import org.apache.ratis.grpc.GrpcConfigKeys;
import org.apache.ratis.grpc.GrpcTlsConfig;
import org.apache.ratis.netty.NettyConfigKeys;
import org.apache.ratis.proto.RaftProtos;
+import org.apache.ratis.protocol.RaftClientReply;
import org.apache.ratis.protocol.RaftGroup;
import org.apache.ratis.protocol.RaftGroupId;
import org.apache.ratis.protocol.RaftPeer;
@@ -488,4 +489,62 @@ public final class RatisHelper {
}
log.debug("{}: {}\n {}", name, buf, builder);
}
+
+
+ /**
+ * Use raft client to send admin request, transfer the leadership.
+ * 1. Set priority and send setConfiguration request
+ * 2. Trigger transferLeadership API.
+ *
+ * @param raftGroup the Raft group
+ * @param targetPeerId the target expected leader
+ * @throws IOException
+ */
+ public static void transferRatisLeadership(ConfigurationSource conf,
+ RaftGroup raftGroup, RaftPeerId targetPeerId)
+ throws IOException {
+ // TODO: need a common raft client related conf.
+ try (RaftClient raftClient = newRaftClient(SupportedRpcType.GRPC, null,
+ null, raftGroup, createRetryPolicy(conf), null, conf)) {
+ if (raftGroup.getPeer(targetPeerId) == null) {
+ throw new IOException("Cannot choose the target leader. The expected " +
+ "leader RaftPeerId is " + targetPeerId + " and the peers are " +
+ raftGroup.getPeers().stream().map(RaftPeer::getId)
+ .collect(Collectors.toList()) + ".");
+ }
+ LOG.info("Chosen the targetLeaderId {} to transfer leadership",
+ targetPeerId);
+
+ // Set priority
+ List<RaftPeer> peersWithNewPriorities = new ArrayList<>();
+ for (RaftPeer peer : raftGroup.getPeers()) {
+ peersWithNewPriorities.add(
+ RaftPeer.newBuilder(peer)
+ .setPriority(peer.getId().equals(targetPeerId) ? 2 : 1)
+ .build()
+ );
+ }
+ RaftClientReply reply;
+ // Set new configuration
+ reply = raftClient.admin().setConfiguration(peersWithNewPriorities);
+ if (reply.isSuccess()) {
+ LOG.info("Successfully set new priority for division: {}",
+ peersWithNewPriorities);
+ } else {
+ LOG.warn("Failed to set new priority for division: {}." +
+ " Ratis reply: {}", peersWithNewPriorities, reply);
+ throw new IOException(reply.getException());
+ }
+
+ // Trigger the transferLeadership
+ reply = raftClient.admin().transferLeadership(targetPeerId, 60000);
+ if (reply.isSuccess()) {
+ LOG.info("Successfully transferred leadership to {}.", targetPeerId);
+ } else {
+ LOG.warn("Failed to transfer leadership to {}. Ratis reply: {}",
+ targetPeerId, reply);
+ throw new IOException(reply.getException());
+ }
+ }
+ }
}
diff --git a/hadoop-hdds/interface-client/src/main/proto/hdds.proto b/hadoop-hdds/interface-client/src/main/proto/hdds.proto
index 2ff39cab58..2a07d2dcc5 100644
--- a/hadoop-hdds/interface-client/src/main/proto/hdds.proto
+++ b/hadoop-hdds/interface-client/src/main/proto/hdds.proto
@@ -452,3 +452,10 @@ message ContainerBalancerConfigurationProto {
required bool shouldRun = 18;
optional int32 nextIterationIndex = 19;
}
+
+message TransferLeadershipRequestProto {
+ required string newLeaderId = 1;
+}
+
+message TransferLeadershipResponseProto {
+}
\ No newline at end of file
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
index 1419a4cdab..1eea3abc3f 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
@@ -280,6 +280,7 @@ public final class OmUtils {
// operation SetRangerServiceVersion.
case GetKeyInfo:
case SnapshotDiff:
+ case TransferLeadership:
return true;
case CreateVolume:
case SetVolumeProperty:
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
index a33e5d073f..30a587cf3e 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/audit/OMAction.java
@@ -61,6 +61,7 @@ public enum OMAction implements AuditAction {
RENEW_DELEGATION_TOKEN,
CANCEL_DELEGATION_TOKEN,
GET_SERVICE_LIST,
+ TRANSFER_LEADERSHIP,
//ACL Actions
ADD_ACL,
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
index 171b8d04d3..5c1fa78a4d 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocol/OzoneManagerProtocol.java
@@ -399,6 +399,14 @@ public interface OzoneManagerProtocol
ServiceInfoEx getServiceInfo() throws IOException;
+ /**
+ * Transfer the raft leadership.
+ *
+ * @param newLeaderId the newLeaderId of the target expected leader
+ * @throws IOException
+ */
+ void transferLeadership(String newLeaderId) throws IOException;
+
/**
* Triggers Ranger background sync task immediately.
*
diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
index fdad0bda97..538583187e 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
@@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hdds.annotation.InterfaceAudience;
import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicationConfig;
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos.TransferLeadershipRequestProto;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos
.UpgradeFinalizationStatus;
import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList;
@@ -1574,6 +1575,19 @@ public final class OzoneManagerProtocolClientSideTranslatorPB
resp.getCaCertificate(), resp.getCaCertsList());
}
+ @Override
+ public void transferLeadership(String newLeaderId)
+ throws IOException {
+ TransferLeadershipRequestProto.Builder builder =
+ TransferLeadershipRequestProto.newBuilder();
+ builder.setNewLeaderId(newLeaderId);
+ OMRequest omRequest = createOMRequest(Type.TransferLeadership)
+ .setTransferOmLeadershipRequest(builder.build())
+ .build();
+ handleError(submitRequest(omRequest));
+ }
+
+
@Override
public boolean triggerRangerBGSync(boolean noWait) throws IOException {
RangerBGSyncRequest req = RangerBGSyncRequest.newBuilder()
diff --git a/hadoop-ozone/dist/src/main/smoketest/omha/testOMHA.robot b/hadoop-ozone/dist/src/main/smoketest/omha/testOMHA.robot
index c3d3c7c981..9793a31149 100644
--- a/hadoop-ozone/dist/src/main/smoketest/omha/testOMHA.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/omha/testOMHA.robot
@@ -102,6 +102,18 @@ Get OM Leader Node
LOG Leader OM: ${leaderOM}
[return] ${leaderOM}
+Get One OM Follower Node
+ ${result} = Execute ozone admin om roles --service-id=omservice
+ LOG ${result}
+ Should Contain ${result} LEADER 1
+ Should Contain ${result} FOLLOWER 2
+ ${omLines} = Get Lines Containing String ${result} FOLLOWER
+ ${omLine} = Get Line ${omLines} 0
+ ${split1} ${split2} Split String ${omLine} :
+ ${followerOM} = Strip String ${split1}
+ LOG Follower OM: ${followerOM}
+ [return] ${followerOM}
+
Get Ratis Logs
[arguments] ${OM_HOST}
Set Global Variable ${HOST} ${OM_HOST}
@@ -182,4 +194,38 @@ Restart OM and Verify Ratis Logs
# Verify that the logs match with the Leader OMs logs
List Should Contain Sub List ${logsAfter} ${logsLeader}
+Transfer Leadership for OM
+ # Check OM write operation before failover
+ Create volume and bucket
+ Write Test File
+
+ # Find Leader OM and one Follower OM
+ ${leaderOM} = Get OM Leader Node
+ LOG Leader OM: ${leaderOM}
+ ${followerOM} = Get One OM Follower Node
+ LOG Follower OM: ${followerOM}
+ # Transfer leadership to the Follower OM
+ ${result} = Execute ozone admin om transfer --service-id=omservice -n ${followerOM}
+ LOG ${result}
+ Should Contain ${result} Transfer leadership successfully
+
+ ${newLeaderOM} = Get OM Leader Node
+ Should be Equal ${followerOM} ${newLeaderOM}
+ Write Test File
+
+Transfer Leadership for OM randomly
+ # Check OM write operation before failover
+ Create volume and bucket
+ Write Test File
+ # Find Leader OM and one Follower OM
+ ${leaderOM} = Get OM Leader Node
+ LOG Leader OM: ${leaderOM}
+ # Transfer leadership to the Follower OM
+ ${result} = Execute ozone admin om transfer -r
+ LOG ${result}
+ Should Contain ${result} Transfer leadership successfully
+
+ ${newLeaderOM} = Get OM Leader Node
+ Should Not be Equal ${leaderOM} ${newLeaderOM}
+ Write Test File
diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestTransferLeadershipShell.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestTransferLeadershipShell.java
new file mode 100644
index 0000000000..06241753b1
--- /dev/null
+++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestTransferLeadershipShell.java
@@ -0,0 +1,105 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.hadoop.ozone.shell;
+
+
+import org.apache.hadoop.hdds.cli.OzoneAdmin;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.scm.ScmConfigKeys;
+import org.apache.hadoop.ozone.MiniOzoneCluster;
+import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl;
+import org.apache.hadoop.ozone.om.OzoneManager;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Test transferLeadership with SCM HA setup.
+ */
+public class TestTransferLeadershipShell {
+ private MiniOzoneHAClusterImpl cluster = null;
+ private OzoneConfiguration conf;
+ private String clusterId;
+ private String scmId;
+ private String omServiceId;
+ private String scmServiceId;
+ private int numOfOMs = 3;
+ private int numOfSCMs = 3;
+
+ private static final long SNAPSHOT_THRESHOLD = 5;
+
+ /**
+ * Create a MiniOzoneCluster for testing.
+ *
+ * @throws IOException Exception
+ */
+ @BeforeEach
+ public void init() throws Exception {
+ conf = new OzoneConfiguration();
+ clusterId = UUID.randomUUID().toString();
+ scmId = UUID.randomUUID().toString();
+ omServiceId = "om-service-test1";
+ scmServiceId = "scm-service-test1";
+ conf.setLong(ScmConfigKeys.OZONE_SCM_HA_RATIS_SNAPSHOT_THRESHOLD,
+ SNAPSHOT_THRESHOLD);
+
+ cluster = (MiniOzoneHAClusterImpl) MiniOzoneCluster.newHABuilder(conf)
+ .setClusterId(clusterId).setScmId(scmId).setOMServiceId(omServiceId)
+ .setSCMServiceId(scmServiceId).setNumOfOzoneManagers(numOfOMs)
+ .setNumOfStorageContainerManagers(numOfSCMs)
+ .setNumOfActiveSCMs(numOfSCMs).setNumOfActiveOMs(numOfOMs)
+ .build();
+ cluster.waitForClusterToBeReady();
+ }
+
+ /**
+ * Shutdown MiniDFSCluster.
+ */
+ @AfterEach
+ public void shutdown() {
+ if (cluster != null) {
+ cluster.shutdown();
+ }
+ }
+
+ @Test
+ public void testOmTransfer() throws Exception {
+ OzoneManager oldLeader = cluster.getOMLeader();
+ List<OzoneManager> omList = new ArrayList<>(cluster.getOzoneManagersList());
+ Assertions.assertTrue(omList.contains(oldLeader));
+ omList.remove(oldLeader);
+ OzoneManager newLeader = omList.get(0);
+ cluster.waitForClusterToBeReady();
+ OzoneAdmin ozoneAdmin = new OzoneAdmin(conf);
+ String[] args1 = {"om", "transfer", "-n", newLeader.getOMNodeId()};
+ ozoneAdmin.execute(args1);
+ Thread.sleep(3000);
+ Assertions.assertEquals(newLeader, cluster.getOMLeader());
+
+ oldLeader = cluster.getOMLeader();
+ String[] args3 = {"om", "transfer", "-r"};
+ ozoneAdmin.execute(args3);
+ Thread.sleep(3000);
+ Assertions.assertNotSame(oldLeader, cluster.getOMLeader());
+ }
+}
diff --git a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index c27a14a5d9..01b0eab792 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -130,6 +130,8 @@ enum Type {
ListSnapshot = 113;
SnapshotDiff = 114;
DeleteSnapshot = 115;
+
+ TransferLeadership = 116;
}
message OMRequest {
@@ -243,6 +245,8 @@ message OMRequest {
optional SnapshotDiffRequest snapshotDiffRequest = 114;
optional DeleteSnapshotRequest DeleteSnapshotRequest = 115;
+ optional hdds.TransferLeadershipRequestProto TransferOmLeadershipRequest = 116;
+
}
message OMResponse {
@@ -348,6 +352,8 @@ message OMResponse {
optional ListSnapshotResponse ListSnapshotResponse = 113;
optional SnapshotDiffResponse snapshotDiffResponse = 114;
optional DeleteSnapshotResponse DeleteSnapshotResponse = 115;
+
+ optional hdds.TransferLeadershipResponseProto TransferOmLeadershipResponse = 116;
}
enum Status {
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
index 9326475e12..0a25300d50 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OzoneManager.java
@@ -74,6 +74,7 @@ import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.ReconfigureProtocolService;
import org.apache.hadoop.hdds.protocolPB.ReconfigureProtocolPB;
import org.apache.hadoop.hdds.protocolPB.ReconfigureProtocolServerSideTranslatorPB;
+import org.apache.hadoop.hdds.ratis.RatisHelper;
import org.apache.hadoop.hdds.scm.ScmInfo;
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
import org.apache.hadoop.hdds.server.OzoneAdmins;
@@ -289,6 +290,7 @@ import org.apache.ratis.proto.RaftProtos.RaftPeerRole;
import org.apache.ratis.protocol.RaftGroupId;
import org.apache.ratis.protocol.RaftPeer;
import org.apache.ratis.protocol.RaftPeerId;
+import org.apache.ratis.server.RaftServer;
import org.apache.ratis.server.protocol.TermIndex;
import org.apache.ratis.util.ExitUtils;
import org.apache.ratis.util.FileUtils;
@@ -3023,6 +3025,52 @@ public final class OzoneManager extends ServiceRuntimeInfoImpl
return new ServiceInfoEx(getServiceList(), caCertPem, caCertPemList);
}
+ @Override
+ public void transferLeadership(String newLeaderId)
+ throws IOException {
+ final UserGroupInformation ugi = getRemoteUser();
+ if (!isAdmin(ugi)) {
+ throw new OMException(
+ "Only Ozone admins are allowed to transfer raft leadership.",
+ PERMISSION_DENIED);
+ }
+ if (!isRatisEnabled) {
+ throw new IOException("OM HA not enabled.");
+ }
+ boolean auditSuccess = true;
+ Map<String, String> auditMap = new LinkedHashMap<>();
+ auditMap.put("newLeaderId", newLeaderId);
+ try {
+ RaftGroupId groupID = omRatisServer.getRaftGroup().getGroupId();
+ RaftServer.Division division = omRatisServer.getServer()
+ .getDivision(groupID);
+ RaftPeerId targetPeerId;
+ if (newLeaderId.isEmpty()) {
+ RaftPeer curLeader = omRatisServer.getLeader();
+ targetPeerId = division.getGroup()
+ .getPeers().stream().filter(a -> !a.equals(curLeader)).findFirst()
+ .map(RaftPeer::getId).orElseThrow(() -> new IOException("Cannot" +
+ " find a new leader to transfer leadership."));
+ } else {
+ targetPeerId = RaftPeerId.valueOf(newLeaderId);
+ }
+ RatisHelper.transferRatisLeadership(configuration, division.getGroup(),
+ targetPeerId);
+ } catch (IOException ex) {
+ auditSuccess = false;
+ AUDIT.logReadFailure(
+ buildAuditMessageForFailure(OMAction.TRANSFER_LEADERSHIP,
+ auditMap, ex));
+ throw ex;
+ } finally {
+ if (auditSuccess) {
+ AUDIT.logReadSuccess(
+ buildAuditMessageForSuccess(OMAction.TRANSFER_LEADERSHIP,
+ auditMap));
+ }
+ }
+ }
+
@Override
public boolean triggerRangerBGSync(boolean noWait) throws IOException {
diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java
index 6ab84a5f02..1032de2542 100644
--- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java
+++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java
@@ -30,6 +30,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos.TransferLeadershipRequestProto;
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos.TransferLeadershipResponseProto;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos.UpgradeFinalizationStatus;
import org.apache.hadoop.hdds.client.ReplicationConfig;
import org.apache.hadoop.hdds.utils.db.SequenceNumberNotFoundException;
@@ -303,6 +305,11 @@ public class OzoneManagerRequestHandler implements RequestHandler {
EchoRPCResponse echoRPCResponse =
echoRPC(request.getEchoRPCRequest());
responseBuilder.setEchoRPCResponse(echoRPCResponse);
+ break;
+ case TransferLeadership:
+ responseBuilder.setTransferOmLeadershipResponse(transferLeadership(
+ request.getTransferOmLeadershipRequest()));
+ break;
default:
responseBuilder.setSuccess(false);
responseBuilder.setMessage("Unrecognized Command Type: " + cmdType);
@@ -1250,4 +1257,11 @@ public class OzoneManagerRequestHandler implements RequestHandler {
return OzoneManagerProtocolProtos.ListSnapshotResponse.newBuilder()
.addAllSnapshotInfo(snapshotInfoList).build();
}
+
+ private TransferLeadershipResponseProto transferLeadership(
+ TransferLeadershipRequestProto req) throws IOException {
+ String newLeaderId = req.getNewLeaderId();
+ impl.transferLeadership(newLeaderId);
+ return TransferLeadershipResponseProto.getDefaultInstance();
+ }
}
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java
index b61438077f..9bb447669d 100644
--- a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/OMAdmin.java
@@ -58,7 +58,8 @@ import java.util.Collection;
CancelPrepareSubCommand.class,
FinalizationStatusSubCommand.class,
DecommissionOMSubcommand.class,
- UpdateRangerSubcommand.class
+ UpdateRangerSubcommand.class,
+ TransferOmLeaderSubCommand.class
})
@MetaInfServices(SubcommandWithParent.class)
public class OMAdmin extends GenericCli implements SubcommandWithParent {
diff --git a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/TransferOmLeaderSubCommand.java b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/TransferOmLeaderSubCommand.java
new file mode 100644
index 0000000000..32e432cd04
--- /dev/null
+++ b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/om/TransferOmLeaderSubCommand.java
@@ -0,0 +1,73 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.hadoop.ozone.admin.om;
+
+import org.apache.hadoop.hdds.cli.HddsVersionProvider;
+import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
+import picocli.CommandLine;
+import java.util.concurrent.Callable;
+
+
+/**
+ * Handler of ozone admin om transfer command.
+ */
+@CommandLine.Command(
+ name = "transfer",
+ description = "Manually transfer the raft leadership to the target node.",
+ mixinStandardHelpOptions = true,
+ versionProvider = HddsVersionProvider.class
+)
+public class TransferOmLeaderSubCommand implements Callable<Void> {
+
+ @CommandLine.ParentCommand
+ private OMAdmin parent;
+
+ @CommandLine.Option(
+ names = {"-id", "--service-id"},
+ description = "Ozone Manager Service ID."
+ )
+ private String omServiceId;
+
+ @CommandLine.ArgGroup(multiplicity = "1")
+ private TransferOption configGroup;
+
+ static class TransferOption {
+ @CommandLine.Option(
+ names = {"-n", "--newLeaderId"},
+ description = "The new leader id of OM to transfer leadership. E.g OM1."
+ )
+ private String omNodeId;
+
+ @CommandLine.Option(names = {"-r", "--random"},
+ description = "Randomly choose a follower to transfer leadership.")
+ private boolean isRandom;
+ }
+
+ @Override
+ public Void call() throws Exception {
+ OzoneManagerProtocol client =
+ parent.createOmClient(omServiceId, null, true);
+ if (configGroup.isRandom) {
+ configGroup.omNodeId = "";
+ }
+ client.transferLeadership(configGroup.omNodeId);
+ System.out.println("Transfer leadership successfully to " +
+ (configGroup.isRandom ? "random node" : configGroup.omNodeId) + ".");
+ return null;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org