YARN-7499. Layout changes to Application details page in new YARN UI. Contributed by Vasudevan Skm.

This commit is contained in:
Sunil G 2017-11-28 18:37:11 +05:30
parent 0ea182d0fa
commit 641ba5c7a1
26 changed files with 528 additions and 347 deletions

View File

@ -39,7 +39,7 @@ export default Ember.Controller.extend({
getCellContent: function(row) {
return {
displayText: row.id,
href: `#/yarn-app/${row.id}/info`
href: `#/yarn-app/${row.id}/attempts`
};
}
}, {
@ -120,7 +120,7 @@ export default Ember.Controller.extend({
getCellContent: function(row) {
return {
displayText: row.get('appName'),
href: `#/yarn-app/${row.id}/info?service=${row.get('appName')}`
href: `#/yarn-app/${row.id}/attempts?service=${row.get('appName')}`
};
}
}, {

View File

@ -32,6 +32,65 @@ export default Ember.Controller.extend({
text: 'App'
}],
actions: {
showStopServiceConfirm() {
this.set('actionResponse', null);
Ember.$("#stopServiceConfirmDialog").modal('show');
},
stopService() {
var self = this;
Ember.$("#stopServiceConfirmDialog").modal('hide');
var adapter = this.store.adapterFor('yarn-servicedef');
self.set('isLoading', true);
adapter.stopService(this.model.serviceName).then(function () {
self.set('actionResponse', { msg: 'Service stopped successfully. Auto refreshing in 5 seconds.', type: 'success' });
Ember.run.later(self, function () {
this.set('actionResponse', null);
this.send("refresh");
}, 5000);
}, function (errr) {
let messg = errr.diagnostics || 'Error: Stop service failed!';
self.set('actionResponse', { msg: messg, type: 'error' });
}).finally(function () {
self.set('isLoading', false);
});
},
showDeleteServiceConfirm() {
this.set('actionResponse', null);
Ember.$("#deleteServiceConfirmDialog").modal('show');
},
deleteService() {
var self = this;
Ember.$("#deleteServiceConfirmDialog").modal('hide');
var adapter = this.store.adapterFor('yarn-servicedef');
self.set('isLoading', true);
adapter.deleteService(this.model.serviceName).then(function () {
self.set('actionResponse', { msg: 'Service deleted successfully. Redirecting to services in 5 seconds.', type: 'success' });
Ember.run.later(self, function () {
this.set('actionResponse', null);
this.transitionToRoute("yarn-services");
}, 5000);
}, function (errr) {
let messg = errr.diagnostics || 'Error: Delete service failed!';
self.set('actionResponse', { msg: messg, type: 'error' });
}).finally(function () {
self.set('isLoading', false);
});
},
resetActionResponse() {
this.set('actionResponse', null);
}
},
isRunningService: Ember.computed('model.serviceName', 'model.app.state', function () {
return this.model.serviceName && this.model.app.get('state') === 'RUNNING';
}),
updateBreadcrumbs(appId, serviceName, tailCrumbs) {
var breadcrumbs = [{
text: "Home",
@ -58,5 +117,13 @@ export default Ember.Controller.extend({
breadcrumbs.pushObjects(tailCrumbs);
}
this.set('breadcrumbs', breadcrumbs);
}
},
amHostHttpAddressFormatted: Ember.computed('model.app.amHostHttpAddress', function () {
var amHostAddress = this.get('model.app.amHostHttpAddress');
if (amHostAddress && amHostAddress.indexOf('://') < 0) {
amHostAddress = 'http://' + amHostAddress;
}
return amHostAddress;
})
});

View File

@ -32,7 +32,7 @@ function createColumn() {
minWidth: "300px",
getCellContent: function (row) {
return {
routeName: 'yarn-app.info',
routeName: 'yarn-app.attempts',
id: row.get('appId'),
displayText: row.get('appId')
};

View File

@ -33,7 +33,7 @@ export default DS.Model.extend({
amContainerLogs: DS.attr('string'),
amHostHttpAddress: DS.attr('string'),
logAggregationStatus: DS.attr('string'),
unmanagedApplication: DS.attr('string'),
unmanagedApplication: DS.attr('boolean'),
amNodeLabelExpression: DS.attr('string'),
applicationTags: DS.attr('string'),
applicationType: DS.attr('string'),
@ -65,6 +65,10 @@ export default DS.Model.extend({
return this.get("finishedTime");
}.property("finishedTime"),
hasFinishedTime: function() {
return this.get("finishedTime") >= this.get("startTime");
}.property("hasFinishedTime"),
formattedElapsedTime: function() {
return Converter.msToElapsedTimeUnit(this.get('elapsedTime'));
}.property('elapsedTime'),

View File

@ -54,12 +54,12 @@ Router.map(function() {
this.route('yarn-deploy-service');
this.route('cluster-overview');
this.route('yarn-app', function() {
this.route('info', {path: '/:app_id/info'});
this.route('attempts', {path: '/:app_id/attempts'});
this.route('components', {path: '/:app_id/components'});
this.route('charts', {path: '/:app_id/charts'});
this.route('configs', {path: '/:app_id/configs'});
this.route('yarn-app', { path: '/yarn-app/:app_id' }, function() {
this.route('info');
this.route('attempts');
this.route('components');
this.route('charts');
this.route('configs');
});
this.route('yarn-component-instances', function() {
this.route('info', {path: '/:component_name/info'});

View File

@ -16,9 +16,30 @@
* limitations under the License.
*/
import Ember from 'ember';
import AbstractRoute from './abstract';
import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
export default AbstractRoute.extend({
export default AbstractRoute.extend(AppAttemptMixin, {
model(param, transition) {
const {service} = transition.queryParams;
transition.send('updateBreadcrumbs', param.app_id, service);
return Ember.RSVP.hash({
appId: param.app_id,
serviceName: service,
app: this.fetchAppInfoFromRMorATS(param.app_id, this.store),
quicklinks: this.store.queryRecord('yarn-service-info', { appId: param.app_id }).then(function (info) {
if (info && info.get('quicklinks')) {
return info.get('quicklinks');
}
return [];
}, function () {
return [];
})
});
},
actions: {
updateBreadcrumbs(appId, serviceName, tailCrumbs) {
var controller = this.controllerFor('yarn-app');

View File

@ -22,14 +22,21 @@ import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
export default AbstractRoute.extend(AppAttemptMixin, {
model(param, transition) {
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: 'Attempts'}]);
const {app_id} = this.paramsFor('yarn-app');
const {service} = param;
transition.send('updateBreadcrumbs', app_id, service, [{text: 'Attempts'}]);
return Ember.RSVP.hash({
appId: param.app_id,
serviceName: param.service,
attempts: this.fetchAttemptListFromRMorATS(param.app_id, this.store)
appId: app_id,
serviceName: service,
attempts: this.fetchAttemptListFromRMorATS(app_id, this.store)
});
},
refresh() {
window.location.reload();
},
unloadAll() {
this.store.unloadAll('yarn-app-attempt');
this.store.unloadAll('yarn-timeline-appattempt');

View File

@ -21,15 +21,17 @@ import AbstractRoute from '../abstract';
export default AbstractRoute.extend({
model(param, transition) {
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: "Charts"}]);
const { app_id } = this.paramsFor('yarn-app');
const { service } = param;
transition.send('updateBreadcrumbs', app_id, service, [{text: "Charts"}]);
return Ember.RSVP.hash({
appId: param.app_id,
serviceName: param.service,
appId: app_id,
serviceName: service,
app: this.store.find('yarn-app', param.app_id),
app: this.store.find('yarn-app', app_id),
rmContainers: this.store.find('yarn-app', param.app_id).then(function() {
return this.store.query('yarn-app-attempt', {appId: param.app_id}).then(function (attempts) {
rmContainers: this.store.find('yarn-app', app_id).then(function() {
return this.store.query('yarn-app-attempt', {appId: app_id}).then(function (attempts) {
if (attempts && attempts.get('firstObject')) {
var appAttemptId = attempts.get('firstObject').get('appAttemptId');
return this.store.query('yarn-container', {
@ -44,6 +46,10 @@ export default AbstractRoute.extend({
});
},
refresh() {
window.location.reload();
},
unloadAll() {
this.store.unloadAll('yarn-app');
this.store.unloadAll('yarn-app-attempt');

View File

@ -21,14 +21,16 @@ import AbstractRoute from '../abstract';
export default AbstractRoute.extend({
model(param, transition) {
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: 'Components'}]);
const { app_id } = this.paramsFor('yarn-app');
const { service } = param;
transition.send('updateBreadcrumbs', app_id, service, [{text: 'Components'}]);
return Ember.RSVP.hash({
appId: param.app_id,
serviceName: param.service,
components: this.store.query('yarn-service-component', {appId: param.app_id, type: 'COMPONENT'}).catch(function() {
appId: app_id,
serviceName: service,
components: this.store.query('yarn-service-component', {appId: app_id, type: 'COMPONENT'}).catch(function() {
return [];
}),
instances: this.store.query('yarn-component-instance', {appId: param.app_id}).catch(function() {
instances: this.store.query('yarn-component-instance', {appId: app_id}).catch(function() {
return [];
})
});
@ -42,6 +44,10 @@ export default AbstractRoute.extend({
});
},
refresh() {
window.location.reload();
},
unloadAll() {
this.store.unloadAll('yarn-service-component');
this.store.unloadAll('yarn-component-instance');

View File

@ -21,12 +21,14 @@ import AbstractRoute from '../abstract';
export default AbstractRoute.extend({
model(param, transition) {
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: "Configurations & Metrics"}]);
const { app_id } = this.paramsFor('yarn-app');
const { service } = param;
transition.send('updateBreadcrumbs', app_id, service, [{text: "Configurations & Metrics"}]);
return Ember.RSVP.hash({
appId: param.app_id,
serviceName: param.service,
appId: app_id,
serviceName: service,
configs: this.store.queryRecord('yarn-service-info', {appId: param.app_id}).then(function(info) {
configs: this.store.queryRecord('yarn-service-info', {appId: app_id}).then(function(info) {
if (info && info.get('configs')) {
return info.get('configs');
}
@ -35,7 +37,7 @@ export default AbstractRoute.extend({
return [];
}),
metrics: this.store.queryRecord('yarn-service-info', {appId: param.app_id}).then(function(info) {
metrics: this.store.queryRecord('yarn-service-info', {appId: app_id}).then(function(info) {
if (info && info.get('metrics')) {
return info.get('metrics');
}
@ -46,6 +48,10 @@ export default AbstractRoute.extend({
});
},
refresh() {
window.location.reload();
},
unloadAll() {
this.store.unloadAll('yarn-service-info');
}

View File

@ -22,13 +22,16 @@ import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
export default AbstractRoute.extend(AppAttemptMixin, {
model(param, transition) {
transition.send('updateBreadcrumbs', param.app_id, param.service);
return Ember.RSVP.hash({
appId: param.app_id,
serviceName: param.service,
app: this.fetchAppInfoFromRMorATS(param.app_id, this.store),
const { app_id } = this.paramsFor('yarn-app');
const { service } = param;
transition.send('updateBreadcrumbs', app_id, service);
quicklinks: this.store.queryRecord('yarn-service-info', {appId: param.app_id}).then(function(info) {
return Ember.RSVP.hash({
appId: app_id,
serviceName: service,
app: this.fetchAppInfoFromRMorATS(app_id, this.store),
quicklinks: this.store.queryRecord('yarn-service-info', {appId: app_id}).then(function(info) {
if (info && info.get('quicklinks')) {
return info.get('quicklinks');
}
@ -39,6 +42,10 @@ export default AbstractRoute.extend(AppAttemptMixin, {
});
},
refresh() {
window.location.reload();
},
unloadAll() {
this.store.unloadAll('yarn-app');
this.store.unloadAll('yarn-app-timeline');

View File

@ -52,7 +52,7 @@ export default DS.JSONAPISerializer.extend({
amContainerLogs: payload.amContainerLogs,
amHostHttpAddress: payload.amHostHttpAddress,
logAggregationStatus: payload.logAggregationStatus,
unmanagedApplication: payload.unmanagedApplication || 'N/A',
unmanagedApplication: payload.unmanagedApplication,
amNodeLabelExpression: payload.amNodeLabelExpression,
priority: (payload.priority !== undefined)? payload.priority : 'N/A',
allocatedMB: payload.allocatedMB,

View File

@ -1,4 +1,6 @@
@import 'variables.scss';
@import 'layout.scss';
@import 'yarn-app.scss';
/**
* Licensed to the Apache Software Foundation (ASF) under one
@ -497,6 +499,9 @@ div.attempt-info-panel table > tbody > tr > td:last-of-type {
.align-center {
text-align: center !important;
}
.align-right {
text-align: right;
}
.bold-text {
font-weight: bold !important;
@ -717,7 +722,26 @@ div.service-action-mask img {
line-height: 2em;
}
.yarn-app-body > div:not(:first-child) {
margin-top: 15px;
}
.em-table .table-column .table-header-cell {
background-color: $yarn-header-bg;
border-bottom: 1px solid $yarn-border-color;
}
.muted-text {
color: $yarn-muted-text;
}
.glyphicon-gray {
color: $yarn-gray-icon;
}
.btn.btn-unstyled {
padding: 5px;
background: none;
border: none;
box-shadow: none;
}

View File

@ -21,6 +21,8 @@ $color-ghost-white: #f1f2f8;
$color-white: #fff;
$color-gray-20: #333;
$color-gray-40: #666666;
$color-gray-60: #999999;
$color-gray-97: #f7f7f7;
$color-light-gray: #d5d5d5;

View File

@ -0,0 +1,42 @@
/**
* 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.
*/
.flex {
display: flex;
}
/** Pushes the flex element to the right corner **/
.flex-right {
margin-left: auto;
}
.offset-1 {
margin-left: 5px
}
.offset-2 {
margin-left: 10px
}
.tail-1 {
margin-right: 5px
}
.tail-2 {
margin-right: 10px
}

View File

@ -36,5 +36,9 @@ $yarn-info-bg: $color-blue-primary;
$yarn-warn-border: $color-yellow-secondary;
$yarn-warn-bg: $color-yellow-primary;
$yarn-gray-icon: $color-gray-40;
$yarn-muted-text: $color-gray-60;
//shadows

View File

@ -0,0 +1,35 @@
/**
* 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.
*/
.yarn-app-header {
padding: 20px;
line-height: 2em;
h3 {
margin: 0px;
}
i.glyphicon {
vertical-align: text-top;
margin-right: 3px;
}
.yarn-app-final-status .label {
vertical-align: middle;
}
}

View File

@ -16,7 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
{{#if attemptModel}}

View File

@ -18,46 +18,131 @@
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">
<div class="col-md-2 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
{{#if serviceName}}
Service
{{else}}
Application
{{/if}}
<div class="panel-group">
<div class="panel panel-default">
<div class="yarn-app-header">
<div class="flex">
<div>
<div class="flex">
<div>
<h3 class="yarn-app-name">
{{#if model.app.unmanagedApplication}}
<span title="This is an unmanaged application" class="yarn-tooltip">
<i class="glyphicon glyphicon-exclamation-sign glyphicon-gray" />
</span>
{{/if}}
{{model.app.appName}}
</h3>
</div>
{{#if model.app.finalStatus}}
<div title="Final status" class="yarn-tooltip yarn-app-final-status offset-1">
<span class={{model.app.finalStatusStyle}}>
{{model.app.finalStatus}}
</span>
</div>
{{/if}}
</div>
<div title="Application id" class="muted-text">{{model.app.id}}</div>
{{em-table-simple-status-cell content=model.app.state}}
<div class="flex">
<div class="tail-2">
<i class="glyphicon glyphicon-user glyphicon-gray" /> {{model.app.user}}
</div>
{{#if model.app.hasFinishedTime}}
<div title="Started at {{model.app.startTime}}. &#10; Ran for {{model.app.formattedElapsedTime}}" class="yarn-tooltip">
<i class="glyphicon glyphicon-time glyphicon-gray" />
Finished at {{model.app.validatedFinishedTs}}
</div>
{{else}}
<div title="Running for {{model.app.formattedElapsedTime}}" class="yarn-tooltip">
<i class="glyphicon glyphicon-time glyphicon-gray" />
Started at {{model.app.startTime}}
</div>
{{/if}}
</div>
</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-app.info' tagName="li" class=(if (eq target.currentPath 'yarn-app.info') "active")}}
{{#link-to 'yarn-app.info' appId (query-params service=serviceName)}}Information{{/link-to}}
{{/link-to}}
{{#link-to 'yarn-app.attempts' tagName="li" class=(if (eq target.currentPath 'yarn-app.attempts') "active")}}
{{#link-to 'yarn-app.attempts' appId (query-params service=serviceName)}}Attempts List{{/link-to}}
{{/link-to}}
{{#link-to 'yarn-app.charts' tagName="li" class=(if (eq target.currentPath 'yarn-app.charts') "active")}}
{{#link-to 'yarn-app.charts' appId (query-params service=serviceName)}}Resource Usage{{/link-to}}
{{/link-to}}
{{#if serviceName}}
{{#link-to 'yarn-app.components' tagName="li" class=(if (eq target.currentPath 'yarn-app.components') "active")}}
{{#link-to 'yarn-app.components' appId (query-params service=serviceName)}}Components{{/link-to}}
{{/link-to}}
{{#link-to 'yarn-app.configs' tagName="li" class=(if (eq target.currentPath 'yarn-app.configs') "active")}}
{{#link-to 'yarn-app.configs' appId (query-params service=serviceName)}}Configurations &amp; Metrics{{/link-to}}
{{/link-to}}
<div class="flex-right">
<div class="links">
<a href="{{model.app.amContainerLogs}}" target="_blank">Master Container Log</a> &nbsp;|&nbsp;
<a href="{{amHostHttpAddressFormatted}}" target="_blank">Master Node</a> &nbsp;|&nbsp;
{{#if isRunningService}}
<div class="btn-group">
<button type="button" class="btn btn-unstyled dropdown-toggle" title="Settings" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="glyphicon glyphicon-cog" />
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li>
<a href="#" {{action "showStopServiceConfirm"}} target="_blank"><i class="glyphicon glyphicon-stop" /> &nbsp;Stop Service</a>
</li>
<li>
<a href="#" target="_blank" {{action "showDeleteServiceConfirm"}}><i class="glyphicon glyphicon-trash" /> &nbsp;Delete Service </a>
</li>
</ul>
</div>
{{/if}}
{{#if model.serviceName}}
{{#if model.quicklinks}}
<div class="btn-group">
<button type="button" class="btn btn-unstyled dropdown-toggle" title="Quick links" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="glyphicon glyphicon-option-vertical" />
</button>
<ul class="dropdown-menu dropdown-menu-right">
{{#each model.quicklinks as |link|}}
<li><a href="{{link.value}}" target="_blank">{{link.name}}</a></li>
{{/each}}
</ul>
</div>
{{/if}}
</ul>
</ul>
{{/if}}
</div>
<div>
<span title="Queue" class="yarn-tooltip"><i class="glyphicon glyphicon-tasks glyphicon-gray" />{{model.app.queue}}</span>
</div>
<div>Priority {{model.app.priority}}</div>
</div>
</div>
</div>
<div class="col-md-10 container-fluid">
<div class="panel-heading">
<div class="clearfix">
<ul class="nav nav-pills">
<ul class="nav nav-pills collapse in">
{{#link-to 'yarn-app.attempts' tagName="li" class=(if (eq target.currentPath 'yarn-app.attempts') "active")}}
{{#link-to 'yarn-app.attempts' appId (query-params service=model.serviceName)}}Attempts List{{/link-to}}
{{/link-to}}
{{#link-to 'yarn-app.charts' tagName="li" class=(if (eq target.currentPath 'yarn-app.charts') "active")}}
{{#link-to 'yarn-app.charts' appId (query-params service=model.serviceName)}}Resource Usage{{/link-to}}
{{/link-to}}
{{#if model.serviceName}}
{{#link-to 'yarn-app.components' tagName="li" class=(if (eq target.currentPath 'yarn-app.components') "active")}}
{{#link-to 'yarn-app.components' appId (query-params service=model.serviceName)}}Components{{/link-to}}
{{/link-to}}
{{#link-to 'yarn-app.configs' tagName="li" class=(if (eq target.currentPath 'yarn-app.configs') "active")}}
{{#link-to 'yarn-app.configs' appId (query-params service=model.serviceName)}}Configurations &amp; Metrics{{/link-to}}
{{/link-to}}
{{/if}}
{{#link-to 'yarn-app.info' tagName="li" class=(if (eq target.currentPath 'yarn-app.info') "active")}}
{{#link-to 'yarn-app.info' appId (query-params service=model.serviceName)}}Diagnostics{{/link-to}}
{{/link-to}}
</ul>
</ul>
</div>
</div>
<div class="panel-body yarn-app-body">
{{outlet}}
</div>
</div>
</div>
{{confirm-dialog
dialogId="stopServiceConfirmDialog"
message=(concat 'Are you sure you want to stop service "' model.serviceName '" ?')
action="stopService"
}}
{{confirm-dialog
dialogId="deleteServiceConfirmDialog"
message=(concat 'Are you sure you want to delete service "' model.serviceName '" ?')
action="deleteService"
}}

View File

@ -16,7 +16,7 @@
* limitations under the License.
}}
<div class="row">
<div>
{{timeline-view
parent-id="attempt-timeline-div"
my-id="timeline-view"

View File

@ -16,28 +16,26 @@
* limitations under the License.
}}
<div class="row">
<div class="col-md-12 container-fluid">
{{#if isRunningApp}}
<div class="row" id="stackd-bar-chart-mem">
{{per-app-memusage-by-nodes-stacked-barchart
nodes=model.nodes
rmContainers=model.rmContainers
parentId="stackd-bar-chart-mem"
title=(concat 'Memory usage by nodes for: [' model.appId ']')}}
</div>
<hr>
<div class="row" id="stackd-bar-chart-ncontainer">
{{per-app-ncontainers-by-nodes-stacked-barchart
nodes=model.nodes
rmContainers=model.rmContainers
parentId="stackd-bar-chart-ncontainer"
title=(concat 'Running #Containers by nodes for: [' model.appId ']')}}
</div>
{{else}}
<div class="panel panel-default">
<h4 class="text-center">No resource usage data is available for this application!</h4>
</div>
{{/if}}
</div>
<div class="col-md-12">
{{#if isRunningApp}}
<div class="row" id="stackd-bar-chart-mem">
{{per-app-memusage-by-nodes-stacked-barchart
nodes=model.nodes
rmContainers=model.rmContainers
parentId="stackd-bar-chart-mem"
title=(concat 'Memory usage by nodes for: [' model.appId ']')}}
</div>
<hr>
<div class="row" id="stackd-bar-chart-ncontainer">
{{per-app-ncontainers-by-nodes-stacked-barchart
nodes=model.nodes
rmContainers=model.rmContainers
parentId="stackd-bar-chart-ncontainer"
title=(concat 'Running #Containers by nodes for: [' model.appId ']')}}
</div>
{{else}}
<div class="panel panel-default">
<h4 class="text-center">No resource usage data is available for this application!</h4>
</div>
{{/if}}
</div>

View File

@ -16,8 +16,6 @@
* limitations under the License.
}}
<div class="row">
<div class="col-md-12">
{{em-table columns=tableColumns rows=model.components}}
</div>
<div class="col-md-12 yarn-applications-container">
{{em-table columns=tableColumns rows=model.components}}
</div>

View File

@ -20,38 +20,36 @@
{{metrics-table metrics=model.metrics type="Service"}}
</div>
<div class="row">
{{#if model.configs}}
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">Service Configurations</div>
</div>
<div class="">
<table class="table table-hover table-custom-bordered table-custom-stripped table-radius-none table-border-none">
<thead>
{{#if model.configs}}
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">Service Configurations</div>
</div>
<div class="">
<table class="table table-hover table-custom-bordered table-custom-stripped table-radius-none table-border-none">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
{{#each model.configs as |config|}}
<tr>
<th>Name</th>
<th>Value</th>
<td>{{config.name}}</td>
<td>{{config.value}}</td>
</tr>
</thead>
<tbody>
{{#each model.configs as |config|}}
<tr>
<td>{{config.name}}</td>
<td>{{config.value}}</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
{{/each}}
</tbody>
</table>
</div>
</div>
{{else}}
<div class="col-md-12">
<div class="panel panel-default">
<h4 class="text-center">No service configurations available!</h4>
</div>
</div>
{{else}}
<div class="col-md-12">
<div class="panel panel-default">
<h4 class="text-center">No service configurations available!</h4>
</div>
{{/if}}
</div>
</div>
{{/if}}

View File

@ -16,19 +16,15 @@
* limitations under the License.
}}
<div class="row">
<div class="col-md-12">
{{app-timeout-bar app=model.app}}
</div>
<div class="col-md-12">
{{app-timeout-bar app=model.app}}
</div>
{{#if actionResponse}}
<div class="row">
<div class="col-md-12">
<div class="alert alert-dismissible {{if (eq actionResponse.type 'error') 'alert-danger' 'alert-success'}}" role="alert">
<button class="close" data-dismiss="alert" aria-label="Close" {{action "resetActionResponse"}}><span aria-hidden="true">&times;</span></button>
<strong>{{actionResponse.msg}}</strong>
</div>
<div class="col-md-12">
<div class="alert alert-dismissible {{if (eq actionResponse.type 'error') 'alert-danger' 'alert-success'}}" role="alert">
<button class="close" data-dismiss="alert" aria-label="Close" {{action "resetActionResponse"}}><span aria-hidden="true">&times;</span></button>
<strong>{{actionResponse.msg}}</strong>
</div>
</div>
{{/if}}
@ -39,220 +35,95 @@
</div>
{{/if}}
<div class="row">
<div class="col-md-12 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
Basic Info
{{#if isRunningService}}
<div class="pull-right" style="display: inline-block; margin: -4px -10px 0 0;">
<button class="btn btn-sm btn-danger" disabled="{{if isLoading 'disabled'}}" {{action "showStopServiceConfirm"}}> Stop </button>
<button class="btn btn-sm btn-danger" disabled="{{if isLoading 'disabled'}}" {{action "showDeleteServiceConfirm"}}> Delete </button>
</div>
{{/if}}
{{#if model.app.diagnostics}}
<div class="col-md-12">
{{#if model.app.isFailed}}
<div class="panel panel-danger">
<div class="panel-heading">
Diagnostics
</div>
<div class="panel-body">{{model.app.diagnostics}}</div>
</div>
<div class="x-scroll">
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Application ID</th>
<th>Name</th>
<th>User</th>
<th>Queue</th>
<th>State</th>
<th>Final Status</th>
<th>Start Time</th>
<th>Elapsed Time</th>
<th>Finished Time</th>
<th>Priority</th>
{{#unless model.serviceName}}
<th>Progress</th>
<th>Is Unmanaged AM</th>
{{/unless}}
</tr>
</thead>
<tbody>
<tr>
<td>{{model.app.id}}</td>
<td>{{model.app.appName}}</td>
<td>{{model.app.user}}</td>
<td>{{model.app.queue}}</td>
<td>{{model.app.state}}</td>
<td>
<span class={{model.app.finalStatusStyle}}>
{{model.app.finalStatus}}
</span>
</td>
<td>{{model.app.startTime}}</td>
<td>{{model.app.formattedElapsedTime}}</td>
<td>{{model.app.validatedFinishedTs}}</td>
<td>{{model.app.priority}}</td>
{{#unless model.serviceName}}
<td>
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar" role="progressbar"
aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100"
style={{model.app.progressStyle}}>
{{model.app.progress}}%
</div>
</div>
</td>
<td>{{model.app.unmanagedApplication}}</td>
{{/unless}}
</tr>
</tbody>
</table>
{{else}}
<div class="panel panel-default">
<div class="panel-heading">
Diagnostics
</div>
<div class="panel-body">{{model.app.diagnostics}}</div>
</div>
</div>
{{/if}}
</div>
</div>
<div class="row">
{{#if model.app.diagnostics}}
<div class="col-md-12 container-fluid">
{{#if model.app.isFailed}}
<div class="panel panel-danger">
<div class="panel-heading">
Diagnostics
</div>
<div class="panel-body">{{model.app.diagnostics}}</div>
</div>
{{else}}
<div class="panel panel-default">
<div class="panel-heading">
Diagnostics
</div>
<div class="panel-body">{{model.app.diagnostics}}</div>
</div>
{{/if}}
</div>
{{/if}}
</div>
{{/if}}
{{#unless model.serviceName}}
<div class="row">
<div class="col-md-12 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">Outstanding Resource Requests</div>
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">Outstanding Resource Requests</div>
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Scheduler Key</th>
<th>Resource Name</th>
<th>Capability</th>
<th># Containers</th>
<th>Relax Locality</th>
<th>Node Label Expression</th>
</tr>
</thead>
<tbody>
{{#each model.app.resourceRequests as |request|}}
<tr>
<th>Scheduler Key</th>
<th>Resource Name</th>
<th>Capability</th>
<th># Containers</th>
<th>Relax Locality</th>
<th>Node Label Expression</th>
<td>{{request.priority}}</td>
<td>{{request.resourceName}}</td>
<td>&lt;Memory:{{request.capability.memory}};vCores:{{request.capability.virtualCores}}&gt;</td>
<td>{{request.numContainers}}</td>
<td>{{request.relaxLocality}}</td>
<td>
{{#if request.nodeLabelExpression}}
{{request.nodeLabelExpression}}
{{else}}
N/A
{{/if}}
</td>
</tr>
</thead>
<tbody>
{{#each model.app.resourceRequests as |request|}}
<tr>
<td>{{request.priority}}</td>
<td>{{request.resourceName}}</td>
<td>&lt;Memory:{{request.capability.memory}};vCores:{{request.capability.virtualCores}}&gt;</td>
<td>{{request.numContainers}}</td>
<td>{{request.relaxLocality}}</td>
<td>
{{#if request.nodeLabelExpression}}
{{request.nodeLabelExpression}}
{{else}}
N/A
{{/if}}
</td>
</tr>
{{else}}
<div class="panel-body">No data available!</div>
{{/each}}
</tbody>
</table>
</div>
{{else}}
<div class="panel-body">No data available!</div>
{{/each}}
</tbody>
</table>
</div>
</div>
{{/unless}}
<div class="row">
<div class="col-md-12 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">Scheduling Info</div>
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Allocated Resource</th>
<th>Running Containers</th>
<th>Preempted Resource</th>
<th>Num Non-AM container preempted</th>
<th>Num AM container preempted</th>
<th>Aggregated Resource Usage</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{model.app.allocatedResource}}</td>
<td>{{model.app.runningContainersNumber}}</td>
<td>{{model.app.preemptedResource}}</td>
<td>{{model.app.numAMContainerPreempted}}</td>
<td>{{model.app.numAMContainerPreempted}}</td>
<td>{{model.app.aggregatedResourceUsage}}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">Scheduling Info</div>
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Allocated Resource</th>
<th>Running Containers</th>
<th>Preempted Resource</th>
<th>Num Non-AM container preempted</th>
<th>Num AM container preempted</th>
<th>Aggregated Resource Usage</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{model.app.allocatedResource}}</td>
<td>{{model.app.runningContainersNumber}}</td>
<td>{{model.app.preemptedResource}}</td>
<td>{{model.app.numAMContainerPreempted}}</td>
<td>{{model.app.numAMContainerPreempted}}</td>
<td>{{model.app.aggregatedResourceUsage}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-md-6 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">Application Master Info</div>
<table class="display table table-striped table-bordered"
cellspacing="0" width="100%">
<thead>
<tr>
<th>Master Container Log</th>
<th>Master Node</th>
<th>Master Node Label Expression</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="{{model.app.amContainerLogs}}" target="_blank">Link</a></td>
<td><a href="{{amHostHttpAddressFormatted}}" target="_blank">Link</a></td>
<td>{{model.app.amNodeLabelExpression}}</td>
</tr>
</tbody>
</table>
</div>
</div>
{{#if model.serviceName}}
<div class="col-md-6 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">Quick Links</div>
<table class="display table table-striped table-bordered">
<tbody>
{{#each model.quicklinks as |link|}}
<tr>
<td>{{link.name}}</td>
<td><a href="{{link.value}}" target="_blank">{{link.value}}</a></td>
</tr>
{{else}}
<tr class="align-center">
<td colspan="2">No quicklinks available!</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</div>
{{/if}}
</div>
{{confirm-dialog

View File

@ -16,7 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
<div class="col-md-12">
<div class="loading-mask">
<img src="assets/images/spinner.gif" alt="Loading...">
</div>

View File

@ -17,7 +17,7 @@
--}}
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<a class="btn btn-primary pull-right" href="#/yarn-deploy-service">New Service</a>
<div class="col-md-12 container-fluid yarn-applications-container">
{{#if model.apps}}
{{em-table columns=serviceColumns rows=model.apps definition=tableDefinition}}