YARN-4515. [YARN-3368] Support hosting web UI framework inside YARN RM. (Sunil G via wangda)
YARN-5000. [YARN-3368] App attempt page is not loading when timeline server is not started (Sunil G via wangda) YARN-5038. [YARN-3368] Application and Container pages shows wrong values when RM is stopped. (Sunil G via wangda)
This commit is contained in:
parent
2c4f164e16
commit
c85cc3b56e
@ -2328,6 +2328,7 @@ The Apache Hadoop YARN Web UI component bundles the following files under the MI
|
||||
- datatables v1.10.8 (https://datatables.net/)
|
||||
- moment v2.10.6 (http://momentjs.com/) - Copyright (c) 2011-2015 Tim Wood, Iskren Chernev, Moment.js contributors
|
||||
- em-helpers v0.5.8 (https://github.com/sreenaths/em-helpers)
|
||||
- ember-array-contains-helper v1.0.2 (https://github.com/bmeurant/ember-array-contains-helper)
|
||||
- ember-cli-app-version v0.5.8 (https://github.com/EmberSherpa/ember-cli-app-version) - Authored by Taras Mankovski <tarasm@gmail.com>
|
||||
- ember-cli-babel v5.1.6 (https://github.com/babel/ember-cli-babel) - Authored by Stefan Penner <stefan.penner@gmail.com>
|
||||
- ember-cli-content-security-policy v0.4.0 (https://github.com/rwjblue/ember-cli-content-security-policy)
|
||||
@ -2341,6 +2342,7 @@ The Apache Hadoop YARN Web UI component bundles the following files under the MI
|
||||
- ember-cli-sri v1.2.1 (https://github.com/jonathanKingston/ember-cli-sri) - Authored by Jonathan Kingston
|
||||
- ember-cli-uglify v1.2.0 (github.com/ember-cli/ember-cli-uglify) - Authored by Robert Jackson <me@rwjblue.com>
|
||||
- ember-d3 v0.1.0 (https://github.com/brzpegasus/ember-d3) - Authored by Estelle DeBlois
|
||||
- ember-truth-helpers v1.2.0 (https://github.com/jmurphyau/ember-truth-helpers)
|
||||
- select2 v4.0.0 (https://select2.github.io/)
|
||||
|
||||
All rights reserved.
|
||||
|
@ -192,6 +192,13 @@
|
||||
<directory>${project.build.directory}/site</directory>
|
||||
<outputDirectory>/share/doc/hadoop/${hadoop.component}</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>hadoop-yarn/hadoop-yarn-ui/target/hadoop-yarn-ui-${project.version}</directory>
|
||||
<outputDirectory>/share/hadoop/${hadoop.component}/webapps/rm</outputDirectory>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<moduleSets>
|
||||
<moduleSet>
|
||||
|
@ -262,7 +262,30 @@ private static void addDeprecatedKeys() {
|
||||
public static final int DEFAULT_RM_WEBAPP_HTTPS_PORT = 8090;
|
||||
public static final String DEFAULT_RM_WEBAPP_HTTPS_ADDRESS = "0.0.0.0:"
|
||||
+ DEFAULT_RM_WEBAPP_HTTPS_PORT;
|
||||
|
||||
/**
|
||||
* Enable YARN WebApp V2.
|
||||
*/
|
||||
public static final String RM_WEBAPP_UI2_ENABLE = RM_PREFIX
|
||||
+ "webapp.ui2.enable";
|
||||
public static final boolean DEFAULT_RM_WEBAPP_UI2_ENABLE = false;
|
||||
|
||||
/** The address of the RM web ui2 application. */
|
||||
public static final String RM_WEBAPP_UI2_ADDRESS = RM_PREFIX
|
||||
+ "webapp.ui2.address";
|
||||
|
||||
public static final int DEFAULT_RM_WEBAPP_UI2_PORT = 8288;
|
||||
public static final String DEFAULT_RM_WEBAPP_UI2_ADDRESS = "0.0.0.0:" +
|
||||
DEFAULT_RM_WEBAPP_UI2_PORT;
|
||||
|
||||
/** The https address of the RM web ui2 application.*/
|
||||
public static final String RM_WEBAPP_UI2_HTTPS_ADDRESS =
|
||||
RM_PREFIX + "webapp.ui2.https.address";
|
||||
|
||||
public static final int DEFAULT_RM_WEBAPP_UI2_HTTPS_PORT = 8290;
|
||||
public static final String DEFAULT_RM_WEBAPP_UI2_HTTPS_ADDRESS = "0.0.0.0:"
|
||||
+ DEFAULT_RM_WEBAPP_UI2_HTTPS_PORT;
|
||||
|
||||
public static final String RM_RESOURCE_TRACKER_ADDRESS =
|
||||
RM_PREFIX + "resource-tracker.address";
|
||||
public static final int DEFAULT_RM_RESOURCE_TRACKER_PORT = 8031;
|
||||
|
@ -179,6 +179,32 @@
|
||||
<value>true</value>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
<description>To enable RM web ui2 application.</description>
|
||||
<name>yarn.resourcemanager.webapp.ui2.enable</name>
|
||||
<value>false</value>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
<description>
|
||||
The http address of the RM web ui2 application.
|
||||
If only a host is provided as the value,
|
||||
the webapp will be served on a random port.
|
||||
</description>
|
||||
<name>yarn.resourcemanager.webapp.ui2.address</name>
|
||||
<value>${yarn.resourcemanager.hostname}:8288</value>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
<description>
|
||||
The https address of the RM web ui2 application.
|
||||
If only a host is provided as the value,
|
||||
the webapp will be served on a random port.
|
||||
</description>
|
||||
<name>yarn.resourcemanager.webapp.ui2.https.address</name>
|
||||
<value>${yarn.resourcemanager.hostname}:8290</value>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
<name>yarn.resourcemanager.resource-tracker.address</name>
|
||||
<value>${yarn.resourcemanager.hostname}:8031</value>
|
||||
|
@ -18,16 +18,6 @@
|
||||
|
||||
package org.apache.hadoop.yarn.server.resourcemanager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.curator.framework.AuthInfo;
|
||||
@ -38,10 +28,12 @@
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.ha.HAServiceProtocol;
|
||||
import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
|
||||
import org.apache.hadoop.http.HttpServer2;
|
||||
import org.apache.hadoop.http.lib.StaticUserWebFilter;
|
||||
import org.apache.hadoop.metrics2.MetricsSystem;
|
||||
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
|
||||
import org.apache.hadoop.metrics2.source.JvmMetrics;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
import org.apache.hadoop.security.AuthenticationFilterInitializer;
|
||||
import org.apache.hadoop.security.Groups;
|
||||
import org.apache.hadoop.security.HttpCrossOriginFilterInitializer;
|
||||
@ -124,6 +116,16 @@
|
||||
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The ResourceManager is the main class that is a set of components.
|
||||
@ -909,7 +911,49 @@ public void handle(RMNodeEvent event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a HttpServer.Builder that the journalnode / namenode / secondary
|
||||
* namenode can use to initialize their HTTP / HTTPS server.
|
||||
*
|
||||
*/
|
||||
public static HttpServer2.Builder httpServerTemplateForRM(Configuration conf,
|
||||
final InetSocketAddress httpAddr, final InetSocketAddress httpsAddr,
|
||||
String name) throws IOException {
|
||||
HttpServer2.Builder builder = new HttpServer2.Builder().setName(name)
|
||||
.setConf(conf).setSecurityEnabled(false);
|
||||
|
||||
if (httpAddr.getPort() == 0) {
|
||||
builder.setFindPort(true);
|
||||
}
|
||||
|
||||
URI uri = URI.create("http://" + NetUtils.getHostPortString(httpAddr));
|
||||
builder.addEndpoint(uri);
|
||||
LOG.info("Starting Web-server for " + name + " at: " + uri);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected void startWebAppV2() throws IOException {
|
||||
Configuration config = getConfig();
|
||||
final InetSocketAddress httpAddr = config.getSocketAddr(
|
||||
YarnConfiguration.RM_WEBAPP_UI2_ADDRESS,
|
||||
YarnConfiguration.DEFAULT_RM_WEBAPP_UI2_ADDRESS,
|
||||
YarnConfiguration.DEFAULT_RM_WEBAPP_UI2_PORT);
|
||||
final InetSocketAddress httpsAddr = config.getSocketAddr(
|
||||
YarnConfiguration.RM_WEBAPP_UI2_HTTPS_ADDRESS,
|
||||
YarnConfiguration.DEFAULT_RM_WEBAPP_UI2_HTTPS_ADDRESS,
|
||||
YarnConfiguration.DEFAULT_RM_WEBAPP_UI2_HTTPS_PORT);
|
||||
|
||||
HttpServer2.Builder builder = httpServerTemplateForRM(config, httpAddr,
|
||||
httpsAddr, "rm");
|
||||
|
||||
HttpServer2 infoServer = builder.build();
|
||||
infoServer.start();
|
||||
|
||||
LOG.info("Web server init done");
|
||||
}
|
||||
|
||||
protected void startWepApp() {
|
||||
|
||||
// Use the customized yarn filter instead of the standard kerberos filter to
|
||||
@ -1128,6 +1172,16 @@ protected void serviceStart() throws Exception {
|
||||
transitionToActive();
|
||||
}
|
||||
|
||||
if (getConfig().getBoolean(YarnConfiguration.RM_WEBAPP_UI2_ENABLE,
|
||||
YarnConfiguration.DEFAULT_RM_WEBAPP_UI2_ENABLE)) {
|
||||
try {
|
||||
startWebAppV2();
|
||||
LOG.info("Yarn WebApp UI 2 is started");
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to start Yarn web app v2:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
startWepApp();
|
||||
if (getConfig().getBoolean(YarnConfiguration.IS_MINI_YARN_CLUSTER,
|
||||
false)) {
|
||||
|
@ -20,12 +20,12 @@
|
||||
<parent>
|
||||
<artifactId>hadoop-yarn</artifactId>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
<version>3.0.0-alpha1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-ui</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
<version>3.0.0-alpha1-SNAPSHOT</version>
|
||||
<name>Apache Hadoop YARN UI</name>
|
||||
<packaging>${packaging.type}</packaging>
|
||||
|
||||
|
@ -31,10 +31,8 @@ export default AbstractAdapter.extend({
|
||||
|
||||
urlForFindRecord(id, modelName, snapshot) {
|
||||
var url = this._buildURL();
|
||||
var url = url + '/apps/' +
|
||||
return url + '/apps/' +
|
||||
Converter.attemptIdToAppId(id) + "/appattempts/" + id;
|
||||
console.log('app-attempt url:',url);
|
||||
return url;
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -42,7 +42,7 @@ export default DS.RESTAdapter.extend({
|
||||
var nodeHttpAddr = splits[0];
|
||||
var containerId = splits[1];
|
||||
var filename = splits[2];
|
||||
this.host = this.host + nodeHttpAddr;
|
||||
this.host = this.get('host') + nodeHttpAddr;
|
||||
var url = this._buildURL();
|
||||
url = url + "/containerlogs/" + containerId + "/" + filename;
|
||||
return url;
|
||||
|
@ -25,14 +25,20 @@ export default AbstractAdapter.extend({
|
||||
serverName: "NM",
|
||||
|
||||
urlForQuery(query) {
|
||||
this.host = this.get("host") + query.nodeAddr;
|
||||
var extension = this.get("host").split('/').pop();
|
||||
if (extension != query.nodeAddr) {
|
||||
this.host = this.get("host") + query.nodeAddr;
|
||||
}
|
||||
var url = this._buildURL();
|
||||
url = url + "/apps";
|
||||
return url;
|
||||
},
|
||||
|
||||
urlForQueryRecord: function (query) {
|
||||
this.host = this.get("host") + query.nodeAddr;
|
||||
var extension = this.get("host").split('/').pop();
|
||||
if (extension != query.nodeAddr) {
|
||||
this.host = this.get("host") + query.nodeAddr;
|
||||
}
|
||||
var url = this._buildURL();
|
||||
url = url + "/apps/" + query.appId;
|
||||
return url;
|
||||
|
@ -25,14 +25,20 @@ export default AbstractAdapter.extend({
|
||||
serverName: "NM",
|
||||
|
||||
urlForQuery(query) {
|
||||
this.host = this.get("host") + query.nodeHttpAddr;
|
||||
var extension = this.get("host").split('/').pop();
|
||||
if (extension != query.nodeHttpAddr) {
|
||||
this.host = this.get("host") + query.nodeHttpAddr;
|
||||
}
|
||||
var url = this._buildURL();
|
||||
url = url + "/containers";
|
||||
return url;
|
||||
},
|
||||
|
||||
urlForQueryRecord(query) {
|
||||
this.host = this.get("host") + query.nodeHttpAddr;
|
||||
var extension = this.get("host").split('/').pop();
|
||||
if (extension != query.nodeHttpAddr) {
|
||||
this.host = this.get("host") + query.nodeHttpAddr;
|
||||
}
|
||||
var url = this._buildURL();
|
||||
url = url + "/containers/" + query.containerId;
|
||||
return url;
|
||||
|
@ -25,7 +25,10 @@ export default AbstractAdapter.extend({
|
||||
serverName: "NM",
|
||||
|
||||
urlForFindRecord(id, modelName, snapshot) {
|
||||
this.host = this.get("host") + id;
|
||||
var extension = this.get("host").split('/').pop();
|
||||
if (extension != id) {
|
||||
this.host = this.get("host") + id;
|
||||
}
|
||||
var url = this._buildURL();
|
||||
return url;
|
||||
},
|
||||
|
@ -225,18 +225,27 @@ export default Ember.Component.extend({
|
||||
didInsertElement: function() {
|
||||
// init tooltip
|
||||
this.initTooltip();
|
||||
this.modelArr = [];
|
||||
|
||||
// init model
|
||||
if (this.get("rmModel")) {
|
||||
this.get("rmModel").forEach(function(o) {
|
||||
this.modelArr.push(o);
|
||||
if(!this.modelArr.contains(o)) {
|
||||
this.modelArr.push(o);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
if (this.get("tsModel")) {
|
||||
this.get("tsModel").forEach(function(o) {
|
||||
this.modelArr.push(o);
|
||||
}.bind(this));
|
||||
this.get("tsModel").forEach(function(o) {
|
||||
if(!this.modelArr.contains(o)) {
|
||||
this.modelArr.push(o);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
if(this.modelArr.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.modelArr.sort(function(a, b) {
|
||||
|
@ -126,7 +126,7 @@ export default Ember.Component.extend({
|
||||
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
|
||||
.on("click", function(d,i){
|
||||
if (d.queueData.get("name") != this.get("selected")) {
|
||||
document.location.href = "yarn-queue/" + d.queueData.get("name");
|
||||
document.location.href = "#/yarn-queue/" + d.queueData.get("name");
|
||||
}
|
||||
}.bind(this));
|
||||
// .on("click", click);
|
||||
@ -176,7 +176,7 @@ export default Ember.Component.extend({
|
||||
.attr("r", 20)
|
||||
.attr("href",
|
||||
function(d) {
|
||||
return "yarn-queues/" + d.queueData.get("name");
|
||||
return "#/yarn-queues/" + d.queueData.get("name");
|
||||
})
|
||||
.style("stroke", function(d) {
|
||||
if (d.queueData.get("name") == this.get("selected")) {
|
||||
|
@ -36,7 +36,7 @@ export default Ember.Helper.helper(function(params,hash) {
|
||||
var html = '<td>';
|
||||
var logFilesCommaSeparated = "";
|
||||
for (var i = 0; i < logFilesLen; i++) {
|
||||
html = html + '<a href="yarn-container-log/' + nodeId + '/' +
|
||||
html = html + '<a href="#/yarn-container-log/' + nodeId + '/' +
|
||||
nodeAddr + '/' + containerId + '/' + logFiles[i] + '">' + logFiles[i] +
|
||||
'</a>';
|
||||
if (i != logFilesLen - 1) {
|
||||
|
@ -29,7 +29,7 @@ export default Ember.Helper.helper(function(params,hash) {
|
||||
if (nodeState == "SHUTDOWN" || nodeState == "LOST") {
|
||||
html = html + nodeHTTPAddress;
|
||||
} else {
|
||||
html = html + '<a href="yarn-node/' + nodeId + "/" + nodeHTTPAddress + '">' +
|
||||
html = html + '<a href="#/yarn-node/' + nodeId + "/" + nodeHTTPAddress + '">' +
|
||||
nodeHTTPAddress + '</a>';
|
||||
}
|
||||
html = html + '</td>';
|
||||
|
@ -50,17 +50,17 @@ export default Ember.Helper.helper(function(params,hash) {
|
||||
if (hash.path == 'yarn-node') {
|
||||
html = html + ' class="active"';
|
||||
}
|
||||
html = html + '><a href="yarn-node/' + hash.nodeId + '/' + hash.nodeAddr +
|
||||
html = html + '><a href="#/yarn-node/' + hash.nodeId + '/' + hash.nodeAddr +
|
||||
'">Node Information</a></li><li';
|
||||
if (hash.path == 'yarn-node-apps') {
|
||||
html = html + ' class="active"';
|
||||
}
|
||||
html = html + '><a href="yarn-node-apps/' + hash.nodeId + '/' + hash.nodeAddr +
|
||||
html = html + '><a href="#/yarn-node-apps/' + hash.nodeId + '/' + hash.nodeAddr +
|
||||
'">List of Applications</a></li><li';
|
||||
if (hash.path == 'yarn-node-containers') {
|
||||
html = html + ' class="active"';
|
||||
}
|
||||
html = html + '><a href="yarn-node-containers/' +hash.nodeId + '/' + hash.nodeAddr +
|
||||
html = html + '><a href="#/yarn-node-containers/' +hash.nodeId + '/' + hash.nodeAddr +
|
||||
'">List of Containers</a></li></ul></ul></div>';
|
||||
return Ember.String.htmlSafe(html);
|
||||
});
|
||||
|
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Ember from 'ember';
|
||||
|
||||
export function nodeName(params/*, hash*/) {
|
||||
// Place a menu within a panel inside col-md-2 container.
|
||||
console.log('nodes-uid', params[0]);
|
||||
var nodeIdSplitAtPort = params[0];
|
||||
var portIndex = nodeIdSplitAtPort.indexOf(':');
|
||||
if (portIndex != -1) {
|
||||
nodeIdSplitAtPort = nodeIdSplitAtPort.substring(0, portIndex) +
|
||||
':​' + nodeIdSplitAtPort.substring(portIndex + 1);
|
||||
}
|
||||
var normalizedNodeId = '';
|
||||
var splitsAlongDots = nodeIdSplitAtPort.split('.');
|
||||
if (splitsAlongDots) {
|
||||
var len = splitsAlongDots.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
normalizedNodeId = normalizedNodeId + splitsAlongDots[i];
|
||||
if (i != len - 1) {
|
||||
normalizedNodeId = normalizedNodeId + '.​';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
normalizedNodeId = nodeIdSplitAtPort;
|
||||
}
|
||||
return Ember.String.htmlSafe(normalizedNodeId);
|
||||
}
|
||||
|
||||
export default Ember.Helper.helper(nodeName);
|
@ -21,14 +21,29 @@ import Converter from 'yarn-ui/utils/converter';
|
||||
|
||||
export default DS.Model.extend({
|
||||
startTime: DS.attr('string'),
|
||||
startedTime: DS.attr('string'),
|
||||
finishedTime: DS.attr('string'),
|
||||
containerId: DS.attr('string'),
|
||||
amContainerId: DS.attr('string'),
|
||||
nodeHttpAddress: DS.attr('string'),
|
||||
nodeId: DS.attr('string'),
|
||||
hosts: DS.attr('string'),
|
||||
logsLink: DS.attr('string'),
|
||||
state: DS.attr('string'),
|
||||
|
||||
attemptStartedTime: function() {
|
||||
var startTime = this.get("startTime");
|
||||
// If startTime variable is not present, get from startedTime
|
||||
if (startTime == undefined ||
|
||||
startTime == "Invalid date") {
|
||||
startTime = this.get("startedTime");
|
||||
}
|
||||
|
||||
return startTime;
|
||||
}.property("startedTime"),
|
||||
|
||||
startTs: function() {
|
||||
return Converter.dateToTimeStamp(this.get("startTime"));
|
||||
return Converter.dateToTimeStamp(this.get('attemptStartedTime'));
|
||||
}.property("startTime"),
|
||||
|
||||
finishedTs: function() {
|
||||
@ -36,11 +51,57 @@ export default DS.Model.extend({
|
||||
return ts;
|
||||
}.property("finishedTime"),
|
||||
|
||||
validatedFinishedTs: function() {
|
||||
if (this.get("finishedTs") < this.get("startTs")) {
|
||||
return "";
|
||||
}
|
||||
return this.get("finishedTime");
|
||||
}.property("finishedTime"),
|
||||
|
||||
shortAppAttemptId: function() {
|
||||
if (!this.get("containerId")) {
|
||||
return this.get("id");
|
||||
}
|
||||
return "attempt_" +
|
||||
parseInt(Converter.containerIdToAttemptId(this.get("containerId")).split("_")[3]);
|
||||
}.property("containerId"),
|
||||
|
||||
appMasterContainerId: function() {
|
||||
var id = this.get("containerId");
|
||||
// If containerId variable is not present, get from amContainerId
|
||||
if (id == undefined) {
|
||||
id = this.get("amContainerId");
|
||||
}
|
||||
return id;
|
||||
}.property("amContainerId"),
|
||||
|
||||
IsAmNodeUrl: function() {
|
||||
var url = this.get("nodeHttpAddress");
|
||||
// If nodeHttpAddress variable is not present, hardcode it.
|
||||
if (url == undefined) {
|
||||
url = "Not Available";
|
||||
}
|
||||
return url != "Not Available";
|
||||
}.property("nodeHttpAddress"),
|
||||
|
||||
amNodeId : function() {
|
||||
var id = this.get("nodeId");
|
||||
// If nodeId variable is not present, get from host
|
||||
if (id == undefined) {
|
||||
id = this.get("hosts");
|
||||
}
|
||||
return id;
|
||||
}.property("nodeId"),
|
||||
|
||||
IsLinkAvailable: function() {
|
||||
var url = this.get("logsLink");
|
||||
// If logsLink variable is not present, hardcode its.
|
||||
if (url == undefined) {
|
||||
url = "Not Available";
|
||||
}
|
||||
return url != "Not Available";
|
||||
}.property("logsLink"),
|
||||
|
||||
elapsedTime: function() {
|
||||
var elapsedMs = this.get("finishedTs") - this.get("startTs");
|
||||
if (elapsedMs <= 0) {
|
||||
@ -59,4 +120,13 @@ export default DS.Model.extend({
|
||||
link: function() {
|
||||
return "/yarn-app-attempt/" + this.get("id");
|
||||
}.property(),
|
||||
|
||||
linkname: function() {
|
||||
return "yarn-app-attempt";
|
||||
}.property(),
|
||||
|
||||
attemptState: function() {
|
||||
return this.get("state");
|
||||
}.property(),
|
||||
|
||||
});
|
@ -51,6 +51,13 @@ export default DS.Model.extend({
|
||||
return this.get('finalStatus') == "FAILED"
|
||||
}.property("finalStatus"),
|
||||
|
||||
validatedFinishedTs: function() {
|
||||
if (this.get("finishedTime") < this.get("startTime")) {
|
||||
return "";
|
||||
}
|
||||
return this.get("finishedTime");
|
||||
}.property("finishedTime"),
|
||||
|
||||
allocatedResource: function() {
|
||||
return Converter.resourceToString(this.get("allocatedMB"), this.get("allocatedVCores"));
|
||||
}.property("allocatedMB", "allocatedVCores"),
|
||||
@ -67,6 +74,13 @@ export default DS.Model.extend({
|
||||
return "width: " + this.get("progress") + "%";
|
||||
}.property("progress"),
|
||||
|
||||
runningContainersNumber: function() {
|
||||
if(this.get("runningContainers") < 0) {
|
||||
return 0;
|
||||
}
|
||||
return this.get("runningContainers");
|
||||
}.property("progress"),
|
||||
|
||||
finalStatusStyle: function() {
|
||||
var style = "default";
|
||||
var finalStatus = this.get("finalStatus");
|
||||
|
@ -40,6 +40,13 @@ export default DS.Model.extend({
|
||||
return ts;
|
||||
}.property("finishedTime"),
|
||||
|
||||
validatedFinishedTs: function() {
|
||||
if (this.get("finishedTs") < this.get("startTs")) {
|
||||
return "";
|
||||
}
|
||||
return this.get("finishedTime");
|
||||
}.property("finishedTime"),
|
||||
|
||||
elapsedTime: function() {
|
||||
var elapsedMs = this.get("finishedTs") - this.get("startTs");
|
||||
if (elapsedMs <= 0) {
|
||||
|
@ -33,7 +33,11 @@ export default Ember.Route.extend({
|
||||
{
|
||||
app_attempt_id: param.app_attempt_id,
|
||||
is_rm: false
|
||||
}),
|
||||
}).catch (function() {
|
||||
// Promise rejected, fulfill with some default value to
|
||||
// use as the route's model and continue on with the transition
|
||||
return [];
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
@ -32,11 +32,14 @@ export default DS.JSONAPISerializer.extend({
|
||||
type: primaryModelClass.modelName, // yarn-app
|
||||
attributes: {
|
||||
startTime: Converter.timeStampToDate(payload.startTime),
|
||||
startedTime: Converter.timeStampToDate(payload.startedTime),
|
||||
finishedTime: Converter.timeStampToDate(payload.finishedTime),
|
||||
containerId: payload.containerId,
|
||||
amContainerId: payload.amContainerId,
|
||||
nodeHttpAddress: payload.nodeHttpAddress,
|
||||
nodeId: payload.nodeId,
|
||||
state: payload.nodeId,
|
||||
hosts: payload.host,
|
||||
state: payload.appAttemptState,
|
||||
logsLink: payload.logsLink
|
||||
}
|
||||
};
|
||||
|
@ -75,10 +75,15 @@ export default DS.JSONAPISerializer.extend({
|
||||
|
||||
// payload has apps : { app: [ {},{},{} ] }
|
||||
// need some error handling for ex apps or app may not be defined.
|
||||
normalizedArrayResponse.data = payload.apps.app.map(singleApp => {
|
||||
return this.internalNormalizeSingleResponse(store, primaryModelClass,
|
||||
if(payload.apps) {
|
||||
normalizedArrayResponse.data = payload.apps.app.map(singleApp => {
|
||||
return this.internalNormalizeSingleResponse(store, primaryModelClass,
|
||||
singleApp, singleApp.id, requestType);
|
||||
}, this);
|
||||
}, this);
|
||||
} else {
|
||||
normalizedArrayResponse.data = [];
|
||||
}
|
||||
|
||||
return normalizedArrayResponse;
|
||||
}
|
||||
});
|
@ -64,9 +64,10 @@ export default DS.JSONAPISerializer.extend({
|
||||
singleContainer, singleContainer.id, requestType);
|
||||
}, this);
|
||||
return normalizedArrayResponse;
|
||||
} else {
|
||||
normalizedArrayResponse.data = [];
|
||||
}
|
||||
|
||||
normalizedArrayResponse.data = [];
|
||||
return normalizedArrayResponse;
|
||||
}
|
||||
});
|
@ -76,10 +76,7 @@ export default DS.JSONAPISerializer.extend({
|
||||
} else {
|
||||
// No container reported inside containers.
|
||||
// Response of the form { "apps": null }
|
||||
normalizedArrayResponse.data = Ember.makeArray({
|
||||
id: "dummy",
|
||||
type: primaryModelClass.modelName,
|
||||
attributes: {}});
|
||||
normalizedArrayResponse.data = [];
|
||||
}
|
||||
return normalizedArrayResponse;
|
||||
}
|
||||
|
@ -64,10 +64,7 @@ export default DS.JSONAPISerializer.extend({
|
||||
} else {
|
||||
// No container reported inside containers.
|
||||
// Response of the form { "containers": null }
|
||||
normalizedArrayResponse.data = Ember.makeArray({
|
||||
id: "dummy",
|
||||
type: primaryModelClass.modelName,
|
||||
attributes: {}});
|
||||
normalizedArrayResponse.data = [];
|
||||
}
|
||||
return normalizedArrayResponse;
|
||||
}
|
||||
|
@ -67,10 +67,7 @@ export default DS.JSONAPISerializer.extend({
|
||||
singleNode, singleNode.id);
|
||||
}, this);
|
||||
} else {
|
||||
normalizedArrayResponse.data = Ember.makeArray({
|
||||
id: "dummy",
|
||||
type: primaryModelClass.modelName,
|
||||
attributes: {}});
|
||||
normalizedArrayResponse.data = [];
|
||||
}
|
||||
return normalizedArrayResponse;
|
||||
}
|
||||
|
@ -32,7 +32,26 @@
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
{{outputMainMenu}}
|
||||
{{#link-to 'yarn-queue' 'root' tagName="li"}}
|
||||
{{#link-to 'yarn-queue' 'root'}}Queues
|
||||
<span class="sr-only">(current)</span>
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-apps' tagName="li"}}
|
||||
{{#link-to 'yarn-apps'}}Applications
|
||||
<span class="sr-only">(current)</span>
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'cluster-overview' tagName="li"}}
|
||||
{{#link-to 'cluster-overview'}}Cluster Overview
|
||||
<span class="sr-only">(current)</span>
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-nodes' tagName="li"}}
|
||||
{{#link-to 'yarn-nodes'}}Nodes
|
||||
<span class="sr-only">(current)</span>
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
|
@ -24,23 +24,39 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Start Time</td>
|
||||
<td>{{attempt.startTime}}</td>
|
||||
<td>{{attempt.attemptStartedTime}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AM Container Id</td>
|
||||
<td>{{attempt.containerId}}</td>
|
||||
<td>{{attempt.appMasterContainerId}}</td>
|
||||
</tr>
|
||||
{{#if attempt.IsAmNodeUrl}}
|
||||
<tr>
|
||||
<td>AM Node Web UI</td>
|
||||
<td><a href={{attempt.nodeHttpAddress}}>{{attempt.nodeHttpAddress}}</a></td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
<tr>
|
||||
<td>AM Node Id</td>
|
||||
<td>{{attempt.nodeId}}</td>
|
||||
<td>{{attempt.amNodeId}}</td>
|
||||
</tr>
|
||||
{{#if attempt.IsLinkAvailable}}
|
||||
<tr>
|
||||
<td>Log</td>
|
||||
<td><a href={{attempt.logsLink}}>link</a></td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#if attempt.attemptState}}
|
||||
<tr>
|
||||
<td>Attempt State</td>
|
||||
<td>{{attempt.attemptState}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#if attempt.elapsedTime}}
|
||||
<tr>
|
||||
<td>Elapsed Time</td>
|
||||
<td>{{attempt.elapsedTime}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
@ -36,7 +36,7 @@
|
||||
{{#if arr}}
|
||||
{{#each arr as |app|}}
|
||||
<tr>
|
||||
<td><a href="yarn-app/{{app.id}}">{{app.id}}</a></td>
|
||||
<td><a href="#/yarn-app/{{app.id}}">{{app.id}}</a></td>
|
||||
<td>{{app.appName}}</td>
|
||||
<td>{{app.user}}</td>
|
||||
<td>{{app.queue}}</td>
|
||||
@ -44,7 +44,7 @@
|
||||
<td><span class={{app.finalStatusStyle}}>{{app.finalStatus}}</span></td>
|
||||
<td>{{app.startTime}}</td>
|
||||
<td>{{app.elapsedTime}}</td>
|
||||
<td>{{app.finishedTime}}</td>
|
||||
<td>{{app.validatedFinishedTs}}</td>
|
||||
<td>{{app.priority}}</td>
|
||||
<td>
|
||||
<div class="progress" style="margin-bottom: 0;">
|
||||
@ -57,7 +57,7 @@
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<tr>
|
||||
<td><a href="yarn-app/{{app.id}}">{{app.id}}</a></td>
|
||||
<td><a href="#/yarn-app/{{app.id}}">{{app.id}}</a></td>
|
||||
<td>{{app.appName}}</td>
|
||||
<td>{{app.user}}</td>
|
||||
<td>{{app.queue}}</td>
|
||||
@ -65,7 +65,7 @@
|
||||
<td><span class={{app.finalStatusStyle}}>{{app.finalStatus}}</span></td>
|
||||
<td>{{app.startTime}}</td>
|
||||
<td>{{app.elapsedTime}}</td>
|
||||
<td>{{app.finishedTime}}</td>
|
||||
<td>{{app.validatedFinishedTs}}</td>
|
||||
<td>{{app.priority}}</td>
|
||||
<td>
|
||||
<div class="progress" style="margin-bottom: 0;">
|
||||
|
@ -24,7 +24,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Finished Time</td>
|
||||
<td>{{container.finishedTime}}</td>
|
||||
<td>{{container.validatedFinishedTs}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Elapsed Time</td>
|
||||
@ -48,7 +48,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>NodeManager UI</td>
|
||||
<td>{{container.nodeHttpAddress}}</td>
|
||||
<td><a href={{container.nodeHttpAddress}}>{{container.nodeHttpAddress}}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
@ -0,0 +1,44 @@
|
||||
{{!
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
}}
|
||||
|
||||
<div class="col-md-2 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4>Node Manager<br>({{node-name nodeId}})</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<ul class="nav nav-pills nav-stacked" id="stacked-menu">
|
||||
<ul class="nav nav-pills nav-stacked collapse in">
|
||||
{{#link-to 'yarn-node' tagName="li"}}
|
||||
{{#link-to 'yarn-node' nodeId nodeAddr}}Node Information
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-node-apps' tagName="li"}}
|
||||
{{#link-to 'yarn-node-apps' nodeId nodeAddr}}List of Applications
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-node-containers' tagName="li"}}
|
||||
{{#link-to 'yarn-node-containers' nodeId nodeAddr}}List of Containers
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{outlet}}
|
@ -34,7 +34,7 @@
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{{#if selected.link}}
|
||||
<a href={{selected.link}}>{{selected.id}}</a>
|
||||
{{#link-to selected.linkname selected.id}}{{selected.id}}{{/link-to}}
|
||||
{{else}}
|
||||
{{selected.id}}
|
||||
{{/if}}
|
||||
|
@ -16,4 +16,4 @@
|
||||
limitations under the License.
|
||||
--}}
|
||||
|
||||
<h3 align = "center">Sorry, Error Occured.</h3>
|
||||
<h3 align = "center">Sorry, Error Occurred.</h3>
|
||||
|
@ -18,12 +18,16 @@
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
{{#if model.attempt}}
|
||||
{{app-attempt-table attempt=model.attempt}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<!-- containers table -->
|
||||
<div class="row">
|
||||
{{#if (or model.rmContainers model.tsContainers)}}
|
||||
{{timeline-view parent-id="containers-timeline-div" my-id="timeline-view" height="400" rmModel=model.rmContainers tsModel=model.tsContainers label="shortAppAttemptId" attemptModel=false}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -61,7 +61,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Running Containers</td>
|
||||
<td>{{model.app.runningContainers}}</td>
|
||||
<td>{{model.app.runningContainersNumber}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Preempted Resource</td>
|
||||
|
@ -15,7 +15,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
}}
|
||||
|
||||
{{app-table table-id="apps-table" arr=model}}
|
||||
{{simple-table table-id="apps-table" bFilter=true colsOrder="0,desc" colTypes="natural elapsed-time" colTargets="0 7"}}
|
||||
{{#if model}}
|
||||
{{app-table table-id="apps-table" arr=model}}
|
||||
{{simple-table table-id="apps-table" bFilter=true colsOrder="0,desc" colTypes="natural elapsed-time" colTargets="0 7"}}
|
||||
{{else}}
|
||||
<h4 align = "center">Could not find any applications from this cluster</h4>
|
||||
{{/if}}
|
||||
{{outlet}}
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="row">
|
||||
{{node-menu path="yarn-node-app" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}
|
||||
{{node-menu-panel path="yarn-node-app" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}
|
||||
<div class="col-md-10 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><b>Application Information</b></div>
|
||||
@ -48,7 +48,7 @@
|
||||
<tbody>
|
||||
{{#each model.nodeApp.containers as |container|}}
|
||||
<tr>
|
||||
<td><a href="yarn-node-container/{{model.nodeInfo.id}}/{{model.nodeInfo.addr}}/{{container}}">{{container}}</a></td>
|
||||
<td><a href="#/yarn-node-container/{{model.nodeInfo.id}}/{{model.nodeInfo.addr}}/{{container}}">{{container}}</a></td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
|
@ -18,7 +18,8 @@
|
||||
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="row">
|
||||
{{node-menu path="yarn-node-apps" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}
|
||||
{{node-menu-panel path="yarn-node-apps" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}
|
||||
{{#if model.apps}}
|
||||
<div class="col-md-10 container-fluid">
|
||||
<table id="node-apps-table" class="display table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
@ -31,21 +32,20 @@
|
||||
<tbody>
|
||||
{{#if model.apps}}
|
||||
{{#each model.apps as |app|}}
|
||||
{{#if app.isDummyApp}}
|
||||
<tr><td colspan="3" align="center">No apps found on this node</td></tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td><a href="yarn-node-app/{{model.nodeInfo.id}}/{{model.nodeInfo.addr}}/{{app.appId}}">{{app.appId}}</a></td>
|
||||
<td><a href="#/yarn-node-app/{{model.nodeInfo.id}}/{{model.nodeInfo.addr}}/{{app.appId}}">{{app.appId}}</a></td>
|
||||
<td><span class={{app.appStateStyle}}>{{app.state}}</span></td>
|
||||
<td>{{app.user}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{simple-table table-id="node-apps-table" bFilter=true colsOrder="0,desc" colTypes="natural" colTargets="0"}}
|
||||
</div>
|
||||
{{else}}
|
||||
<h4 align = "center">No apps found on this node</h4>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{outlet}}
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="row">
|
||||
{{node-menu path="yarn-node-container" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}
|
||||
{{node-menu-panel path="yarn-node-container" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}
|
||||
<div class="col-md-10 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><b>Container Information</b></div>
|
||||
|
@ -18,7 +18,8 @@
|
||||
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="row">
|
||||
{{node-menu path="yarn-node-containers" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}
|
||||
{{node-menu-panel path="yarn-node-containers" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}
|
||||
{{#if model.containers}}
|
||||
<div class="col-md-10 container-fluid">
|
||||
<table id="node-containers-table" class="display table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
@ -32,11 +33,8 @@
|
||||
<tbody>
|
||||
{{#if model.containers}}
|
||||
{{#each model.containers as |container|}}
|
||||
{{#if container.isDummyContainer}}
|
||||
<tr><td colspan="4" align="center">No containers found on this node</td></tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td><a href="yarn-node-container/{{model.nodeInfo.id}}/{{model.nodeInfo.addr}}/{{container.containerId}}">{{container.containerId}}</a></td>
|
||||
<td><a href="#/yarn-node-container/{{model.nodeInfo.id}}/{{model.nodeInfo.addr}}/{{container.containerId}}">{{container.containerId}}</a></td>
|
||||
<td><span class={{container.containerStateStyle}}>{{container.state}}</span></td>
|
||||
<td>{{container.user}}</td>
|
||||
<td>
|
||||
@ -46,13 +44,15 @@
|
||||
logFiles=container.containerLogFiles}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{simple-table table-id="node-containers-table" bFilter=true colsOrder="0,desc" colTypes="natural" colTargets="0"}}
|
||||
</div>
|
||||
{{else}}
|
||||
<h4 align = "center">No containers found on this node</h4>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{outlet}}
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="row">
|
||||
{{node-menu path="yarn-node" nodeId=model.rmNode.id nodeAddr=model.node.id}}
|
||||
{{node-menu-panel path="yarn-node" nodeId=model.rmNode.id nodeAddr=model.node.id}}
|
||||
<div class="col-md-10 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Node Information</div>
|
||||
|
@ -16,6 +16,7 @@
|
||||
limitations under the License.
|
||||
--}}
|
||||
|
||||
{{#if model}}
|
||||
<table id="nodes-table" class="display table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -35,11 +36,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#if model}}
|
||||
{{#each model as |node|}}
|
||||
{{#if node.isDummyNode}}
|
||||
<tr><td colspan="13" align="center">No nodes found on this cluster</td></tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<td>{{node.nodeLabelsAsString}}</td>
|
||||
<td>{{node.rack}}</td>
|
||||
@ -55,11 +52,12 @@
|
||||
<td>{{node.availableVirtualCores}}</td>
|
||||
<td>{{node.version}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{simple-table table-id="nodes-table" bFilter=true}}
|
||||
{{else}}
|
||||
<h4 align = "center">No nodes found on this cluster</h4>
|
||||
{{/if}}
|
||||
{{outlet}}
|
||||
|
@ -58,8 +58,12 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 container-fluid">
|
||||
{{app-table table-id="apps-table" arr=model.apps}}
|
||||
{{simple-table table-id="apps-table" bFilter=true colTypes="elapsed-time" colTargets="7"}}
|
||||
{{#if model.apps}}
|
||||
{{app-table table-id="apps-table" arr=model.apps}}
|
||||
{{simple-table table-id="apps-table" bFilter=true colTypes="elapsed-time" colTargets="7"}}
|
||||
{{else}}
|
||||
<h4 align = "center">Could not find any applications from this cluster</h4>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -25,7 +25,7 @@ module.exports = function(environment) {
|
||||
modulePrefix: 'yarn-ui',
|
||||
environment: environment,
|
||||
baseURL: '/',
|
||||
locationType: 'auto',
|
||||
locationType: 'hash',
|
||||
EmberENV: {
|
||||
FEATURES: {
|
||||
// Here you can enable experimental features on an ember canary build
|
||||
|
@ -22,6 +22,7 @@
|
||||
"broccoli-asset-rev": "2.4.2",
|
||||
"broccoli-funnel": "1.0.1",
|
||||
"ember-bootstrap": "0.5.1",
|
||||
"ember-array-contains-helper": "1.0.2",
|
||||
"ember-cli": "1.13.13",
|
||||
"ember-cli-app-version": "1.0.0",
|
||||
"ember-cli-babel": "5.1.6",
|
||||
@ -42,6 +43,7 @@
|
||||
"ember-export-application-global": "1.0.5",
|
||||
"ember-resolver": "2.0.3",
|
||||
"ember-spin-spinner": "0.2.3",
|
||||
"ember-truth-helpers": "1.2.0",
|
||||
"select2": "4.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { nodeName } from '../../../helpers/node-name';
|
||||
import { module, test } from 'qunit';
|
||||
|
||||
module('Unit | Helper | node name');
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it works', function(assert) {
|
||||
let result = nodeName(42);
|
||||
assert.ok(result);
|
||||
});
|
Loading…
Reference in New Issue
Block a user