You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by pa...@apache.org on 2016/10/05 10:03:44 UTC
[1/2] ambari git commit: AMBARI-18313. Capacity Scheduler View: Xml
diff view tool to show changes made and queue capacity chart (Akhil PB via
pallavkul)
Repository: ambari
Updated Branches:
refs/heads/trunk 26660f20e -> 62dc775ee
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/xmldiffViewer.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/xmldiffViewer.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/xmldiffViewer.hbs
new file mode 100644
index 0000000..94cc8e0
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/xmldiffViewer.hbs
@@ -0,0 +1,41 @@
+{{!
+* 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 id="xmldiffViewerDialog" class="modal fade xmldiff-viewer" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" {{action "closeDiffViewer"}}>×</button>
+ <h4 class="modal-title">
+ {{#if diffConfig}}
+ XML Diff Tool
+ {{else}}
+ Capacity Scheduler XML
+ {{/if}}
+ </h4>
+ </div>
+ <div class="modal-body">
+ <div id="xmldiffOutput"></div>
+ <textarea id="capshedViewXml" class="viewxml-textarea" rows="19" cols="172" readonly="readonly"></textarea>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal" {{action "closeDiffViewer"}}>Close</button>
+ </div>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/bower.json
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/bower.json b/contrib/views/capacity-scheduler/src/main/resources/ui/bower.json
index 911856f..582ef3e 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/bower.json
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/bower.json
@@ -12,8 +12,10 @@
"font-awesome": "~4.1",
"bootstrap3-typeahead": "~3.0.3",
"perfect-scrollbar": "~0.5.8",
- "file-saver": "*",
- "Blob": "*"
+ "file-saver": "https://github.com/eligrey/FileSaver.js.git#eb8d76f845ef6ad1e39a840c29bb852098c6a401",
+ "Blob": "https://github.com/eligrey/Blob.js.git#079824b6c118fbcd0b99c561d57ad192d2c6619b",
+ "d3": "~3.5.17",
+ "jsdifflib": "https://github.com/cemerick/jsdifflib.git#ce74529f9d51943db440dbd7c15d515597cda2e1"
},
"overrides": {
"jquery": {
@@ -41,6 +43,13 @@
},
"Blob": {
"main": "Blob.js"
+ },
+ "jsdifflib": {
+ "main": [
+ "difflib.js",
+ "diffview.js",
+ "diffview.css"
+ ]
}
}
}
[2/2] ambari git commit: AMBARI-18313. Capacity Scheduler View: Xml
diff view tool to show changes made and queue capacity chart (Akhil PB via
pallavkul)
Posted by pa...@apache.org.
AMBARI-18313. Capacity Scheduler View: Xml diff view tool to show changes made and queue capacity chart (Akhil PB via pallavkul)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/62dc775e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/62dc775e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/62dc775e
Branch: refs/heads/trunk
Commit: 62dc775ee4156e1a43ce0b991f3f47f68155128d
Parents: 26660f2
Author: Pallav Kulshreshtha <pa...@gmail.com>
Authored: Wed Oct 5 15:32:19 2016 +0530
Committer: Pallav Kulshreshtha <pa...@gmail.com>
Committed: Wed Oct 5 15:32:19 2016 +0530
----------------------------------------------------------------------
.../src/main/resources/ui/app/components.js | 2 +
.../ui/app/components/labelCapacityBar.js | 12 +-
.../resources/ui/app/components/queueBadge.js | 6 +-
.../ui/app/components/queueHierarchy.js | 11 +
.../resources/ui/app/components/queueMapping.js | 25 +-
.../resources/ui/app/components/queueSummary.js | 23 +-
.../ui/app/components/sunburstChart.js | 339 +++++++++++++++++++
.../ui/app/components/xmldiffViewer.js | 101 ++++++
.../resources/ui/app/controllers/advanced.js | 21 +-
.../resources/ui/app/controllers/capsched.js | 39 ++-
.../resources/ui/app/controllers/editqueue.js | 66 +++-
.../resources/ui/app/controllers/queuesconf.js | 106 +++++-
.../resources/ui/app/controllers/scheduler.js | 21 +-
.../src/main/resources/ui/app/models/queue.js | 9 +-
.../src/main/resources/ui/app/router.js | 49 ++-
.../resources/ui/app/styles/application.less | 59 ++++
.../src/main/resources/ui/app/templates.js | 2 +
.../resources/ui/app/templates/capsched.hbs | 6 +
.../ui/app/templates/capsched/advanced.hbs | 13 +-
.../capsched/partials/accessControlList.hbs | 4 +-
.../capsched/partials/labelCapacity.hbs | 4 +-
.../templates/capsched/partials/preemption.hbs | 4 +-
.../capsched/partials/queueCapacity.hbs | 34 +-
.../capsched/partials/queueResources.hbs | 4 +-
.../ui/app/templates/capsched/queuesconf.hbs | 15 +-
.../ui/app/templates/capsched/scheduler.hbs | 6 +-
.../app/templates/components/queueHierarchy.hbs | 8 +-
.../app/templates/components/queueMapping.hbs | 14 +-
.../app/templates/components/queueSummary.hbs | 13 -
.../app/templates/components/sunburstChart.hbs | 44 +++
.../app/templates/components/xmldiffViewer.hbs | 41 +++
.../src/main/resources/ui/bower.json | 13 +-
32 files changed, 1003 insertions(+), 111 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.js
index 8dd7108..8cf9a64 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.js
@@ -39,3 +39,5 @@ require('components/editLabelCapacity');
require('components/editQueueCapacity');
require('components/labelCapacityBar');
require('components/displayNodeLabels');
+require('components/xmldiffViewer');
+require('components/sunburstChart');
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/labelCapacityBar.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/labelCapacityBar.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/labelCapacityBar.js
index 7776452..032b2ec 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/labelCapacityBar.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/labelCapacityBar.js
@@ -49,10 +49,14 @@ App.LabelCapacityBarComponent = Ember.Component.extend({
warnInvalidLabelCapacity: function() {
var totalCap = this.get('childrenQueueLabelsTotalCapacity');
- var isInvalid = false;
- if (totalCap > 100 || totalCap < 100) {
- isInvalid = true;
- }
+ var isInvalid = totalCap !== 100;
+ this.get('labels').forEach(function(label) {
+ if (isInvalid) {
+ label.set('overCapMessage', 'Invalid Total Capacity for label: '+label.get('name'));
+ } else {
+ label.set('overCapMessage', undefined);
+ }
+ });
this.get('labels').setEach('overCapacity', isInvalid);
this.set('warnInvalidTotalLabelCapacity', isInvalid);
return isInvalid;
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueBadge.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueBadge.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueBadge.js
index f8978c2..0403b3d 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueBadge.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueBadge.js
@@ -34,11 +34,13 @@ App.WarningInfoComponent = Em.Component.extend({
layout:Em.Handlebars.compile('<i class="fa fa-fw fa-lg fa-warning"></i>'),
tagName:'span',
tooltip:'Warning',
+ placement:'bottom',
initTooltip: function(){
- var tipMsg = this.get('tooltip');
+ var tipMsg = this.get('tooltip'),
+ postion = this.get('placement');
this.$().tooltip({
title:tipMsg,
- placement:'bottom'
+ placement:postion
});
}.on('didInsertElement'),
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueHierarchy.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueHierarchy.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueHierarchy.js
index 64a28343..674c9c7 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueHierarchy.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueHierarchy.js
@@ -29,6 +29,17 @@
.filterBy('parentPath', this.get('parent'));
}.property('depth', 'parent', 'queues.length', 'queues.@each.name'),
+ cildrenQueues: function() {
+ var leafQs = this.get('leafQs'),
+ deltedQs = this.get('deletedQs');
+
+ var deletedAtDepth = deltedQs
+ .filterBy('depth', this.get('depth'))
+ .filterBy('parentPath', this.get('parent'));
+
+ return leafQs.pushObjects(deletedAtDepth);
+ }.property('leafQs.length', 'deletedQs.[]'),
+
childDepth: function () {
return this.get('leafQs.firstObject.depth') + 1;
}.property('depth'),
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueMapping.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueMapping.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueMapping.js
index 107b377..1d07351 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueMapping.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueMapping.js
@@ -34,6 +34,7 @@
selectedLeafQueueNameForUsers: null,
selectedLeafQueueNameForGroups: null,
isQueueMappingsDirty: false,
+ scheduler: null,
actions: {
showMappingOptions: function(){
@@ -51,6 +52,13 @@
},
toggleMappingOverride: function() {
this.toggleProperty('mappingsOverrideEnable');
+ },
+ rollbackProp: function(prop, item) {
+ if (prop === "queue_mappings") {
+ var oldMappings = (item.changedAttributes()[prop][0])? item.changedAttributes()[prop][0].split(',') : [];
+ this.set('queueMappings', oldMappings);
+ }
+ this.sendAction("rollbackProp", prop, item);
}
},
@@ -103,9 +111,10 @@
addCustomQueueMappings: function(csValues, selectedLeafQName){
var that = this;
- csValues = csValues.trim() || '',
- userOrGroupNames = csValues.split(',') || [],
- mappingPattern = this.get('selectedMapping');
+ csValues = csValues.trim() || '',
+ userOrGroupNames = csValues.split(',') || [],
+ mappingPattern = this.get('selectedMapping');
+
userOrGroupNames.forEach(function(ugname){
that.get('queueMappings').pushObject(mappingPattern.replace('%name', ugname).replace('%qname', selectedLeafQName));
});
@@ -143,5 +152,13 @@
destroyEventListeners: function() {
this.$('#collapseQueueMappingsBtn').off('click');
- }.on('willDestroyElement')
+ }.on('willDestroyElement'),
+
+ isMappingsDirty: function() {
+ return this.get('scheduler').changedAttributes().hasOwnProperty('queue_mappings');
+ }.property('scheduler.queue_mappings'),
+
+ isOverrideEnableDirty: function() {
+ return this.get('scheduler').changedAttributes().hasOwnProperty('queue_mappings_override_enable');
+ }.property('scheduler.queue_mappings_override_enable')
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueSummary.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueSummary.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueSummary.js
index 2690c40..8923e8e 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueSummary.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueSummary.js
@@ -31,7 +31,7 @@
isQueueStateNeedRefresh: function() {
var qsNeedRefresh = this.get('queuesNeedRefresh'),
- qq = this.get('queue');
+ qq = this.get('queue');
if (qsNeedRefresh && qsNeedRefresh.findBy('path', qq.get('path'))) {
return true;
@@ -44,7 +44,7 @@
isQueueCapacityNeedRefresh: function() {
var qsNeedRefresh = this.get('queuesNeedRefresh'),
- qq = this.get('queue');
+ qq = this.get('queue');
if (qsNeedRefresh && qsNeedRefresh.findBy('path', qq.get('path'))) {
return true;
@@ -89,22 +89,5 @@
isNewQueue: function() {
return this.get('queue.isNewQueue');
- }.property('queue.isNewQueue'),
-
- effectiveCapacity: function() {
- var currentQ = this.get('queue'),
- allQueues = this.get('allQueues'),
- effectiveCapacityRatio = 1;
-
- while (currentQ !== null) {
- effectiveCapacityRatio *= (currentQ.get('capacity') / 100);
- currentQ = allQueues.findBy('id', currentQ.get('parentPath').toLowerCase()) || null;
- }
-
- var effectiveCapacityPercent = effectiveCapacityRatio * 100,
- absoluteCapacity = parseFloat(parseFloat(effectiveCapacityPercent).toFixed(this.get('precision')));
- this.get('queue').set('absolute_capacity', absoluteCapacity || 0);
-
- return absoluteCapacity;
- }.property('queue.capacity', 'allQueues.@each.capacity', 'allQueues.length')
+ }.property('queue.isNewQueue')
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/sunburstChart.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/sunburstChart.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/sunburstChart.js
new file mode 100644
index 0000000..d5b19ae
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/sunburstChart.js
@@ -0,0 +1,339 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+function _getSunburstChartDataForDefault(queue, json, allQueues) {
+ var childrenQs = allQueues.filterBy('parentPath', queue.get('path')),
+ qdata = {
+ "name": queue.get('name'),
+ "path": queue.get('path'),
+ "capacity": queue.get('capacity'),
+ "absoluteCapacity": queue.get('absolute_capacity')||0,
+ "size": queue.get('capacity'),
+ "isLabel": false
+ };
+
+ if (!Ember.isEmpty(childrenQs)) {
+ qdata["children"] = [];
+ }
+
+ if (json["children"]) {
+ json["children"].push(qdata);
+ }
+
+ childrenQs.forEach(function(child) {
+ return _getSunburstChartDataForDefault(child, qdata, allQueues);
+ });
+ return json;
+}
+
+function _getSunburstChartDataForLabel(queue, json, allQueues, labelName) {
+ var childrenQs = allQueues.filterBy('parentPath', queue.get('path')),
+ qLabel = queue.get('labels').findBy('name', labelName),
+ qdata = {
+ "name": queue.get('name'),
+ "path": queue.get('path'),
+ "capacity": qLabel?qLabel.get('capacity') : 0,
+ "absoluteCapacity": 0,
+ "size": qLabel? qLabel.get('capacity') : 0,
+ "isLabel": true
+ };
+
+ if (!Ember.isEmpty(childrenQs)) {
+ qdata["children"] = [];
+ }
+
+ if (json["children"]) {
+ json["children"].push(qdata);
+ }
+
+ childrenQs.forEach(function(child) {
+ return _getSunburstChartDataForLabel(child, qdata, allQueues, labelName);
+ });
+ return json;
+}
+
+App.SunburstChartComponent = Ember.Component.extend({
+ layoutName: 'components/sunburstChart',
+ queues: null,
+ selectedQueue: null,
+ allNodeLabels: null,
+
+ width: 0,
+ height: 0,
+ radius: 0,
+ data: null,
+ colorScale: null,
+ chartRendered: false,
+ queueCapacityTypeSelected: null,
+
+ queueCapacityTypeValues: null,
+
+ didInsertElement: function() {
+ this.initializeChart();
+ this.initializeCapacityTypeOptions();
+ this.set("queueCapacityTypeSelected", null);
+ this.setChartDataForDefault();
+ this.renderChart();
+ },
+
+ initializeChart: function() {
+ var width = this.$().width();
+ this.$('.panel-default').height(width);
+ var height = this.$('.panel-default').height() - this.$('#top_container').outerHeight();
+
+ var vizWidth = width - 60;
+ var vizHeight = height - 80;
+ var radius = Math.min(vizWidth, vizHeight) / 2;
+
+ this.set('width', vizWidth);
+ this.set('height', vizHeight);
+ this.set('radius', radius);
+ this.set('colorScale', d3.scale.category20());
+ },
+
+ initializeCapacityTypeOptions: function() {
+ var options = [{
+ name: "Default",
+ value: null
+ }];
+ if (this.get('allNodeLabels') !== null) {
+ this.get('allNodeLabels').forEach(function(label) {
+ options.push({
+ name: "Label: " + label.name,
+ value: label.name
+ });
+ });
+ }
+ this.set("queueCapacityTypeValues", options);
+ },
+
+ setChartDataForDefault: function() {
+ var queues = this.get('queues'),
+ rootQ = queues.findBy('name', 'root'),
+ dataJson = {
+ "name": "sunburst",
+ "children": []
+ };
+
+ var data = _getSunburstChartDataForDefault(rootQ, dataJson, queues);
+ this.set("data", data);
+ },
+
+ setChartDataForLabel: function() {
+ var queues = this.get('queues'),
+ allNodeLabels = this.get('allNodeLabels'),
+ rootQ = queues.findBy('name', 'root'),
+ labelName = this.get('queueCapacityTypeSelected');
+
+ var dataJson = {
+ "name": "sunburst",
+ "children": []
+ };
+ var data = _getSunburstChartDataForLabel(rootQ, dataJson, queues, labelName);
+ this.set("data", data);
+ },
+
+ renderChart: function() {
+ var self = this,
+ width = this.get('width'),
+ height = this.get('height'),
+ radius = this.get('radius'),
+ data = this.get('data'),
+ colors = this.get('colorScale');
+
+ var vis = d3.select("#sunburst_chart").append("svg:svg")
+ .attr("width", width)
+ .attr("height", height)
+ .append("svg:g")
+ .attr("id", "sunburst_container")
+ .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
+
+ var partition = d3.layout.partition()
+ .size([2 * Math.PI, radius * radius])
+ .value(function(d) {
+ return d.size;
+ });
+
+ var arc = d3.svg.arc()
+ .startAngle(function(d) { return d.x; })
+ .endAngle(function(d) { return d.x + d.dx; })
+ .innerRadius(function(d) { return Math.sqrt(d.y); })
+ .outerRadius(function(d) { return Math.sqrt(d.y + d.dy); });
+
+ vis.append("svg:circle")
+ .attr("r", radius)
+ .style("opacity", 0);
+
+ var nodes = partition.nodes(data)
+ .filter(function(d) {
+ return (d.dx > 0.005);
+ });
+
+ var path = vis.data([data]).selectAll("path")
+ .data(nodes)
+ .enter().append("svg:path")
+ .attr("id", function(d) { return d.path; })
+ .attr("data-node", function(d) {
+ var node = {
+ name: d.name,
+ path: d.path,
+ capacity: d.capacity,
+ absoluteCapacity: d.absoluteCapacity,
+ isLabel: d.isLabel
+ };
+ return JSON.stringify(node);
+ })
+ .attr("display", function(d) { return d.depth ? null : "none"; })
+ .attr("d", arc)
+ .attr("fill-rule", "evenodd")
+ .style("fill", function(d) {
+ var colr = colors(d.name);
+ d.color = colr;
+ return colr;
+ })
+ .style("opacity", 1);
+
+ this.set('chartRendered', true);
+ this.adjustPositions();
+ },
+
+ mouseover: function(d, elem) {
+ this.showQueueInfo(d);
+ d3.selectAll("path").style("opacity", 0.3);
+ d3.select(elem).style("opacity", 1);
+ },
+
+ showQueueInfo: function(node) {
+ var precentage = node.isLabel? node.capacity : node.absoluteCapacity;
+ var percentageString = precentage + "%";
+ d3.select("#capacityPercentage").text(percentageString);
+ d3.select("#queuePath").text(node.path);
+ if (node.isLabel) {
+ d3.select("#type_text").text("Capacity:");
+ } else {
+ d3.select("#type_text").text("Abs Cap:");
+ }
+ d3.select("#explanation").style("visibility", "");
+ d3.select("#queue_info").style("visibility", "");
+ },
+
+ hideQueueInfo: function() {
+ d3.select("#queuePath").text("");
+ d3.select("#type_text").text("");
+ d3.select("#capacityPercentage").text("");
+ d3.select("#explanation").style("visibility", "hidden");
+ d3.select("#queue_info").style("visibility", "hidden");
+ },
+
+ mouseleave: function(d) {
+ d3.selectAll("path").style("opacity", 1);
+ d3.select("#explanation").style("visibility", "hidden");
+ d3.select("#queue_info").style("visibility", "hidden");
+ var queue = this.get("selectedQueue");
+ if (queue) {
+ var node = this.$("path[id='"+queue.get('path')+"']").data('node');
+ this.showQueueInfo({
+ name: node.name,
+ path: node.path,
+ capacity: node.capacity,
+ absoluteCapacity: node.absoluteCapacity,
+ isLabel: node.isLabel
+ });
+ }
+ },
+
+ hightlightSelectedQueue: function() {
+ this.removeHighlightFromChart();
+ var width = this.get('width'),
+ height = this.get('height'),
+ queue = this.get("selectedQueue");
+ if (queue) {
+ d3.selectAll("path").style("opacity", 0.3);
+ d3.select("path[id='"+queue.get('path')+"']")
+ .style("fill", "#3276b1")
+ .style("opacity", 1);
+ var node = this.$("path[id='"+queue.get('path')+"']").data('node');
+ this.showQueueInfo({
+ name: node.name,
+ path: node.path,
+ capacity: node.capacity,
+ absoluteCapacity: node.absoluteCapacity,
+ isLabel: node.isLabel
+ });
+ }
+ },
+
+ removeHighlightFromChart: function() {
+ d3.selectAll("path").style("opacity", 1);
+ d3.selectAll("path").each(function(node) {
+ if (node.path) {
+ d3.select("path[id='"+node.path+"']")
+ .style("fill", node.color);
+ }
+ });
+ this.hideQueueInfo();
+ },
+
+ adjustPositions: function() {
+ var rootOffset = this.$("path[id='root']").offset(),
+ rootPathDims = this.$("path[id='root']")[0].getBoundingClientRect(),
+ rootW = rootPathDims.width,
+ rootH = rootPathDims.height,
+ explanationH = this.$("#explanation").height(),
+ explanationW = this.$("#explanation").width();
+
+ var rootCenterX = rootOffset.left + rootW / 2,
+ rootCenterY = rootOffset.top + rootH / 2,
+ posX = rootCenterX - explanationW / 2,
+ posY = rootCenterY - explanationH / 2;
+
+ this.$("#explanation").offset({left: posX, top: posY});
+ },
+
+ renderObserver: function() {
+ d3.select("#sunburst_chart svg").remove();
+ this.set('chartRendered', false);
+ this.set("queueCapacityTypeSelected", null);
+ this.setChartDataForDefault();
+ this.renderChart();
+ this.hightlightSelectedQueue();
+ }.observes('queues', 'queues.[]', 'queues.@each.capacity'),
+
+ queueSelectionObserver: function() {
+ if (this.get('selectedQueue') && this.get('chartRendered')) {
+ this.hightlightSelectedQueue();
+ } else {
+ this.removeHighlightFromChart();
+ }
+ }.observes('selectedQueue', 'chartRendered'),
+
+ watchTypeSelection: function() {
+ d3.select("#sunburst_chart svg").remove();
+ this.set('chartRendered', false);
+ if (this.get("queueCapacityTypeSelected") !== null) {
+ this.setChartDataForLabel();
+ } else {
+ this.setChartDataForDefault();
+ }
+ this.renderChart();
+ this.hightlightSelectedQueue();
+ }.observes("queueCapacityTypeSelected")
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/xmldiffViewer.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/xmldiffViewer.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/xmldiffViewer.js
new file mode 100644
index 0000000..62431f6
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/xmldiffViewer.js
@@ -0,0 +1,101 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+
+App.XmldiffViewerComponent = Ember.Component.extend({
+ layoutName: 'components/xmldiffViewer',
+ diffConfig: null,
+ viewConfig: null,
+
+ actions: {
+ closeDiffViewer: function() {
+ this.set('diffConfig', null);
+ this.set('viewConfig', null);
+ }
+ },
+
+ diffViewObserver: function() {
+ if (this.get('diffConfig')) {
+ this.showXmlDiffView();
+ }
+ }.observes('diffConfig'),
+
+ viewConfigObserver: function() {
+ if (this.get('viewConfig')) {
+ this.showCapSchedViewXml();
+ }
+ }.observes('viewConfig'),
+
+ showXmlDiffView: function() {
+ this.$("#xmldiffViewerDialog").modal('show');
+ var config = this.get('diffConfig'),
+ basetxt = difflib.stringAsLines(config.baseXML);
+ newtxt = difflib.stringAsLines(config.newXML),
+ sm = new difflib.SequenceMatcher(basetxt, newtxt),
+ opcodes = sm.get_opcodes(),
+ $diffOutput = this.$('#xmldiffOutput');
+
+ this.showHideOutputContainers('diffView');
+ this.setDialogDimentions();
+
+ $diffOutput.append(diffview.buildView({
+ baseTextLines: basetxt,
+ newTextLines: newtxt,
+ opcodes: opcodes,
+ baseTextName: 'Base XML',
+ newTextName: 'New XML',
+ contextSize: 2,
+ viewType: 0
+ }));
+ },
+
+ showCapSchedViewXml: function() {
+ this.$("#xmldiffViewerDialog").modal('show');
+ var config = this.get('viewConfig'),
+ $output = this.$('#capshedViewXml');
+
+ this.showHideOutputContainers('xmlView');
+ this.setDialogDimentions(true);
+ $output.text(config.xmlConfig);
+ },
+
+ showHideOutputContainers: function(viewType) {
+ this.$('#xmldiffOutput').empty().hide();
+ this.$('#capshedViewXml').empty().hide();
+ if (viewType === 'diffView') {
+ this.$('#xmldiffOutput').show();
+ } else {
+ this.$('#capshedViewXml').show();
+ }
+ },
+
+ setDialogDimentions: function(hideOverflow) {
+ var dialogHt = this.$("#xmldiffViewerDialog").height(),
+ contentHt = dialogHt-60,
+ bodyHt = contentHt-170;
+
+ this.$("#xmldiffViewerDialog").find('.modal-content').height(contentHt);
+ this.$("#xmldiffViewerDialog").find('.modal-body').height(bodyHt);
+ if (hideOverflow) {
+ this.$("#xmldiffViewerDialog").find('.modal-body').css('overflow', 'hidden');
+ } else {
+ this.$("#xmldiffViewerDialog").find('.modal-body').css('overflow', 'auto');
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/advanced.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/advanced.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/advanced.js
index c079079..af15fa5 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/advanced.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/advanced.js
@@ -25,6 +25,7 @@ App.CapschedAdvancedController = Ember.Controller.extend({
actions: {
rollbackQueueMappingProps: function() {
+ var tempRefreshNeeded = this.get('isRefreshOrRestartNeeded');
var sched = this.get('scheduler'),
attributes = sched.changedAttributes(),
props = this.queueMappingProps;
@@ -33,6 +34,16 @@ App.CapschedAdvancedController = Ember.Controller.extend({
sched.set(prop, attributes[prop][0]);
}
});
+ this.set('isRefreshOrRestartNeeded', tempRefreshNeeded);
+ },
+ rollbackProp: function(prop, item) {
+ var tempRefreshNeeded = this.get('isRefreshOrRestartNeeded');
+ var attributes = item.changedAttributes();
+ if (attributes.hasOwnProperty(prop)) {
+ item.set(prop, attributes[prop][0]);
+ }
+ this.set('isRefreshOrRestartNeeded', tempRefreshNeeded);
+ this.afterRollbackProp();
},
showSaveConfigDialog: function(mode) {
if (mode) {
@@ -76,5 +87,13 @@ App.CapschedAdvancedController = Ember.Controller.extend({
forceRefreshRequired: function() {
return !this.get('isQueueMappingsDirty') && this.get('isRefreshOrRestartNeeded');
- }.property('isQueueMappingsDirty', 'isRefreshOrRestartNeeded')
+ }.property('isQueueMappingsDirty', 'isRefreshOrRestartNeeded'),
+
+ afterRollbackProp: function() {
+ if (this.get('isQueueMappingsDirty')) {
+ this.set('isRefreshOrRestartNeeded', true);
+ } else {
+ this.set('isRefreshOrRestartNeeded', false);
+ }
+ }
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/capsched.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/capsched.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/capsched.js
index 447cae0..631edbb 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/capsched.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/capsched.js
@@ -19,6 +19,11 @@
var App = require('app');
App.CapschedController = Ember.Controller.extend({
+ queues: null,
+ precision: 2,
+ selectedQueue: null,
+ allNodeLabels: Ember.computed.alias('store.nodeLabels.content'),
+
actions: {
loadTagged: function (tag) {
this.transitionToRoute('capsched.scheduler').then(function() {
@@ -27,7 +32,7 @@ App.CapschedController = Ember.Controller.extend({
},
clearAlert: function () {
this.set('alertMessage',null);
- },
+ }
},
/**
@@ -42,6 +47,26 @@ App.CapschedController = Ember.Controller.extend({
*/
isNotOperator: Ember.computed.not('isOperator'),
+ queuesWatcher: function() {
+ var allQueues = this.get('queues') || [];
+ allQueues.forEach(function(queue) {
+ var absCap = this.getAbsoluteCapacityForQueue(queue);
+ queue.set('absolute_capacity', absCap);
+ }.bind(this));
+ }.observes('queues', 'queues.[]', 'queues.@each.capacity').on('init'),
+
+ getAbsoluteCapacityForQueue: function(queue) {
+ var allQueues = this.get('queues');
+ var effectCapRatio = 1;
+ while (queue !== null) {
+ effectCapRatio *= queue.get('capacity') / 100;
+ queue = allQueues.findBy('id', queue.get('parentPath').toLowerCase()) || null;
+ }
+ var effectCapPercent = effectCapRatio * 100,
+ absoluteCap = parseFloat(parseFloat(effectCapPercent).toFixed(this.get('precision')));;
+ return absoluteCap;
+ },
+
alertMessage: null,
tags: function () {
@@ -60,5 +85,17 @@ App.CapschedController = Ember.Controller.extend({
stopSpinner: function() {
this.set('showSpinner', false);
+ },
+
+ diffXmlConfig: null,
+
+ viewConfigXmlDiff: function(config) {
+ this.set('diffXmlConfig', config);
+ },
+
+ viewXmlConfig: null,
+
+ viewCapSchedXml: function(config) {
+ this.set('viewXmlConfig', config);
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/editqueue.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/editqueue.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/editqueue.js
index 7c62ef0..9d84704 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/editqueue.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/editqueue.js
@@ -66,16 +66,19 @@ App.CapschedQueuesconfEditqueueController = Ember.Controller.extend({
editQueueName: function() {
this.set('enableEditQName', true);
this.set('updatedQName', this.get('content.name'));
+ this.set('controllers.capschedQueuesconf.isEditingQueueName', true);
},
cancelQNameEdit: function() {
this.set('enableEditQName', false);
this.set('isInvalidQName', false);
this.set('invalidQNameMessage', '');
+ this.set('controllers.capschedQueuesconf.isEditingQueueName', false);
},
renameQueue: function() {
if (this.validateQName()) {
return;
}
+ this.set('controllers.capschedQueuesconf.isEditingQueueName', false);
this.set('content.name', this.get('updatedQName'));
this.set('enableEditQName', false);
},
@@ -83,6 +86,24 @@ App.CapschedQueuesconfEditqueueController = Ember.Controller.extend({
this.send('rollbackProp', 'disable_preemption', this.get('content'));
this.send('rollbackProp', 'isPreemptionInherited', this.get('content'));
this.set('content.isPreemptionOverriden', false);
+ },
+ rollbackProp: function(prop, item) {
+ var tempRefreshNeeded = this.get('isRefreshOrRestartNeeded');
+ var attributes = item.changedAttributes();
+ if (attributes.hasOwnProperty(prop)) {
+ item.set(prop, attributes[prop][0]);
+ }
+ this.set('isRefreshOrRestartNeeded', tempRefreshNeeded);
+ this.afterRollbackProp();
+ }
+ },
+
+ afterRollbackProp: function() {
+ var isAnyQDirty = this.get('allQueues').isAny('isAnyDirty', true);
+ if (isAnyQDirty) {
+ this.set('isRefreshOrRestartNeeded', true);
+ } else {
+ this.set('isRefreshOrRestartNeeded', false);
}
},
@@ -114,6 +135,15 @@ App.CapschedQueuesconfEditqueueController = Ember.Controller.extend({
this.validateQName();
}.observes('updatedQName', 'updatedQName.length'),
+ absoluteClusterCapacity: function() {
+ return this.get('content.absolute_capacity');
+ }.property('content', 'content.absolute_capacity'),
+
+ absoluteClusterBarWidth: function() {
+ var absCap = this.get('absoluteClusterCapacity');
+ return this.get('widthPattern').fmt(absCap);
+ }.property('absoluteClusterCapacity'),
+
/**
* Collection of modified fields in queue.
* @type {Object} - { [fileldName] : {Boolean} }
@@ -250,9 +280,10 @@ App.CapschedQueuesconfEditqueueController = Ember.Controller.extend({
},
isAnyQueueResourcesDirty: function() {
- return this.get('queueDirtyFields.user_limit_factor') || this.get('queueDirtyFields.minimum_user_limit_percent')
- || this.get('queueDirtyFields.maximum_applications') || this.get('queueDirtyFields.maximum_am_resource_percent')
- || this.get('queueDirtyFields.ordering_policy') || this.get('queueDirtyFields.enable_size_based_weight');
+ var changedAttrs = this.get('content').changedAttributes();
+ return changedAttrs.hasOwnProperty('user_limit_factor') || changedAttrs.hasOwnProperty('minimum_user_limit_percent')
+ || changedAttrs.hasOwnProperty('maximum_applications') || changedAttrs.hasOwnProperty('maximum_am_resource_percent')
+ || changedAttrs.hasOwnProperty('ordering_policy') || changedAttrs.hasOwnProperty('enable_size_based_weight');
}.property(
'content.user_limit_factor',
'content.minimum_user_limit_percent',
@@ -382,7 +413,8 @@ App.CapschedQueuesconfEditqueueController = Ember.Controller.extend({
},
isAnyAccessControlListDirty: function() {
- return this.get('queueDirtyFields.acl_administer_queue') || this.get('queueDirtyFields.acl_submit_applications');
+ var chagedAttrs = this.get('content').changedAttributes();
+ return chagedAttrs.hasOwnProperty('acl_administer_queue') || chagedAttrs.hasOwnProperty('acl_submit_applications');
}.property('content.acl_submit_applications', 'content.acl_administer_queue'),
/**
@@ -443,8 +475,9 @@ App.CapschedQueuesconfEditqueueController = Ember.Controller.extend({
if (this.get('isLeafQ')) {
return false;
}
- return this.get('queueDirtyFields.queues') || this.get('childrenQueues').anyBy('isDirtyCapacity', true) || this.get('childrenQueues').anyBy('isDirtyMaxCapacity', true);
- }.property('content', 'content.queues', 'childrenQueues.@each.isDirtyCapacity', 'childrenQueues.@each.isDirtyMaxCapacity'),
+ return this.get('queueDirtyFields.queues') || this.get('childrenQueues').anyBy('isDirtyCapacity', true)
+ || this.get('childrenQueues').anyBy('isDirtyMaxCapacity', true) || this.get('warnInvalidCapacity');
+ }.property('content', 'content.queues', 'childrenQueues.@each.isDirtyCapacity', 'childrenQueues.@each.isDirtyMaxCapacity', 'warnInvalidCapacity'),
/**
* Adds observers for each queue attribute.
@@ -598,12 +631,14 @@ App.CapschedQueuesconfEditqueueController = Ember.Controller.extend({
warnInvalidTotalLabelCapacity: false,
isAnyChildrenQueueLabelDirty: function() {
- if (this.get('isLeafQ')) {
- return this.get('queueDirtyFields.default_node_label_expression') || false;
+ var changedAttrs = this.get('content').changedAttributes();
+ if (this.get('content.queues') === null) {
+ return changedAttrs.hasOwnProperty('default_node_label_expression');
}
- return this.get('childrenQueues').anyBy('isLabelsDirty', true) || this.get('queueDirtyFields.default_node_label_expression')
- || this.get('childrenLabelsForQueue').anyBy('isDirtyLabelCapacity', true) || this.get('childrenLabelsForQueue').anyBy('isDirtyLabelMaxCapacity', true);
- }.property('content', 'childrenQueues.@each.isLabelsDirty', 'childrenLabelsForQueue.@each.isDirtyLabelCapacity', 'childrenLabelsForQueue.@each.isDirtyLabelMaxCapacity', 'content.default_node_label_expression'),
+ return this.get('childrenQueues').anyBy('isLabelsDirty', true) || changedAttrs.hasOwnProperty('default_node_label_expression')
+ || this.get('childrenLabelsForQueue').anyBy('isDirtyLabelCapacity', true) || this.get('childrenLabelsForQueue').anyBy('isDirtyLabelMaxCapacity', true)
+ || this.get('warnInvalidTotalLabelCapacity');
+ }.property('content', 'childrenQueues.@each.isLabelsDirty', 'childrenLabelsForQueue.@each.isDirtyLabelCapacity', 'childrenLabelsForQueue.@each.isDirtyLabelMaxCapacity', 'content.default_node_label_expression', 'warnInvalidTotalLabelCapacity'),
//Preemption
isPreemptionSupported: Ember.computed.alias('store.isPreemptionSupported'),
@@ -644,7 +679,7 @@ App.CapschedQueuesconfEditqueueController = Ember.Controller.extend({
},
isQueuePreemptionDirty: function() {
- return this.get('queueDirtyFields.disable_preemption');
+ return this.get('content').changedAttributes().hasOwnProperty('disable_preemption');
}.property('content.disable_preemption', 'content.isPreemptionInherited'),
doOverridePreemption: function(key, value) {
@@ -667,10 +702,5 @@ App.CapschedQueuesconfEditqueueController = Ember.Controller.extend({
this.set('content.isPreemptionInherited', true);
this.set('content.disable_preemption', '');
}
- }.observes('content.isPreemptionOverriden'),
-
- saveRefreshRestartWatcher: function() {
- this.set('isRefreshOrRestartNeeded', this.get('isAnyQueueResourcesDirty') || this.get('isAnyAccessControlListDirty')
- || this.get('isAnyChildrenQueueCapacityDirty') || this.get('isAnyChildrenQueueLabelDirty') || this.get('isQueuePreemptionDirty'));
- }.observes('isAnyQueueResourcesDirty', 'isAnyAccessControlListDirty', 'isAnyChildrenQueueCapacityDirty', 'isAnyChildrenQueueLabelDirty', 'isQueuePreemptionDirty')
+ }.observes('content.isPreemptionOverriden')
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queuesconf.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queuesconf.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queuesconf.js
index 6a6717a..e7fba41 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queuesconf.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queuesconf.js
@@ -32,16 +32,19 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
allNodeLabelRecords: [],
queuesNeedRefresh: Ember.computed.alias('store.queuesNeedRefresh'),
isRefreshOrRestartNeeded: false,
+ deletedQueues: Ember.computed.alias('store.deletedQueues'),
actions: {
addNewQueue: function() {
this.set('newQueueName', '');
this.set('showQueueNameInput', true);
+ this.set('isCreatingNewQueue', true);
},
createNewQueue: function() {
if (this.validateQueueName()) {
return;
}
+ this.set('isCreatingNewQueue', false);
var store = this.get('store'),
queueName = this.get('newQueueName'),
parentPath = this.get('selectedQueue.path'),
@@ -61,6 +64,7 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
freeLeafCapacity = (totalLeafCapacity < 100) ? 100 - totalLeafCapacity : 0;
}
var qCapacity = (newInLeaf) ? 100 : freeLeafCapacity;
+ var requireRestart = (this.get('selectedQueue.isLeafQ') && !this.get('selectedQueue.isNewQueue'))? true : false;
newQueue = store.createRecord('queue', {
id: queuePath.toLowerCase(),
name: queueName,
@@ -69,7 +73,8 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
depth: depth,
isNewQueue: true,
capacity: qCapacity,
- maximum_capacity: 100
+ maximum_capacity: 100,
+ requireRestart: requireRestart
});
this.set('newQueue', newQueue);
store.saveAndUpdateQueue(newQueue).then(Em.run.bind(this, 'saveAndUpdateQueueSuccess', newQueue));
@@ -86,8 +91,11 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
this.set('showQueueNameInput', false);
this.set('isInvalidQueueName', false);
this.set('invalidQueueNameMessage', '');
+ this.set('isCreatingNewQueue', false);
},
discardQueuesChanges: function() {
+ var tempRefreshNeeded = this.get('isRefreshOrRestartNeeded');
+ var tempRestart = this.get('isQueuesMustNeedRestart');
var allQueues = this.get('queues');
allQueues.forEach(function(qq){
var qAttrs = qq.changedAttributes();
@@ -105,12 +113,13 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
}
}
});
- //Setting root label capacities back to 100,
- //if discard changes set root label capacity to 0.
+ //Setting root label capacities back to 100, if discard changes set root label capacity to 0.
if (qq.get('id') === 'root') {
qq.get('labels').setEach('capacity', 100);
}
});
+ this.set('isRefreshOrRestartNeeded', tempRefreshNeeded);
+ this.set('isQueuesMustNeedRestart', tempRestart);
},
stopQueue: function() {
this.set('selectedQueue.state', _stopState);
@@ -139,6 +148,17 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
},
showConfirmDialog: function() {
this.set('isConfirmDialogOpen', true);
+ },
+ saveCapSchedConfigs: function() {
+ if (this.get('saveMode') === '') {
+ var holder = {
+ refresh: this.get('isRefreshOrRestartNeeded')
+ };
+ this.set('tempRefreshHolder', holder);
+ } else {
+ this.set('tempRefreshHolder', null);
+ }
+ return true;
}
},
@@ -146,11 +166,48 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
return this.get('queues').isAny('isAnyDirty', true);
}.property('queues.@each.isAnyDirty'),
- isQueuesNeedRefreshOrRestart: Ember.computed.or('isAnyQueueDirty', 'needRefresh', 'needRestart', 'isRefreshOrRestartNeeded'),
+ isQueuesNeedRefreshOrRestart: function() {
+ var isNeed = this.get('isAnyQueueDirty') || this.get('needRefresh')
+ || this.get('queuesRequireRestart') || this.get('isRefreshOrRestartNeeded');
+ return isNeed;
+ }.property('isAnyQueueDirty', 'needRefresh', 'queuesRequireRestart', 'isRefreshOrRestartNeeded', 'canNotSave'),
+
+ isQueuesMustNeedRestart: false,
forceRefreshOrRestartRequired: function() {
- return !this.get('isAnyQueueDirty') && this.get('isRefreshOrRestartNeeded');
- }.property('isAnyQueueDirty', 'isRefreshOrRestartNeeded'),
+ return !this.get('isAnyQueueDirty') && (this.get('isRefreshOrRestartNeeded') || this.get('isQueuesMustNeedRestart'));
+ }.property('isAnyQueueDirty', 'isRefreshOrRestartNeeded', 'isQueuesMustNeedRestart'),
+
+ refreshRestartWatcher: function() {
+ if (this.get('tempRefreshHolder')) {
+ var holder = this.get('tempRefreshHolder');
+ this.set('isRefreshOrRestartNeeded', holder.refresh||false);
+ this.set('tempRefreshHolder', null);
+ }
+ }.observes('isRefreshOrRestartNeeded'),
+
+ isDirtyQueuesNeedRefreshQsOp: function() {
+ if (this.get('isAnyQueueDirty') || this.get('needRefresh') || this.get('isRefreshOrRestartNeeded')) {
+ if (this.get('queuesRequireRestart')) {
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }.property('isAnyQueueDirty', 'needRefresh', 'queuesRequireRestart', 'isRefreshOrRestartNeeded', 'canNotSave'),
+
+ isDirtyQueuesNeedRestartRmOp: function() {
+ if (this.get('queuesRequireRestart') || this.get('isQueuesMustNeedRestart')) {
+ return true;
+ } else {
+ return false;
+ }
+ }.property('isAnyQueueDirty', 'queuesRequireRestart', 'isQueuesMustNeedRestart', 'canNotSave'),
+
+ showNeedRefreshOrRestartWarning: function() {
+ return this.get('isQueuesNeedRefreshOrRestart') && !this.get('canNotSave');
+ }.property('isQueuesNeedRefreshOrRestart', 'canNotSave'),
selectedQueue: null,
newQueue: null,
@@ -159,6 +216,13 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
isInvalidQueueName: false,
invalidQueueNameMessage: '',
+ isCreatingNewQueue: false,
+ isEditingQueueName: false,
+
+ isCreaingOrRenamingQueue: function() {
+ return this.get('isCreatingNewQueue')||this.get('isEditingQueueName');
+ }.property('isCreatingNewQueue', 'isEditingQueueName'),
+
validateQueueName: function() {
var parentPath = this.get('selectedQueue.path'),
queueName = this.get('newQueueName'),
@@ -289,6 +353,34 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
}.bind(this));
}.observes('queues.length','queues.@each.capacity'),
+ newQueuesNeedRestart: function() {
+ return this.get('queues')
+ .filterBy('isNewQueue', true)
+ .filterBy('requireRestart', true);
+ }.property('queues.length', 'queues.@each.isNewQueue', 'queues.@each.requireRestart'),
+
+ hasNewQueuesNeedRestart: Ember.computed.notEmpty('newQueuesNeedRestart.[]'),
+
+ queuesRequireRestart: Ember.computed.or('needRestart', 'hasNewQueuesNeedRestart', 'isQueuesMustNeedRestart'),
+
+ disableRefreshBtn: function() {
+ var disable = this.get('canNotSave') || this.get('queuesRequireRestart');
+ return disable;
+ }.property('canNotSave', 'queuesRequireRestart', 'isAnyQueueDirty'),
+
+ restartWatcher: function() {
+ var restart = this.get('needRestart') || this.get('hasNewQueuesNeedRestart');
+ this.set('isQueuesMustNeedRestart', restart);
+ }.observes('needRestart', 'hasNewQueuesNeedRestart'),
+
+ dirtyQueueWatcher: function() {
+ if (this.get('isAnyQueueDirty')) {
+ this.set('isRefreshOrRestartNeeded', true);
+ } else {
+ this.set('isRefreshOrRestartNeeded', false);
+ }
+ }.observes('isAnyQueueDirty'),
+
/**
* True if newQueue is not empty.
* @type {Boolean}
@@ -347,7 +439,7 @@ App.CapschedQueuesconfController = Ember.Controller.extend({
* check if RM needs restart
* @type {bool}
*/
- needRestart: Em.computed.and('hasDeletedQueues', 'isOperator'),
+ needRestart: Ember.computed.and('hasDeletedQueues', 'isOperator'),
/**
* check there is some changes for save
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/scheduler.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/scheduler.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/scheduler.js
index 40e3e24..aa139b1 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/scheduler.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/scheduler.js
@@ -28,6 +28,7 @@ App.CapschedSchedulerController = Ember.Controller.extend({
actions: {
rollbackSchedulerProps: function() {
+ var tempRefreshNeeded = this.get('isRefreshOrRestartNeeded');
var sched = this.get('scheduler'),
attributes = sched.changedAttributes(),
props = this.schedulerProps;
@@ -36,6 +37,16 @@ App.CapschedSchedulerController = Ember.Controller.extend({
sched.set(prop, attributes[prop][0]);
}
});
+ this.set('isRefreshOrRestartNeeded', tempRefreshNeeded);
+ },
+ rollbackProp: function(prop, item) {
+ var tempRefreshNeeded = this.get('isRefreshOrRestartNeeded');
+ var attributes = item.changedAttributes();
+ if (attributes.hasOwnProperty(prop)) {
+ item.set(prop, attributes[prop][0]);
+ }
+ this.set('isRefreshOrRestartNeeded', tempRefreshNeeded);
+ this.afterRollbackProp();
},
showConfirmDialog: function() {
this.set('isConfirmDialogOpen', true);
@@ -102,5 +113,13 @@ App.CapschedSchedulerController = Ember.Controller.extend({
}, {
label: 'Dominant Resource Calculator',
value: 'org.apache.hadoop.yarn.util.resource.DominantResourceCalculator'
- }]
+ }],
+
+ afterRollbackProp: function() {
+ if (this.get('isSchedulerDirty')) {
+ this.set('isRefreshOrRestartNeeded', true);
+ } else {
+ this.set('isRefreshOrRestartNeeded', false);
+ }
+ }
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js
index 0f68a10..e2d67bd 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js
@@ -36,7 +36,6 @@ App.Label = DS.Model.extend({
isDefault: function () {
return this.get('queue.default_node_label_expression') === this.get('name');
}.property('queue.default_node_label_expression'),
- absoluteCapacity: 0,
setCapacity: function(cap) {
this.set('capacity', cap);
},
@@ -244,7 +243,7 @@ App.Queue = DS.Model.extend({
capacity: DS.attr('number', { defaultValue: 0 }),
maximum_capacity: DS.attr('number', { defaultValue: 0 }),
- //unfunded_capacity: DS.attr('number', { defaultValue: 0 }),
+ absolute_capacity: 0,
isDirtyCapacity: false,
isDirtyMaxCapacity: false,
@@ -320,5 +319,9 @@ App.Queue = DS.Model.extend({
if (Em.isEmpty(this.get('labels').findBy('name',this.get('default_node_label_expression')))) {
this.set('default_node_label_expression',null);
}
- }.observes('labels','default_node_label_expression')
+ }.observes('labels','default_node_label_expression'),
+
+ isLeafQ: function() {
+ return this.get('queues') === null;
+ }.property('queues')
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
index fd996ae..d838958 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
@@ -202,12 +202,6 @@ App.ErrorRoute = Ember.Route.extend({
App.CapschedRoute = Ember.Route.extend({
actions: {
- rollbackProp: function(prop, item) {
- var attributes = item.changedAttributes();
- if (attributes.hasOwnProperty(prop)) {
- item.set(prop, attributes[prop][0]);
- }
- },
saveCapSchedConfigs: function(saveMode, forceRefresh) {
var store = this.get('store'),
that = this,
@@ -217,7 +211,8 @@ App.CapschedRoute = Ember.Route.extend({
advancedCtrl = this.controllerFor("capsched.advanced"),
restartOrRefreshMap = {
schedulerTab: schedulerCtrl.get('isRefreshOrRestartNeeded') || false,
- queuesTab: queuesconfCtrl.get('isRefreshOrRestartNeeded') || false,
+ queuesTabRefresh: queuesconfCtrl.get('isRefreshOrRestartNeeded') || false,
+ queuesTabRestart: queuesconfCtrl.get('isQueuesMustNeedRestart') || false,
advancedTab: advancedCtrl.get('isRefreshOrRestartNeeded') || false
};
@@ -246,7 +241,8 @@ App.CapschedRoute = Ember.Route.extend({
Em.run.bind(that,'saveConfigsError', 'save')
).then(function () {
schedulerCtrl.set('isRefreshOrRestartNeeded', restartOrRefreshMap.schedulerTab);
- queuesconfCtrl.set('isRefreshOrRestartNeeded', restartOrRefreshMap.queuesTab);
+ queuesconfCtrl.set('isRefreshOrRestartNeeded', restartOrRefreshMap.queuesTabRefresh);
+ queuesconfCtrl.set('isQueuesMustNeedRestart', restartOrRefreshMap.queuesTabRestart);
advancedCtrl.set('isRefreshOrRestartNeeded', restartOrRefreshMap.advancedTab);
if (opt) {
return store.relaunchCapSched(opt);
@@ -255,6 +251,7 @@ App.CapschedRoute = Ember.Route.extend({
if (opt) {
schedulerCtrl.set('isRefreshOrRestartNeeded', false);
queuesconfCtrl.set('isRefreshOrRestartNeeded', false);
+ queuesconfCtrl.set('isQueuesMustNeedRestart', false);
advancedCtrl.set('isRefreshOrRestartNeeded', false);
}
return store.getRmSchedulerConfigInfo();
@@ -271,6 +268,15 @@ App.CapschedRoute = Ember.Route.extend({
lastSavedXML = store.get('lastSavedConfigXML'),
currentXmlConfigs = store.buildConfig('xml'),
diffConfigs = {baseXML: lastSavedXML, newXML: currentXmlConfigs};
+
+ controller.viewConfigXmlDiff(diffConfigs);
+ },
+ viewCapSchedConfigXml: function() {
+ var store = this.get('store'),
+ controller = this.controllerFor("capsched"),
+ viewXmlConfigs = store.buildConfig('xml');
+
+ controller.viewCapSchedXml({xmlConfig: viewXmlConfigs});
}
},
beforeModel: function(transition) {
@@ -383,6 +389,7 @@ App.CapschedRoute = Ember.Route.extend({
schedulerCtrl.set('isRefreshOrRestartNeeded', false);
advancedCtrl.set('isRefreshOrRestartNeeded', false);
queuesconfCtrl.set('isRefreshOrRestartNeeded', false);
+ queuesconfCtrl.set('isQueuesMustNeedRestart', false);
}).catch(
Em.run.bind(that, 'saveConfigsError', opt)
).finally(function() {
@@ -398,6 +405,14 @@ App.CapschedIndexRoute = Ember.Route.extend({
}
});
+App.CapschedSchedulerRoute = Ember.Route.extend({
+ actions: {
+ didTransition: function() {
+ this.controllerFor('capsched').set('selectedQueue', null);
+ }
+ }
+});
+
App.CapschedQueuesconfIndexRoute = Ember.Route.extend({
beforeModel: function(transition) {
var rootQ = this.store.getById('queue', 'root');
@@ -406,6 +421,16 @@ App.CapschedQueuesconfIndexRoute = Ember.Route.extend({
});
App.CapschedQueuesconfEditqueueRoute = Ember.Route.extend({
+ actions: {
+ willTransition: function(transition) {
+ if (this.controllerFor('capsched.queuesconf').get('isCreaingOrRenamingQueue')) {
+ transition.abort();
+ }
+ },
+ didTransition: function() {
+ this.controllerFor('capsched').set('selectedQueue', this.controller.get('model'));
+ }
+ },
model: function(params, transition) {
var queue = this.store.getById('queue', params.queue_id);
if (queue) {
@@ -419,6 +444,14 @@ App.CapschedQueuesconfEditqueueRoute = Ember.Route.extend({
}
});
+App.CapschedAdvancedRoute = Ember.Route.extend({
+ actions: {
+ didTransition: function() {
+ this.controllerFor('capsched').set('selectedQueue', null);
+ }
+ }
+});
+
App.CapschedTraceRoute = Ember.Route.extend({
model: function() {
return this.controllerFor('capsched').get('alertMessage');
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less b/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less
index bd875ba..1ab1740 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less
@@ -1140,6 +1140,9 @@
vertical-align: middle;
font-size: 1.5em;
}
+ .collapsible-panel-btn {
+ cursor: pointer;
+ }
}
.queue-summary {
@@ -1298,3 +1301,59 @@
.alert-message-dialog {
display: block;
}
+
+.xmldiff-viewer {
+ overflow: hidden;
+ .modal-dialog {
+ width: 98%;
+ .modal-body {
+ overflow: auto;
+ }
+ .modal-footer {
+ padding: 12px 20px 0 0;
+ }
+ .viewxml-textarea {
+ resize: none;
+ }
+ }
+ table.diff {
+ th.author {
+ display: none;
+ }
+ }
+}
+
+.hierarchical-piechart {
+ .sunburst-chart {
+ position: relative;
+ path {
+ stroke: #fff;
+ stroke-width: 1.5px;
+ }
+ svg {
+ margin-left: 20px;
+ }
+ .top-container {
+ padding-bottom: 15px;
+ }
+ .queue-explanation {
+ position: absolute;
+ width: 70px;
+ text-align: center;
+ color: #666;
+ z-index: 999;
+ }
+ .percentage, .queue-name, .queue-path {
+ font-weight: bold;
+ }
+ .queue-info {
+ width: 50%;
+ display: inline-block;
+ }
+ .select-capacity-type {
+ width: 45%;
+ display: inline-block;
+ vertical-align: top;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js
index 2c9609f..487d09a 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js
@@ -60,3 +60,5 @@ require('templates/components/labelCapacityBar');
require('templates/components/displayRootLabel');
require('templates/components/displayLeafLabel');
require('templates/capsched/partials/preemption');
+require('templates/components/xmldiffViewer');
+require('templates/components/sunburstChart');
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched.hbs
index 14625c1..7dc0d51 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched.hbs
@@ -40,6 +40,10 @@
</div>
</div>
<div class="col-lg-4 capsched-versions-wrapper">
+ {{#if selectedQueue}}
+ {{sunburst-chart queues=queues selectedQueue=selectedQueue allNodeLabels=allNodeLabels}}
+ {{/if}}
+
{{partial "versionsPanel"}}
</div>
@@ -64,3 +68,5 @@
</div>
</div>
</div>
+
+{{xmldiff-viewer diffConfig=diffXmlConfig viewConfig=viewXmlConfig}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/advanced.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/advanced.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/advanced.hbs
index 5a54d85..9973708 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/advanced.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/advanced.hbs
@@ -20,18 +20,25 @@
{{!-- QUEUE MAPPING --}}
{{#if isOperator}}
<div class="hidden-sm hidden-xs">
- {{queue-mapping mappings=scheduler.queue_mappings mappingsOverrideEnable=scheduler.queue_mappings_override_enable queues=queues isQueueMappingsDirty=isQueueMappingsDirty}}
+ {{queue-mapping mappings=scheduler.queue_mappings
+ mappingsOverrideEnable=scheduler.queue_mappings_override_enable
+ queues=queues
+ isQueueMappingsDirty=isQueueMappingsDirty
+ scheduler=scheduler
+ rollbackProp="rollbackProp"}}
</div>
{{/if}}
</div>
<div class="row">
- <div class="btn btn-group-sm col-sm-offset-3">
+ <div class="btn btn-group-sm col-sm-offset-2">
{{#if isQueueMappignsNeedSaveOrRefresh}}
- {{warning-info class="yellow-warning fa-2x resfresh-restart-warning" tooltip="Refresh queues is required"}}
+ {{warning-info class="yellow-warning fa-2x resfresh-restart-warning" tooltip="Refresh queues is required" placement="top"}}
{{/if}}
<button type="button" {{bind-attr class=":btn :btn-default :btn-success isQueueMappingsDirty::disabled"}} name="saveOnly" {{action "showSaveConfigDialog"}}>Save Only</button>
<button type="button" {{bind-attr class=":btn :btn-default :btn-success isQueueMappignsNeedSaveOrRefresh::disabled"}} name="saveRefresh" {{action "showSaveConfigDialog" "refresh"}}>Save And Refresh Queues</button>
<button type="button" {{bind-attr class=":btn :btn-default :btn-danger isQueueMappingsDirty::disabled"}} name="cancelAdvanced" {{action "showConfirmDialog"}}>Discard Changes</button>
+ <button type="button" {{bind-attr class=":btn :btn-primary isQueueMappingsDirty::disabled"}} name="viewXmlDiff" {{action "viewConfigXmlDiff"}}>View Diff</button>
+ <button type="button" class="btn btn-default" name="viewCapSchedXml" {{action "viewCapSchedConfigXml"}}>View XML</button>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/accessControlList.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/accessControlList.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/accessControlList.hbs
index 922e27e..f5b552a 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/accessControlList.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/accessControlList.hbs
@@ -19,12 +19,12 @@
<div class="queue-acl-container">
<div class="panel panel-default">
<div class="panel-heading">
- <div class="panel-title">
+ <div id="collapseQueueAclPanelBtn" href="#collapsibleQueueAclPanel" data-toggle="collapse" {{bind-attr class=":panel-title :collapsible-panel-btn view.isAclPanelCollapsed:collapsed"}}>
Access Control List
{{#if isAnyAccessControlListDirty}}
{{warning-info class="yellow-warning" tooltip="Need refresh queues / restart RM"}}
{{/if}}
- <a id="collapseQueueAclPanelBtn" href="#collapsibleQueueAclPanel" data-toggle="collapse" {{bind-attr class=":pull-right view.isAclPanelCollapsed:collapsed"}}><i {{bind-attr class=":fa view.isAclPanelCollapsed:fa-plus:fa-minus"}}></i></a>
+ <a class="pull-right"><i {{bind-attr class=":fa view.isAclPanelCollapsed:fa-plus:fa-minus"}}></i></a>
</div>
</div>
<div id="collapsibleQueueAclPanel" {{bind-attr class=":panel-collapse :collapse view.isAclPanelCollapsed::in"}}>
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/labelCapacity.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/labelCapacity.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/labelCapacity.hbs
index 873fb6f..429ef3f 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/labelCapacity.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/labelCapacity.hbs
@@ -19,7 +19,7 @@
<div class="label-capacity-container">
<div class="panel panel-default">
<div class="panel-heading">
- <div class="panel-title">
+ <div id="collapseLabelCapacityPanelBtn" href="#collapsibleLabelCapacityPanel" data-toggle="collapse" {{bind-attr class=":panel-title :collapsible-panel-btn view.isLabelsPanelCollapsed:collapsed"}}>
Label Capacity
{{#if isAnyChildrenQueueLabelDirty}}
{{#if warnInvalidTotalLabelCapacity}}
@@ -28,7 +28,7 @@
{{warning-info class="yellow-warning" tooltip="Need refresh queues / restart RM"}}
{{/if}}
{{/if}}
- <a id="collapseLabelCapacityPanelBtn" href="#collapsibleLabelCapacityPanel" data-toggle="collapse" {{bind-attr class=":pull-right view.isLabelsPanelCollapsed:collapsed"}}><i {{bind-attr class=":fa view.isLabelsPanelCollapsed:fa-plus:fa-minus"}}></i></a>
+ <a class="pull-right"><i {{bind-attr class=":fa view.isLabelsPanelCollapsed:fa-plus:fa-minus"}}></i></a>
</div>
</div>
<div id="collapsibleLabelCapacityPanel" {{bind-attr class=":panel-collapse :collapse view.isLabelsPanelCollapsed::in"}}>
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/preemption.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/preemption.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/preemption.hbs
index d594c7e..6d398f6 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/preemption.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/preemption.hbs
@@ -19,12 +19,12 @@
<div class="preemption-container">
<div class="panel panel-default">
<div class="panel-heading">
- <div class="panel-title">
+ <div id="collapseQueuePreemptionPanelBtn" href="#collapsibleQueuePreemptionPanel" data-toggle="collapse" {{bind-attr class=":panel-title :collapsible-panel-btn view.isPreemptionPanelCollapsed:collapsed"}}>
Preemption
{{#if isQueuePreemptionDirty}}
{{warning-info class="yellow-warning" tooltip="Need refresh queues / restart RM"}}
{{/if}}
- <a id="collapseQueuePreemptionPanelBtn" href="#collapsibleQueuePreemptionPanel" data-toggle="collapse" {{bind-attr class=":pull-right view.isPreemptionPanelCollapsed:collapsed"}}><i {{bind-attr class=":fa view.isPreemptionPanelCollapsed:fa-plus:fa-minus"}}></i></a>
+ <a class="pull-right"><i {{bind-attr class=":fa view.isPreemptionPanelCollapsed:fa-plus:fa-minus"}}></i></a>
</div>
</div>
<div id="collapsibleQueuePreemptionPanel" {{bind-attr class=":panel-collapse :collapse view.isPreemptionPanelCollapsed::in"}}>
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueCapacity.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueCapacity.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueCapacity.hbs
index 608758f..fdc6800 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueCapacity.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueCapacity.hbs
@@ -19,7 +19,7 @@
<div class="queue-capacity-container">
<div class="panel panel-default">
<div class="panel-heading">
- <div class="panel-title">
+ <div id="collapseQueueCapacityPanelBtn" href="#collapsibleQueueCapacityPanel" data-toggle="collapse" {{bind-attr class=":panel-title :collapsible-panel-btn view.isCapacityPanelCollapsed:collapsed"}}>
Children Queue Capacites for Default Partition
{{#if isAnyChildrenQueueCapacityDirty}}
{{#if warnInvalidCapacity}}
@@ -28,7 +28,7 @@
{{warning-info class="yellow-warning" tooltip="Need refresh queues / restart RM"}}
{{/if}}
{{/if}}
- <a id="collapseQueueCapacityPanelBtn" href="#collapsibleQueueCapacityPanel" data-toggle="collapse" {{bind-attr class=":pull-right view.isCapacityPanelCollapsed:collapsed"}}><i {{bind-attr class=":fa view.isCapacityPanelCollapsed:fa-plus:fa-minus"}}></i></a>
+ <a class="pull-right"><i {{bind-attr class=":fa view.isCapacityPanelCollapsed:fa-plus:fa-minus"}}></i></a>
</div>
</div>
<div id="collapsibleQueueCapacityPanel" {{bind-attr class=":panel-collapse :collapse view.isCapacityPanelCollapsed::in"}}>
@@ -59,13 +59,23 @@
<div class="col-md-2 col-sm-2">
<label>Total Capacity</label>
</div>
- <div class="col-sm-5 col-md-5">
+ <div class="col-sm-4 col-md-4">
<div class="progress total-capacity-progress">
<div role="progressbar" {{bind-attr class=":progress-bar warnInvalidCapacity:progress-bar-danger:progress-bar-success" style="totalCapacityBarWidth"}}>
{{childrenQueuesTotalCapacity}}%
</div>
</div>
</div>
+ <div class="col-md-3 col-sm-3">
+ <label>Absolute Capacity of Cluster</label>
+ </div>
+ <div class="col-md-3 col-sm-3">
+ <div class="progress total-capacity-progress">
+ <div role="progressbar" class="progress-bar progress-bar-success" {{bind-attr style="absoluteClusterBarWidth"}}>
+ {{absoluteClusterCapacity}}%
+ </div>
+ </div>
+ </div>
</div>
{{#if warnInvalidCapacity}}
<div class="row">
@@ -94,6 +104,18 @@
</div>
</div>
<div class="row">
+ <div class="col-md-4 col-sm-4">
+ <label>Absolute Capacity of Cluster</label>
+ </div>
+ <div class="col-md-4 col-sm-4">
+ <div class="progress total-capacity-progress">
+ <div role="progressbar" class="progress-bar progress-bar-success" {{bind-attr style="absoluteClusterBarWidth"}}>
+ {{absoluteClusterCapacity}}%
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="row">
<div class="col-md-10 col-sm-10">
<small><strong>For this queue:</strong> To edit capacity and maximum capacity at parent queue level</small>
<small>{{#link-to 'capsched.queuesconf.editqueue' parentQueue}}Click Here{{/link-to}}</small>
@@ -111,6 +133,12 @@
<span>{{content.maximum_capacity}}%</span>
</div>
</div>
+ <div class="row">
+ <div class="col-md-10 col-sm-10">
+ <label>Absolute Capacity of Cluster: </label>
+ <span>{{absoluteClusterCapacity}}%</span>
+ </div>
+ </div>
{{/if}}
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueResources.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueResources.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueResources.hbs
index 809c1c0..7fc5fde 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueResources.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/partials/queueResources.hbs
@@ -19,12 +19,12 @@
<div class="queue-resources-container">
<div class="panel panel-default">
<div class="panel-heading">
- <div class="panel-title">
+ <div id="collapseResourcesPanelBtn" href="#collapsibleQueueResourcesPanel" data-toggle="collapse" {{bind-attr class=":panel-title :collapsible-panel-btn view.isResourcesPanelCollapsed:collapsed"}}>
Other Configs (User Limit factor, Max AM Resource etc)
{{#if isAnyQueueResourcesDirty}}
{{warning-info class="yellow-warning" tooltip="Need refresh queues / restart RM"}}
{{/if}}
- <a id="collapseResourcesPanelBtn" href="#collapsibleQueueResourcesPanel" data-toggle="collapse" {{bind-attr class=":pull-right view.isResourcesPanelCollapsed:collapsed"}}><i {{bind-attr class=":fa view.isResourcesPanelCollapsed:fa-plus:fa-minus"}}></i></a>
+ <a class="pull-right"><i {{bind-attr class=":fa view.isResourcesPanelCollapsed:fa-plus:fa-minus"}}></i></a>
</div>
</div>
<div id="collapsibleQueueResourcesPanel" {{bind-attr class=":panel-collapse :collapse view.isResourcesPanelCollapsed::in"}}>
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/queuesconf.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/queuesconf.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/queuesconf.hbs
index 0c70ee5..3b8ceb5 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/queuesconf.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/queuesconf.hbs
@@ -22,7 +22,7 @@
<div class="row">
<div class="col-sm-7">
<div class="list-group queue-hierarchy">
- {{queue-hierarchy depth=0 queues=queues}}
+ {{queue-hierarchy depth=0 queues=queues deletedQs=deletedQueues}}
</div>
{{#if isOperator}}
{{#if selectedQueue}}
@@ -81,15 +81,16 @@
</div>
</div>
{{#if isOperator}}
- <div class="btn btn-group-sm col-sm-offset-2">
- {{#if isQueuesNeedRefreshOrRestart}}
- {{warning-info class="yellow-warning fa-2x resfresh-restart-warning" tooltip="Refresh queues / restart RM is required"}}
+ <div class="btn btn-group-sm col-sm-offset-1">
+ {{#if showNeedRefreshOrRestartWarning}}
+ {{warning-info class="yellow-warning fa-2x resfresh-restart-warning" tooltip="Require refresh queues/restart RM" placement="top"}}
{{/if}}
<button type="button" {{bind-attr class=":btn :btn-success canNotSave:disabled needSave::disabled"}} name="saveOnly" {{action "showSaveConfigDialog"}}>Save Only</button>
- <button type="button" {{bind-attr class=":btn :btn-success canNotSave:disabled isQueuesNeedRefreshOrRestart::disabled"}} name="saveAndRefresh" {{action "showSaveConfigDialog" "refresh"}}>Save And Refresh Queues</button>
- <button type="button" {{bind-attr class=":btn :btn-success canNotSave:disabled isQueuesNeedRefreshOrRestart::disabled"}} name="saveAndRestart" {{action "showSaveConfigDialog" "restart"}}>Save And Restart RM</button>
+ <button type="button" {{bind-attr class=":btn :btn-success canNotSave:disabled isDirtyQueuesNeedRefreshQsOp::disabled"}} name="saveAndRefresh" {{action "showSaveConfigDialog" "refresh"}}>Save And Refresh Queues</button>
+ <button type="button" {{bind-attr class=":btn :btn-success canNotSave:disabled isDirtyQueuesNeedRestartRmOp::disabled"}} name="saveAndRestart" {{action "showSaveConfigDialog" "restart"}}>Save And Restart RM</button>
<button type="button" {{bind-attr class=":btn :btn-danger isAnyQueueDirty::disabled"}} name="cancelQueuesconfBtn" {{action "showConfirmDialog"}}>Discard Changes</button>
- <button type="button" {{bind-attr class=":btn :btn-primary isAnyQueueDirty::disabled"}} name="viewXmlDiff" {{action "viewConfigXmlDiff"}} style="display:none;">View XML Diff</button>
+ <button type="button" {{bind-attr class=":btn :btn-primary isAnyQueueDirty::disabled"}} name="viewXmlDiff" {{action "viewConfigXmlDiff"}}>View Diff</button>
+ <button type="button" class="btn btn-default" name="viewCapSchedXml" {{action "viewCapSchedConfigXml"}}>View XML</button>
</div>
{{/if}}
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/scheduler.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/scheduler.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/scheduler.hbs
index 66ef1ad..26150fb 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/scheduler.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capsched/scheduler.hbs
@@ -137,13 +137,15 @@
</div>
{{#if isOperator}}
<div class="row">
- <div class="btn btn-group-sm col-sm-offset-3">
+ <div class="btn btn-group-sm col-sm-offset-2">
{{#if isSchedulerPropsNeedSaveOrRestart}}
- {{warning-info class="yellow-warning fa-2x resfresh-restart-warning" tooltip="Restart RM is required"}}
+ {{warning-info class="yellow-warning fa-2x resfresh-restart-warning" tooltip="Restart RM is required" placement="top"}}
{{/if}}
<button type="button" {{bind-attr class=":btn :btn-default :btn-success isSchedulerDirty::disabled"}} name="saveOnly" {{action 'showSaveConfigDialog'}}>Save Only</button>
<button type="button" {{bind-attr class=":btn :btn-default :btn-success isSchedulerPropsNeedSaveOrRestart::disabled"}} name="saveRestart" {{action 'showSaveConfigDialog' 'restart'}}>Save And Restart RM</button>
<button type="button" {{bind-attr class=":btn :btn-default :btn-danger isSchedulerDirty::disabled"}} name="cancelAdvanced" {{action 'showConfirmDialog'}}>Discard Changes</button>
+ <button type="button" {{bind-attr class=":btn :btn-primary isSchedulerDirty::disabled"}} name="viewXmlDiff" {{action "viewConfigXmlDiff"}}>View Diff</button>
+ <button type="button" class="btn btn-default" name="viewCapSchedXml" {{action "viewCapSchedConfigXml"}}>View XML</button>
</div>
</div>
{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueHierarchy.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueHierarchy.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueHierarchy.hbs
index fb34d51..e7ff559 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueHierarchy.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueHierarchy.hbs
@@ -15,7 +15,7 @@
* limitations under the License.
}}
-{{#each queue in leafQs}}
+{{#each queue in cildrenQueues}}
{{#link-to 'capsched.queuesconf.editqueue' queue classNameBindings=":list-group-item queue.overCapacity:list-group-item-danger queue.isNew:list-group-item-info" disabled=queue.isDeletedQueue}}
<div class="col-md-offset-{{unbound queue.depth}} col-sm-offset-{{unbound queue.depth}}">
@@ -35,8 +35,12 @@
{{warn-badge}}
{{/if}}
+ {{#if queue.isDeletedQueue}}
+ {{warning-info class="yellow-warning pull-right" tooltip="Queue is marked for deletion"}}
+ {{/if}}
+
{{queue-badge q=queue class="badge pull-right"}}
</div>
{{/link-to}}
- {{queue-hierarchy depth=childDepth parent=queue.path queues=queues}}
+ {{queue-hierarchy depth=childDepth parent=queue.path queues=queues deletedQs=deletedQs}}
{{/each}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueMapping.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueMapping.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueMapping.hbs
index 33540e9..f143911 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueMapping.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueMapping.hbs
@@ -17,12 +17,12 @@
<div class="panel panel-default panel-queue-mapping">
<div class="panel-heading">
- <div class="panel-title">
+ <div id="collapseQueueMappingsBtn" href="#queueMappingsCollapsiblePanel" data-toggle="collapse" {{bind-attr class=":panel-title :collapsible-panel-btn isCollapsed:collapsed"}}>
Queue Mappings
{{#if isQueueMappingsDirty}}
{{warning-info class="yellow-warning" tooltip="Need refresh queues"}}
{{/if}}
- <a href="#queueMappingsCollapsiblePanel" id="collapseQueueMappingsBtn" data-toggle="collapse" {{bind-attr class=":pull-right isCollapsed:collapsed"}}><i {{bind-attr class=":fa isCollapsed:fa-plus:fa-minus"}}></i></a>
+ <a class="pull-right"><i {{bind-attr class=":fa isCollapsed:fa-plus:fa-minus"}}></i></a>
</div>
</div>
<div id="queueMappingsCollapsiblePanel" {{bind-attr class=":panel-collapse :collapse isCollapsed::in"}}>
@@ -46,6 +46,11 @@
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-default btn-primary" name="button" {{action "showMappingOptions"}}>Add Mapping</button>
</div>
+ {{#if isMappingsDirty}}
+ <div class="btn-group btn-group-xs">
+ <a {{action 'rollbackProp' 'queue_mappings' scheduler}} href="#" class="btn btn-default btn-warning"><i class="fa fa-undo"></i></a>
+ </div>
+ {{/if}}
</div>
{{#if isShowing}}
<div class="queue-mapping-options">
@@ -164,6 +169,11 @@
message='When checked, applications submitted with queues specified will be used other than those defined in configured queue mapping'
}}
</label>
+ {{#if isOverrideEnableDirty}}
+ <span class="btn-group btn-group-xs">
+ <a {{action 'rollbackProp' 'queue_mappings_override_enable' scheduler}} href="#" class="btn btn-default btn-warning"><i class="fa fa-undo"></i></a>
+ </span>
+ {{/if}}
</div>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueSummary.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueSummary.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueSummary.hbs
index a7ae9b0..fd46308 100644
--- a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueSummary.hbs
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueSummary.hbs
@@ -51,19 +51,6 @@
</div>
<div class="row">
<div class="col-sm-5">
- <label>Absolute Capacity of Cluster</label>
- </div>
- <div class="col-sm-5">
- <span>{{effectiveCapacity}}%</span>
- </div>
- {{#if isQueueCapacityNeedRefresh}}
- <div class="col-sm-2">
- {{warning-info class="yellow-warning" tooltip="Need refresh queues/restart RM to take effect"}}
- </div>
- {{/if}}
- </div>
- <div class="row">
- <div class="col-sm-5">
<label>State</label>
</div>
<div class="col-sm-5">
http://git-wip-us.apache.org/repos/asf/ambari/blob/62dc775e/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/sunburstChart.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/sunburstChart.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/sunburstChart.hbs
new file mode 100644
index 0000000..462ddf7
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/sunburstChart.hbs
@@ -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="panel panel-default hierarchical-piechart">
+ <div class="panel-heading">
+ <div class="panel-title">
+ Queue Capacity Chart
+ </div>
+ </div>
+ <div class="panel-body">
+ <div id="sunburst_chart" class="sunburst-chart">
+ <div id="top_container" class="top-container">
+ <div id="queue_info" class="queue-info" style="visibility:hidden;">
+ <span>Path: </span> <span id="queuePath" class="queue-path"></span>
+ </div>
+ {{view Ember.Select
+ class="form-control input-sm select-capacity-type"
+ content=queueCapacityTypeValues
+ optionLabelPath="content.name"
+ optionValuePath="content.value"
+ value=queueCapacityTypeSelected
+ }}
+ </div>
+ <div id="explanation" class="queue-explanation" style="visibility:hidden;">
+ <span id="type_text"></span> <br/> <span id="capacityPercentage" class="percentage"></span>
+ </div>
+ </div>
+ </div>
+</div>