This is an automated email from the ASF dual-hosted git repository.
ivandika 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 e0060a8f50 HDDS-11196. Improve SCM WebUI Display (#6960)
e0060a8f50 is described below
commit e0060a8f50fc8c919e08dbba2294b29d9fb5c84a
Author: slfan1989 <[email protected]>
AuthorDate: Tue Sep 17 18:07:44 2024 +0800
HDDS-11196. Improve SCM WebUI Display (#6960)
---
.../src/main/resources/webapps/static/ozone.css | 4 ++
.../resources/webapps/static/templates/jvm.html | 2 +-
.../hadoop/hdds/scm/node/SCMNodeManager.java | 21 +++++++++
.../apache/hadoop/hdds/scm/server/SCMMXBean.java | 3 +-
.../hdds/scm/server/StorageContainerManager.java | 51 ++++++++++++++++++++--
.../main/resources/webapps/scm/scm-overview.html | 39 +++++++++++++++--
.../src/main/resources/webapps/scm/scm.js | 7 +++
7 files changed, 118 insertions(+), 9 deletions(-)
diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.css
b/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.css
index e08e9c5206..389d9d78f2 100644
--- a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.css
+++ b/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.css
@@ -91,3 +91,7 @@ body {
.om-roles-background {
background-color: #dcfbcd!important;
}
+
+.scm-roles-background {
+ background-color: #dcfbcd!important;
+}
\ No newline at end of file
diff --git
a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/jvm.html
b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/jvm.html
index c1f7d16aef..9706ebdf6b 100644
--- a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/jvm.html
+++ b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/jvm.html
@@ -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>
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
index fa8f316aa4..7121d8f7a9 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
@@ -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.
*/
@@ -447,6 +449,11 @@ public class SCMNodeManager implements NodeManager {
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",
@@ -508,6 +515,18 @@ public class SCMNodeManager implements NodeManager {
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.
*
@@ -1136,6 +1155,8 @@ public class SCMNodeManager implements NodeManager {
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;
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMMXBean.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMMXBean.java
index de609356b2..75a5193116 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMMXBean.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMMXBean.java
@@ -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;
@@ -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.
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java
index 868e54f193..5f69d9fee2 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java
@@ -171,6 +171,7 @@ 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.protocol.RaftPeerId;
+import org.apache.ratis.server.RaftServer;
import org.apache.ratis.util.ExitUtils;
import org.apache.ratis.util.JvmPauseMonitor;
import org.slf4j.Logger;
@@ -2131,10 +2132,54 @@ public final class StorageContainerManager extends
ServiceRuntimeInfoImpl
}
@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));
}
/**
diff --git
a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm-overview.html
b/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm-overview.html
index 3f825d4e25..0f233bf4ea 100644
--- a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm-overview.html
+++ b/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm-overview.html
@@ -140,6 +140,10 @@
'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>
@@ -157,6 +161,8 @@
<td>{{typestat.opstate}}</td>
<td>{{typestat.comstate}}</td>
<td>{{typestat.lastheartbeat}}</td>
+ <td>{{typestat.uuid}}</td>
+ <td>{{typestat.version}}</td>
</tr>
</tbody>
</table>
@@ -210,10 +216,6 @@
<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>
@@ -235,6 +237,35 @@
</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">
diff --git a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js
b/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js
index 6fac684953..e00f8b8ede 100644
--- a/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js
+++ b/hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js
@@ -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;
@@ -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
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]