diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js index c9e735dee5d..3d72b2fbbf7 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js @@ -128,7 +128,7 @@ export default Ember.Component.extend({ .attr("transform", function() { return "translate(" + source.y0 + "," + source.x0 + ")"; }) .on("mouseover", function(d){ if (d.queueData.get("name") !== this.get("selected")) { - document.location.href = "#/yarn-queues/" + d.queueData.get("name"); + document.location.href = "#/yarn-queues/" + d.queueData.get("name") + "!"; } Ember.run.later(this, function () { @@ -143,7 +143,7 @@ export default Ember.Component.extend({ }.bind(this)) .on("click", function (d) { - document.location.href = "#/yarn-queue/" + d.queueData.get("name"); + document.location.href = "#/yarn-queue/" + d.queueData.get("name") + "/info"; }); nodeEnter.append("circle") @@ -190,7 +190,7 @@ export default Ember.Component.extend({ nodeUpdate.select("circle") .attr("r", 30) - .attr("href", + .attr("href", function(d) { return "#/yarn-queues/" + d.queueData.get("name"); }) @@ -294,4 +294,4 @@ export default Ember.Component.extend({ didInsertElement: function() { this.reDraw(); } -}); \ No newline at end of file +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue.js index 0b4150fce46..3a72b606fef 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue.js @@ -22,10 +22,11 @@ export default Ember.Controller.extend({ needReload: true, selectedQueue: undefined, - breadcrumbs: Ember.computed("model.selected", function () { + breadcrumbs: Ember.computed("model.selected", "target.currentPath", function () { var queueName = this.get("model.selected"); + var path = this.get("target.currentPath"); - return [{ + var crumbs = [{ text: "Home", routeName: 'application' }, { @@ -34,11 +35,19 @@ export default Ember.Controller.extend({ model: 'root' }, { text: `Queue [ ${queueName} ]`, - routeName: 'yarn-queue', + routeName: 'yarn-queue.info', model: queueName }]; - }), + if (path && path === "yarn-queue.apps") { + crumbs.push({ + text: "Applications", + routeName: 'yarn-queue.apps', + model: queueName + }); + } + return crumbs; + }) }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js index 941e150121b..9658ded0ca2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js @@ -21,6 +21,7 @@ import Ember from 'ember'; export default Ember.Controller.extend({ needReload: true, selectedQueue: undefined, + showLoading: true, breadcrumbs: [{ text: "Home", diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js index 87a018d38e5..03ec7808424 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/router.js @@ -32,6 +32,10 @@ Router.map(function() { this.route('table'); this.route('heatmap'); }); + this.route('yarn-queue', {path: '/yarn-queue/:queue_name'}, function() { + this.route('info'); + this.route('apps'); + }); this.route('yarn-nodes-heatmap'); this.route('yarn-node', { path: '/yarn-node/:node_id/:node_addr' }); this.route('yarn-node-apps', { path: '/yarn-node-apps/:node_id/:node_addr' }); @@ -43,7 +47,6 @@ Router.map(function() { { path: '/yarn-node-container/:node_id/:node_addr/:container_id' }); this.route('yarn-container-log', { path: '/yarn-container-log/:node_id/:node_addr/:container_id/:filename' }); - this.route('yarn-queue', { path: '/yarn-queue/:queue_name' }); this.route('cluster-overview'); this.route('yarn-app', { path: '/yarn-app/:app_id' }); @@ -52,7 +55,6 @@ Router.map(function() { this.route('notfound', { path: '*:' }); this.route('yarn-app-attempts', { path: '/yarn-app-attempts/:app_id' }); this.route('yarn-queues', { path: '/yarn-queues/:queue_name' }); - this.route('yarn-queue-apps', { path: '/yarn-queue-apps/:queue_name' }); }); export default Router; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js index 10681265b84..b5db17db051 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/cluster-overview.js @@ -23,7 +23,7 @@ import AbstractRoute from './abstract'; export default AbstractRoute.extend({ model() { return Ember.RSVP.hash({ - clusterMetrics: this.store.findAll('ClusterMetric'), + clusterMetrics: this.store.findAll('ClusterMetric', {reload: true}), apps: this.store.query('yarn-app', { state: "RUNNING" @@ -41,4 +41,4 @@ export default AbstractRoute.extend({ this.store.unloadAll('yarn-app'); this.store.unloadAll('yarn-queue'); } -}); \ No newline at end of file +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js index 762fb2908bb..d449adf2ade 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-app-attempt.js @@ -23,15 +23,15 @@ import AbstractRoute from './abstract'; export default AbstractRoute.extend({ model(param) { return Ember.RSVP.hash({ - attempt: this.store.findRecord('yarn-app-attempt', param.app_attempt_id), - - rmContainers: this.store.query('yarn-container', + attempt: this.store.findRecord('yarn-app-attempt', param.app_attempt_id, {reload: true}), + + rmContainers: this.store.query('yarn-container', { app_attempt_id: param.app_attempt_id, is_rm: true }), - - tsContainers: this.store.query('yarn-container', + + tsContainers: this.store.query('yarn-container', { app_attempt_id: param.app_attempt_id, is_rm: false @@ -47,4 +47,4 @@ export default AbstractRoute.extend({ this.store.unloadAll('yarn-app-attempt'); this.store.unloadAll('yarn-container'); } -}); \ No newline at end of file +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js index 0ac503cd6d2..1b671dae742 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-apps.js @@ -23,8 +23,8 @@ import AbstractRoute from './abstract'; export default AbstractRoute.extend({ model() { return Ember.RSVP.hash({ - apps: this.store.findAll('yarn-app'), - clusterMetrics: this.store.findAll('ClusterMetric'), + apps: this.store.findAll('yarn-app', {reload: true}), + clusterMetrics: this.store.findAll('ClusterMetric', {reload: true}), }); }, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-node.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-node.js index 967d007ef95..3d548460d4f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-node.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-node.js @@ -25,8 +25,8 @@ export default AbstractRoute.extend({ // Fetches data from both NM and RM. RM is queried to get node usage info. return Ember.RSVP.hash({ nodeInfo: { id: param.node_id, addr: param.node_addr }, - node: this.store.findRecord('yarn-node', param.node_addr), - rmNode: this.store.findRecord('yarn-rm-node', param.node_id) + node: this.store.findRecord('yarn-node', param.node_addr, {reload: true}), + rmNode: this.store.findRecord('yarn-rm-node', param.node_id, {reload: true}) }); }, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes.js index 4439569c3df..d31eb5c6bfc 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-nodes.js @@ -23,8 +23,8 @@ import AbstractRoute from './abstract'; export default AbstractRoute.extend({ model() { return Ember.RSVP.hash({ - nodes: this.store.findAll('yarn-rm-node'), - clusterMetrics: this.store.findAll('ClusterMetric'), + nodes: this.store.findAll('yarn-rm-node', {reload: true}), + clusterMetrics: this.store.findAll('ClusterMetric', {reload: true}), }); }, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue.js index 534291333a0..faae8b12fa5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue.js @@ -26,13 +26,12 @@ export default AbstractRoute.extend({ selected : param.queue_name, queues: this.store.query('yarn-queue', {}), selectedQueue : undefined, - apps: undefined, // apps of selected queue + apps: this.store.findAll('yarn-app', {reload: true}) }); }, afterModel(model) { model.selectedQueue = this.store.peekRecord('yarn-queue', model.selected); - model.apps = this.store.findAll('yarn-app'); }, unloadAll() { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue/apps.js similarity index 62% rename from hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue-apps.js rename to hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue/apps.js index e7bedd64390..871917068fd 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queue-apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue/apps.js @@ -18,29 +18,5 @@ import Ember from 'ember'; -export default Ember.Controller.extend({ - needReload: true, - selectedQueue: undefined, - - breadcrumbs: Ember.computed("model.selected", function () { - var queueName = this.get("model.selected"); - - return [{ - text: "Home", - routeName: 'application' - }, { - text: "Queues", - routeName: 'yarn-queues', - model: 'root' - }, { - text: `Queue [ ${queueName} ]`, - routeName: 'yarn-queue', - model: queueName - }, { - text: "Applications", - }]; - - }), - - +export default Ember.Route.extend({ }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue-apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue/info.js similarity index 60% rename from hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue-apps.js rename to hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue/info.js index 373e1bebc0d..871917068fd 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue-apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queue/info.js @@ -18,25 +18,5 @@ import Ember from 'ember'; -import AbstractRoute from './abstract'; - -export default AbstractRoute.extend({ - model(param) { - return Ember.RSVP.hash({ - selected : param.queue_name, - queues: this.store.findAll('yarn-queue'), - selectedQueue : undefined, - apps: undefined, // apps of selected queue - }); - }, - - afterModel(model) { - model.selectedQueue = this.store.peekRecord('yarn-queue', model.selected); - model.apps = this.store.findAll('yarn-app'); - }, - - unloadAll() { - this.store.unloadAll('yarn-queue'); - this.store.unloadAll('yarn-app'); - } +export default Ember.Route.extend({ }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queues.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queues.js index 534291333a0..7ef7ac358f9 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queues.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-queues.js @@ -22,21 +22,50 @@ import AbstractRoute from './abstract'; export default AbstractRoute.extend({ model(param) { + var queueName = param.queue_name? param.queue_name.split('!')[0] : 'root'; + if (param.queue_name && param.queue_name.split('!').length > 1) { + this.controllerFor('yarn-queues').set('showLoading', false); + } else { + this.controllerFor('yarn-queues').set('showLoading', true); + } return Ember.RSVP.hash({ - selected : param.queue_name, + selected : queueName, queues: this.store.query('yarn-queue', {}), selectedQueue : undefined, - apps: undefined, // apps of selected queue + apps: this.store.findAll('yarn-app', {reload: true}) }); }, afterModel(model) { model.selectedQueue = this.store.peekRecord('yarn-queue', model.selected); - model.apps = this.store.findAll('yarn-app'); }, unloadAll() { this.store.unloadAll('yarn-queue'); this.store.unloadAll('yarn-app'); + }, + + refreshModel() { + var param = this.paramsFor('yarn-queues'); + var queueName = param.queue_name? param.queue_name.split('!')[0] : 'root'; + if (queueName !== param.queue_name) { + this.transitionTo('yarn-queues', queueName); + } else { + this.refresh(); + } + }, + + actions: { + refresh: function () { + this.unloadAll(); + this.refreshModel(); + }, + + loading() { + if (!this.controllerFor('yarn-queues').get('showLoading')) { + return false; + } + return true; + } } }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/styles/app.css b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/styles/app.css index eb5fe613744..7ac21bcfe68 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/styles/app.css +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/styles/app.css @@ -137,6 +137,14 @@ div.tooltip { pointer-events: none; } +/* + * Loading icon styles + */ +.loading-mask > img { + display: block; + margin: 0 auto; +} + /* * Data table */ diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/loading.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/loading.hbs new file mode 100644 index 00000000000..a95af2bdb39 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/loading.hbs @@ -0,0 +1,23 @@ +{{! + * 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. +}} + +