Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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