Skip to content

Commit

Permalink
HDDS-11196. Improve SCM WebUI Display (apache#6960)
Browse files Browse the repository at this point in the history
  • Loading branch information
slfan1989 authored and sarvekshayr committed Oct 7, 2024
1 parent 5a28102 commit b0e6467
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 9 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,11 @@ 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())) {
LOG.info("Update the version for registered datanode = {}, " +
"oldVersion = {}, newVersion = {}.",
datanodeDetails.getUuid(), oldNode.getVersion(), datanodeDetails.getVersion());
nodeStateManager.updateNode(datanodeDetails, layoutInfo);
}
} catch (NodeNotFoundException e) {
LOG.error("Cannot find datanode {} from nodeStateManager",
Expand Down Expand Up @@ -508,6 +515,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 versionChanged = !Objects.equals(oldVersion, newVersion);
return versionChanged;
}

/**
* Send heartbeat to indicate the datanode is alive and doing well.
*
Expand Down Expand Up @@ -1136,6 +1155,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 @@ -72,7 +73,7 @@ public interface SCMMXBean extends ServiceRuntimeInfo {

String getClusterId();

String getScmRatisRoles();
List<List<String>> getScmRatisRoles();

/**
* Primordial node is the node on which scm init operation is performed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@
import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.util.ReflectionUtils;
import org.apache.ratis.protocol.RaftPeerId;
import org.apache.ratis.server.RaftServer;
import org.apache.ratis.util.ExitUtils;
import org.apache.ratis.util.JvmPauseMonitor;
import org.slf4j.Logger;
Expand Down Expand Up @@ -2131,10 +2132,54 @@ public ContainerTokenGenerator getContainerTokenGenerator() {
}

@Override
public String getScmRatisRoles() {
public List<List<String>> getScmRatisRoles() {
final SCMRatisServer server = getScmHAManager().getRatisServer();
return server != null ?
HddsUtils.format(server.getRatisRoles()) : "STANDALONE";

// If Ratis is disabled
if (server == null) {
return getRatisRolesException("Ratis is disabled");
}

// 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();
RaftPeerId leaderId = division.getInfo().getLeaderId();
if (leaderId == 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());
}
}

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

/**
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.ScmRatisRoles.length == 1 && $ctrl.overview.jmx.ScmRatisRoles[0].length == 1">{{$ctrl.overview.jmx.ScmRatisRoles[0][0]}}</h4>
<div ng-show="$ctrl.overview.jmx.ScmRatisRoles.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.ScmRatisRoles">
<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 b0e6467

Please sign in to comment.