You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ja...@apache.org on 2014/07/21 22:48:57 UTC
[2/4] AMBARI-6519. View: Capacity Scheduler view. (jaimin)
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/assets/index.html
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/assets/index.html b/contrib/views/capacity-scheduler/src/main/resources/ui/app/assets/index.html
new file mode 100644
index 0000000..ce0972c
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/assets/index.html
@@ -0,0 +1,48 @@
+<!--
+ 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.
+-->
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Capacity Scheduler</title>
+ <link rel="stylesheet" href="stylesheets/vendor.css">
+ <link rel="stylesheet" href="stylesheets/app.css">
+ <script src="javascripts/vendor.js"></script>
+ <script src="javascripts/app.js"></script>
+ <script>
+ $(document).ready(function() {
+ require('initialize');
+ });
+ </script>
+</head>
+<body>
+ <script type="text/x-handlebars">
+ <div class="wrap">
+ <div class="container-fluid">
+ <div class="row">
+ {{outlet}}
+ </div>
+ </div>
+ </div>
+ </script>
+
+
+ </body>
+</html>
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/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
new file mode 100644
index 0000000..eb743c4
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components.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.
+ */
+
+require('components/capacityBar');
+require('components/capacityInput');
+require('components/totalCapacity');
+require('components/queueListItem');
+require('components/pathInput');
+require('components/radioButton');
+require('components/userGroupInput');
+require('components/escapeAcl');
+require('components/confirmDelete');
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityBar.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityBar.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityBar.js
new file mode 100644
index 0000000..22d511b
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityBar.js
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.CapacityBarComponent = Em.Component.extend({
+ layoutName:'components/capacityBar',
+ classNames:['capacity-bar'],
+ mark:function () {
+ if (this.$().parent().hasClass('active')) {
+ Ember.run.next(this, 'addInClass');
+ };
+ }.on('didInsertElement'),
+ addInClass:function () {
+ this.$().children().addClass('in');
+ },
+ capacityWidth: function() {
+ return (Number(this.get('capacityValue'))<=100)?('width: '+this.get('capacityValue')+'%'):'width: 100%';
+ }.property('capacityValue'),
+ maxCapacityWidth: function() {
+ var val = Number(this.get('maxCapacityValue')) - Number(this.get('capacityValue'));
+ return (val<=100)?('width: '+val+'%'):'width: 100%';
+ }.property('maxCapacityValue','capacityValue'),
+ showMaxCapacity:function () {
+ return this.get('maxCapacityValue') > this.get('capacityValue');
+ }.property('maxCapacityValue','capacityValue')
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityInput.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityInput.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityInput.js
new file mode 100644
index 0000000..b46933a
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/capacityInput.js
@@ -0,0 +1,94 @@
+/**
+ * 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.FocusInputComponent = Ember.TextField.extend({
+ becomeFocused: function() {
+ this.$().focus().val(this.value);
+ }.on('didInsertElement'),
+ cancel:function () {
+ this.get('targetObject').send(this.get('revert'),'cancel');
+ }
+});
+
+App.IntInputComponent = Ember.TextField.extend({
+ classNames:['form-control'],
+ maxVal:null,
+ intVal:function () {
+ var val = parseFloat(this.get('value'))||0;
+ var maxVal = this.get('maxVal');
+ val = (maxVal && maxVal < val)?maxVal:val;
+ this.set('value', val);
+ }.on('change'),
+ checkNumber:function () {
+ var val = this.get('value'),
+ num = Number(val),
+ str = String(val);
+ if (typeof val !== "number" && !isNaN(num) && str == num.toString()) {
+ this.set('value', Number(val));
+ };
+ }.observes('value')
+});
+
+App.CapacityInputComponent = App.IntInputComponent.extend({
+
+ totalCapacity:null,
+ queue:null,
+
+ keyDown: function(evt) {
+ var newChar, val = this.get('value')||0;
+ val = val.toString();
+
+ if ((evt.keyCode > 64 && evt.keyCode < 91) ||
+ (evt.keyCode > 185 && evt.keyCode < 193) ||
+ (evt.keyCode > 218 && evt.keyCode < 223)) {
+ return false;
+ };
+
+ if (evt.keyCode > 95 && evt.keyCode < 106) {
+ newChar = (evt.keyCode - 96).toString();
+ } else {
+ newChar = String.fromCharCode(evt.keyCode);
+ }
+
+ if (newChar.match(/[0-9]/)) {
+ val = val.substring(0, evt.target.selectionStart) + newChar + val.substring(evt.target.selectionEnd);
+ };
+
+ return parseFloat(val)<=100;
+ },
+});
+
+App.MaxCapacityInputComponent = App.CapacityInputComponent.extend({
+ isInvalid:false,
+ invalid:function (c,o) {
+ var queue = this.get('queue'),
+ max_capacity = Number(queue.get('maximum_capacity')),
+ capacity = Number(queue.get('capacity'));
+ if (o == 'queue.capacity' && max_capacity < capacity) {
+ return queue.set('maximum_capacity',capacity);
+ };
+ if (max_capacity < capacity && queue.get('isDirty')) {
+ queue.get('errors').add('maximum_capacity', 'Maximum capacity must be greater then capacity');
+ } else {
+ queue.get('errors').remove('maximum_capacity');
+ }
+ }.observes('queue.maximum_capacity','queue.capacity')
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/confirmDelete.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/confirmDelete.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/confirmDelete.js
new file mode 100644
index 0000000..5b465bc
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/confirmDelete.js
@@ -0,0 +1,87 @@
+/**
+ * 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');
+
+var bound;
+
+bound = function(fnName) {
+ return Ember.computed(fnName,function() {
+ return this.get(fnName).bind(this);
+ });
+};
+
+App.ClickElsewhereMixin = Ember.Mixin.create({
+ onClickElsewhere: Ember.K,
+ clickHandler: bound("elsewhereHandler"),
+ elsewhereHandler: function(e) {
+ var $target, element, thisIsElement;
+ element = this.get("element");
+ $target = $(e.target);
+ thisIsElement = $target.closest(element).length === 1;
+ if (!thisIsElement) {
+ return this.onClickElsewhere(event);
+ }
+ },
+ didInsertElement: function() {
+ this._super.apply(this, arguments);
+ return $(window).on("click", this.get("clickHandler"));
+ },
+ willDestroyElement: function() {
+ $(window).off("click", this.get("clickHandler"));
+ return this._super.apply(this, arguments);
+ }
+});
+
+App.ComfirmDeleteComponent = Em.Component.extend(App.ClickElsewhereMixin,{
+ confirm:false,
+ onClickElsewhere:function () {
+ this.set('confirm',false);
+ },
+ actions: {
+ delete: function() {
+ if (this.get('confirm')) {
+ this.toggleProperty('confirm');
+ this.sendAction('action', this.get('param'));
+ } else {
+ this.toggleProperty('confirm');
+ };
+ }
+ },
+ tagName:'a',
+ tooltip:function () {
+ var element = this.$();
+ if (this.get('confirm')) {
+ element.tooltip({
+ placement:'left',
+ title:'Click again to confirm'
+ }).tooltip('show');
+ } else {
+ element.tooltip('destroy')
+ };
+ }.observes('confirm'),
+ click:function (e) {
+ this.send('delete');
+ },
+ didChange:function () {
+ this.set('confirm',false);
+ }.observes('param'),
+
+ classNames:['pull-right rm-queue'],
+ layout:Em.Handlebars.compile('<span class="fa-stack"> <i class="fa fa-times fa-stack-2x"></i> {{#if confirm}} <i class="fa fa-check fa-stack-1x fa-stack-bottom green"></i> {{/if}} </span> ')
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/escapeAcl.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/escapeAcl.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/escapeAcl.js
new file mode 100644
index 0000000..b5a3e07
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/escapeAcl.js
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+
+Ember.Handlebars.helper('escapeACL', function(value) {
+ var output = '';
+
+ value = value || '';
+
+ if (value.trim() == '') {
+ output = '<span class="label label-danger"> <i class="fa fa-ban fa-fw"></i> Nobody </span> ';
+ } else if (value.trim() == '*') {
+ output = '<label class="label label-success"> <i class="fa fa-asterisk fa-fw"></i> Anyone</label>';
+ } else {
+ var ug = value.split(' ');
+ var users = ug[0].split(',')||[];
+ var groups = (ug.length == 2)?ug[1].split(',')||[]:[];
+
+ output += ' <span class="users"> '
+
+ users.forEach(function (user) {
+ output += (user)?'<span class="label label-primary"><i class="fa fa-user fa-fw"></i> '+ user +'</span> ':'';
+ });
+
+ output += ' </span> <span class="groups"> '
+
+ groups.forEach(function (group) {
+ output += (group)?'<span class="label label-primary"><i class="fa fa-users fa-fw"></i> '+ group +'</span> ':'';
+ });
+ output += ' </span> '
+ }
+ return new Ember.Handlebars.SafeString(output);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/pathInput.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/pathInput.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/pathInput.js
new file mode 100644
index 0000000..ccdd5f1
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/pathInput.js
@@ -0,0 +1,61 @@
+/**
+ * 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.PathInputComponent = Em.Component.extend({
+ layoutName:'components/pathInput',
+ actions:{
+ add:function () {
+ var path = this.get('path'),
+ basedir = path.substr(0,path.lastIndexOf('.'));
+
+ if (this.get('pathMap').contains(path)) {
+ this.sendAction('action',path);
+ this.set('activeFlag',false);
+ } else if (this.get('pathMap').contains(basedir)) {
+ this.sendAction('action',basedir,path.substr(path.lastIndexOf('.')+1));
+ this.set('activeFlag',false);
+ }
+ },
+ cancel:function () {
+ this.set('activeFlag',false);
+ }
+ },
+ queues:[],
+ activeFlag:false,
+ pathMap:Em.computed.mapBy('queues','path'),
+ path:'',
+ inputFieldView: Em.TextField.extend({
+ classNames:['form-control newQPath'],
+ action:'add',
+ pathSource:[],
+ placeholder:"Enter queue path...",
+ typeaheadInit:function () {
+ $(this.get('element')).typeahead({
+ source: this.get('pathSource'),
+ matcher: function (item) {
+ return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+ },
+ minLength:0,
+ items:100,
+ scrollHeight:5
+ }).focus();
+ }.observes('pathSource').on('didInsertElement'),
+ })
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueListItem.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueListItem.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueListItem.js
new file mode 100644
index 0000000..c9bf813
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/queueListItem.js
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+App.RecurceQueuesComponent = Ember.View.extend({
+ templateName: "components/queueListItem",
+ depth:0,
+ parent:'',
+ leaf:function () {
+ return this.get('controller.arrangedContent')
+ .filterBy('depth',this.get('depth'))
+ .filterBy('parentPath',this.get('parent'));
+ }.property('depth','parent','controller.content.length','controller.content.@each.name'),
+ childDepth:function () {
+ return this.get('leaf.firstObject.depth')+1;
+ }.property('depth'),
+ didInsertElement:function () {
+ Ember.run.scheduleOnce('afterRender',null, this.setFirstAndLast, this);
+ },
+ setFirstAndLast:function (item) {
+ var items = item.$().parents('.queue-list').find('.list-group-item');
+ items.first().addClass('first');
+ items.last().addClass('last');
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/radioButton.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/radioButton.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/radioButton.js
new file mode 100644
index 0000000..30fd531
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/radioButton.js
@@ -0,0 +1,46 @@
+/**
+ * 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.RadioButtonInputComponent = Ember.View.extend({
+ tagName : "input",
+ type : "radio",
+ attributeBindings : [ "type", "value", "checked:checked" ],
+ click : function() {
+ this.set("selection", this.get('value'))
+ }
+});
+
+App.RadioButtonComponent = Em.Component.extend({
+ tagName:'label',
+ classNames:['btn btn-default'],
+ classNameBindings:['isActive:active'],
+
+ //arguments
+ selection:null,
+ label:null,
+ value:null,
+ click : function() {
+ this.set("selection", this.get('value'))
+ },
+ isActive : function() {
+ return this.get("value") == this.get("selection");
+ }.property("selection"),
+ layout:Em.Handlebars.compile('{{label}} {{radio-button-input selection=selection value=value checked=isActive}}')
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/totalCapacity.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/totalCapacity.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/totalCapacity.js
new file mode 100644
index 0000000..aad6682
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/totalCapacity.js
@@ -0,0 +1,98 @@
+/**
+ * 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.TotalCapacityComponent = Ember.Component.extend({
+ layoutName:'components/totalCapacity',
+
+ actions:{
+ toggleEdit:function () {
+ this.toggleProperty('isEdit');
+ },
+ addQueue:function (path) {
+ this.sendAction('addQueue',path);
+ },
+ createQueue:function (queue) {
+ this.sendAction('createQueue',queue);
+ },
+ deleteQueue:function (queue) {
+ this.sendAction('deleteQueue',queue);
+ },
+ },
+
+ /**
+ * passed params
+ */
+ currentQueue:null,
+ allQueues:[],
+ allQueuesArranged:[],
+
+ isEdit:false,
+
+ disableEdit:function () {
+ this.set('isEdit',false);
+ }.observes('allQueues'),
+
+ currentPrPath:Em.computed.alias('currentQueue.parentPath'),
+
+ leafQueuesCapacity: Ember.computed.map('leafQueues.@each.capacity', function (queue) {
+ return Number(queue.get('capacity'));
+ }),
+
+ totalCapacity: Ember.computed.sum('leafQueuesCapacity'),
+
+ leafQueues:function () {
+ return this.allQueuesArranged.filterBy('parentPath',this.get('currentPrPath')).filterBy('isNew',false);
+ }.property('allQueuesArranged.length','currentPrPath'),
+
+ newLeafQueues:function () {
+ return this.allQueues.filterBy('parentPath',this.get('currentPrPath')).filterBy('isNew',true);
+ }.property('allQueues.length','currentPrPath'),
+
+ parentQueue:function () {
+ return this.allQueues.findBy('path',this.get('currentPrPath'));
+ }.property('allQueues','currentPrPath'),
+
+ currentInLeaf:function (argument) {
+ var leaf = this.get('leafQueues');
+ leaf.setEach('isCurrent',false);
+ if(!this.get('currentQueue.currentState.stateName').match(/root.deleted/)) {
+ this.get('currentQueue').set('isCurrent',true);
+ }
+ }.observes('leafQueues','currentQueue').on('init'),
+
+ newQueueNameField: Em.TextField.extend({
+ queue:null,
+ classNames:['form-control'],
+ classNameBindings:['isValid::input-error'],
+ isValid:Em.computed.bool('queue.isValid')
+ })
+});
+
+App.CapacityEditFormView = Em.View.extend({
+ mark:function () {
+ this.addObserver('controller.target.isEdit',this,'slide');
+ if (!this.get('controller.target.isEdit')) {
+ this.$('.capacity-edit-form').hide();
+ };
+ }.on('didInsertElement'),
+ slide:function () {
+ this.$('.capacity-edit-form').slideToggle(100);
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/userGroupInput.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/userGroupInput.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/userGroupInput.js
new file mode 100644
index 0000000..ff0300d
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/components/userGroupInput.js
@@ -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.
+ */
+
+var App = require('app');
+
+App.UserGroupInputComponent = Em.Component.extend({
+ layoutName:'components/userGroupInput',
+
+ users:null,
+ groups:null,
+
+ splitter:function () {
+ if (this.ug == '*') return;
+ var ug = this.ug || '';
+ var spl = ug.split(' ');
+ this.setProperties({
+ users:spl[0],
+ groups:spl[1]
+ });
+ }.observes('ug').on('init'),
+
+ setter:function () {
+ this.set('ug',[this.get('users'),this.get('groups')].join(' '));
+ }.observes('users','groups'),
+
+ noSpace:function (e) {
+ return (e.keyCode==32)?false:true;
+ },
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers.js
new file mode 100644
index 0000000..0101a82
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers.js
@@ -0,0 +1,21 @@
+/**
+ * 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.
+ */
+
+require('controllers/queue');
+require('controllers/queues');
+require('controllers/trace');
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queue.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queue.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queue.js
new file mode 100644
index 0000000..91e3903
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queue.js
@@ -0,0 +1,186 @@
+/**
+ * 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');
+
+var _runState = 'RUNNING';
+var _stopState = 'STOPPED';
+
+App.QueueController = Ember.ObjectController.extend({
+ needs:['queues'],
+ actions:{
+ setState:function (state) {
+ var state = (state === "running")?_runState:_stopState;
+ this.content.set('state',state);
+ },
+ createQ:function (record) {
+ this.get('controllers.queues').send('createQ',this.get('content'));
+ },
+ addQ:function (path) {
+ this.get('controllers.queues').send('addQ',path);
+ },
+ delQ:function (record) {
+ this.get('controllers.queues').send('delQ',this.get('content'));
+ },
+ renameQ:function (opt) {
+ if (opt == 'ask') {
+ this.content.addObserver('name',this,this.setQueuePath);
+ this.toggleProperty('isRenaming');
+ return;
+ };
+ if (opt == 'cancel') {
+ this.send('rollbackProp','name');
+ this.send('rollbackProp','id');
+ this.send('rollbackProp','path');
+ this.content.removeObserver('name',this,this.setQueuePath);
+ this.toggleProperty('isRenaming');
+ return;
+ };
+ if (opt) {
+ var self = this;
+ this.store.filter('queue',function (q) {
+ return q.id === self.content.id;
+ }).then(function(queues){
+ if (queues.get('length') > 1) {
+ return self.content.get('errors').add('path', 'Queue already exists');
+ };
+ self.toggleProperty('isRenaming');
+ self.content.removeObserver('name',self,self.setQueuePath);
+ self.transitionToRoute('queue',self.content.id);
+ })
+ }
+
+ },
+ toggleEditRA:function () {
+ this.toggleProperty('isEditRA');
+ },
+ toggleEditACL:function () {
+ this.toggleProperty('isEditACL');
+ },
+ rollbackProp:function(prop){
+ attributes = this.content.changedAttributes();
+ if (attributes.hasOwnProperty(prop)) {
+ this.content.set(prop,attributes[prop][0]);
+ }
+ }
+ },
+ setQueuePath:function (queue,o) {
+ var name = queue.get(o);
+ var parentPath = queue.get('parentPath');
+
+ queue.setProperties({
+ name:name.replace(/\s|\./g, ''),
+ path:parentPath+'.'+name,
+ id:(parentPath+'.'+name).dasherize(),
+ });
+
+ if (name == '') {
+ queue.get('errors').add('path', 'This field is required');
+ }
+ },
+
+ isRenaming:false,
+
+ unsetRenaming:function () {
+ this.set('isRenaming',false);
+ }.observes('content'),
+
+ isRoot:Ember.computed.equal('content.id', 'root'),
+ isRunning:Ember.computed.equal('content.state', _runState),
+ allQueues:Em.computed.alias('controllers.queues.content'),
+ allQueuesArranged:Em.computed.alias('controllers.queues.arrangedContent'),
+
+ isEditRA:false,
+ isEditACL:false,
+
+ acl_administer_queue:null,
+ aaq_anyone:Ember.computed.equal('acl_administer_queue', '*'),
+ aaq_dirty:function () {
+ var attributes = this.content.changedAttributes();
+ return attributes.hasOwnProperty('acl_administer_queue');
+ }.property('content.acl_administer_queue'),
+
+ acl_administer_jobs:null,
+ aaj_anyone:Ember.computed.equal('acl_administer_jobs', '*'),
+ aaj_dirty:function () {
+ var attributes = this.content.changedAttributes();
+ return attributes.hasOwnProperty('acl_administer_jobs');
+ }.property('content.acl_administer_jobs'),
+
+ acl_submit_applications:null,
+ asa_anyone:Ember.computed.equal('acl_submit_applications', '*'),
+ asa_dirty:function () {
+ var attributes = this.content.changedAttributes();
+ return attributes.hasOwnProperty('acl_submit_applications');
+ }.property('content.acl_submit_applications'),
+
+ aclSerializer:function (c,o) {
+ var acl = o.substr(o.indexOf('.')+1);
+ var aclProp = c.get(o);
+ var aclVal;
+ switch(aclProp) {
+ case '*':
+ aclVal = '*';
+ break;
+
+ default:
+ aclVal = 'custom';
+ }
+ c.set(acl,aclVal);
+ }.observes('content.acl_administer_queue','content.acl_administer_jobs','content.acl_submit_applications'),
+
+ aclDeserializer:function (c,o) {
+ var aclVal = c.get(o);
+ var aclProp;
+ switch(aclVal) {
+ case '*':
+ aclProp = '*';
+ this.set('content.'+o,aclProp);
+ break;
+
+ default:
+ if (this.get('content.'+o)=='*') {
+ this.set('content.'+o,' ');
+ }
+ }
+ }.observes('acl_administer_queue','acl_administer_jobs','acl_submit_applications'),
+
+ capacityControl:function () {
+ var leafQueues = this.get('leafQueues');
+ var total = 0;
+
+ leafQueues.forEach(function (queue) {
+ total+=Number(queue.get('capacity'));
+ });
+ leafQueues.setEach('overCapacity',total>100)
+ }.observes('content.capacity','leafQueues.@each.capacity'),
+ leafQueues:function () {
+ return this.get('allQueues').filterBy('parentPath',this.get('content.parentPath'));
+ }.property('allQueues.length','content.parentPath'),
+
+ queueNamesControl:function (c,o) {
+ var leaf = c.get('leafQueues');
+ var parent = c.get('allQueues').filterBy('path',c.get('content.parentPath')).get('firstObject');
+ if (parent) parent.set('queueNames',leaf.mapBy('name').join());
+ }.observes('allQueues.length','allQueues.@each.name'),
+
+ pathErrors:Ember.computed.mapBy('content.errors.path','message')
+
+});
+
+App.ErrorController = Ember.ObjectController.extend();
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queues.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queues.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queues.js
new file mode 100644
index 0000000..cdbf41b
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/queues.js
@@ -0,0 +1,154 @@
+/**
+ * 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');
+
+var cmp = Ember.computed;
+
+App.QueuesController = Ember.ArrayController.extend({
+ sortProperties: ['name'],
+ sortAscending: true,
+ actions:{
+ goToQueue:function (queue) {
+ this.transitionToRoute('queue',queue)
+ },
+ askPath:function () {
+ this.set('isWaitingPath',true);
+ },
+ addQ:function (parentPath,name) {
+ if (!parentPath || this.get('hasNewQueue')) {
+ return;
+ };
+ name = name || '';
+ var newQueue = this.store.createRecord('queue',{
+ name:name,
+ parentPath: parentPath,
+ depth: parentPath.split('.').length,
+ isNewQueue:true
+ });
+ this.set('newQueue',newQueue);
+ this.send('goToQueue',newQueue);
+ },
+ createQ:function (record) {
+ record.save().then(Em.run.bind(this,this.set,'newQueue',null));
+ },
+ delQ:function (record) {
+ if (record.get('isNew')) {
+ this.set('newQueue',null);
+ };
+ if (!record.get('isNewQueue')) {
+ this.set('hasDeletedQueues',true);
+ };
+ if (record.isCurrent) {
+ this.transitionToRoute('queue',record.get('parentPath'));
+ };
+ this.store.deleteRecord(record);
+ },
+ saveConfig:function (mark) {
+ if (mark == 'restart') {
+ this.get('store').markForRestart();
+ } else if (mark == 'refresh') {
+ this.get('store').markForRefresh();
+ };
+ Em.RSVP.Promise.all([this.get('scheduler').save(),this.get('model').save()])
+ .catch(Em.run.bind(this,this.saveError));
+ },
+ toggleEditScheduler:function () {
+ this.toggleProperty('isEditScheduler');
+ },
+ clearAlert:function () {
+ this.set('alertMessage',null);
+ }
+ },
+
+ alertMessage:null,
+ saveError:function (error) {
+ var response = JSON.parse(error.responseText);
+ this.set('alertMessage',response);
+ },
+
+ isEditScheduler:false,
+
+ isWaitingPath:false,
+ /**
+ * check if RM needs refresh
+ * @type {bool}
+ */
+ needRefresh: cmp.any('hasChanges', 'hasNewQueues','dirtyScheduler'),
+
+ /**
+ * props for 'needRefresh'
+ */
+ dirtyQueues: cmp.filterBy('content', 'isDirty', true),
+ dirtyScheduler: cmp.bool('scheduler.isDirty'),
+ newQueues: cmp.filterBy('content', 'isNewQueue', true),
+ hasChanges: cmp.notEmpty('dirtyQueues.[]'),
+ hasNewQueues: cmp.notEmpty('newQueues.[]'),
+
+ /**
+ * check if RM needs restart
+ * @type {bool}
+ */
+ needRestart: cmp.any('hasDeletedQueues', 'hasRenamedQueues'),
+
+ /**
+ * props for 'needRestart'
+ */
+ hasDeletedQueues:false,
+ hasRenamedQueues: cmp.notEmpty('renamedQueues.[]'),
+ renamedQueues:function () {
+ return this.content.filter(function(queue){
+ var attr = queue.changedAttributes();
+ return attr.hasOwnProperty('name') && !queue.get('isNewQueue');
+ });
+ }.property('content.@each.name'),
+
+ /**
+ * check if can save configs
+ * @type {bool}
+ */
+ canNotSave: cmp.any('hasOverCapacity', 'hasUncompetedAddings','hasNotValid'),
+
+ /**
+ * props for canNotSave
+ */
+ notValid:cmp.filterBy('content','isValid',false),
+ overCapacityQ:cmp.filterBy('content','overCapacity',true),
+ uncompetedAddings:cmp.filterBy('content', 'isNew', true),
+ hasNotValid:cmp.notEmpty('notValid.[]'),
+ hasOverCapacity:cmp.notEmpty('overCapacityQ.[]'),
+ hasUncompetedAddings:cmp.notEmpty('uncompetedAddings.[]'),
+
+ newQueue:null,
+ hasNewQueue: cmp.bool('newQueue'),
+ trackNewQueue:function () {
+ var newQueue = this.get('newQueue');
+ if (Em.isEmpty(newQueue)){
+ return;
+ };
+ var name = newQueue.get('name');
+ var parentPath = newQueue.get('parentPath');
+
+ this.get('newQueue').setProperties({
+ name:name.replace(/\s/g, ''),
+ path:parentPath+'.'+name,
+ id:(parentPath+'.'+name).dasherize(),
+ });
+
+ }.observes('newQueue.name')
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/trace.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/trace.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/trace.js
new file mode 100644
index 0000000..54c257c
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/controllers/trace.js
@@ -0,0 +1,26 @@
+/**
+ * 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.TraceController = Ember.ObjectController.extend({
+ needs:['queues'],
+ trace:function () {
+ return this.get('controllers.queues.alertMessage.trace')||'No trace';
+ }.property('controllers.queues.alertMessage')
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/initialize.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/initialize.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/initialize.js
new file mode 100644
index 0000000..ebea5ff
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/initialize.js
@@ -0,0 +1,40 @@
+/**
+ * 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.
+ */
+
+window.App = require('app');
+
+// Set this value to true to run in test mode with local data
+App.testMode = false;
+
+// adapters
+require('adapters');
+
+//components
+require('components');
+
+//controllers
+require('controllers');
+
+// templates
+require('templates');
+
+// models
+require('models');
+
+// routes
+require('router');
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/models.js
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/models.js b/contrib/views/capacity-scheduler/src/main/resources/ui/app/models.js
new file mode 100644
index 0000000..89bbdaa
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/models.js
@@ -0,0 +1,19 @@
+/**
+ * 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.
+ */
+
+require('models/queue');
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/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
new file mode 100644
index 0000000..4b951d3
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/models/queue.js
@@ -0,0 +1,64 @@
+/**
+ * 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.Scheduler = DS.Model.extend({
+ maximum_am_resource_percent: DS.attr('number', { defaultValue: 0 }),
+ maximum_applications: DS.attr('number', { defaultValue: 0 }),
+ node_locality_delay: DS.attr('number', { defaultValue: 0 })
+});
+
+/**
+ * Represents the queue.
+ *
+ */
+App.Queue = DS.Model.extend({
+ name: DS.attr('string'),
+ parentPath: DS.attr('string'),
+ depth: DS.attr('number'),
+ path: DS.attr('string'),
+
+ // cs props
+
+ // queue props
+ state: DS.attr('string', { defaultValue: 'RUNNING' }),
+
+ capacity: DS.attr('number', { defaultValue: 0 }),
+ maximum_capacity: DS.attr('number', { defaultValue: 0 }),
+ unfunded_capacity: DS.attr('number', { defaultValue: 0 }),
+
+ acl_administer_queue: DS.attr('string', { defaultValue: '*' }),
+ acl_administer_jobs: DS.attr('string', { defaultValue: '*' }),
+ acl_submit_applications: DS.attr('string', { defaultValue: '*' }),
+
+ minimum_user_limit_percent: DS.attr('number', { defaultValue: 0 }),
+ user_limit_factor: DS.attr('number', { defaultValue: 0 }),
+
+ queueNames: DS.attr('string'),
+ queueNamesArray:function () {
+ return (this.get('queueNames.length')>0)?this.get('queueNames').split(','):[];
+ }.property('queueNames'),
+
+
+
+ overCapacity:false,
+
+ //new queue flag
+ isNewQueue:DS.attr('boolean', {defaultValue: false})
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/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
new file mode 100644
index 0000000..fc9108c
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/router.js
@@ -0,0 +1,122 @@
+/**
+ * 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.Router.map(function() {
+ this.resource('queues', { path: '/queues' }, function() {
+ this.resource('queue', { path: '/:queue_id' });
+ this.resource('trace', { path: '/log' });
+ });
+});
+
+
+/**
+ * The queues route.
+ *
+ * /queues
+ */
+App.TraceRoute = Ember.Route.extend({
+ model: function() {
+ return this.controllerFor('queues').get('alertMessage');
+ }
+});
+
+/**
+ * The queues route.
+ *
+ * /queues
+ */
+App.QueuesRoute = Ember.Route.extend({
+ actions:{
+ },
+ model: function() {
+ return this.store.find('queue');
+ },
+ setupController:function (c,model) {
+ c.set('model',model);
+ this.store.find('scheduler','scheduler').then(function (s) {
+ c.set('scheduler',s);
+ });
+ }
+});
+
+/**
+ * The queue route.
+ *
+ * /queues/:id
+ */
+App.QueueRoute = Ember.Route.extend({
+ model: function(params,tr) {
+ var queues = this.modelFor('queues') || this.store.find('queue'),
+ filterQueues = function (queues) {
+ return queues.filterBy('id',params.queue_id).get('firstObject');
+ };
+
+ return (queues instanceof DS.PromiseArray)?queues.then(filterQueues):filterQueues(queues);
+ },
+ afterModel:function (model) {
+ if (!model) {
+ this.transitionTo('queues');
+ }
+ },
+
+ actions: {
+ refreshQueue: function() {
+ var x = "{ \"RequestInfo\" : { \"command\" : \"REFRESHQUEUES\", \"context\" : \"Refresh YARN Capacity Scheduler\" }, "
+ x = x + "\"Requests/resource_filters\":[{\"service_name\":\"YARN\",\"component_name\":\"RESOURCEMANAGER\",\"hosts\":\"c6403.ambari.apache.org\"}]}";
+
+ App.Adapter.ajaxPost("/api/v1/clusters/MyCluster/requests", x);
+ },
+ willTransition:function (tr) {
+ if (this.get('controller.isRenaming')) {
+ tr.abort();
+ };
+ }
+ }
+
+});
+
+/**
+ * Routes index to /queues path
+ *
+ */
+App.IndexRoute = Ember.Route.extend({
+ beforeModel: function() {
+ this.transitionTo('queues');
+ }
+});
+
+/**
+ * Loading spinner page.
+ *
+ */
+App.LoadingRoute = Ember.Route.extend();
+
+/**
+ * Error page.
+ *
+ */
+App.ErrorRoute = Ember.Route.extend({
+ setupController:function (controller,model) {
+ var response = JSON.parse(model.responseText);
+ controller.set('model',response);
+ }
+});
+
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/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
new file mode 100644
index 0000000..94e3996
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/styles/application.less
@@ -0,0 +1,238 @@
+/**
+ * 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.
+ */
+
+.wrap {
+ padding: 15px;
+}
+
+.btn {
+ padding: 6px 10px;
+ transition: background-color .08s linear 0s;
+}
+
+.input-error {
+ color: #a94442;
+ border-color: #a94442;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.input-error:focus {
+ border-color: #843534;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
+}
+
+.gray {
+ color: #999;
+}
+
+.green {
+ color: #5cb85c;
+}
+
+.blue {
+ color: #428bca;
+}
+
+.red {
+ color: #d9534f;
+}
+
+.add-queue {
+ margin-bottom: 5px;
+}
+
+.rm-queue {
+ cursor: pointer;
+ .gray;
+ transition: color .1s linear;
+ &:hover {
+ .red;
+ }
+}
+
+.fa-stack-bottom {
+ text-align: right;
+ bottom: 0;
+ line-height: 1em;
+ //opacity: 0.9;
+ text-shadow: 0px -1px 3px #111;
+}
+
+.queue-list{
+ .badge {
+ color: #999;
+ background-color: #fff;
+ margin-left: 5px;
+ }
+ .progress {
+ height: 3px;
+ margin: 0;
+ }
+ .spacer {
+ height: 25px;
+ }
+ .spacer.col-md-0 {
+ height: 0;
+ }
+ .capacity-bar {
+ display: inline-block;
+ float: right;
+ margin-top: 8px;
+ width: 20%;
+ }
+ .list-group-item {
+ cursor: pointer;
+ transition: background-color .1s linear 0s;
+ }
+ .list-group-item.last {
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ }
+ .list-group-item.first {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ }
+}
+
+.path-input {
+ .btn-cancel {
+ border-radius: 0;
+ }
+}
+
+.user-group-input.has-feedback {
+ .form-control-feedback {
+ top: -2px;
+ right: 15px;
+ opacity: 0.4;
+ }
+}
+
+.btn-group-save {
+ table-layout: auto;
+ .btn-group {
+ width: 100%;
+ .btn-save {
+ border-top-left-radius: 4px !important;
+ border-bottom-left-radius: 4px !important;
+ }
+ }
+}
+
+.form-acl {
+ .users .label,.groups .label {
+ border-radius: 0;
+ }
+ .users .label:first-child,.groups .label:first-child {
+ border-top-left-radius: .25em;
+ border-bottom-left-radius: .25em;
+ }
+ .users .label:last-child,.groups .label:last-child {
+ border-top-right-radius: .25em;
+ border-bottom-right-radius: .25em;
+ }
+ .label {
+ vertical-align: text-top;
+ }
+}
+
+.panel-capacity {
+ .new-queue {
+ .input-row {
+ margin-bottom: 5px;
+ }
+ }
+ .progress{
+ background-color: #ddd;
+ .marks {
+ width: 100%;
+ top: 20px;
+ position: absolute;
+ label {
+ width: 25%;
+ display: block;
+ text-align: center;
+ position: absolute;
+ margin-left: -12.5%;
+ div {
+ position: absolute;
+ left: 50%;
+ top: -5px;
+ height: 20px;
+ border-left: solid 1px #fff;
+ -webkit-box-shadow:0px 0px 2px 1px rgba(0, 0, 0, .15);
+ box-shadow:0px 0px 2px 1px rgba(0, 0, 0, .15);
+ }
+ }
+ }
+ }
+ .panel-title {
+ position: relative;
+ a {
+ position: absolute;
+ right: 0;
+ color: #428bca;
+ }
+ }
+ .panel-body.total{
+ .progress {
+ margin: 0;
+ }
+ }
+ .panel-body.queues {
+ border-top: 1px solid #dddddd;
+ background-color: #f5f5f5;
+ }
+ .queue-capacity{
+ border-bottom: 1px solid #dddddd;
+ padding-bottom: 8px;
+ padding-top: 8px;
+ &.active {
+ .progress {
+ -webkit-box-shadow: 0px 0px 0px #888888;
+ -moz-shadow: 0px 0px 0px #888888;
+ box-shadow: 0px 0px 0px #888888;
+ transition: box-shadow .25s linear 0s;
+ }
+ .progress.in {
+ -webkit-box-shadow: 3px 5px 5px #888888;
+ -moz-shadow: 3px 5px 5px #888888;
+ box-shadow: 3px 5px 5px #888888;
+ }
+ }
+ .form-inline .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: top;
+ }
+ .help-block {
+ display: inline;
+ }
+ /*input {
+ width: auto;
+ }*/
+ }
+}
+
+.queue-heading-row {
+ h3 {
+ margin:10px;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/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
new file mode 100644
index 0000000..18c06a7
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates.js
@@ -0,0 +1,36 @@
+/**
+ * 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.
+ */
+
+// load templates
+
+require('templates/error');
+require('templates/trace');
+require('templates/loading');
+require('templates/queue');
+require('templates/queues');
+require('templates/error');
+require('templates/queues/index');
+
+require('templates/capacityEditForm');
+require('templates/schedulerPanel');
+
+require('templates/components/capacityBar');
+require('templates/components/totalCapacity');
+require('templates/components/queueListItem');
+require('templates/components/pathInput');
+require('templates/components/userGroupInput');
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capacityEditForm.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capacityEditForm.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capacityEditForm.hbs
new file mode 100644
index 0000000..9442973
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/capacityEditForm.hbs
@@ -0,0 +1,34 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<form {{bind-attr class=":form-inline :capacity-edit-form " }} role="form">
+ <div {{bind-attr class=":form-group" }}>
+ <label class="control-label">Capacity: </label>
+ {{capacity-input class='input-sm' value=this.capacity totalCapacity=view.totalCapacity queue=this maxVal=100}}
+
+ </div>
+ <div {{bind-attr class=":form-group this.isValid::has-error" }}>
+ <label class="control-label">Maximum capacity: </label>
+ {{max-capacity-input class='input-sm' value=this.maximum_capacity totalCapacity=view.totalCapacity queue=this maxVal=100}}
+ {{#each this.errors.maximum_capacity}}
+ <span class="help-block">
+ {{message}}
+ </span>
+ {{/each}}
+ </div>
+</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/capacityBar.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/capacityBar.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/capacityBar.hbs
new file mode 100644
index 0000000..d860cc4
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/capacityBar.hbs
@@ -0,0 +1,35 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class="progress progress-labelled" data-label-max="100" data-label-step="25" style="position: relative;">
+ <div {{bind-attr style="capacityWidth" class=":progress-bar warn:progress-bar-danger:progress-bar-success"}}>
+ <span>
+ {{capacityValue}}%
+ </span>
+ </div>
+ <div class="progress-bar progress-bar-warning" {{bind-attr style="maxCapacityWidth"}}>
+ </div>
+
+ <div class="marks">
+ <label style="left: 25%;"><div></div></label>
+ <label style="left: 50%;"><div></div></label>
+ <label style="left: 75%;"><div></div></label>
+ </div>
+
+</div>
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/pathInput.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/pathInput.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/pathInput.hbs
new file mode 100644
index 0000000..ec4ec4c
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/pathInput.hbs
@@ -0,0 +1,29 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class="input-group path-input">
+ {{view inputFieldView pathSource=pathMap value=path}}
+ <span class="input-group-btn">
+ <button {{action cancel}} class="btn btn-danger" type="button">
+ <i class="fa fa-times"></i>
+ </button>
+ <button {{action add}} class="btn btn-success" type="button">
+ <i class="fa fa-check"></i>
+ </button>
+ </span>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueListItem.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueListItem.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueListItem.hbs
new file mode 100644
index 0000000..9c23541
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/queueListItem.hbs
@@ -0,0 +1,60 @@
+{{!
+* 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.
+}}
+
+{{#each view.leaf}}
+ {{#link-to "queue" this classNameBindings=":list-group-item overCapacity:list-group-item-danger isNew:list-group-item-info" }}
+ <div class="col-md-offset-{{unbound this.depth}} col-sm-offset-{{unbound this.depth}} col-xs-offset-{{unbound this.depth}}">
+
+ {{name}} ({{capacity}}%)
+
+ <span class="badge pull-right">
+ {{#if overCapacity}}
+ <i class="fa fa-fw fa-lg red fa-warning"></i>
+ {{/if}}
+ {{#if isNewQueue }}
+ {{#if isSaving}}
+ <i class="fa fa-fw fa-lg gray fa-spinner fa-spin"></i>
+ {{else}}
+ <i class="fa fa-fw fa-lg blue fa-plus"></i>
+ {{/if}}
+ {{else}}
+ {{#if isError}}
+ {{#if isSaving}}
+ <i class="fa fa-fw fa-lg gray fa-spinner fa-spin"></i>
+ {{else}}
+ <span> queue was not saved </span> <i class="fa fa-fw fa-lg red fa-warning"></i>
+ {{/if}}
+ {{else}}
+ {{#if isDirty}}
+ {{#if isSaving}}
+ <i class="fa fa-fw fa-lg gray fa-spinner fa-spin"></i>
+ {{else}}
+ <i class="fa fa-fw fa-lg blue fa-pencil"></i>
+ {{/if}}
+ {{else}}
+ <i class="fa fa-fw fa-lg green fa-check"></i>
+ {{/if}}
+ {{/if}}
+ {{/if}}
+ </span>
+
+ </div>
+ {{/link-to}}
+
+ {{recurce-queues depth=view.childDepth parent=this.path}}
+{{/each}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/totalCapacity.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/totalCapacity.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/totalCapacity.hbs
new file mode 100644
index 0000000..c934081
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/totalCapacity.hbs
@@ -0,0 +1,72 @@
+{{!
+* 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 panel-capacity">
+ <div class="panel-heading">
+ <div class="panel-title">
+ <strong>Capacity</strong>
+ <a href="#" {{action 'toggleEdit'}} class="text-right">
+ {{#if view.isEdit}}
+ <i class="fa fa-edit">Hide edit</i>
+ {{else}}
+ <i class="fa fa-edit">Show edit</i>
+ {{/if}}
+ </a>
+ </div>
+ </div>
+ <div class="panel-body total">
+ TOTAL
+ {{capacity-bar capacityValue=totalCapacity maxCapacityValue=totalCapacity warn=leafQueues.firstObject.overCapacity}}
+ </div>
+ <div class="panel-body queues">
+ {{#each leafQueues}}
+ <div {{bind-attr class=":queue-capacity this.isCurrent:active"}}>
+ <p>
+ {{this.name}} {{#if isCurrent}} <span class="label label-default">Current</span> {{/if}}
+ </p>
+ {{capacity-bar capacityValue=this.capacity maxCapacityValue=this.maximum_capacity warn=this.overCapacity}}
+ {{render "capacityEditForm" this}}
+ </div>
+ {{/each}}
+ {{#each newLeafQueues}}
+ <div {{bind-attr class=":queue-capacity :new-queue this.isCurrent:active"}} >
+ <div class="input-row row" >
+ <div class="col-md-5">
+ <div class="input-group">
+ {{view view.newQueueNameField value=this.name queue=this placeholder="Enter queue name..."}}
+ <span class="input-group-btn">
+ <button {{action "deleteQueue" this}} {{bind-attr class=":btn :btn-danger"}} type="button">Cancel</button>
+ <button {{action "createQueue" this}} {{bind-attr class=":btn :btn-default this.isValid::disabled"}} type="button">Create</button>
+ </span>
+ </div>
+ {{#each this.errors.path}}
+ <p class="help-block red">{{this.message}}</p>
+ {{/each}}
+ </div>
+ </div>
+ {{capacity-bar capacityValue=this.capacity maxCapacityValue=this.maximum_capacity warn=this.overCapacity}}
+ {{render "capacityEditForm" this}}
+ </div>
+ {{/each}}
+ {{#if currentQueue.parentPath}}
+ <div class="queue-capacity" >
+ <button {{action "addQueue" currentQueue.parentPath}} {{bind-attr class=":btn :btn-default :btn-block hasNew:disabled"}}><i class="fa fa-plus"></i> Add queue</button>
+ </div>
+ {{/if}}
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/userGroupInput.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/userGroupInput.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/userGroupInput.hbs
new file mode 100644
index 0000000..fab7ea8
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/components/userGroupInput.hbs
@@ -0,0 +1,37 @@
+{{!
+* 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="user-group-input form-group has-feedback ">
+ <div class="col-sm-4 control-label">
+ Users:
+ </div>
+ <div class="col-sm-8">
+ {{input keyDown=noSpace disabledBinding="disabled" class="form-control input-sm" value=users placeholder="Comma-separated list of users"}}
+ <i class="fa fa-user form-control-feedback"></i>
+ </div>
+</div>
+<div class="form-group has-feedback user-group-input">
+ <div class="col-sm-4 control-label">
+ Groups:
+ </div>
+ <div class="col-sm-8">
+ {{input keyDown=noSpace disabledBinding="disabled" class="form-control input-sm" value=groups placeholder="Comma-separated list of groups"}}
+ <i class="fa fa-users form-control-feedback"></i>
+ </div>
+</div>
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/error.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/error.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/error.hbs
new file mode 100644
index 0000000..a45c1e7
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/error.hbs
@@ -0,0 +1,35 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class="panel panel-danger">
+ <div class="panel-heading">
+ <div class="text-center">
+ <strong>{{content.status}}</strong> {{content.message}}
+ {{#if content.trace}}
+ <a data-toggle="collapse" class="btn btn-danger btn-xs" href="#collapseOne">Trace <span class="caret"></span></a>
+ {{/if}}
+ </div>
+ </div>
+ <div id="collapseOne" class="panel-collapse collapse">
+ <div class="panel-body">
+ <pre>
+ {{content.trace}}
+ </pre>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/loading.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/loading.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/loading.hbs
new file mode 100644
index 0000000..8017bcf
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/loading.hbs
@@ -0,0 +1,19 @@
+{{!
+ 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="spinner spinner-bg"></div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/bb0116c3/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/queue.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/queue.hbs b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/queue.hbs
new file mode 100644
index 0000000..f92eedd
--- /dev/null
+++ b/contrib/views/capacity-scheduler/src/main/resources/ui/app/templates/queue.hbs
@@ -0,0 +1,229 @@
+{{!
+* 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="well">
+
+ <div class="row queue-heading-row">
+ <div class="col-md-12">
+ {{#if content.isNew}}
+ <div class="input-group">
+ {{focus-input value=content.name class="form-control" classBinding="content.isValid::input-error" action="createQ" revert="delQ" placeholder="Enter queue name..."}}
+ <span class="input-group-btn">
+ <button {{action "delQ" content target="controllers.queues"}} {{bind-attr class=":btn :btn-danger"}} type="button">Cancel</button>
+ <button {{action "createQ" content target="controllers.queues"}} {{bind-attr class=":btn :btn-default content.isValid::disabled"}} type="button">Create</button>
+ </span>
+ </div>
+ {{else}}
+ {{#unless isRenaming}}
+ <h3>
+ {{content.name}}
+ {{#unless isRoot}}
+ <small>
+ <a href="#" {{action "renameQ" 'ask'}} class="">
+ <i class="fa fa-edit"></i>
+ </a>
+ </small>
+ <small>
+ {{comfirm-delete action="delQ" param=content}}
+ </small>
+ {{/unless}}
+ </h3>
+ {{else}}
+ <div class="input-group">
+ {{focus-input value=content.name class="form-control" action="renameQ" revert="renameQ" classBinding="content.isValid::input-error" placeholder="Enter queue name..."}}
+ <span class="input-group-btn">
+ <button {{action "renameQ" 'cancel'}} {{bind-attr class=":btn :btn-danger"}} type="button">Cancel</button>
+ <button {{action "renameQ" 'rename'}} {{bind-attr class=":btn :btn-default content.isValid::disabled"}} type="button">Rename</button>
+ </span>
+ </div>
+ {{/unless}}
+ {{/if}}
+ {{#each pathErrors}}
+ <p class="help-block red">{{this}}</p>
+ {{/each}}
+ <h4 ><small>{{content.path}}</small>
+ <div class="btn-group btn-group-xs" data-toggle="buttons" >
+ <label {{action 'setState' 'running'}} {{bind-attr class=":btn isRunning:btn-success:btn-default isRunning:active" }}>
+ <input type="radio" name="options"> Running
+ </label>
+ <label {{action 'setState' 'stopped'}} {{bind-attr class=":btn isRunning:btn-default:btn-danger isRunning::active" }}>
+ <input type="radio" name="options"> Stopped
+ </label>
+ </div>
+ </h4>
+ </div>
+ </div>
+ <div class="row queue-capacity-row">
+ <div class="col-md-12">
+ {{total-capacity
+ currentQueue=content
+ allQueues=allQueues
+ allQueuesArranged=allQueuesArranged
+ addQueue="addQ"
+ createQueue="createQ"
+ deleteQueue="delQ"
+ hasNew=controllers.queues.hasNewQueue
+ }}
+ </div>
+ </div>
+ <div class="row queue-acl-row">
+ <div class="col-md-6">
+ <div class="panel panel-default panel-capacity">
+ <div class="panel-heading">
+ <div class="panel-title">
+ Access control
+ <a href="#" {{action 'toggleEditACL'}} class="text-right">
+ {{#if isEditACL}}
+ <small><i class="fa fa-edit"> Hide edit</i> </small>
+ {{else}}
+ <small><i class="fa fa-edit">Show edit</i> </small>
+ {{/if}}
+ </a>
+ </div>
+ </div>
+ <div class="panel-body">
+ <form class="form-horizontal form-acl" role="form">
+ {{#if isEditACL}}
+
+ <div class="form-group row">
+ <label class="col-lg-6 col-md-6 col-sm-4 col-xs-5 control-label">Administer Queue ACL</label>
+ <div class="col-lg-6 col-md-6 col-sm-8 col-xs-7">
+ <div class="btn-group btn-group-xs" data-toggle="buttons">
+ {{radio-button label="Anyone" selectionBinding="acl_administer_queue" value="*"}}
+ {{radio-button label="Custom" selectionBinding="acl_administer_queue" value="custom"}}
+ </div>
+ {{#if aaq_dirty}}
+ <a {{action 'rollbackProp' 'acl_administer_queue'}} href="#"><i class="fa fa-undo"></i></a>
+ {{/if}}
+ </div>
+ </div>
+ {{#unless aaq_anyone}}
+ {{user-group-input ug=content.acl_administer_queue disabled=aaq_anyone}}
+ {{/unless}}
+
+ <div class="form-group row">
+ <label class="col-lg-6 col-md-6 col-sm-4 col-xs-5 control-label">Administer Jobs ACL</label>
+ <div class="col-lg-6 col-md-6 col-sm-8 col-xs-7">
+ <div class="btn-group btn-group-xs" data-toggle="buttons">
+ {{radio-button label="Anyone" selectionBinding="acl_administer_jobs" value="*"}}
+ {{radio-button label="Custom" selectionBinding="acl_administer_jobs" value="custom"}}
+ </div>
+ {{#if aaj_dirty}}
+ <a {{action 'rollbackProp' 'acl_administer_jobs'}} href="#"><i class="fa fa-undo"></i></a>
+ {{/if}}
+ </div>
+ </div>
+ {{#unless aaj_anyone}}
+ {{user-group-input ug=content.acl_administer_jobs disabled=aaj_anyone}}
+ {{/unless}}
+
+
+ <div class="form-group row">
+ <label class="col-lg-6 col-md-6 col-sm-4 col-xs-5 control-label">Submit Applications ACL</label>
+ <div class="col-lg-6 col-md-6 col-sm-8 col-xs-7">
+ <div class="btn-group btn-group-xs" data-toggle="buttons">
+ {{radio-button label="Anyone" selectionBinding="acl_submit_applications" value="*"}}
+ {{radio-button label="Custom" selectionBinding="acl_submit_applications" value="custom"}}
+ </div>
+ {{#if asa_dirty}}
+ <a {{action 'rollbackProp' 'acl_submit_applications'}} href="#"><i class="fa fa-undo"></i></a>
+ {{/if}}
+ </div>
+ </div>
+ {{#unless asa_anyone}}
+ {{user-group-input ug=content.acl_submit_applications disabled=asa_anyone}}
+ {{/unless}}
+
+ {{else}}
+ <div class="form-group">
+ <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">Administer Queue ACL</label>
+ <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+ <p class="form-control-static">
+ {{escapeACL content.acl_administer_queue}}
+ </p>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">Administer Jobs ACL</label>
+ <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+ <p class="form-control-static">
+ {{escapeACL content.acl_administer_jobs}}
+ </p>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">Submit Applications ACL</label>
+ <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+ <p class="form-control-static">
+ {{escapeACL content.acl_submit_applications}}
+ </p>
+ </div>
+ </div>
+ {{/if}}
+ </form>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-md-6">
+ <div class="panel panel-default panel-capacity">
+ <div class="panel-heading">
+ <div class="panel-title">
+ Resource Allocation
+ <a href="#" {{action 'toggleEditRA'}} class="text-right">
+ {{#if isEditRA}}
+ <small><i class="fa fa-edit"> Hide edit</i> </small>
+ {{else}}
+ <small><i class="fa fa-edit">Show edit</i> </small>
+ {{/if}}
+ </a>
+ </div>
+ </div>
+ <div class="panel-body">
+ <form class="form-horizontal" role="form">
+ <div class="form-group">
+ <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">User Limit Factor</label>
+ <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+ {{#if isEditRA}}
+ {{int-input value=content.user_limit_factor class="input-sm"}}
+ {{else}}
+ <p class="form-control-static">{{content.user_limit_factor}}</p>
+ {{/if}}
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="col-lg-6 col-md-6 col-sm-6 col-xs-6 control-label">Minimum User Limit</label>
+ <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
+ {{#if isEditRA}}
+ <div class="input-group">
+ {{int-input value=content.minimum_user_limit_percent class="input-sm" maxVal=100}}
+ <span class="input-group-addon">%</span>
+ </div>
+ {{else}}
+ <p class="form-control-static">{{content.minimum_user_limit_percent}} %</p>
+ {{/if}}
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>