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 853a14aa1e68..6cfe04554ed1 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 @@ -36,11 +36,14 @@ import java.util.Optional; import java.util.OptionalInt; import java.util.Set; +import java.util.stream.Collectors; +import java.util.Comparator; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hdds.conf.ConfigurationSource; import org.apache.hadoop.hdds.conf.OzoneConfiguration; +import org.apache.hadoop.hdds.protocol.proto.HddsProtos; import org.apache.hadoop.hdds.scm.client.HddsClientUtils; import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.ozone.conf.OMClientConfig; @@ -49,6 +52,7 @@ import org.apache.hadoop.ozone.om.helpers.OMNodeDetails; import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; import org.apache.hadoop.ozone.om.helpers.RepeatedOmKeyInfo; +import org.apache.hadoop.ozone.om.helpers.ServiceInfo; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos; import org.apache.commons.lang3.StringUtils; @@ -789,4 +793,38 @@ public static String getOMAddressListPrintString(List omList) { printString.append("]"); return printString.toString(); } + + public static String format(List nodes, int port, + String leaderId) { + StringBuilder sb = new StringBuilder(); + // Ensuring OM's are printed in correct order + List omNodes = nodes.stream() + .filter(node -> node.getNodeType() == HddsProtos.NodeType.OM) + .sorted(Comparator.comparing(ServiceInfo::getHostname)) + .collect(Collectors.toList()); + int count = 0; + for (ServiceInfo info : omNodes) { + // Printing only the OM's running + if (info.getNodeType() == HddsProtos.NodeType.OM) { + String role = + info.getOmRoleInfo().getNodeId().equals(leaderId) ? "LEADER" : + "FOLLOWER"; + sb.append( + String.format( + " { HostName: %s | Node-Id: %s | Ratis-Port : %d | Role: %s} ", + info.getHostname(), + info.getOmRoleInfo().getNodeId(), + port, + role + )); + count++; + } + } + // Print Stand-alone if only one OM exists + if (count == 1) { + return "STANDALONE"; + } else { + return sb.toString(); + } + } } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMXBean.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMXBean.java index f378a8a07590..791379bdc86b 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMXBean.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/OMMXBean.java @@ -29,6 +29,8 @@ public interface OMMXBean extends ServiceRuntimeInfo { String getRpcPort(); + String getRatisRoles(); + String getRatisLogDirectory(); String getRocksDbDirectory(); 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 a277c2d67bad..289b9c550834 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 @@ -277,6 +277,7 @@ import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.PrepareStatusResponse.PrepareStatus; 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.protocol.TermIndex; import org.apache.ratis.util.ExitUtils; @@ -2966,6 +2967,24 @@ public String getRpcPort() { } @Override + public String getRatisRoles() { + List serviceList = null; + int port = omNodeDetails.getRatisPort(); + RaftPeer leaderId; + if (isRatisEnabled) { + try { + leaderId = omRatisServer.getLeader(); + serviceList = getServiceList(); + } catch (IOException e) { + LOG.error("IO-Exception Occurred", e); + return "Exception: " + e.toString(); + } + return OmUtils.format(serviceList, port, leaderId.getId().toString()); + } else { + return "Ratis-Disabled"; + } + } + public String getRatisLogDirectory() { return OzoneManagerRatisUtils.getOMRatisDirectory(configuration); } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/OzoneManagerRatisServer.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/OzoneManagerRatisServer.java index 5ee7b27c8295..92b685d6a89f 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/OzoneManagerRatisServer.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/ratis/OzoneManagerRatisServer.java @@ -82,6 +82,7 @@ import org.apache.ratis.server.RaftServer; import org.apache.ratis.server.RaftServerConfigKeys; import org.apache.ratis.server.protocol.TermIndex; +import org.apache.ratis.thirdparty.com.google.protobuf.ByteString; import org.apache.ratis.util.LifeCycle; import org.apache.ratis.util.SizeInBytes; import org.apache.ratis.util.StringUtils; @@ -728,6 +729,18 @@ private static Map getOMHAConfigs( .getPropsMatchPrefixAndTrimPrefix(OZONE_OM_HA_PREFIX + "."); } + public RaftPeer getLeader() throws IOException { + RaftServer.Division division = server.getDivision(raftGroupId); + if (division.getInfo().isLeader()) { + return division.getPeer(); + } else { + ByteString leaderId = division.getInfo().getRoleInfoProto() + .getFollowerInfo().getLeaderInfo().getId().getId(); + return leaderId.isEmpty() ? null : + division.getRaftConf().getPeer(RaftPeerId.valueOf(leaderId)); + } + } + /** * Defines RaftServer Status. */ diff --git a/hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/om-overview.html b/hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/om-overview.html index 66bcfd8bf5a3..8a54aa0adc55 100644 --- a/hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/om-overview.html +++ b/hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/om-overview.html @@ -22,6 +22,26 @@

Status

Rpc port {{$ctrl.overview.jmx.RpcPort}} + + OM Roles (HA) + {{$ctrl.overview.jmx.RatisRoles}} + + + Current-Role + {{$ctrl.role.Role}} + + + Group-Id + {{$ctrl.role.GroupId}} + + + Election-Count + {{$ctrl.electionCount.Count}} + + + Last Election Elapsed Time + {{$ctrl.elapsedTime.Value}} + diff --git a/hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/ozoneManager.js b/hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/ozoneManager.js index 6c59a5be5856..bd402b1b43a0 100644 --- a/hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/ozoneManager.js +++ b/hadoop-ozone/ozone-manager/src/main/resources/webapps/ozoneManager/ozoneManager.js @@ -113,5 +113,35 @@ require: { overview: "^overview" }, + controller: function ($http) { + var ctrl = this; + $http.get("jmx?qry=Ratis:service=RaftServer,group=*,id=*") + .then(function (result) { + ctrl.role = result.data.beans[0]; + }); + + $http.get("jmx?qry=ratis:name=ratis.leader_election.*electionCount") + .then(function (result) { + ctrl.electionCount = result.data.beans[0]; + }); + + $http.get("jmx?qry=ratis:name=ratis.leader_election.*lastLeaderElectionElapsedTime") + .then(function (result) { + ctrl.elapsedTime = result.data.beans[0]; + if(ctrl.elapsedTime.Value != -1){ + ctrl.elapsedTime.Value = convertMsToTime(ctrl.elapsedTime.Value); + } + }); + } }); + function convertMsToTime(ms) { + let seconds = (ms / 1000).toFixed(1); + let minutes = (ms / (1000 * 60)).toFixed(1); + let hours = (ms / (1000 * 60 * 60)).toFixed(1); + let days = (ms / (1000 * 60 * 60 * 24)).toFixed(1); + if (seconds < 60) return seconds + " Seconds"; + else if (minutes < 60) return minutes + " Minutes"; + else if (hours < 24) return hours + " Hours"; + else return days + " Days" + } })();