Skip to content

Commit

Permalink
HDDS-11196. Improve SCM WebUI Display.
Browse files Browse the repository at this point in the history
  • Loading branch information
slfan1989 committed Sep 14, 2024
1 parent e573701 commit 3ce5a53
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,7 @@ body {
.om-roles-background {
background-color: #dcfbcd!important;
}

.scm-roles-background {
background-color: #dcfbcd!important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
</tr>
<tr>
<th>Input arguments:</th>
<td>{{$ctrl.jmx.InputArguments}}</td>
<td><pre>{{$ctrl.jmx.InputArguments.join('\n')}}</pre></td>
</tr>
</table>
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ public class SCMNodeManager implements NodeManager {
private static final String LASTHEARTBEAT = "LASTHEARTBEAT";
private static final String USEDSPACEPERCENT = "USEDSPACEPERCENT";
private static final String TOTALCAPACITY = "CAPACITY";
private static final String DNUUID = "UUID";
private static final String VERSION = "VERSION";
/**
* Constructs SCM machine Manager.
*/
Expand Down Expand Up @@ -447,6 +449,8 @@ public RegisteredCommand register(
processNodeReport(datanodeDetails, nodeReport);
LOG.info("Updated datanode to: {}", dn);
scmNodeEventPublisher.fireEvent(SCMEvents.NODE_ADDRESS_UPDATE, dn);
} else if (isVersionChange(oldNode.getVersion(), datanodeDetails.getVersion())) {
nodeStateManager.updateNode(datanodeDetails, layoutInfo);
}
} catch (NodeNotFoundException e) {
LOG.error("Cannot find datanode {} from nodeStateManager",
Expand Down Expand Up @@ -508,6 +512,18 @@ private boolean updateDnsToUuidMap(
return ipChanged || hostNameChanged;
}

/**
* Check if the version has been updated.
*
* @param oldVersion datanode oldVersion
* @param newVersion datanode newVersion
* @return true means replacement is needed, while false means replacement is not needed.
*/
private boolean isVersionChange(String oldVersion, String newVersion) {
final boolean ipChanged = !Objects.equals(oldVersion, newVersion);
return ipChanged;
}

/**
* Send heartbeat to indicate the datanode is alive and doing well.
*
Expand Down Expand Up @@ -1136,6 +1152,8 @@ public Map<String, Map<String, String>> getNodeStatusInfo() {
String nonScmUsedPerc = storagePercentage[1];
map.put(USEDSPACEPERCENT,
"Ozone: " + scmUsedPerc + "%, other: " + nonScmUsedPerc + "%");
map.put(DNUUID, dni.getUuidString());
map.put(VERSION, dni.getVersion());
nodes.put(hostName, map);
}
return nodes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.apache.hadoop.hdds.scm.server;

import java.util.List;
import java.util.Map;

import org.apache.hadoop.hdds.annotation.InterfaceAudience;
Expand Down Expand Up @@ -74,6 +75,8 @@ public interface SCMMXBean extends ServiceRuntimeInfo {

String getScmRatisRoles();

List<List<String>> getRatisRoles();

/**
* Primordial node is the node on which scm init operation is performed.
* @return hostname of primordialNode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,12 @@
import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.util.ReflectionUtils;
import org.apache.ratis.proto.RaftProtos;
import org.apache.ratis.protocol.RaftPeer;
import org.apache.ratis.protocol.RaftPeerId;
import org.apache.ratis.server.DivisionInfo;
import org.apache.ratis.server.RaftServer;
import org.apache.ratis.thirdparty.com.google.protobuf.ByteString;
import org.apache.ratis.util.ExitUtils;
import org.apache.ratis.util.JvmPauseMonitor;
import org.slf4j.Logger;
Expand Down Expand Up @@ -2137,6 +2142,74 @@ public String getScmRatisRoles() {
HddsUtils.format(server.getRatisRoles()) : "STANDALONE";
}

@Override
public List<List<String>> getRatisRoles() {
final SCMRatisServer server = getScmHAManager().getRatisServer();

// If Ratis is enabled
if(server != null) {

// To attempt to find the SCM Leader,
// and if the Leader is not found
// return Leader is not found message.
RaftServer.Division division = server.getDivision();
RaftPeer leader = getLeader(division);
if (leader == null) {
return getRatisRolesException("No leader found");
}

// If the SCMRatisServer is stopped, return a service stopped message.
if (server.isStopped()) {
return getRatisRolesException("Server is shutting down");
}

// Attempt to retrieve role information.
try {
List<String> ratisRoles = server.getRatisRoles();
List<List<String>> result = new ArrayList<>();
for (String role : ratisRoles) {
String[] roleArr = role.split(":");
List<String> scmInfo = new ArrayList<>();
// Host Name
scmInfo.add(roleArr[0]);
// Node ID
scmInfo.add(roleArr[3]);
// Ratis Port
scmInfo.add(roleArr[1]);
// Role
scmInfo.add(roleArr[2]);
result.add(scmInfo);
}
return result;
} catch (Exception e) {
LOG.error("Failed to getRatisRoles.", e);
return getRatisRolesException("Exception Occurred, " + e.getMessage());
}
}

// If Ratis is not enabled, we will throw an exception directly.
return getRatisRolesException("Ratis is disabled");
}

public RaftPeer getLeader(RaftServer.Division division) {
if (division.getInfo().isLeader()) {
return division.getPeer();
} else {
DivisionInfo info = division.getInfo();
RaftProtos.RoleInfoProto roleInfoProto = info.getRoleInfoProto();
RaftProtos.FollowerInfoProto followerInfo = roleInfoProto.getFollowerInfo();
RaftProtos.ServerRpcProto leaderInfo = followerInfo.getLeaderInfo();
RaftProtos.RaftPeerProto peerLeaderId = leaderInfo.getId();
ByteString leaderId = peerLeaderId.getId();
return leaderId.isEmpty() ? null :
division.getRaftConf().getPeer(RaftPeerId.valueOf(leaderId));
}
}

private static List<List<String>> getRatisRolesException(String exceptionString) {
return Collections.singletonList(Collections.singletonList(exceptionString));
}

/**
* @return hostname of primordialNode
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ <h2>Node Status</h2>
'sortdesc':(columnName == 'comstate' && !reverse)}">Commisioned State</span> </th>
<th ng-click = "columnSort('lastheartbeat')" class="nodeStatusInfo"> <span ng-class="{'sorting' : (columnName != 'lastheartbeat'), 'sortasc' : (columnName == 'heartbeat' && !reverse),
'sortdesc':(columnName == 'lastheartbeat' && !reverse)}">Last Heartbeat</span> </th>
<th ng-click = "columnSort('uuid')" class="uuId" ><span ng-class="{'sorting' : (columnName != 'uuid'), 'sortasc' : (columnName == 'uuid' && !reverse),
'sortdesc':(columnName == 'uuid' && !reverse)}">UUID</span></th>
<th ng-click = "columnSort('version')" class="version" ><span ng-class="{'sorting' : (columnName != 'version'), 'sortasc' : (columnName == 'version' && !reverse),
'sortdesc':(columnName == 'version' && !reverse)}">Version</span></th>
</tr>
</thead>
<tbody>
Expand All @@ -157,6 +161,8 @@ <h2>Node Status</h2>
<td>{{typestat.opstate}}</td>
<td>{{typestat.comstate}}</td>
<td>{{typestat.lastheartbeat}}</td>
<td>{{typestat.uuid}}</td>
<td>{{typestat.version}}</td>
</tr>
</tbody>
</table>
Expand Down Expand Up @@ -210,10 +216,6 @@ <h2>Status</h2>
<td> Force Exit Safe Mode </td>
<td>{{$ctrl.overview.jmx.SafeModeExitForceful}}</td>
</tr>
<tr>
<td> SCM Roles (HA) </td>
<td>{{$ctrl.overview.jmx.ScmRatisRoles}}</td>
</tr>
<tr ng-hide="!$ctrl.overview.jmx.PrimordialNode">
<td> Primordial Node (HA) </td>
<td>{{$ctrl.overview.jmx.PrimordialNode}}</td>
Expand All @@ -235,6 +237,35 @@ <h2>Meta-Data Volume Information</h2>
</tbody>
</table>

<h2>SCM Roles (HA)</h2>
<h4 ng-show="$ctrl.overview.jmx.RatisRoles.length == 1 && $ctrl.overview.jmx.RatisRoles[0].length == 1">{{$ctrl.overview.jmx.RatisRoles[0][0]}}</h4>
<div ng-show="$ctrl.overview.jmx.RatisRoles.length > 1">
<table class="table table-striped table-bordered" class="col-md-6">
<thead>
<tr>
<th>Host Name</th>
<th>Node ID</th>
<th>Ratis Port</th>
<th>Role</th>
</tr>
</thead>
<tbody ng-repeat="roles in $ctrl.overview.jmx.RatisRoles">
<tr class="scm-roles-background" ng-if="$ctrl.role.Id == roles[1]">
<td>{{roles[0]}}</td>
<td>{{roles[1]}}</td>
<td>{{roles[2]}}</td>
<td>{{roles[3]}}</td>
</tr>
<tr ng-if="$ctrl.role.Id != roles[1]">
<td>{{roles[0]}}</td>
<td>{{roles[1]}}</td>
<td>{{roles[2]}}</td>
<td>{{roles[3]}}</td>
</tr>
</tbody>
</table>
</div>

<h2>Safemode rules statuses</h2>

<table class="table table-bordered table-striped" class="col-md-6">
Expand Down
7 changes: 7 additions & 0 deletions hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
}
}

$http.get("jmx?qry=Ratis:service=RaftServer,group=*,id=*")
.then(function (result) {
ctrl.role = result.data.beans[0];
});

function get_protocol(URLScheme, value, baseProto, fallbackProto) {
let protocol = "unknown"
let port = -1;
Expand Down Expand Up @@ -95,6 +100,8 @@
capacity: value && value.find((element) => element.key === "CAPACITY").value,
comstate: value && value.find((element) => element.key === "COMSTATE").value,
lastheartbeat: value && value.find((element) => element.key === "LASTHEARTBEAT").value,
uuid: value && value.find((element) => element.key === "UUID").value,
version: value && value.find((element) => element.key === "VERSION").value,
port: portSpec.port,
protocol: portSpec.proto
}
Expand Down

0 comments on commit 3ce5a53

Please sign in to comment.