diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-capacity-sunburst-chart.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-capacity-sunburst-chart.js new file mode 100644 index 00000000000..0fdb5d1b827 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-capacity-sunburst-chart.js @@ -0,0 +1,338 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import QueueSelector from 'yarn-ui/components/queue-selector'; +import Converter from 'yarn-ui/utils/converter'; + +const MARGIN = 10; +const LEGEND_WIDTH = 200; + +export default QueueSelector.extend({ + queuesMap: undefined, + nodes: undefined, + + tooltip : undefined, + svg: undefined, + g: undefined, + + type: "used", + transitioning: false, + + initTooltip: function() { + if (!this.tooltip) { + this.tooltip = d3.select("body") + .append("div") + .attr("class", "tooltip") + .attr("id", "chart-tooltip") + .style("opacity", 0); + } + }, + + bindTooltip: function(d) { + d.on("mouseover", function() { + this.tooltip + .style("left", (d3.event.pageX) + "px") + .style("top", (d3.event.pageY - 28) + "px"); + }.bind(this)) + .on("mousemove", function(d) { + // Handle pie chart case + var data = d; + if (d.data) { + data = d.data; + } + + this.tooltip.style("opacity", 0.7); + var value = data.value; + if (this.get("type") === "memory") { + value = Converter.memoryToSimpliedUnit(value); + } + this.tooltip.html(data.label + " = " + value) + .style("left", (d3.event.pageX) + "px") + .style("top", (d3.event.pageY - 28) + "px"); + }.bind(this)) + .on("mouseout", function() { + this.tooltip.style("opacity", 0); + }.bind(this)); + }, + + defineGradient: function(name, start, stop) { + var gradient = this.svg.append("defs") + .append("linearGradient") + .attr("id", name) + .attr("x1", "0%") + .attr("y1", "50%") + .attr("x2", "100%") + .attr("y2", "50%"); + gradient.append("stop") + .attr("offset", "0%") + .attr("stop-color", start); + gradient.append("stop") + .attr("offset", "100%") + .attr("stop-color", stop); + }, + + round: function(number, decimals=4) { + var e = Math.pow(10, decimals); + return Math.round(number * e) / e; + }, + + partitionValue: function(d) { + if (this.type === "configured") { + return d.capacity.configured; + } else { + return d.capacity.used; + } + }, + + changeChartType: function(chartType, path, partition, arc) { + this.type = chartType; + this.sendAction("setSunburstChartType", this.type); + d3.selectAll(".radio-center") + .style("opacity", 0); + d3.selectAll("#radio-" + this.type) + .style("opacity", 1); + this.transitioning = true; + path.data(partition.value(this.partitionValue.bind(this)).nodes) + .transition() + .duration(1000) + .attrTween("d", function(finish) { + var start = { + x: finish.xOld, + dx: finish.dxOld + }; + return function(t) { + var end = d3.interpolate(start, finish)(t); + finish.xOld = end.x; + finish.dxOld = end.dx; + return arc(end); + }; + }) + .each("end", function() { + this.transitioning = false; + }.bind(this)); + }, + + reDraw: function() { + this.initData(); + + var parentId = this.get("parentId"); + var parent = d3.select("#" + parentId); + parent.selectAll("*").remove(); + var bbox = parent.node().getBoundingClientRect(); + this.width = bbox.width; + this.height = this.width - LEGEND_WIDTH; + + this.svg = d3 + .select("#" + parentId) + .append("svg") + .attr("width", this.width) + .attr("height", this.height); + this.g = this.svg.append("g"); + + var radius = (Math.max(400, (this.width - 2 * MARGIN)) - LEGEND_WIDTH) / 2; + + var cx = (this.width - LEGEND_WIDTH) / 2; + var cy = MARGIN + radius; + + var partition = d3.layout.partition() + .sort(null) + .size([2 * Math.PI, radius]) + .value(this.partitionValue.bind(this)); + + var arc = d3.svg.arc() + .startAngle(function(d) { return d.x; }) + .endAngle(function(d) { return d.x + d.dx; }) + .innerRadius(function(d) { return d.y; }) + .outerRadius(function(d) { return d.y + d.dy; }); + + var underCapColorStart = "#26bbf0", underCapColorEnd = "#1c95c0"; + var overCapColorStart = "#ffbc0b", overCapColorEnd = "#dca41b"; + var underCapColorFunc = d3.interpolate( + d3.rgb(underCapColorStart), d3.rgb(underCapColorEnd)); + var overCapColorFunc = d3.interpolate( + d3.rgb(overCapColorStart), d3.rgb(overCapColorEnd)); + this.defineGradient("under", underCapColorStart, underCapColorEnd); + this.defineGradient("over", overCapColorStart, overCapColorEnd); + + var path = this.g.datum(this.treeData).selectAll("path") + .data(partition.nodes) + .enter() + .append("path") + .attr("d", arc) + .style("stroke", "#fff") + .style("fill", function(d) { + if (d.capacity.used > d.capacity.configured) { + return overCapColorFunc(d.capacity.used / d.capacity.max); + } + return underCapColorFunc(d.capacity.used / d.capacity.configured); + }) + .each(function(d) { + d.xOld = d.x; + d.dxOld = d.dx; + }) + .attr("transform", "translate(" + cx + "," + cy + ")"); + + path.on("mousemove", function(d) { + if (this.transitioning) { return; } + + this.g.selectAll("path").transition(); + var path = []; + var current = d; + while (current) { + path.push(current); + current = current.parent; + } + this.g.selectAll("path") + .style("opacity", 0.3); + this.g.selectAll("path") + .filter(function(d) { + return path.indexOf(d) !== -1; + }) + .style("opacity", 1); + + this.tooltip.style("opacity", 0.7); + this.tooltip.html( + "

" + d.name + "

" + + "

Used: " + this.round(d.capacity.used) + "%

" + + "

Configured: " + this.round(d.capacity.configured) + "%

" + + "

Max: " + this.round(d.capacity.max) + "%

") + .style("left", d3.event.pageX + "px") + .style("top", (d3.event.pageY - 28) + "px"); + }.bind(this)); + + path.on("mouseout", function() { + if (this.transitioning) { return; } + + this.g.selectAll("path") + .transition() + .duration(500) + .style("opacity", 1); + this.tooltip.style("opacity", 0); + }.bind(this)); + + path.on("click", function (d) { + if (d.queueData.get("name") !== this.get("selected")) { + document.location.href = + "#/yarn-queues/" + d.queueData.get("name") + + "!?viewType=sunburst&sunburstChartType=" + this.type; + } + }.bind(this)); + + path.on("dblclick", function(d) { + document.location.href = + "#/yarn-queue/" + d.queueData.get("name") + "/apps"; + }); + + if (this.get("showLabels")) { + var lx = this.width - LEGEND_WIDTH; + var ly = 75; + var squareW = 15; + var margin = 10; + + var labels = [ + {label: "Under capacity", gradient: "url(#under)"}, + {label: "Over capacity", gradient: "url(#over)"} + ]; + var select = this.g.selectAll("rect") + .data(labels) + .enter(); + select.append("rect") + .attr("fill", function(d) { return d.gradient; }) + .attr("x", lx) + .attr("y", function(d, i) { + return ly + (squareW + margin) * i + margin; + }) + .attr("width", squareW) + .attr("height", squareW); + select.append("text") + .attr("x", lx + squareW + margin) + .attr("y", function(d, i) { + return ly + 5 + (squareW + margin) * i + margin + squareW / 2; + }) + .text(function(d) { return d.label; }); + + this.g.append("text") + .attr("x", lx - 2) + .attr("y", ly + (squareW + margin) * 4 + margin) + .style("font-weight", "bold") + .text("Chart type"); + var types = [ + {label: "Configured capacity", type: "configured"}, + {label: "Used capacity", type: "used"} + ]; + select = this.g.selectAll("circle") + .data(types) + .enter(); + select.append("circle") + .attr("cx", lx + squareW / 2) + .attr("cy", function(d, i) { + return ly + (squareW + margin) * (5 + i) + margin; + }) + .attr("r", squareW / 2) + .attr("fill", "white") + .attr("stroke", "black") + .on("click", function(d) { + this.changeChartType(d.type, path, partition, arc); + }.bind(this)); + select.append("circle") + .attr("cx", lx + squareW / 2) + .attr("cy", function(d, i) { + return ly + (squareW + margin) * (5 + i) + margin; + }) + .attr("r", squareW / 2 - 2) + .attr("fill", "green") + .attr("id", function(d) { return "radio-" + d.type; }) + .attr("class", "radio-center") + .attr("opacity", function(d) { + return d.type === this.type ? 1 : 0; + }.bind(this)) + .on("click", function(d) { + this.type = d.type; + this.changeChartType(d.type, path, partition, arc); + }.bind(this)); + select.append("text") + .attr("x", lx + squareW + margin) + .attr("y", function(d, i) { + return ly + 6 + (squareW + margin) * (5 + i) + margin; + }) + .text(function(d) { return d.label; }); + } + + this.transitioning = true; + path.transition() + .duration(500) + .attrTween("d", function(finish) { + var start = {x: 0, dx: 0}; + return function(d) { + return arc(d3.interpolate(start, finish)(d)); + }; + }) + .each("end", function() { + this.transitioning = false; + }.bind(this)); + }, + + didInsertElement: function() { + this.initTooltip(); + this.reDraw(); + }, + + willDestroy: function() { + this.tooltip.remove(); + } +}); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-navigator.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-navigator.js index 2cecefb7720..2e0e351a129 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-navigator.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-navigator.js @@ -23,6 +23,15 @@ export default Ember.Component.extend(Ember.TargetActionSupport,{ filterQueuesByPartition(filter) { this.set("filteredPartition", filter); this.sendAction("setFilter", filter); + }, + showTreeView() { + this.sendAction("setViewType", "tree"); + }, + showSunburstView() { + this.sendAction("setViewType", "sunburst"); + }, + setSunburstChartType(param) { + this.sendAction("setSunburstChartType", param); } }, didInsertElement: function() { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-selector.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-selector.js new file mode 100644 index 00000000000..ea32356b6fa --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/queue-selector.js @@ -0,0 +1,145 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Ember from "ember"; +import {PARTITION_LABEL} from '../constants'; + +export default Ember.Component.extend({ + // Map: + queuesMap: undefined, + + // Normalized data for d3 + treeData: undefined, + + // folded queues, folded[] == true means is folded + foldedQueues: {}, + + // maxDepth + maxDepth: 0, + + // num of leaf queue, folded queue is treated as leaf queue + numOfLeafQueue: 0, + + used: undefined, + max: undefined, + + didUpdateAttrs: function({ oldAttrs, newAttrs }) { + if (oldAttrs.filteredPartition.value !== newAttrs.filteredPartition.value) { + this.reDraw(); + } + }, + + initData: function() { + this.queuesMap = {}; + this.treeData = {}; + this.maxDepth = 0; + this.numOfLeafQueue = 0; + + this.get("model").forEach( + function(o) { + this.queuesMap[o.id] = o; + }.bind(this) + ); + + // var selected = this.get("selected"); + this.used = this.get("used"); + this.max = this.get("max"); + this.initQueue("root", 1, this.treeData); + }, + + // get Children array of given queue + getChildrenNamesArray: function(q) { + var namesArr = []; + + // Folded queue's children is empty + if (this.foldedQueues[q.get("name")]) { + return namesArr; + } + + var names = q.get("children"); + if (names) { + names.forEach(function(name) { + namesArr.push(name); + }); + } + + return namesArr; + }, + + // Init queues + initQueue: function(queueName, depth, node) { + if (!queueName || !this.queuesMap[queueName]) { + // Queue is not existed + return false; + } + if (depth > this.maxDepth) { + this.maxDepth = this.maxDepth + 1; + } + + var queue = this.queuesMap[queueName]; + + if ( + this.filteredPartition && + !queue.get("partitions").contains(this.filteredPartition) + ) { + return false; + } + + var names = this.getChildrenNamesArray(queue); + + node.name = queueName; + node.parent = queue.get("parent"); + node.queueData = queue; + node.capacity = { + max: this.getMaxCapacity(queue.get("partitionMap"), this.filteredPartition), + configured: this.getConfiguredCapacity(queue.get("partitionMap"), this.filteredPartition), + used: this.getUsedCapacity(queue.get("partitionMap"), this.filteredPartition) + }; + + if (names.length > 0) { + node.children = []; + + names.forEach( + function(name) { + var childQueueData = {}; + node.children.push(childQueueData); + const status = this.initQueue(name, depth + 1, childQueueData); + if (!status) { + node.children.pop(); + } + }.bind(this) + ); + } else { + this.numOfLeafQueue = this.numOfLeafQueue + 1; + } + + return true; + }, + + getUsedCapacity: function(partitionMap, filter=PARTITION_LABEL) { + return partitionMap[filter].absoluteUsedCapacity; + }, + + getConfiguredCapacity: function(partitionMap, filter=PARTITION_LABEL) { + return partitionMap[filter].absoluteCapacity; + }, + + getMaxCapacity: function(partitionMap, filter=PARTITION_LABEL) { + return partitionMap[filter].absoluteMaxCapacity; + }, +}) \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js index 5168c0e0a7c..5ef4d7e6caf 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/tree-selector.js @@ -17,120 +17,13 @@ */ import Ember from "ember"; -import {PARTITION_LABEL} from '../constants'; +import QueueSelector from 'yarn-ui/components/queue-selector'; const INBETWEEN_HEIGHT = 130; -export default Ember.Component.extend({ - // Map: - map: undefined, - - // Normalized data for d3 - treeData: undefined, - - // folded queues, folded[] == true means is folded - foldedQueues: {}, - - // maxDepth - maxDepth: 0, - - // num of leaf queue, folded queue is treated as leaf queue - numOfLeafQueue: 0, - - // mainSvg +export default QueueSelector.extend({ mainSvg: undefined, - used: undefined, - max: undefined, - - didUpdateAttrs: function({ oldAttrs, newAttrs }) { - if (oldAttrs.filteredPartition.value !== newAttrs.filteredPartition.value) { - this.reDraw(); - } - }, - // Init data - initData: function() { - this.map = {}; - this.treeData = {}; - this.maxDepth = 0; - this.numOfLeafQueue = 0; - - this.get("model").forEach( - function(o) { - this.map[o.id] = o; - }.bind(this) - ); - - // var selected = this.get("selected"); - this.used = this.get("used"); - this.max = this.get("max"); - this.initQueue("root", 1, this.treeData); - }, - - // get Children array of given queue - getChildrenNamesArray: function(q) { - var namesArr = []; - - // Folded queue's children is empty - if (this.foldedQueues[q.get("name")]) { - return namesArr; - } - - var names = q.get("children"); - if (names) { - names.forEach(function(name) { - namesArr.push(name); - }); - } - - return namesArr; - }, - - // Init queues - initQueue: function(queueName, depth, node) { - if (!queueName || !this.map[queueName]) { - // Queue is not existed - return false; - } - if (depth > this.maxDepth) { - this.maxDepth = this.maxDepth + 1; - } - - var queue = this.map[queueName]; - - if ( - this.filteredPartition && - !queue.get("partitions").contains(this.filteredPartition) - ) { - return false; - } - - var names = this.getChildrenNamesArray(queue); - - node.name = queueName; - node.parent = queue.get("parent"); - node.queueData = queue; - - if (names.length > 0) { - node.children = []; - - names.forEach( - function(name) { - var childQueueData = {}; - node.children.push(childQueueData); - const status = this.initQueue(name, depth + 1, childQueueData); - if (!status) { - node.children.pop(); - } - }.bind(this) - ); - } else { - this.numOfLeafQueue = this.numOfLeafQueue + 1; - } - - return true; - }, - update: function(source, root, tree, diagonal) { var duration = 300; var i = 0; @@ -163,6 +56,7 @@ export default Ember.Component.extend({ if (d.queueData.get("name") !== this.get("selected")) { document.location.href = "#/yarn-queues/" + d.queueData.get("name") + "!"; + this.set("selected", d.queueData.get("name")); } Ember.run.later( @@ -174,7 +68,6 @@ export default Ember.Component.extend({ var diagonal = d3.svg.diagonal().projection(function(d) { return [d.y + 50, d.x]; }); - this.update(this.treeData, this.treeData, tree, diagonal); }, 100 @@ -192,7 +85,9 @@ export default Ember.Component.extend({ .style( "fill", function(d) { - const usedCapacity = getUsedCapacity(d.queueData.get("partitionMap"), this.filteredPartition); + const usedCapacity = + this.getUsedCapacity(d.queueData.get("partitionMap"), + this.filteredPartition); if (usedCapacity <= 60.0) { return "#60cea5"; } else if (usedCapacity <= 100.0) { @@ -216,7 +111,7 @@ export default Ember.Component.extend({ }) .text( function(d) { - const usedCapacity = getUsedCapacity(d.queueData.get("partitionMap"), this.filteredPartition); + const usedCapacity = this.getUsedCapacity(d.queueData.get("partitionMap"), this.filteredPartition); if (usedCapacity >= 100.0) { return usedCapacity.toFixed(0) + "%"; } else { @@ -336,18 +231,16 @@ export default Ember.Component.extend({ var width = treeWidth + margin.left + margin.right; var height = treeHeight + margin.top + margin.bottom; - if (this.mainSvg) { - this.mainSvg.selectAll("*").remove(); - } else { - this.mainSvg = d3 - .select("#" + this.get("parentId")) - .append("svg") - .attr("width", width) - .attr("height", height) - .attr("class", "tree-selector"); - } - - this.mainSvg + var parentId = this.get("parentId"); + var parent = d3.select("#" + parentId); + parent.selectAll("*").remove(); + this.mainSvg = parent + .append("svg") + .attr("width", width) + .attr("height", height) + .attr("class", "tree-selector"); + + this.g = this.mainSvg .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); @@ -369,9 +262,4 @@ export default Ember.Component.extend({ didInsertElement: function() { this.reDraw(); } -}); - - -const getUsedCapacity = (partitionMap, filter=PARTITION_LABEL) => { - return partitionMap[filter].absoluteUsedCapacity; -}; \ No newline at end of file +}); \ No newline at end of file diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js index 6cc87675b50..51233d33b80 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-queues.js @@ -24,6 +24,9 @@ export default Ember.Controller.extend({ selectedQueue: undefined, showLoading: true, filteredPartition: PARTITION_LABEL, + viewType: "tree", + sunburstChartType: "used", + queryParams: ["viewType", "sunburstChartType"], breadcrumbs: [ { @@ -46,10 +49,18 @@ export default Ember.Controller.extend({ // reset it to root if (!selectedQueue.get('partitions').contains(partition)) { const root = model.queues.get('firstObject'); - document.location.href = "#/yarn-queues/" + root.get("id") + "!"; + document.location.href = "#/yarn-queues/" + root.get("id") + "!?" + + "viewType=" + this.viewType + + "&sunburstChartType=" + this.sunburstChartType; this.set("model.selectedQueue", root); this.set("model.selected", root.get('id')); } + }, + setViewType(param) { + this.set("viewType", param); + }, + setSunburstChartType(param) { + this.set("sunburstChartType", param); } } }); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/helpers/capitalize.js b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/helpers/capitalize.js new file mode 100644 index 00000000000..67b0c451223 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/helpers/capitalize.js @@ -0,0 +1,27 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import Ember from 'ember'; + +export function capitalize(params) { + const string = params[0]; + return string.capitalize(); +} + +export default Ember.Helper.helper(capitalize); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/queue-navigator.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/queue-navigator.hbs index b063aae8eda..4bfbc50c9c1 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/queue-navigator.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/queue-navigator.hbs @@ -19,27 +19,58 @@
-
-
- {{#if filteredPartition}} - {{model.firstObject.type}} scheduler - Showing queues from partition {{lower filteredPartition}} - {{else}} - {{model.firstObject.type}} scheduler - Showing queues from all partitions - {{/if}} -
- {{#if (eq model.firstObject.type "capacity")}} -
-
- - +
+
+
+
+
+

{{capitalize model.firstObject.type}} Scheduler

+ {{#if filteredPartition}} + Showing queues from partition {{lower filteredPartition}} + {{else}} + Showing queues from all partitions + {{/if}} +
+ {{#if (eq model.firstObject.type "capacity")}} +
+ + +
+ {{/if}} +
+
+
+
+ +
-
- {{/if}} - {{tree-selector model=model parentId="tree-selector-container" selected=selected used=used max=max filteredPartition=filteredPartition}} +
+
+ {{#if (eq viewType "tree")}} + {{tree-selector model=model parentId="queue-selector" selected=selected used=used max=max + filteredPartition=filteredPartition}} + {{else}} + {{queue-capacity-sunburst-chart model=model showLabels=true parentId="queue-selector" + selected=selected filteredPartition=filteredPartition type=sunburstChartType + setSunburstChartType=(action setSunburstChartType) }} + {{/if}} +
+
+
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/capacity-queue.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/capacity-queue.hbs index 9ad2a6f1a5d..c6802142bcc 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/capacity-queue.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/capacity-queue.hbs @@ -17,7 +17,9 @@ }} {{queue-navigator model=model.queues selected=model.selected - used="usedCapacity" max="absMaxCapacity" setFilter=(action setFilter)}} + used="usedCapacity" max="absMaxCapacity" setFilter=(action setFilter) + setViewType=(action setViewType) viewType=viewType + setSunburstChartType=(action setSunburstChartType) sunburstChartType=sunburstChartType}}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/fair-queue.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/fair-queue.hbs index dcc80c10b30..d8646f8327e 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/fair-queue.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/fair-queue.hbs @@ -17,7 +17,9 @@ }} {{queue-navigator model=model.queues selected=model.selected - used="usedResources.memory" max="clusterResources.memory"}} + used="usedResources.memory" max="clusterResources.memory" setFilter=(action setFilter) + setViewType=(action setViewType) viewType=viewType + setSunburstChartType=(action setSunburstChartType) sunburstChartType=sunburstChartType}}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/fifo-queue.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/fifo-queue.hbs index 98db5cb4153..f94ccc849c5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/fifo-queue.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/components/yarn-queue/fifo-queue.hbs @@ -17,7 +17,9 @@ }} {{queue-navigator model=model.queues selected=model.selected - used="usedNodeCapacity" max="totalNodeCapacity"}} + used="usedNodeCapacity" max="totalNodeCapacity" setFilter=(action setFilter) + setViewType=(action setViewType) viewType=viewType + setSunburstChartType=(action setSunburstChartType) sunburstChartType=sunburstChartType}}
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-queues.hbs b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-queues.hbs index ede29946f0c..2901658bd5b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-queues.hbs +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/templates/yarn-queues.hbs @@ -21,7 +21,9 @@
{{#if (eq model.queues.firstObject.type "capacity")}} - {{yarn-queue.capacity-queue model=model setFilter=(action "setFilter") filteredPartition=filteredPartition}} + {{yarn-queue.capacity-queue model=model setFilter=(action "setFilter") filteredPartition=filteredPartition + setViewType=(action "setViewType") viewType=viewType + setSunburstChartType=(action "setSunburstChartType") sunburstChartType=sunburstChartType}} {{else if (eq model.queues.firstObject.type "fair")}} {{yarn-queue.fair-queue model=model}} {{else}}