From c0cf11e1078b2d8a74a6dbec55a5763a619afefd Mon Sep 17 00:00:00 2001 From: Sunil G Date: Thu, 20 Apr 2017 12:33:53 +0530 Subject: [PATCH] YARN-6402. Move 'Long Running Services' to an independent tab at top level for new Yarn UI. Contributed by Akhil PB. --- .../src/main/webapp/app/adapters/yarn-app.js | 2 +- .../app/components/em-table-html-cell.js | 23 ++ .../webapp/app/components/timeline-view.js | 13 +- .../app/controllers/app-table-columns.js | 213 ++++++++++++------ .../app/controllers/yarn-app-attempt.js | 32 ++- .../app/controllers/yarn-app-attempts.js | 23 +- .../main/webapp/app/controllers/yarn-app.js | 21 +- .../webapp/app/controllers/yarn-apps/apps.js | 3 - .../app/controllers/yarn-apps/services.js | 3 - .../webapp/app/controllers/yarn-services.js | 79 ++++++- .../src/main/webapp/app/models/yarn-app.js | 6 +- .../src/main/webapp/app/router.js | 1 + .../main/webapp/app/routes/yarn-services.js | 34 +++ .../src/main/webapp/app/styles/app.css | 9 + .../main/webapp/app/templates/application.hbs | 13 +- .../components/app-attempt-table.hbs | 8 +- .../templates/components/container-table.hbs | 2 +- .../components/em-table-html-cell.hbs | 23 ++ .../templates/components/timeline-view.hbs | 8 +- .../app/templates/yarn-app-attempts.hbs | 8 +- .../main/webapp/app/templates/yarn-app.hbs | 12 +- .../main/webapp/app/templates/yarn-apps.hbs | 4 - .../webapp/app/templates/yarn-services.hbs | 86 +++++++ .../src/main/webapp/app/utils/converter.js | 24 ++ .../components/em-table-html-cell-test.js | 43 ++++ .../tests/unit/routes/yarn-services-test.js | 29 +++ 26 files changed, 594 insertions(+), 128 deletions(-) create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/em-table-html-cell.js create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-services.js create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/em-table-html-cell.hbs create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-services.hbs create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/integration/components/em-table-html-cell-test.js create mode 100644 hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/routes/yarn-services-test.js diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js index fc52f7cb81..111e468f9c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app.js @@ -23,7 +23,7 @@ export default AbstractAdapter.extend({ restNameSpace: "cluster", serverName: "RM", - urlForQuery(query/*, modelName*/) { + urlForQuery(/*query, modelName*/) { var url = this._buildURL(); url = url + '/apps'; return url; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/em-table-html-cell.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/em-table-html-cell.js new file mode 100644 index 0000000000..56fc68a2b0 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/em-table-html-cell.js @@ -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. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ + content: null +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js index 4a33d5b6d9..865fe521d9 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/timeline-view.js @@ -34,6 +34,7 @@ export default Ember.Component.extend({ _selected: undefined, gridColumns: [], gridRows: [], + serviceName: undefined, selected: function() { return this._selected; @@ -290,6 +291,7 @@ export default Ember.Component.extend({ setAttemptsGridColumnsAndRows: function() { var self = this; var columns = []; + var serviceName = this.get('serviceName'); columns.push({ id: 'id', @@ -298,10 +300,11 @@ export default Ember.Component.extend({ cellComponentName: 'em-table-linked-cell', minWidth: '300px', getCellContent: function(row) { + var attemptId = row.get('id'); + var query = serviceName? '?service='+serviceName : ''; return { - displayText: row.get('id'), - routeName: 'yarn-app-attempt', - id: row.get('id') + displayText: attemptId, + href: `#/yarn-app-attempt/${attemptId}${query}` }; } }, { @@ -326,7 +329,7 @@ export default Ember.Component.extend({ id: 'appMasterContainerId', headerTitle: 'AM Container ID', contentPath: 'appMasterContainerId', - minWidth: '300px' + minWidth: '350px' }, { id: 'amNodeId', headerTitle: 'AM Node ID', @@ -384,7 +387,7 @@ export default Ember.Component.extend({ id: 'id', headerTitle: 'Container ID', contentPath: 'id', - minWidth: '300px' + minWidth: '350px' }, { id: 'startedTime', headerTitle: 'Started Time', diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/app-table-columns.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/app-table-columns.js index 53a6439987..704abfbc6e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/app-table-columns.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/app-table-columns.js @@ -19,80 +19,145 @@ import Ember from 'ember'; import ColumnDef from 'em-table/utils/column-definition'; +import TableDef from 'em-table/utils/table-definition'; export default Ember.Controller.extend({ - columns: function() { - var colums = []; - colums.push({ - id: 'appId', - headerTitle: 'Application ID', - contentPath: 'id', - cellComponentName: 'em-table-linked-cell', - getCellContent: function(row) { -   return { -     displayText: row.id, -     routeName: 'yarn-app', -     id: row.id - }; - }, - minWidth: "250px" - }, { - id: 'appType', - headerTitle: 'Application Type', - contentPath: 'applicationType', - }, { - id: 'appName', - headerTitle: 'Application Name', - contentPath: 'appName', - }, { - id: 'appUsr', - headerTitle: 'User', - contentPath: 'user', - minWidth: "50px" - }, { - id: 'queue', - headerTitle: 'Queue', - contentPath: 'queue', - }, { - id: 'state', - headerTitle: 'State', - contentPath: 'state', - cellComponentName: 'em-table-status-cell', - minWidth: "50px" - }, { - id: 'progress', - headerTitle: 'Progress', - contentPath: 'progress', - cellComponentName: 'em-table-progress-cell', - cellDefinition: { -       valueMax: 100 -     }, - }, { - id: 'stTime', - headerTitle: 'Start Time', - contentPath: 'startTime', - }, { - id: 'elTime', - headerTitle: 'Elapsed Time', - contentPath: 'elapsedTime', - cellDefinition: { - type: "duration" - } - }, { - id: 'finishTime', - headerTitle: 'Finished Time', - contentPath: 'validatedFinishedTs', - observePath: true - }, { - id: 'priority', - headerTitle: 'Priority', - contentPath: 'priority', - }, { - id: 'cluster', - headerTitle: '%Cluster', - contentPath: 'clusterUsagePercentage', - observePath: true - }); - return ColumnDef.make(colums); - }.property() + tableDefinition: TableDef.create({ + sortColumnId: 'stTime', + sortOrder: 'desc' + }), + + columns: function() { + var colums = []; + colums.push({ + id: 'appId', + headerTitle: 'Application ID', + contentPath: 'id', + cellComponentName: 'em-table-linked-cell', + minWidth: "250px", + getCellContent: function(row) { + return { + displayText: row.id, + href: `#/yarn-app/${row.id}` + }; + } + }, { + id: 'appType', + headerTitle: 'Application Type', + contentPath: 'applicationType', + }, { + id: 'appName', + headerTitle: 'Application Name', + contentPath: 'appName', + }, { + id: 'appUsr', + headerTitle: 'User', + contentPath: 'user', + minWidth: "50px" + }, { + id: 'queue', + headerTitle: 'Queue', + contentPath: 'queue', + }, { + id: 'state', + headerTitle: 'State', + contentPath: 'state', + cellComponentName: 'em-table-status-cell', + minWidth: "50px" + }, { + id: 'progress', + headerTitle: 'Progress', + contentPath: 'progress', + cellComponentName: 'em-table-progress-cell', + cellDefinition: { + valueMax: 100 + } + }, { + id: 'stTime', + headerTitle: 'Start Time', + contentPath: 'startTime', + }, { + id: 'elTime', + headerTitle: 'Elapsed Time', + contentPath: 'elapsedTime', + cellDefinition: { + type: "duration" + } + }, { + id: 'finishTime', + headerTitle: 'Finished Time', + contentPath: 'validatedFinishedTs', + observePath: true + }, { + id: 'priority', + headerTitle: 'Priority', + contentPath: 'priority', + }, { + id: 'cluster', + headerTitle: '%Cluster', + contentPath: 'clusterUsagePercentage', + observePath: true + }); + return ColumnDef.make(colums); + }.property(), + + serviceColumns: function() { + var colums = []; + colums.push({ + id: 'appName', + headerTitle: 'Service Name', + contentPath: 'appName', + minWidth: "200px", + cellComponentName: 'em-table-linked-cell', + getCellContent: function(row) { + return { + displayText: row.get('appName'), + href: `#/yarn-app/${row.id}?service=${row.get('appName')}` + }; + } + }, { + id: 'appId', + headerTitle: 'Application ID', + contentPath: 'id', + minWidth: "250px" + }, { + id: 'state', + headerTitle: 'State', + contentPath: 'state', + cellComponentName: 'em-table-status-cell', + minWidth: "50px" + }, { + id: 'cluster', + headerTitle: '%Cluster', + contentPath: 'clusterUsagePercentage', + observePath: true + }, { + id: 'elTime', + headerTitle: 'Elapsed Time', + contentPath: 'elapsedTime', + cellDefinition: { + type: "duration" + }, + minWidth: "200px" + }, { + id: 'appUsr', + headerTitle: 'User', + contentPath: 'user', + minWidth: "50px" + }, { + id: 'queue', + headerTitle: 'Queue', + contentPath: 'queue', + }, { + id: 'stTime', + headerTitle: 'Started Time', + contentPath: 'startTime', + }, { + id: 'finishTime', + headerTitle: 'Finished Time', + contentPath: 'validatedFinishedTs', + observePath: true + }); + return ColumnDef.make(colums); + }.property(), }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js index 4c02361090..fbe6fa9e27 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempt.js @@ -19,10 +19,14 @@ import Ember from 'ember'; export default Ember.Controller.extend({ + queryParams: ["service"], + service: undefined, breadcrumbs: Ember.computed("model.attempt.appId", function () { var appId = this.get("model.attempt.appId"); - return [{ + var attemptId = this.get("model.attempt.id"); + var serviceName = this.get('service'); + var breadcrumbs = [{ text: "Home", routeName: 'application' },{ @@ -30,11 +34,31 @@ export default Ember.Controller.extend({ routeName: 'yarn-apps.apps' }, { text: `App [${appId}]`, - routeName: 'yarn-app', - model: appId + href: `#/yarn-app/${appId}` }, { - text: "Attempt", + text: "Attempts", + href: `#/yarn-app-attempts/${appId}` + }, { + text: `Attempt [${attemptId}]` }]; + if (serviceName) { + breadcrumbs = [{ + text: "Home", + routeName: 'application' + }, { + text: "Services", + routeName: 'yarn-services' + }, { + text: `${serviceName} [${appId}]`, + href: `#/yarn-app/${appId}?service=${serviceName}` + }, { + text: "Attempts", + href: `#/yarn-app-attempts/${appId}?service=${serviceName}` + }, { + text: `Attempt [${attemptId}]` + }]; + } + return breadcrumbs; }) }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js index 92de2f99e6..77e531ea28 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app-attempts.js @@ -19,10 +19,13 @@ import Ember from 'ember'; export default Ember.Controller.extend({ + queryParams: ["service"], + service: undefined, breadcrumbs: Ember.computed("model.appId", function () { var appId = this.get("model.appId"); - return [{ + var serviceName = this.get('service'); + var breadcrumbs = [{ text: "Home", routeName: 'application' },{ @@ -30,11 +33,25 @@ export default Ember.Controller.extend({ routeName: 'yarn-apps.apps' }, { text: `App [${appId}]`, - routeName: 'yarn-app', - model: appId + href: `#/yarn-app/${appId}` }, { text: "Attempts", }]; + if (serviceName) { + breadcrumbs = [{ + text: "Home", + routeName: 'application' + }, { + text: "Services", + routeName: 'yarn-services' + }, { + text: `${serviceName} [${appId}]`, + href: `#/yarn-app/${appId}?service=${serviceName}` + }, { + text: "Attempts" + }]; + } + return breadcrumbs; }) }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js index f699a22f66..e7d65cde0f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-app.js @@ -19,10 +19,13 @@ import Ember from 'ember'; export default Ember.Controller.extend({ + queryParams: ["service"], + service: undefined, breadcrumbs: Ember.computed("model.app.id", function () { var appId = this.get("model.app.id"); - return [{ + var serviceName = this.get('service'); + var breadcrumbs = [{ text: "Home", routeName: 'application' },{ @@ -30,9 +33,21 @@ export default Ember.Controller.extend({ routeName: 'yarn-apps.apps' }, { text: `App [${appId}]`, - routeName: 'yarn-app', - model: appId + href: `#/yarn-app/${appId}` }]; + if (serviceName) { + breadcrumbs = [{ + text: "Home", + routeName: 'application' + }, { + text: "Services", + routeName: 'yarn-services' + }, { + text: `${serviceName} [${appId}]`, + href: `#/yarn-app/${appId}?service=${serviceName}` + }]; + } + return breadcrumbs; }), amHostHttpAddressFormatted: Ember.computed('model.app.amHostHttpAddress', function() { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js index 5c5063b94e..0b0be20f81 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js @@ -16,9 +16,6 @@ * limitations under the License. */ - -import Ember from 'ember'; -import ColumnDef from 'em-table/utils/column-definition'; import AppTableController from '../app-table-columns'; export default AppTableController.extend({ diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js index 5c5063b94e..0b0be20f81 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js @@ -16,9 +16,6 @@ * limitations under the License. */ - -import Ember from 'ember'; -import ColumnDef from 'em-table/utils/column-definition'; import AppTableController from '../app-table-columns'; export default AppTableController.extend({ diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js index 75bebf6e33..eeb6205c7d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js @@ -17,18 +17,85 @@ */ import Ember from 'ember'; +import AppTableController from './app-table-columns'; -export default Ember.Controller.extend({ + +export default AppTableController.extend({ breadcrumbs: [{ text: "Home", routeName: 'application' }, { - text: "Applications", - routeName: 'yarn-apps.apps', - }, { - text: "Long Running Services", + text: "Services", routeName: 'yarn-services', - }] + }], + + getFinishedServicesDataForDonutChart: Ember.computed('model.apps', function() { + + var finishdApps = 0; + var failedApps = 0; + var killedApps = 0; + + this.get('model.apps').forEach(function(service){ + if (service.get('state') === "FINISHED") { + finishdApps++; + } + + if (service.get('state') === "FAILED") { + failedApps++; + } + + if (service.get('state') === "KILLED") { + killedApps++; + } + }); + + var arr = []; + arr.push({ + label: "Completed", + value: finishdApps + }); + arr.push({ + label: "Killed", + value: killedApps + }); + arr.push({ + label: "Failed", + value: failedApps + }); + + return arr; + }), + + + getRunningServicesDataForDonutChart: Ember.computed('model.apps', function() { + var pendingApps = 0; + var runningApps = 0; + + this.get('model.apps').forEach(function(service){ + if (service.get('state') === "RUNNING") { + runningApps++; + } + + if (service.get('state') === "ACCEPTED" || + service.get('state') === "SUBMITTED" || + service.get('state') === "NEW" || + service.get('state') === "NEW_SAVING") { + pendingApps++; + } + }); + + var arr = []; + arr.push({ + label: "Pending", + value: pendingApps + }); + arr.push({ + label: "Running", + value: runningApps + }); + + return arr; + }), }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app.js index 638e5b02c5..47814e48c2 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app.js @@ -59,11 +59,15 @@ export default DS.Model.extend({ validatedFinishedTs: function() { if (this.get("finishedTime") < this.get("startTime")) { - return ""; + return "N/A"; } return this.get("finishedTime"); }.property("finishedTime"), + formattedElapsedTime: function() { + return Converter.msToElapsedTimeUnit(this.get('elapsedTime')); + }.property('elapsedTime'), + allocatedResource: function() { return Converter.resourceToString(this.get("allocatedMB"), this.get("allocatedVCores")); }.property("allocatedMB", "allocatedVCores"), 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 03ec780842..a45861e905 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 @@ -28,6 +28,7 @@ Router.map(function() { this.route('apps'); this.route('services'); }); + this.route('yarn-services'); this.route('yarn-nodes', function(){ this.route('table'); this.route('heatmap'); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-services.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-services.js new file mode 100644 index 0000000000..fb01138d5a --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/routes/yarn-services.js @@ -0,0 +1,34 @@ +/** + * 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'; +import AbstractRoute from './abstract'; + +export default AbstractRoute.extend({ + model() { + return Ember.RSVP.hash({ + apps: this.store.query('yarn-app', { + applicationTypes: "org-apache-slider" + }), + }); + }, + + unloadAll() { + this.store.unloadAll('yarn-app'); + } +}); 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 dca5b92087..e3dfcd9c72 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 @@ -305,3 +305,12 @@ li a.navigation-link.ember-view { .donut-chart svg { width: 100%; } + +div.attempt-info-panel table { + table-layout: fixed; +} + +div.attempt-info-panel table > tbody > tr > td:last-of-type { + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs index 4a2ba386ef..a6d247b3f0 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/application.hbs @@ -46,13 +46,18 @@ (current) {{/link-to}} {{/link-to}} - {{#link-to 'yarn-apps.apps' tagName="li" currentWhen="yarn-apps.apps yarn-apps.services"}} - {{#link-to 'yarn-apps.apps' class="navigation-link" currentWhen="yarn-apps.apps yarn-apps.services"}}Applications + {{#link-to 'yarn-apps.apps' tagName="li" current-when="yarn-apps.apps yarn-apps.services"}} + {{#link-to 'yarn-apps.apps' class="navigation-link"}}Applications (current) {{/link-to}} {{/link-to}} - {{#link-to 'yarn-nodes.table' tagName="li" currentWhen="yarn-nodes.table yarn-nodes.heatmap"}} - {{#link-to 'yarn-nodes.table' class="navigation-link" currentWhen="yarn-nodes.table yarn-nodes.heatmap"}}Nodes + {{#link-to 'yarn-services' tagName="li"}} + {{#link-to 'yarn-services' class="navigation-link"}}Services + (current) + {{/link-to}} + {{/link-to}} + {{#link-to 'yarn-nodes.table' tagName="li" current-when="yarn-nodes.table yarn-nodes.heatmap"}} + {{#link-to 'yarn-nodes.table' class="navigation-link"}}Nodes (current) {{/link-to}} {{/link-to}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/app-attempt-table.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/app-attempt-table.hbs index c3a9e32e77..d33bf2f975 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/app-attempt-table.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/app-attempt-table.hbs @@ -20,7 +20,7 @@ Application Attempt Id - {{attempt.id}} + {{attempt.id}} Started Time @@ -38,11 +38,11 @@ AM Container Id - {{attempt.appMasterContainerId}} + {{attempt.appMasterContainerId}} AM Node Id - {{attempt.amNodeId}} + {{attempt.amNodeId}} {{#if attempt.attemptState}} @@ -53,7 +53,7 @@ {{#if attempt.nodeHttpAddress}} AM Node Web UI - {{attempt.nodeHttpAddress}} + {{attempt.nodeHttpAddress}} {{/if}} {{#if attempt.logsLink}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/container-table.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/container-table.hbs index ab353d25d5..3860f1550c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/container-table.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/container-table.hbs @@ -51,7 +51,7 @@ {{#if container.nodeHttpAddress}} NodeManager UI - {{container.nodeHttpAddress}} + {{container.nodeHttpAddress}} {{/if}} {{#if container.logUrl}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/em-table-html-cell.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/em-table-html-cell.hbs new file mode 100644 index 0000000000..cf0b59a831 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/em-table-html-cell.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. +}} + +{{#if content}} + {{{content}}} +{{else}} + Not Available! +{{/if}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/timeline-view.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/timeline-view.hbs index 78561948f1..a39d9b1fd4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/timeline-view.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/timeline-view.hbs @@ -38,13 +38,13 @@


-
+
-
-
+
+
{{#if selected.link}} - {{#link-to selected.linkname selected.id}}{{selected.id}}{{/link-to}} + {{#link-to selected.linkname selected.id (query-params service=serviceName)}}{{selected.id}}{{/link-to}} {{else}} {{selected.id}} {{/if}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempts.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempts.hbs index c0fa7e1c1c..0af1457cd3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempts.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app-attempts.hbs @@ -30,11 +30,11 @@
-{{outlet}} \ No newline at end of file +{{outlet}} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs index 8ce8e8b3f2..17ec11e09c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-app.hbs @@ -25,17 +25,21 @@
-

Application

+ {{#if service}} +

Service

+ {{else}} +

Application

+ {{/if}}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-services.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-services.hbs new file mode 100644 index 0000000000..649834abba --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-services.hbs @@ -0,0 +1,86 @@ +{{!-- + 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. +--}} + +{{breadcrumb-bar breadcrumbs=breadcrumbs}} + + +
+
+ +
+
+
+

Services

+
+
+ +
+
+
+ +
+
+
+
+
+ Finished Services +
+
+ {{donut-chart data=getFinishedServicesDataForDonutChart + showLabels=true + parentId="finishedapps-donut-chart" + ratio=0.6 + maxHeight=350 + colorTargets="good warn error" + }} +
+
+
+ +
+
+
+ Running Services +
+
+ {{donut-chart data=getRunningServicesDataForDonutChart + showLabels=true + parentId="runningapps-donut-chart" + ratio=0.6 + maxHeight=350 + colorTargets="warn good" + }} +
+
+
+
+ {{#if model.apps}} + {{em-table columns=serviceColumns rows=model.apps definition=tableDefinition}} + {{else}} +

Could not find any services from this cluster

+ {{/if}} +
+
+
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/utils/converter.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/utils/converter.js index 448dd18719..4f246512c3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/utils/converter.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/utils/converter.js @@ -125,5 +125,29 @@ export default { unit = "PB"; } return value.toFixed(1) + " " + unit; + }, + msToElapsedTimeUnit: function(millisecs) { + var seconds = Math.floor(millisecs / 1000); + var days = Math.floor(seconds / (3600 * 24)); + var hours = Math.floor(seconds / 3600) - (days * 24); + var mins = Math.floor((seconds - (hours * 3600) - (days * 24 * 3600)) / 60); + var secs = seconds - (days * 24 * 3600) - (hours * 3600) - (mins * 60); + var timeStrArr = []; + var pluralize = ""; + if (days > 0) { + pluralize = days > 1? " Days" : " Day"; + timeStrArr.push(days + pluralize); + } + if (hours > 0) { + pluralize = hours > 1? " Hrs" : " Hour"; + timeStrArr.push(hours + pluralize); + } + if (mins > 0) { + pluralize = mins > 1? " Mins" : " Min"; + timeStrArr.push(mins + pluralize); + } + pluralize = secs > 1? " Secs" : " Sec"; + timeStrArr.push(secs + pluralize); + return timeStrArr.join(" : "); } }; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/integration/components/em-table-html-cell-test.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/integration/components/em-table-html-cell-test.js new file mode 100644 index 0000000000..777b9a88c4 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/integration/components/em-table-html-cell-test.js @@ -0,0 +1,43 @@ +/** + * 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 { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('em-table-html-cell', 'Integration | Component | em table html cell', { + integration: true +}); + +test('it renders', function(assert) { + + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL + + + this.render(hbs`{{em-table-html-cell}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage:" + EOL + + this.render(hbs` + {{#em-table-html-cell}} + template block text + {{/em-table-html-cell}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/routes/yarn-services-test.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/routes/yarn-services-test.js new file mode 100644 index 0000000000..6348f860b6 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/tests/unit/routes/yarn-services-test.js @@ -0,0 +1,29 @@ +/** + * 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 { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:yarn-services', 'Unit | Route | yarn services', { + // Specify the other units that are required for this test. + // needs: ['controller:foo'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +});