goiri commented on code in PR #4924:
URL: https://github.com/apache/hadoop/pull/4924#discussion_r979129686
##########
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/webapp/FederationBlock.java:
##########
@@ -58,119 +58,232 @@ class FederationBlock extends HtmlBlock {
@Override
public void render(Block html) {
+
Configuration conf = this.router.getConfig();
boolean isEnabled = conf.getBoolean(
YarnConfiguration.FEDERATION_ENABLED,
YarnConfiguration.DEFAULT_FEDERATION_ENABLED);
+
+ // If Yarn Federation is enabled.
if (isEnabled) {
- setTitle("Federation");
-
- // Table header
- TBODY<TABLE<Hamlet>> tbody = html.table("#rms").thead().tr()
- .th(".id", "SubCluster")
- .th(".submittedA", "Applications Submitted*")
- .th(".pendingA", "Applications Pending*")
- .th(".runningA", "Applications Running*")
- .th(".failedA", "Applications Failed*")
- .th(".killedA", "Applications Killed*")
- .th(".completedA", "Applications Completed*")
- .th(".contAllocated", "Containers Allocated")
- .th(".contReserved", "Containers Reserved")
- .th(".contPending", "Containers Pending")
- .th(".availableM", "Available Memory")
- .th(".allocatedM", "Allocated Memory")
- .th(".reservedM", "Reserved Memory")
- .th(".totalM", "Total Memory")
- .th(".availableVC", "Available VirtualCores")
- .th(".allocatedVC", "Allocated VirtualCores")
- .th(".reservedVC", "Reserved VirtualCores")
- .th(".totalVC", "Total VirtualCores")
- .th(".activeN", "Active Nodes")
- .th(".lostN", "Lost Nodes")
- .th(".availableN", "Available Nodes")
- .th(".unhealtyN", "Unhealthy Nodes")
- .th(".rebootedN", "Rebooted Nodes")
- .th(".totalN", "Total Nodes")
- .__().__().tbody();
-
- try {
- // Binding to the FederationStateStore
- FederationStateStoreFacade facade =
- FederationStateStoreFacade.getInstance();
- Map<SubClusterId, SubClusterInfo> subClustersInfo =
- facade.getSubClusters(true);
-
- // Sort the SubClusters
- List<SubClusterInfo> subclusters = new ArrayList<>();
- subclusters.addAll(subClustersInfo.values());
- Comparator<? super SubClusterInfo> cmp =
- new Comparator<SubClusterInfo>() {
- @Override
- public int compare(SubClusterInfo o1, SubClusterInfo o2) {
- return o1.getSubClusterId().compareTo(o2.getSubClusterId());
- }
- };
- Collections.sort(subclusters, cmp);
-
- for (SubClusterInfo subcluster : subclusters) {
- SubClusterId subClusterId = subcluster.getSubClusterId();
- String webAppAddress = subcluster.getRMWebServiceAddress();
- String capability = subcluster.getCapability();
- ClusterMetricsInfo subClusterInfo =
getClusterMetricsInfo(capability);
-
- // Building row per SubCluster
- tbody.tr().td().a("//" + webAppAddress, subClusterId.toString()).__()
- .td(Integer.toString(subClusterInfo.getAppsSubmitted()))
- .td(Integer.toString(subClusterInfo.getAppsPending()))
- .td(Integer.toString(subClusterInfo.getAppsRunning()))
- .td(Integer.toString(subClusterInfo.getAppsFailed()))
- .td(Integer.toString(subClusterInfo.getAppsKilled()))
- .td(Integer.toString(subClusterInfo.getAppsCompleted()))
- .td(Integer.toString(subClusterInfo.getContainersAllocated()))
- .td(Integer.toString(subClusterInfo.getReservedContainers()))
- .td(Integer.toString(subClusterInfo.getPendingContainers()))
- .td(StringUtils.byteDesc(
- subClusterInfo.getAvailableMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getAllocatedMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getReservedMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getTotalMB() * BYTES_IN_MB))
- .td(Long.toString(subClusterInfo.getAvailableVirtualCores()))
- .td(Long.toString(subClusterInfo.getAllocatedVirtualCores()))
- .td(Long.toString(subClusterInfo.getReservedVirtualCores()))
- .td(Long.toString(subClusterInfo.getTotalVirtualCores()))
- .td(Integer.toString(subClusterInfo.getActiveNodes()))
- .td(Integer.toString(subClusterInfo.getLostNodes()))
- .td(Integer.toString(subClusterInfo.getDecommissionedNodes()))
- .td(Integer.toString(subClusterInfo.getUnhealthyNodes()))
- .td(Integer.toString(subClusterInfo.getRebootedNodes()))
- .td(Integer.toString(subClusterInfo.getTotalNodes())).__();
- }
- } catch (YarnException e) {
- LOG.error("Cannot render ResourceManager", e);
- }
+ initHtmlPageFederationEnabled(html);
+ }
- tbody.__().__().div()
- .p().__("*The application counts are local per
subcluster").__().__();
- } else {
- setTitle("Federation is not Enabled!");
+ // If Yarn Federation is not enabled.
+ if(!isEnabled) {
Review Comment:
else?
##########
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/webapp/FederationBlock.java:
##########
@@ -58,119 +58,232 @@ class FederationBlock extends HtmlBlock {
@Override
public void render(Block html) {
+
Configuration conf = this.router.getConfig();
boolean isEnabled = conf.getBoolean(
YarnConfiguration.FEDERATION_ENABLED,
YarnConfiguration.DEFAULT_FEDERATION_ENABLED);
+
+ // If Yarn Federation is enabled.
if (isEnabled) {
- setTitle("Federation");
-
- // Table header
- TBODY<TABLE<Hamlet>> tbody = html.table("#rms").thead().tr()
- .th(".id", "SubCluster")
- .th(".submittedA", "Applications Submitted*")
- .th(".pendingA", "Applications Pending*")
- .th(".runningA", "Applications Running*")
- .th(".failedA", "Applications Failed*")
- .th(".killedA", "Applications Killed*")
- .th(".completedA", "Applications Completed*")
- .th(".contAllocated", "Containers Allocated")
- .th(".contReserved", "Containers Reserved")
- .th(".contPending", "Containers Pending")
- .th(".availableM", "Available Memory")
- .th(".allocatedM", "Allocated Memory")
- .th(".reservedM", "Reserved Memory")
- .th(".totalM", "Total Memory")
- .th(".availableVC", "Available VirtualCores")
- .th(".allocatedVC", "Allocated VirtualCores")
- .th(".reservedVC", "Reserved VirtualCores")
- .th(".totalVC", "Total VirtualCores")
- .th(".activeN", "Active Nodes")
- .th(".lostN", "Lost Nodes")
- .th(".availableN", "Available Nodes")
- .th(".unhealtyN", "Unhealthy Nodes")
- .th(".rebootedN", "Rebooted Nodes")
- .th(".totalN", "Total Nodes")
- .__().__().tbody();
-
- try {
- // Binding to the FederationStateStore
- FederationStateStoreFacade facade =
- FederationStateStoreFacade.getInstance();
- Map<SubClusterId, SubClusterInfo> subClustersInfo =
- facade.getSubClusters(true);
-
- // Sort the SubClusters
- List<SubClusterInfo> subclusters = new ArrayList<>();
- subclusters.addAll(subClustersInfo.values());
- Comparator<? super SubClusterInfo> cmp =
- new Comparator<SubClusterInfo>() {
- @Override
- public int compare(SubClusterInfo o1, SubClusterInfo o2) {
- return o1.getSubClusterId().compareTo(o2.getSubClusterId());
- }
- };
- Collections.sort(subclusters, cmp);
-
- for (SubClusterInfo subcluster : subclusters) {
- SubClusterId subClusterId = subcluster.getSubClusterId();
- String webAppAddress = subcluster.getRMWebServiceAddress();
- String capability = subcluster.getCapability();
- ClusterMetricsInfo subClusterInfo =
getClusterMetricsInfo(capability);
-
- // Building row per SubCluster
- tbody.tr().td().a("//" + webAppAddress, subClusterId.toString()).__()
- .td(Integer.toString(subClusterInfo.getAppsSubmitted()))
- .td(Integer.toString(subClusterInfo.getAppsPending()))
- .td(Integer.toString(subClusterInfo.getAppsRunning()))
- .td(Integer.toString(subClusterInfo.getAppsFailed()))
- .td(Integer.toString(subClusterInfo.getAppsKilled()))
- .td(Integer.toString(subClusterInfo.getAppsCompleted()))
- .td(Integer.toString(subClusterInfo.getContainersAllocated()))
- .td(Integer.toString(subClusterInfo.getReservedContainers()))
- .td(Integer.toString(subClusterInfo.getPendingContainers()))
- .td(StringUtils.byteDesc(
- subClusterInfo.getAvailableMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getAllocatedMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getReservedMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getTotalMB() * BYTES_IN_MB))
- .td(Long.toString(subClusterInfo.getAvailableVirtualCores()))
- .td(Long.toString(subClusterInfo.getAllocatedVirtualCores()))
- .td(Long.toString(subClusterInfo.getReservedVirtualCores()))
- .td(Long.toString(subClusterInfo.getTotalVirtualCores()))
- .td(Integer.toString(subClusterInfo.getActiveNodes()))
- .td(Integer.toString(subClusterInfo.getLostNodes()))
- .td(Integer.toString(subClusterInfo.getDecommissionedNodes()))
- .td(Integer.toString(subClusterInfo.getUnhealthyNodes()))
- .td(Integer.toString(subClusterInfo.getRebootedNodes()))
- .td(Integer.toString(subClusterInfo.getTotalNodes())).__();
- }
- } catch (YarnException e) {
- LOG.error("Cannot render ResourceManager", e);
- }
+ initHtmlPageFederationEnabled(html);
+ }
- tbody.__().__().div()
- .p().__("*The application counts are local per
subcluster").__().__();
- } else {
- setTitle("Federation is not Enabled!");
+ // If Yarn Federation is not enabled.
+ if(!isEnabled) {
+ initHtmlPageFederationNotEnabled(html);
}
}
- private static ClusterMetricsInfo getClusterMetricsInfo(String capability) {
- ClusterMetricsInfo clusterMetrics = null;
+ /**
+ * Parse the capability and obtain the metric information of the cluster.
+ *
+ * @param capability metric json obtained from RM.
+ * @return ClusterMetricsInfo Object
+ */
+ private ClusterMetricsInfo getClusterMetricsInfo(String capability) {
try {
- JSONJAXBContext jc = new JSONJAXBContext(
- JSONConfiguration.mapped().rootUnwrapping(false).build(),
- ClusterMetricsInfo.class);
- JSONUnmarshaller unmarshaller = jc.createJSONUnmarshaller();
- clusterMetrics = unmarshaller.unmarshalFromJSON(
- new StringReader(capability), ClusterMetricsInfo.class);
+ if (capability != null && !capability.isEmpty()) {
+ JSONJAXBContext jc = new JSONJAXBContext(
+ JSONConfiguration.mapped().rootUnwrapping(false).build(),
ClusterMetricsInfo.class);
+ JSONUnmarshaller unmarShaller = jc.createJSONUnmarshaller();
+ StringReader stringReader = new StringReader(capability);
+ ClusterMetricsInfo clusterMetrics =
+ unmarShaller.unmarshalFromJSON(stringReader,
ClusterMetricsInfo.class);
+ return clusterMetrics;
+ }
} catch (Exception e) {
LOG.error("Cannot parse SubCluster info", e);
}
- return clusterMetrics;
+ return null;
+ }
+
+ /**
+ * Initialize the subCluster details JavaScript of the Federation page.
+ *
+ * This part of the js script will control to display or hide the detailed
information
+ * of the subCluster when the user clicks on the subClusterId.
+ *
+ * We will obtain the specific information of a SubCluster,
+ * including the information of Applications, Resources, and Nodes.
+ *
+ * @param html html object
+ * @param subClusterDetailMap subCluster Detail Map
+ */
+ private void initFederationSubClusterDetailTableJs(Block html,
+ List<Map<String, String>> subClusterDetailMap) {
+ Gson gson = new Gson();
+ html.script().$type("text/javascript").
+ __("$(document).ready(function() { " +
+ " var scTableData = " + gson.toJson(subClusterDetailMap) + "; " +
+ " var table = $('#rms').DataTable(); " +
+ " $('#rms tbody').on('click', 'td.details-control', function () { " +
+ " var tr = $(this).closest('tr'); " +
+ " var row = table.row(tr); " +
+ " if (row.child.isShown()) { " +
+ " row.child.hide(); " +
+ " tr.removeClass('shown'); " +
+ " } else { " +
+ " var capabilityArr = scTableData.filter(item => (item.subcluster
=== row.id())); " +
+ " var capabilityObj =
JSON.parse(capabilityArr[0].capability).clusterMetrics; " +
+ " row.child(" +
+ " '<table>" +
+ " <tr>" +
+ " <td>" +
+ " <h3>Application Metrics</h3>" +
+ " ApplicationSubmitted* : '+
capabilityObj.appsSubmitted +' </p>" +
+ " ApplicationCompleted* : '+
capabilityObj.appsCompleted +' </p>" +
+ " ApplicationPending* : '+
capabilityObj.appsPending +' </p>" +
+ " ApplicationRunning* : '+
capabilityObj.appsRunning +' </p>" +
+ " ApplicationFailed* : '+
capabilityObj.appsFailed +' </p> " +
+ " ApplicationKilled* : '+
capabilityObj.appsKilled +' </p>" +
+ " </td>" +
+ " <td>" +
+ " <h3>Resource Metrics</h3>" +
+ " <h4>Memory</h4>" +
+ " TotalMB : '+ capabilityObj.totalMB +' </p>" +
+ " ReservedMB : '+ capabilityObj.reservedMB +' </p>" +
+ " AvailableMB : '+ capabilityObj.availableMB +'
</p>" +
+ " AllocatedMB : '+ capabilityObj.allocatedMB +'
</p>" +
+ " PendingMB : '+ capabilityObj.pendingMB +' </p>" +
+ " <h4>VirtualCores</h4>" +
+ " TotalVirtualCores :
'+capabilityObj.totalVirtualCores+' </p>" +
+ " ReservedVirtualCores :
'+capabilityObj.reservedVirtualCores+' </p>" +
+ " AvailableVirtualCore :
'+capabilityObj.availableVirtualCores+' </p>" +
+ " AllocatedVirtualCores :
'+capabilityObj.allocatedVirtualCores+' </p>" +
+ " PendingVirtualCores :
'+capabilityObj.pendingVirtualCores+' </p>" +
+ " <h4>Containers</h4>" +
+ " ContainersAllocated :
'+capabilityObj.containersAllocated+' </p>" +
+ " ContainersReserved :
'+capabilityObj.containersReserved+' </p>" +
+ " ContainersPending :
'+capabilityObj.containersPending+' </p>" +
+ " </td>" +
+ " <td>" +
+ " <h3>Node Metrics</h3>" +
+ " TotalNodes : '+capabilityObj.totalNodes+' </p>" +
+ " LostNodes : '+capabilityObj.lostNodes+' </p>" +
+ " UnhealthyNodes : '+capabilityObj.unhealthyNodes+'
</p>" +
+ " DecommissioningNodes :
'+capabilityObj.decommissioningNodes+' </p>" +
+ " DecommissionedNodes :
'+capabilityObj.decommissionedNodes+' </p>" +
+ " RebootedNodes : '+capabilityObj.rebootedNodes+'
</p>" +
+ " ActiveNodes : '+capabilityObj.activeNodes+' </p>" +
+ " ShutdownNodes : '+capabilityObj.shutdownNodes+' " +
+ " </td>" +
+ " </tr>" +
+ " </table>').show(); "+
+ " tr.addClass('shown'); " +
+ " } " +
+ " }); });").__();
+ }
+
+ /**
+ * Initialize the Html page when Federation is enabled.
+ *
+ * @param html html object
+ */
+ private void initHtmlPageFederationEnabled(Block html) {
+ List<Map<String, String>> lists = new ArrayList<>();
+
+ // Table header
+ TBODY<TABLE<Hamlet>> tbody =
+
html.table("#rms").$class("cell-border").$style("width:100%").thead().tr()
+ .th(".id", "SubCluster")
+ .th(".state", "State")
+ .th(".lastStartTime", "LastStartTime")
+ .th(".lastHeartBeat", "LastHeartBeat")
+ .th(".resources", "Resources")
+ .th(".nodes", "Nodes")
+ .__().__().tbody();
+
+ try {
+ // Binding to the FederationStateStore
+ FederationStateStoreFacade facade =
FederationStateStoreFacade.getInstance();
+
+ Map<SubClusterId, SubClusterInfo> subClustersInfo =
+ facade.getSubClusters(true);
+
+ // Sort the SubClusters
+ List<SubClusterInfo> subclusters = new ArrayList<>();
+ subclusters.addAll(subClustersInfo.values());
+ Comparator<? super SubClusterInfo> cmp = Comparator.comparing(o ->
o.getSubClusterId());
+ Collections.sort(subclusters, cmp);
+
+ for (SubClusterInfo subcluster : subclusters) {
+
+ Map<String, String> subclusterMap = new HashMap<>();
+
+ // Prepare subCluster
+ SubClusterId subClusterId = subcluster.getSubClusterId();
+ String subClusterIdText = subClusterId.getId();
+
+ // Prepare WebAppAddress
+ String webAppAddress = subcluster.getRMWebServiceAddress();
+ String herfWebAppAddress = "";
+ if (webAppAddress != null && !webAppAddress.isEmpty()) {
+ herfWebAppAddress = "//" + webAppAddress;
+ }
+
+ // Prepare Capability
+ String capability = subcluster.getCapability();
+ ClusterMetricsInfo subClusterInfo = getClusterMetricsInfo(capability);
+
+ // Prepare LastStartTime & LastHeartBeat
+ String lastStartTime =
+ DateFormatUtils.format(subcluster.getLastStartTime(),
DATE_PATTERN);
+ String lastHeartBeat =
+ DateFormatUtils.format(subcluster.getLastHeartBeat(),
DATE_PATTERN);
+
+ // Prepare Resource
+ long totalMB = subClusterInfo.getTotalMB();
+ String totalMBDesc = StringUtils.byteDesc(totalMB * BYTES_IN_MB);
+ long totalVirtualCores = subClusterInfo.getTotalVirtualCores();
+ String resources = String.format("<Memory:%s, VCore:%s>", totalMBDesc,
totalVirtualCores);
+
+ // Prepare Node
+ long totalNodes = subClusterInfo.getTotalNodes();
+ long activeNodes = subClusterInfo.getActiveNodes();
+ String nodes = String.format("<Total Nodes:%s, Active Nodes:%s>",
Review Comment:
Single line?
##########
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/webapp/RouterController.java:
##########
@@ -34,7 +34,7 @@ public class RouterController extends Controller {
@Override
public void index() {
- setTitle("Router");
+ setTitle("About the Router");
Review Comment:
`About the YARN Router`?
##########
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/webapp/FederationBlock.java:
##########
@@ -58,119 +58,232 @@ class FederationBlock extends HtmlBlock {
@Override
public void render(Block html) {
+
Configuration conf = this.router.getConfig();
boolean isEnabled = conf.getBoolean(
YarnConfiguration.FEDERATION_ENABLED,
YarnConfiguration.DEFAULT_FEDERATION_ENABLED);
+
+ // If Yarn Federation is enabled.
if (isEnabled) {
- setTitle("Federation");
-
- // Table header
- TBODY<TABLE<Hamlet>> tbody = html.table("#rms").thead().tr()
- .th(".id", "SubCluster")
- .th(".submittedA", "Applications Submitted*")
- .th(".pendingA", "Applications Pending*")
- .th(".runningA", "Applications Running*")
- .th(".failedA", "Applications Failed*")
- .th(".killedA", "Applications Killed*")
- .th(".completedA", "Applications Completed*")
- .th(".contAllocated", "Containers Allocated")
- .th(".contReserved", "Containers Reserved")
- .th(".contPending", "Containers Pending")
- .th(".availableM", "Available Memory")
- .th(".allocatedM", "Allocated Memory")
- .th(".reservedM", "Reserved Memory")
- .th(".totalM", "Total Memory")
- .th(".availableVC", "Available VirtualCores")
- .th(".allocatedVC", "Allocated VirtualCores")
- .th(".reservedVC", "Reserved VirtualCores")
- .th(".totalVC", "Total VirtualCores")
- .th(".activeN", "Active Nodes")
- .th(".lostN", "Lost Nodes")
- .th(".availableN", "Available Nodes")
- .th(".unhealtyN", "Unhealthy Nodes")
- .th(".rebootedN", "Rebooted Nodes")
- .th(".totalN", "Total Nodes")
- .__().__().tbody();
-
- try {
- // Binding to the FederationStateStore
- FederationStateStoreFacade facade =
- FederationStateStoreFacade.getInstance();
- Map<SubClusterId, SubClusterInfo> subClustersInfo =
- facade.getSubClusters(true);
-
- // Sort the SubClusters
- List<SubClusterInfo> subclusters = new ArrayList<>();
- subclusters.addAll(subClustersInfo.values());
- Comparator<? super SubClusterInfo> cmp =
- new Comparator<SubClusterInfo>() {
- @Override
- public int compare(SubClusterInfo o1, SubClusterInfo o2) {
- return o1.getSubClusterId().compareTo(o2.getSubClusterId());
- }
- };
- Collections.sort(subclusters, cmp);
-
- for (SubClusterInfo subcluster : subclusters) {
- SubClusterId subClusterId = subcluster.getSubClusterId();
- String webAppAddress = subcluster.getRMWebServiceAddress();
- String capability = subcluster.getCapability();
- ClusterMetricsInfo subClusterInfo =
getClusterMetricsInfo(capability);
-
- // Building row per SubCluster
- tbody.tr().td().a("//" + webAppAddress, subClusterId.toString()).__()
- .td(Integer.toString(subClusterInfo.getAppsSubmitted()))
- .td(Integer.toString(subClusterInfo.getAppsPending()))
- .td(Integer.toString(subClusterInfo.getAppsRunning()))
- .td(Integer.toString(subClusterInfo.getAppsFailed()))
- .td(Integer.toString(subClusterInfo.getAppsKilled()))
- .td(Integer.toString(subClusterInfo.getAppsCompleted()))
- .td(Integer.toString(subClusterInfo.getContainersAllocated()))
- .td(Integer.toString(subClusterInfo.getReservedContainers()))
- .td(Integer.toString(subClusterInfo.getPendingContainers()))
- .td(StringUtils.byteDesc(
- subClusterInfo.getAvailableMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getAllocatedMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getReservedMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getTotalMB() * BYTES_IN_MB))
- .td(Long.toString(subClusterInfo.getAvailableVirtualCores()))
- .td(Long.toString(subClusterInfo.getAllocatedVirtualCores()))
- .td(Long.toString(subClusterInfo.getReservedVirtualCores()))
- .td(Long.toString(subClusterInfo.getTotalVirtualCores()))
- .td(Integer.toString(subClusterInfo.getActiveNodes()))
- .td(Integer.toString(subClusterInfo.getLostNodes()))
- .td(Integer.toString(subClusterInfo.getDecommissionedNodes()))
- .td(Integer.toString(subClusterInfo.getUnhealthyNodes()))
- .td(Integer.toString(subClusterInfo.getRebootedNodes()))
- .td(Integer.toString(subClusterInfo.getTotalNodes())).__();
- }
- } catch (YarnException e) {
- LOG.error("Cannot render ResourceManager", e);
- }
+ initHtmlPageFederationEnabled(html);
+ }
- tbody.__().__().div()
- .p().__("*The application counts are local per
subcluster").__().__();
- } else {
- setTitle("Federation is not Enabled!");
+ // If Yarn Federation is not enabled.
+ if(!isEnabled) {
+ initHtmlPageFederationNotEnabled(html);
}
}
- private static ClusterMetricsInfo getClusterMetricsInfo(String capability) {
- ClusterMetricsInfo clusterMetrics = null;
+ /**
+ * Parse the capability and obtain the metric information of the cluster.
+ *
+ * @param capability metric json obtained from RM.
+ * @return ClusterMetricsInfo Object
+ */
+ private ClusterMetricsInfo getClusterMetricsInfo(String capability) {
try {
- JSONJAXBContext jc = new JSONJAXBContext(
- JSONConfiguration.mapped().rootUnwrapping(false).build(),
- ClusterMetricsInfo.class);
- JSONUnmarshaller unmarshaller = jc.createJSONUnmarshaller();
- clusterMetrics = unmarshaller.unmarshalFromJSON(
- new StringReader(capability), ClusterMetricsInfo.class);
+ if (capability != null && !capability.isEmpty()) {
+ JSONJAXBContext jc = new JSONJAXBContext(
+ JSONConfiguration.mapped().rootUnwrapping(false).build(),
ClusterMetricsInfo.class);
+ JSONUnmarshaller unmarShaller = jc.createJSONUnmarshaller();
+ StringReader stringReader = new StringReader(capability);
+ ClusterMetricsInfo clusterMetrics =
+ unmarShaller.unmarshalFromJSON(stringReader,
ClusterMetricsInfo.class);
+ return clusterMetrics;
+ }
} catch (Exception e) {
LOG.error("Cannot parse SubCluster info", e);
}
- return clusterMetrics;
+ return null;
+ }
+
+ /**
+ * Initialize the subCluster details JavaScript of the Federation page.
+ *
+ * This part of the js script will control to display or hide the detailed
information
+ * of the subCluster when the user clicks on the subClusterId.
+ *
+ * We will obtain the specific information of a SubCluster,
+ * including the information of Applications, Resources, and Nodes.
+ *
+ * @param html html object
+ * @param subClusterDetailMap subCluster Detail Map
+ */
+ private void initFederationSubClusterDetailTableJs(Block html,
+ List<Map<String, String>> subClusterDetailMap) {
+ Gson gson = new Gson();
+ html.script().$type("text/javascript").
+ __("$(document).ready(function() { " +
Review Comment:
This massive string with double embedding is very dangerous.
Isn't there a better way to have some javascript file and some html template?
##########
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/webapp/FederationPage.java:
##########
@@ -33,8 +33,9 @@ class FederationPage extends RouterView {
@Override
protected void preHead(Page.HTML<__> html) {
commonPreHead(html);
- setTitle("Federation");
+ setTitle("About The Federation");
Review Comment:
I think it makes more sense to have `About YARN federation`
##########
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/webapp/FederationBlock.java:
##########
@@ -58,119 +58,232 @@ class FederationBlock extends HtmlBlock {
@Override
public void render(Block html) {
+
Configuration conf = this.router.getConfig();
boolean isEnabled = conf.getBoolean(
YarnConfiguration.FEDERATION_ENABLED,
YarnConfiguration.DEFAULT_FEDERATION_ENABLED);
+
+ // If Yarn Federation is enabled.
if (isEnabled) {
- setTitle("Federation");
-
- // Table header
- TBODY<TABLE<Hamlet>> tbody = html.table("#rms").thead().tr()
- .th(".id", "SubCluster")
- .th(".submittedA", "Applications Submitted*")
- .th(".pendingA", "Applications Pending*")
- .th(".runningA", "Applications Running*")
- .th(".failedA", "Applications Failed*")
- .th(".killedA", "Applications Killed*")
- .th(".completedA", "Applications Completed*")
- .th(".contAllocated", "Containers Allocated")
- .th(".contReserved", "Containers Reserved")
- .th(".contPending", "Containers Pending")
- .th(".availableM", "Available Memory")
- .th(".allocatedM", "Allocated Memory")
- .th(".reservedM", "Reserved Memory")
- .th(".totalM", "Total Memory")
- .th(".availableVC", "Available VirtualCores")
- .th(".allocatedVC", "Allocated VirtualCores")
- .th(".reservedVC", "Reserved VirtualCores")
- .th(".totalVC", "Total VirtualCores")
- .th(".activeN", "Active Nodes")
- .th(".lostN", "Lost Nodes")
- .th(".availableN", "Available Nodes")
- .th(".unhealtyN", "Unhealthy Nodes")
- .th(".rebootedN", "Rebooted Nodes")
- .th(".totalN", "Total Nodes")
- .__().__().tbody();
-
- try {
- // Binding to the FederationStateStore
- FederationStateStoreFacade facade =
- FederationStateStoreFacade.getInstance();
- Map<SubClusterId, SubClusterInfo> subClustersInfo =
- facade.getSubClusters(true);
-
- // Sort the SubClusters
- List<SubClusterInfo> subclusters = new ArrayList<>();
- subclusters.addAll(subClustersInfo.values());
- Comparator<? super SubClusterInfo> cmp =
- new Comparator<SubClusterInfo>() {
- @Override
- public int compare(SubClusterInfo o1, SubClusterInfo o2) {
- return o1.getSubClusterId().compareTo(o2.getSubClusterId());
- }
- };
- Collections.sort(subclusters, cmp);
-
- for (SubClusterInfo subcluster : subclusters) {
- SubClusterId subClusterId = subcluster.getSubClusterId();
- String webAppAddress = subcluster.getRMWebServiceAddress();
- String capability = subcluster.getCapability();
- ClusterMetricsInfo subClusterInfo =
getClusterMetricsInfo(capability);
-
- // Building row per SubCluster
- tbody.tr().td().a("//" + webAppAddress, subClusterId.toString()).__()
- .td(Integer.toString(subClusterInfo.getAppsSubmitted()))
- .td(Integer.toString(subClusterInfo.getAppsPending()))
- .td(Integer.toString(subClusterInfo.getAppsRunning()))
- .td(Integer.toString(subClusterInfo.getAppsFailed()))
- .td(Integer.toString(subClusterInfo.getAppsKilled()))
- .td(Integer.toString(subClusterInfo.getAppsCompleted()))
- .td(Integer.toString(subClusterInfo.getContainersAllocated()))
- .td(Integer.toString(subClusterInfo.getReservedContainers()))
- .td(Integer.toString(subClusterInfo.getPendingContainers()))
- .td(StringUtils.byteDesc(
- subClusterInfo.getAvailableMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getAllocatedMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getReservedMB() * BYTES_IN_MB))
- .td(StringUtils.byteDesc(
- subClusterInfo.getTotalMB() * BYTES_IN_MB))
- .td(Long.toString(subClusterInfo.getAvailableVirtualCores()))
- .td(Long.toString(subClusterInfo.getAllocatedVirtualCores()))
- .td(Long.toString(subClusterInfo.getReservedVirtualCores()))
- .td(Long.toString(subClusterInfo.getTotalVirtualCores()))
- .td(Integer.toString(subClusterInfo.getActiveNodes()))
- .td(Integer.toString(subClusterInfo.getLostNodes()))
- .td(Integer.toString(subClusterInfo.getDecommissionedNodes()))
- .td(Integer.toString(subClusterInfo.getUnhealthyNodes()))
- .td(Integer.toString(subClusterInfo.getRebootedNodes()))
- .td(Integer.toString(subClusterInfo.getTotalNodes())).__();
- }
- } catch (YarnException e) {
- LOG.error("Cannot render ResourceManager", e);
- }
+ initHtmlPageFederationEnabled(html);
+ }
- tbody.__().__().div()
- .p().__("*The application counts are local per
subcluster").__().__();
- } else {
- setTitle("Federation is not Enabled!");
+ // If Yarn Federation is not enabled.
+ if(!isEnabled) {
+ initHtmlPageFederationNotEnabled(html);
}
}
- private static ClusterMetricsInfo getClusterMetricsInfo(String capability) {
- ClusterMetricsInfo clusterMetrics = null;
+ /**
+ * Parse the capability and obtain the metric information of the cluster.
+ *
+ * @param capability metric json obtained from RM.
+ * @return ClusterMetricsInfo Object
+ */
+ private ClusterMetricsInfo getClusterMetricsInfo(String capability) {
try {
- JSONJAXBContext jc = new JSONJAXBContext(
- JSONConfiguration.mapped().rootUnwrapping(false).build(),
- ClusterMetricsInfo.class);
- JSONUnmarshaller unmarshaller = jc.createJSONUnmarshaller();
- clusterMetrics = unmarshaller.unmarshalFromJSON(
- new StringReader(capability), ClusterMetricsInfo.class);
+ if (capability != null && !capability.isEmpty()) {
+ JSONJAXBContext jc = new JSONJAXBContext(
+ JSONConfiguration.mapped().rootUnwrapping(false).build(),
ClusterMetricsInfo.class);
+ JSONUnmarshaller unmarShaller = jc.createJSONUnmarshaller();
+ StringReader stringReader = new StringReader(capability);
+ ClusterMetricsInfo clusterMetrics =
+ unmarShaller.unmarshalFromJSON(stringReader,
ClusterMetricsInfo.class);
+ return clusterMetrics;
+ }
} catch (Exception e) {
LOG.error("Cannot parse SubCluster info", e);
}
- return clusterMetrics;
+ return null;
+ }
+
+ /**
+ * Initialize the subCluster details JavaScript of the Federation page.
+ *
+ * This part of the js script will control to display or hide the detailed
information
+ * of the subCluster when the user clicks on the subClusterId.
+ *
+ * We will obtain the specific information of a SubCluster,
+ * including the information of Applications, Resources, and Nodes.
+ *
+ * @param html html object
+ * @param subClusterDetailMap subCluster Detail Map
+ */
+ private void initFederationSubClusterDetailTableJs(Block html,
+ List<Map<String, String>> subClusterDetailMap) {
+ Gson gson = new Gson();
+ html.script().$type("text/javascript").
+ __("$(document).ready(function() { " +
+ " var scTableData = " + gson.toJson(subClusterDetailMap) + "; " +
+ " var table = $('#rms').DataTable(); " +
+ " $('#rms tbody').on('click', 'td.details-control', function () { " +
+ " var tr = $(this).closest('tr'); " +
+ " var row = table.row(tr); " +
+ " if (row.child.isShown()) { " +
+ " row.child.hide(); " +
+ " tr.removeClass('shown'); " +
+ " } else { " +
+ " var capabilityArr = scTableData.filter(item => (item.subcluster
=== row.id())); " +
+ " var capabilityObj =
JSON.parse(capabilityArr[0].capability).clusterMetrics; " +
+ " row.child(" +
+ " '<table>" +
+ " <tr>" +
+ " <td>" +
+ " <h3>Application Metrics</h3>" +
+ " ApplicationSubmitted* : '+
capabilityObj.appsSubmitted +' </p>" +
+ " ApplicationCompleted* : '+
capabilityObj.appsCompleted +' </p>" +
+ " ApplicationPending* : '+
capabilityObj.appsPending +' </p>" +
+ " ApplicationRunning* : '+
capabilityObj.appsRunning +' </p>" +
+ " ApplicationFailed* : '+
capabilityObj.appsFailed +' </p> " +
+ " ApplicationKilled* : '+
capabilityObj.appsKilled +' </p>" +
+ " </td>" +
+ " <td>" +
+ " <h3>Resource Metrics</h3>" +
+ " <h4>Memory</h4>" +
+ " TotalMB : '+ capabilityObj.totalMB +' </p>" +
+ " ReservedMB : '+ capabilityObj.reservedMB +' </p>" +
+ " AvailableMB : '+ capabilityObj.availableMB +'
</p>" +
+ " AllocatedMB : '+ capabilityObj.allocatedMB +'
</p>" +
+ " PendingMB : '+ capabilityObj.pendingMB +' </p>" +
+ " <h4>VirtualCores</h4>" +
+ " TotalVirtualCores :
'+capabilityObj.totalVirtualCores+' </p>" +
+ " ReservedVirtualCores :
'+capabilityObj.reservedVirtualCores+' </p>" +
+ " AvailableVirtualCore :
'+capabilityObj.availableVirtualCores+' </p>" +
+ " AllocatedVirtualCores :
'+capabilityObj.allocatedVirtualCores+' </p>" +
+ " PendingVirtualCores :
'+capabilityObj.pendingVirtualCores+' </p>" +
+ " <h4>Containers</h4>" +
+ " ContainersAllocated :
'+capabilityObj.containersAllocated+' </p>" +
+ " ContainersReserved :
'+capabilityObj.containersReserved+' </p>" +
+ " ContainersPending :
'+capabilityObj.containersPending+' </p>" +
+ " </td>" +
+ " <td>" +
+ " <h3>Node Metrics</h3>" +
+ " TotalNodes : '+capabilityObj.totalNodes+' </p>" +
+ " LostNodes : '+capabilityObj.lostNodes+' </p>" +
+ " UnhealthyNodes : '+capabilityObj.unhealthyNodes+'
</p>" +
+ " DecommissioningNodes :
'+capabilityObj.decommissioningNodes+' </p>" +
+ " DecommissionedNodes :
'+capabilityObj.decommissionedNodes+' </p>" +
+ " RebootedNodes : '+capabilityObj.rebootedNodes+'
</p>" +
+ " ActiveNodes : '+capabilityObj.activeNodes+' </p>" +
+ " ShutdownNodes : '+capabilityObj.shutdownNodes+' " +
+ " </td>" +
+ " </tr>" +
+ " </table>').show(); "+
+ " tr.addClass('shown'); " +
+ " } " +
+ " }); });").__();
+ }
+
+ /**
+ * Initialize the Html page when Federation is enabled.
+ *
+ * @param html html object
+ */
+ private void initHtmlPageFederationEnabled(Block html) {
+ List<Map<String, String>> lists = new ArrayList<>();
+
+ // Table header
+ TBODY<TABLE<Hamlet>> tbody =
+
html.table("#rms").$class("cell-border").$style("width:100%").thead().tr()
+ .th(".id", "SubCluster")
+ .th(".state", "State")
+ .th(".lastStartTime", "LastStartTime")
+ .th(".lastHeartBeat", "LastHeartBeat")
+ .th(".resources", "Resources")
+ .th(".nodes", "Nodes")
+ .__().__().tbody();
+
+ try {
+ // Binding to the FederationStateStore
+ FederationStateStoreFacade facade =
FederationStateStoreFacade.getInstance();
+
+ Map<SubClusterId, SubClusterInfo> subClustersInfo =
Review Comment:
Single line?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]