12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181 |
- /**
- * 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 validator = require('utils/validator');
- App.ServicesConfigView = Em.View.extend({
- templateName: require('templates/common/configs/services_config'),
- didInsertElement: function () {
- var controller = this.get('controller');
- controller.loadStep();
- }
- });
- App.ServiceConfigView = Em.View.extend({
- templateName: require('templates/common/configs/service_config'),
- isRestartMessageCollapsed: false,
- filter: '', //from template
- columns: [], //from template
- canEdit: true, // View is editable or read-only?
- toggleRestartMessageView: function(){
- this.$('.service-body').toggle('blind', 200);
- this.set('isRestartMessageCollapsed', !this.get('isRestartMessageCollapsed'));
- },
- didInsertElement: function () {
- this.$('.service-body').hide();
- $(".restart-required-property").tooltip({html:true});
- }
- });
- App.ServiceConfigsByCategoryView = Ember.View.extend({
- classNames: ['accordion-group', 'common-config-category'],
- classNameBindings: ['category.name', 'isShowBlock::hidden'],
- content: null,
- category: null,
- service: null,
- canEdit: true, // View is editable or read-only?
- serviceConfigs: null, // General, Advanced, NameNode, SNameNode, DataNode, etc.
- // total number of
- // hosts (by
- // default,
- // cacheable )
- categoryConfigs: function () {
- return this.get('serviceConfigs').filterProperty('category', this.get('category.name')).filterProperty('isVisible', true);
- }.property('serviceConfigs.@each', 'categoryConfigsAll.@each.isVisible').cacheable(),
- /**
- * This method provides all the properties which apply
- * to this category, irrespective of visibility. This
- * is helpful in Oozie/Hive database configuration, where
- * MySQL etc. database options don't show up, because
- * they were not visible initially.
- */
- categoryConfigsAll: function () {
- return this.get('serviceConfigs').filterProperty('category', this.get('category.name'));
- }.property('serviceConfigs.@each').cacheable(),
- /**
- * When the view is in read-only mode, it marks
- * the properties as read-only.
- */
- updateReadOnlyFlags: function(){
- var configs = this.get('serviceConfigs');
- var canEdit = this.get('canEdit');
- if(!canEdit && configs){
- configs.forEach(function(config){
- config.set('isEditable', false);
- });
- }
- },
- /**
- * Filtered <code>categoryConfigs</code> array. Used to show filtered result
- */
- filteredCategoryConfigs: function() {
- var filter = this.get('parentView.filter').toLowerCase();
- var isOnlyModified = this.get('parentView.columns').length && this.get('parentView.columns')[1].get('selected');
- var isOnlyOverridden = this.get('parentView.columns').length && this.get('parentView.columns')[0].get('selected');
- var isOnlyRestartRequired = this.get('parentView.columns').length && this.get('parentView.columns')[2].get('selected');
- var filteredResult = this.get('categoryConfigs').filter(function(config){
- if(isOnlyModified && !config.get('isNotDefaultValue')){
- return false;
- }
-
- if(isOnlyOverridden && !config.get('isOverridden')){
- return false;
- }
- if(isOnlyRestartRequired && !config.get('isRestartRequired')){
- return false;
- }
- var searchString = config.get('defaultValue') + config.get('description') +
- config.get('displayName') + config.get('name');
- return searchString.toLowerCase().indexOf(filter) > -1;
- });
- // modify the display order of Oozie/Hive server category to make it look in the same order
- if(filteredResult.someProperty('displayName', 'Oozie Database')) {
- var displayNameArray = ['Oozie Database', 'Database Type', 'Database Name', 'Database Username', 'Database Password', 'Database Host', 'Oozie Data Dir', 'Oozie Server host'];
- var sortedArray = [];
- displayNameArray.forEach(function(item){
- var obj = filteredResult.findProperty('displayName', item);
- if(obj) {
- sortedArray.push(obj);
- }
- }, this);
- return sortedArray;
- }
- else {
- if(filteredResult.someProperty('displayName', 'Hive Database')) {
- var displayNameArray = ['Hive Database', 'Database Type', 'Database Name', 'Database Username', 'Database Password', 'Database Host', 'Hive Metastore host'];
- var sortedArray = [];
- displayNameArray.forEach(function(item){
- var obj = filteredResult.findProperty('displayName', item);
- if(obj) {
- sortedArray.push(obj);
- }
- }, this);
- return sortedArray;
- }
- else {
- return filteredResult;
- }
- }
- }.property('categoryConfigs','parentView.filter', 'parentView.columns.@each.selected'),
- /**
- * Onclick handler for Config Group Header. Used to show/hide block
- */
- onToggleBlock: function () {
- this.$('.accordion-body').toggle('blind', 500);
- this.set('category.isCollapsed', !this.get('category.isCollapsed'));
- },
- /**
- * Should we show config group or not
- */
- isShowBlock: function(){
- return this.get('category.canAddProperty') || this.get('filteredCategoryConfigs').length > 0;
- }.property('category.canAddProperty', 'filteredCategoryConfigs.length'),
- didInsertElement: function () {
- var isCollapsed = (this.get('category.name').indexOf('Advanced') != -1);
- this.set('category.isCollapsed', isCollapsed);
- if(isCollapsed){
- this.$('.accordion-body').hide();
- }
- this.updateReadOnlyFlags();
- },
- childView: App.ServiceConfigsOverridesView,
- changeFlag: Ember.Object.create({
- val: 1
- }),
- isOneOfAdvancedSections: function () {
- var category = this.get('category');
- return category.indexOf("Advanced") != -1;
- },
- showAddPropertyWindow: function (event) {
- var serviceConfigNames = this.get('categoryConfigs').mapProperty('name');
- var serviceConfigObj = Ember.Object.create({
- name: '',
- value: '',
- defaultValue: null,
- filename: '',
- isUserProperty: true,
- isKeyError:false,
- errorMessage:"",
- observeAddPropertyValue:function(){
- var name = this.get('name');
- if(name.trim() != ""){
- if(validator.isValidConfigKey(name)){
- var configMappingProperty = App.config.configMapping.all().findProperty('name', name);
- if((configMappingProperty == null) && (!serviceConfigNames.contains(name))){
- this.set("isKeyError", false);
- this.set("errorMessage", "");
- } else {
- this.set("isKeyError", true);
- this.set("errorMessage", Em.I18n.t('services.service.config.addPropertyWindow.error.derivedKey'));
- }
- } else {
- this.set("isKeyError", true);
- this.set("errorMessage", Em.I18n.t('form.validator.configKey'));
- }
- } else {
- this.set("isKeyError", true);
- this.set("errorMessage", Em.I18n.t('services.service.config.addPropertyWindow.errorMessage'));
- }
- }.observes("name")
- });
- var category = this.get('category');
- serviceConfigObj.displayType = "advanced";
- serviceConfigObj.category = category.get('name');
- var serviceName = this.get('service.serviceName');
- var serviceConfigsMetaData = require('data/service_configs');
- var serviceConfigMetaData = serviceConfigsMetaData.findProperty('serviceName', serviceName);
- var categoryMetaData = serviceConfigMetaData == null ? null : serviceConfigMetaData.configCategories.findProperty('name', category.get('name'));
- if (categoryMetaData != null) {
- serviceConfigObj.filename = categoryMetaData.siteFileName;
- }
-
- var self = this;
- App.ModalPopup.show({
- // classNames: ['big-modal'],
- classNames: [ 'sixty-percent-width-modal'],
- header: "Add Property",
- primary: 'Add',
- secondary: 'Cancel',
- onPrimary: function () {
- serviceConfigObj.observeAddPropertyValue();
- /**
- * For the first entrance use this if (serviceConfigObj.name.trim() != "")
- */
- if (!serviceConfigObj.isKeyError) {
- serviceConfigObj.displayName = serviceConfigObj.name;
- serviceConfigObj.id = 'site property';
- serviceConfigObj.serviceName = serviceName;
- var serviceConfigProperty = App.ServiceConfigProperty.create(serviceConfigObj);
- self.get('serviceConfigs').pushObject(serviceConfigProperty);
- this.hide();
- }
- },
- onSecondary: function () {
- this.hide();
- },
- bodyClass: Ember.View.extend({
- templateName: require('templates/common/configs/addPropertyWindow'),
- controllerBinding: 'App.router.mainServiceInfoConfigsController',
- serviceConfigProperty: serviceConfigObj
- })
- });
- },
-
- /**
- * Removes the top-level property from list of properties.
- * Should be only called on user properties.
- */
- removeProperty: function (event) {
- var serviceConfigProperty = event.contexts[0];
- this.get('serviceConfigs').removeObject(serviceConfigProperty);
- },
-
- /**
- * Restores given property's value to be its default value.
- * Does not update if there is no default value.
- */
- doRestoreDefaultValue: function (event) {
- var serviceConfigProperty = event.contexts[0];
- var value = serviceConfigProperty.get('value');
- var dValue = serviceConfigProperty.get('defaultValue');
- if (dValue != null) {
- if(serviceConfigProperty.get('displayType') === 'password'){
- serviceConfigProperty.set('retypedPassword', dValue);
- }
- serviceConfigProperty.set('value', dValue);
- }
- },
-
- createOverrideProperty: function (event) {
- var serviceConfigProperty = event.contexts[0];
- var overrides = serviceConfigProperty.get('overrides');
- if (!overrides) {
- overrides = [];
- serviceConfigProperty.set('overrides', overrides);
- }
-
- // create new override with new value
- var newSCP = App.ServiceConfigProperty.create(serviceConfigProperty);
- newSCP.set('value', '');
- newSCP.set('isOriginalSCP', false); // indicated this is overridden value,
- newSCP.set('parentSCP', serviceConfigProperty);
- newSCP.set('selectedHostOptions', Ember.A([]));
- console.debug("createOverrideProperty(): Added:", newSCP, " to main-property:", serviceConfigProperty);
- overrides.pushObject(newSCP);
-
- // Launch override window
- var dummyEvent = {contexts: [newSCP]};
- this.showOverrideWindow(dummyEvent);
- },
- showOverrideWindow: function (event) {
- // argument 1
- var serviceConfigProperty = event.contexts[0];
- var parentServiceConfigProperty = serviceConfigProperty.get('parentSCP');
- var alreadyOverriddenHosts = [];
- parentServiceConfigProperty.get('overrides').forEach(function(override){
- if (override!=null && override!=serviceConfigProperty && override.get('selectedHostOptions')!=null){
- alreadyOverriddenHosts = alreadyOverriddenHosts.concat(override.get('selectedHostOptions'))
- }
- });
- var selectedHosts = serviceConfigProperty.get('selectedHostOptions');
- /**
- * Get all the hosts available for selection. Since data is dependent on
- * controller, we ask it, instead of doing regular Ember's App.Host.find().
- * This should be an array of App.Host.
- */
- var allHosts = this.get('controller.getAllHosts');
- var availableHosts = Ember.A([]);
- allHosts.forEach(function(host){
- var hostId = host.get('id');
- if(alreadyOverriddenHosts.indexOf(hostId)<0){
- availableHosts.pushObject(Ember.Object.create({
- selected: selectedHosts.indexOf(hostId)>-1,
- host: host
- }));
- }
- });
- /**
- * From the currently selected service we want the service-components.
- * We only need an array of objects which have the 'componentName' and
- * 'displayName' properties. Since each controller has its own objects,
- * we ask for a normalized array back.
- */
- var validComponents = this.get('controller.getCurrentServiceComponents');
- App.ModalPopup.show({
- classNames: [ 'sixty-percent-width-modal' ],
- header: Em.I18n.t('hosts.selectHostsDialog.title'),
- primary: Em.I18n.t('ok'),
- secondary: Em.I18n.t('common.cancel'),
- warningMessage: null,
- onPrimary: function () {
- console.debug('serviceConfigProperty.(old-selectedHosts)=' + serviceConfigProperty.get('selectedHosts'));
- var arrayOfSelectedHosts = [];
- var selectedHosts = availableHosts.filterProperty('selected', true);
- selectedHosts.forEach(function(host){
- arrayOfSelectedHosts.push(host.get('host.id'));
- });
- if(arrayOfSelectedHosts.length>0){
- this.set('warningMessage', null);
- serviceConfigProperty.set('selectedHostOptions', arrayOfSelectedHosts);
- serviceConfigProperty.validate();
- console.debug('serviceConfigProperty.(new-selectedHosts)=', arrayOfSelectedHosts);
- this.hide();
- }else{
- this.set('warningMessage', 'Atleast one host needs to be selected.');
- }
- },
- onSecondary: function () {
- // If property has no hosts already, then remove it from the parent.
- var hostCount = serviceConfigProperty.get('selectedHostOptions.length');
- if( hostCount < 1 ){
- var parentSCP = serviceConfigProperty.get('parentSCP');
- var overrides = parentSCP.get('overrides');
- overrides.removeObject(serviceConfigProperty);
- }
- this.hide();
- },
- bodyClass: Ember.View.extend({
- templateName: require('templates/common/configs/overrideWindow'),
- controllerBinding: 'App.router.mainServiceInfoConfigsController',
- serviceConfigProperty: serviceConfigProperty,
- filterText: '',
- filterTextPlaceholder: Em.I18n.t('hosts.selectHostsDialog.filter.placeHolder'),
- availableHosts: availableHosts,
- filterColumn: Ember.Object.create({id:'ip', name:'IP Address', selected:false}),
- filterColumns: Ember.A([
- Ember.Object.create({id:'ip', name:'IP Address', selected:false}),
- Ember.Object.create({id:'cpu', name:'CPU', selected:false}),
- Ember.Object.create({id:'memory', name:'RAM', selected:false}),
- Ember.Object.create({id:'diskUsage', name:'Disk Usage', selected:false}),
- Ember.Object.create({id:'loadAvg', name:'Load Average', selected:false}),
- Ember.Object.create({id:'osArch', name:'OS Architecture', selected:false}),
- Ember.Object.create({id:'osType', name:'OS Type', selected:false})
- ]),
- showOnlySelectedHosts: false,
- filterComponents: validComponents,
- filterComponent: null,
- filteredHosts: function () {
- var hosts = this.get('availableHosts');
- var filterText = this.get('filterText');
- var showOnlySelectedHosts = this.get('showOnlySelectedHosts');
- var filteredHosts = Ember.A([]);
- var self = this;
- hosts.forEach(function (host) {
- var skip = false;
- var ahost = host.get('host');
- var filterColumn = self.get('filterColumn');
- if (filterColumn == null) {
- filterColumn = self.get('filterColumns').objectAt(0);
- }
- var value = ahost.get(filterColumn.id);
- host.set('filterColumnValue', value);
- if (filterText != null && filterText.length > 0) {
- if ((value==null || !value.match(filterText)) && !host.get('host.publicHostName').match(filterText)) {
- skip = true;
- }
- }
- var filterComponent = self.get('filterComponent');
- if (!skip && filterComponent != null) {
- var componentFound = false;
- var fcn = filterComponent.get('componentName');
- var hcs = ahost.get('hostComponents');
- if (hcs != null) {
- hcs.forEach(function (hc) {
- if (fcn === hc.get('componentName')) {
- componentFound = true;
- }
- });
- }
- if (!componentFound) {
- skip = true;
- }
- }
- if (!skip && showOnlySelectedHosts && !host.get('selected')){
- skip = true;
- }
- if (!skip) {
- filteredHosts.pushObject(host);
- }
- });
- return filteredHosts;
- }.property('availableHosts', 'filterText', 'filterColumn', 'filterComponent', 'filterComponent.componentName', 'showOnlySelectedHosts'),
- hostColumnValue: function(host, column){
- return host.get(column.id);
- },
- hostSelectMessage: function () {
- var hosts = this.get('availableHosts');
- var selectedHosts = hosts.filterProperty('selected', true);
- return this.t('hosts.selectHostsDialog.selectedHostsLink').format(selectedHosts.get('length'), hosts.get('length'))
- }.property('availableHosts.@each.selected'),
- selectFilterColumn: function(event){
- if(event!=null && event.context!=null && event.context.id!=null){
- var filterColumn = this.get('filterColumn');
- if(filterColumn!=null){
- filterColumn.set('selected', false);
- }
- event.context.set('selected', true);
- this.set('filterColumn', event.context);
- }
- },
- selectFilterComponent: function(event){
- if(event!=null && event.context!=null && event.context.componentName!=null){
- var currentFilter = this.get('filterComponent');
- if(currentFilter!=null){
- currentFilter.set('selected', false);
- }
- if(currentFilter!=null && currentFilter.componentName===event.context.componentName){
- // selecting the same filter deselects it.
- this.set('filterComponent', null);
- }else{
- this.set('filterComponent', event.context);
- event.context.set('selected', true);
- }
- }
- },
- allHostsSelected: false,
- toggleSelectAllHosts: function(event){
- if(this.get('allHostsSelected')){
- // Select all hosts
- this.get('availableHosts').setEach('selected', true);
- }else{
- // Deselect all hosts
- this.get('availableHosts').setEach('selected', false);
- }
- }.observes('allHostsSelected'),
- toggleShowSelectedHosts: function () {
- var currentFilter = this.get('filterComponent');
- if (currentFilter != null) {
- currentFilter.set('selected', false);
- }
- this.set('filterComponent', null);
- this.set('filterText', null);
- this.set('showOnlySelectedHosts', !this.get('showOnlySelectedHosts'));
- }
- })
- });
- }
- });
- App.ServiceConfigTab = Ember.View.extend({
- tagName: 'li',
- selectService: function (event) {
- this.set('controller.selectedService', event.context);
- },
- didInsertElement: function () {
- var serviceName = this.get('controller.selectedService.serviceName');
- this.$('a[href="#' + serviceName + '"]').tab('show');
- }
- });
- /**
- * custom view for capacity scheduler category
- * @type {*}
- */
- App.ServiceConfigCapacityScheduler = App.ServiceConfigsByCategoryView.extend({
- templateName: require('templates/common/configs/capacity_scheduler'),
- category: null,
- service: null,
- serviceConfigs: null,
- customConfigs: require('data/custom_configs'),
- /**
- * configs filtered by capacity-scheduler category
- */
- categoryConfigs: function () {
- return this.get('serviceConfigs').filterProperty('category', this.get('category.name'));
- }.property('queueObserver', 'serviceConfigs.@each'),
- /**
- * rewrote method to avoid incompatibility with parent
- */
- filteredCategoryConfigs: function(){
- return this.get('categoryConfigs');
- }.property(),
- advancedConfigs: function(){
- return this.get('categoryConfigs').filterProperty('isQueue', undefined) || [];
- }.property('categoryConfigs.@each'),
- didInsertElement: function(){
- this._super();
- this.createEmptyQueue(this.get('customConfigs').filterProperty('isQueue'));
- },
- //list of fields which will be populated by default in a new queue
- fieldsToPopulate: [
- "mapred.capacity-scheduler.queue.<queue-name>.minimum-user-limit-percent",
- "mapred.capacity-scheduler.queue.<queue-name>.user-limit-factor",
- "mapred.capacity-scheduler.queue.<queue-name>.supports-priority",
- "mapred.capacity-scheduler.queue.<queue-name>.maximum-initialized-active-tasks",
- "mapred.capacity-scheduler.queue.<queue-name>.maximum-initialized-active-tasks-per-user",
- "mapred.capacity-scheduler.queue.<queue-name>.init-accept-jobs-factor"
- ],
- /**
- * create empty queue
- * take some queue then copy it and set all config values to null
- * @param customConfigs
- */
- createEmptyQueue: function(customConfigs){
- var emptyQueue = {
- name: '<queue-name>',
- configs: []
- };
- var fieldsToPopulate = this.get('fieldsToPopulate');
- customConfigs.forEach(function(config){
- var newConfig = $.extend({}, config);
- if(fieldsToPopulate.contains(config.name)){
- App.config.setDefaultQueue(newConfig, emptyQueue.name);
- }
- newConfig = App.ServiceConfigProperty.create(newConfig);
- newConfig.validate();
- emptyQueue.configs.push(newConfig);
- });
- this.set('emptyQueue', emptyQueue);
- },
- queues: function(){
- var configs = this.get('categoryConfigs').filterProperty('isQueue', true);
- var queueNames = [];
- var queues = [];
- configs.mapProperty('name').forEach(function(name){
- var queueName = /^mapred\.capacity-scheduler\.queue\.(.*?)\./.exec(name);
- if(queueName){
- queueNames.push(queueName[1]);
- }
- });
- queueNames = queueNames.uniq();
- queueNames.forEach(function(queueName){
- queues.push({
- name: queueName,
- color: this.generateColor(queueName),
- configs: this.filterConfigsByQueue(queueName, configs)
- })
- }, this);
- return queues;
- }.property('queueObserver'),
- /**
- * filter configs by queue
- * @param queueName
- * @param configs
- */
- filterConfigsByQueue: function (queueName, configs) {
- var customConfigs = this.get('customConfigs');
- var queue = [];
- configs.forEach(function (config) {
- var customConfig = customConfigs.findProperty('name', config.name.replace('queue.' + queueName, 'queue.<queue-name>'));
- if ((config.name.indexOf('mapred.capacity-scheduler.queue.' + queueName) !== -1) ||
- (config.name.indexOf('mapred.queue.' + queueName) !== -1)) {
- if (customConfig) {
- config.set('description', customConfig.description);
- config.set('displayName', customConfig.displayName);
- config.set('isRequired', customConfig.isRequired);
- config.set('unit', customConfig.unit);
- config.set('displayType', customConfig.displayType);
- config.set('valueRange', customConfig.valueRange);
- config.set('isVisible', customConfig.isVisible);
- config.set('index', customConfig.index);
- }
- queue.push(config);
- }
- });
- //each queue consists of 10 properties if less then add missing properties
- if(queue.length < 10){
- this.addMissingProperties(queue, queueName);
- }
- return queue;
- },
- /**
- * add missing properties to queue
- * @param queue
- * @param queueName
- */
- addMissingProperties: function(queue, queueName){
- var customConfigs = this.get('customConfigs');
- customConfigs.forEach(function(_config){
- var serviceConfigProperty = $.extend({}, _config);
- serviceConfigProperty.name = serviceConfigProperty.name.replace(/<queue-name>/, queueName);
- if(!queue.someProperty('name', serviceConfigProperty.name)){
- App.config.setDefaultQueue(serviceConfigProperty, queueName);
- serviceConfigProperty = App.ServiceConfigProperty.create(serviceConfigProperty);
- serviceConfigProperty.validate();
- queue.push(serviceConfigProperty);
- }
- }, this);
- },
- /**
- * format table content from queues
- */
- tableContent: function(){
- var result = [];
- this.get('queues').forEach(function(queue){
- var usersAndGroups = queue.configs.findProperty('name', 'mapred.queue.' + queue.name + '.acl-submit-job').get('value');
- usersAndGroups = (usersAndGroups) ? usersAndGroups.split(' ') : [''];
- if(usersAndGroups.length == 1){
- usersAndGroups.push('');
- }
- var queueObject = {
- name: queue.name,
- color: 'background-color:' + queue.color + ';',
- users: usersAndGroups[0],
- groups: usersAndGroups[1],
- capacity: queue.configs.findProperty('name', 'mapred.capacity-scheduler.queue.' + queue.name + '.capacity').get('value'),
- maxCapacity: queue.configs.findProperty('name', 'mapred.capacity-scheduler.queue.' + queue.name + '.maximum-capacity').get('value'),
- minUserLimit: queue.configs.findProperty('name', 'mapred.capacity-scheduler.queue.' + queue.name + '.minimum-user-limit-percent').get('value'),
- userLimitFactor: queue.configs.findProperty('name', 'mapred.capacity-scheduler.queue.' + queue.name + '.user-limit-factor').get('value'),
- supportsPriority: queue.configs.findProperty('name', 'mapred.capacity-scheduler.queue.' + queue.name + '.supports-priority').get('value')
- };
- result.push(queueObject);
- }, this);
- return result;
- }.property('queues'),
- queueObserver: null,
- /**
- * uses as template for adding new queue
- */
- emptyQueue: [],
- generateColor: function(str){
- var hash = 0;
- for (var i = 0; i < str.length; i++) {
- hash = str.charCodeAt(i) + ((hash << 5) - hash);
- }
- return '#' + Number(Math.abs(hash)).toString(16).concat('00000').substr(0, 6);
- },
- /**
- * add new queue
- * add created configs to serviceConfigs with current queue name
- * @param queue
- */
- addQueue: function(queue){
- var serviceConfigs = this.get('serviceConfigs');
- var admin = [];
- var submit = [];
- var submitConfig;
- var adminConfig;
- queue.name = queue.configs.findProperty('name', 'queueName').get('value');
- queue.configs.forEach(function(config){
- if(config.name == 'mapred.queue.<queue-name>.acl-administer-jobs'){
- if(config.type == 'USERS'){
- admin[0] = config.value;
- }
- if(config.type == 'GROUPS'){
- admin[1] = config.value;
- }
- if(config.isQueue){
- adminConfig = config;
- }
- }
- if(config.name == 'mapred.queue.<queue-name>.acl-submit-job'){
- if(config.type == 'USERS'){
- submit[0] = config.value;
- }
- if(config.type == 'GROUPS'){
- submit[1] = config.value;
- }
- if(config.isQueue){
- submitConfig = config;
- }
- }
- config.set('name', config.get('name').replace('<queue-name>', queue.name));
- config.set('value', config.get('value').toString());
- if(config.isQueue){
- serviceConfigs.push(config);
- }
- });
- adminConfig.set('value', admin.join(' '));
- submitConfig.set('value', submit.join(' '));
- this.set('queueObserver', new Date().getTime());
- },
- /**
- * delete queue
- * delete configs from serviceConfigs which have current queue name
- * @param queue
- */
- deleteQueue: function(queue){
- var serviceConfigs = this.get('serviceConfigs');
- var configNames = queue.configs.filterProperty('isQueue').mapProperty('name');
- for(var i = 0, l = serviceConfigs.length; i < l; i++){
- if(configNames.contains(serviceConfigs[i].name)){
- serviceConfigs.splice(i, 1);
- l--;
- i--;
- }
- }
- this.set('queueObserver', new Date().getTime());
- },
- /**
- * save changes that was made to queue
- * edit configs from serviceConfigs which have current queue name
- * @param queue
- */
- editQueue: function(queue){
- var serviceConfigs = this.get('serviceConfigs');
- var configNames = queue.configs.filterProperty('isQueue').mapProperty('name');
- serviceConfigs.forEach(function(_config){
- var configName = _config.get('name');
- var admin = [];
- var submit = [];
- if(configNames.contains(_config.get('name'))){
- if(configName == 'mapred.queue.' + queue.name + '.acl-submit-job'){
- submit = queue.configs.filterProperty('name', configName);
- submit = submit.findProperty('type', 'USERS').get('value') + ' ' + submit.findProperty('type', 'GROUPS').get('value');
- _config.set('value', submit);
- } else if(configName == 'mapred.queue.' + queue.name + '.acl-administer-jobs'){
- admin = queue.configs.filterProperty('name', configName);
- admin = admin.findProperty('type', 'USERS').get('value') + ' ' + admin.findProperty('type', 'GROUPS').get('value');
- _config.set('value', admin);
- } else {
- _config.set('value', queue.configs.findProperty('name', _config.get('name')).get('value').toString());
- }
- //comparison executes including 'queue.<queue-name>' to avoid false matches
- _config.set('name', configName.replace('queue.' + queue.name, 'queue.' + queue.configs.findProperty('name', 'queueName').get('value')));
- }
- });
- this.set('queueObserver', new Date().getTime());
- },
- pieChart: App.ChartPieView.extend({
- w: 200,
- h: 200,
- queues: null,
- didInsertElement: function(){
- this.update();
- },
- data: [{"label":"default", "value":100}],
- update: function(){
- var self = this;
- var data = [];
- var queues = this.get('queues');
- var capacitiesSum = 0;
- queues.forEach(function(queue){
- data.push({
- label: queue.name,
- value: parseInt(queue.configs.findProperty('name', 'mapred.capacity-scheduler.queue.' + queue.name + '.capacity').get('value')),
- color: queue.color
- })
- });
- data.mapProperty('value').forEach(function(capacity){
- capacitiesSum += capacity;
- });
- if(capacitiesSum < 100){
- data.push({
- label: Em.I18n.t('common.empty'),
- value: (100 - capacitiesSum),
- color: 'transparent',
- isEmpty: true
- })
- }
- $(d3.select(this.get('selector'))[0]).children().remove();
- this.set('data', data);
- this.set('palette', new Rickshaw.Color.Palette({
- scheme: data.mapProperty('color')
- }));
- this.appendSvg();
- this.get('arcs')
- .on("click", function(d,i) {
- var event = {context: d.data.label};
- if (d.data.isEmpty !== true) self.get('parentView').queuePopup(event);
- }).on('mouseover', function(d, i){
- var position = d3.svg.mouse(this);
- var label = $('#section_label');
- label.css('left', position[0] + 100);
- label.css('top', position[1] + 100);
- label.text(d.data.label);
- label.show();
- })
- .on('mouseout', function(d, i){
- $('#section_label').hide();
- })
- }.observes('queues'),
- donut:d3.layout.pie().sort(null).value(function(d) {return d.value;})
- }),
- /**
- * open popup with chosen queue
- * @param event
- */
- queuePopup: function(event){
- //if queueName was handed that means "Edit" mode, otherwise "Add" mode
- var queueName = event.context || null;
- var self = this;
- App.ModalPopup.show({
- didInsertElement: function(){
- if(queueName){
- this.set('header', Em.I18n.t('services.mapReduce.config.editQueue'));
- this.set('secondary', Em.I18n.t('common.save'));
- if(self.get('queues').length > 1 && self.get('canEdit')){
- this.set('delete', Em.I18n.t('common.delete'));
- }
- }
- },
- header: Em.I18n.t('services.mapReduce.config.addQueue'),
- secondary: Em.I18n.t('common.add'),
- primary: Em.I18n.t('common.cancel'),
- delete: null,
- isError: function(){
- if(!self.get('canEdit')){
- return true;
- }
- var content = this.get('content');
- var configs = content.configs.filter(function(config){
- if((config.name == 'mapred.queue.' + content.name + '.acl-submit-job' ||
- config.name == 'mapred.queue.' + content.name + '.acl-administer-jobs') &&
- (config.isQueue)){
- return false;
- }
- return true;
- });
- return configs.someProperty('isValid', false);
- }.property('content.configs.@each.isValid'),
- onDelete: function(){
- var view = this;
- App.ModalPopup.show({
- header: Em.I18n.t('popup.confirmation.commonHeader'),
- body: Em.I18n.t('hosts.delete.popup.body'),
- primary: Em.I18n.t('yes'),
- onPrimary: function(){
- self.deleteQueue(view.get('content'));
- view.hide();
- this.hide();
- }
- });
- },
- onSecondary: function() {
- if(queueName){
- self.editQueue(this.get('content'));
- } else {
- self.addQueue(this.get('content'));
- }
- this.hide();
- },
- /**
- * Queue properties order:
- * 1. Queue Name
- * 2. Capacity
- * 3. Max Capacity
- * 4. Users
- * 5. Groups
- * 6. Admin Users
- * 7. Admin Groups
- * 8. Support Priority
- * ...
- */
- content: function(){
- var content = (queueName) ? self.get('queues').findProperty('name', queueName) : self.get('emptyQueue');
- var configs = [];
- var tableContent = self.get('tableContent');
- // copy of queue configs
- content.configs.forEach(function (config, index) {
- if (config.name == 'mapred.capacity-scheduler.queue.' + content.name + '.capacity') {
- config.reopen({
- validate: function () {
- var value = this.get('value');
- var isError = false;
- var capacities = [];
- var capacitySum = 0;
- if(tableContent){
- capacities = tableContent.mapProperty('capacity');
- for (var i = 0, l = capacities.length; i < l; i++) {
- capacitySum += parseInt(capacities[i]);
- }
- if (content.name != '<queue-name>') {
- capacitySum = capacitySum - parseInt(tableContent.findProperty('name', content.name).capacity);
- }
- }
- if (value == '') {
- if (this.get('isRequired')) {
- this.set('errorMessage', 'This is required');
- isError = true;
- } else {
- return;
- }
- }
- if (!isError) {
- if (!validator.isValidInt(value)) {
- this.set('errorMessage', 'Must contain digits only');
- isError = true;
- }
- }
- if (!isError) {
- if ((capacitySum + parseInt(value)) > 100) {
- isError = true;
- this.set('errorMessage', 'The sum of capacities more than 100');
- }
- if (!isError) {
- this.set('errorMessage', '');
- }
- }
- }.observes('value')
- });
- }
- if(config.name == 'mapred.capacity-scheduler.queue.' + content.name + '.supports-priority'){
- if(config.get('value') == 'true' || config.get('value') === true){
- config.set('value', true);
- } else {
- config.set('value', false);
- }
- }
- configs[index] = App.ServiceConfigProperty.create(config);
- });
- content = {
- name: content.name,
- configs: configs
- };
- content = this.insertExtraConfigs(content);
- content.configs = this.sortQueueProperties(content.configs);
- return content;
- }.property(),
- footerClass: Ember.View.extend({
- classNames: ['modal-footer', 'host-checks-update'],
- template: Ember.Handlebars.compile([
- '{{#if view.parentView.delete}}<div class="pull-left">',
- '<button class="btn btn-danger" {{action onDelete target="view.parentView"}}>',
- '{{view.parentView.delete}}</button></div>{{/if}}',
- '<p class="pull-right">',
- '{{#if view.parentView.primary}}<button type="button" class="btn" {{action onPrimary target="view.parentView"}}>',
- '{{view.parentView.primary}}</button>{{/if}}',
- '{{#if view.parentView.secondary}}',
- '<button type="button" {{bindAttr disabled="view.parentView.isError"}} class="btn btn-success" {{action onSecondary target="view.parentView"}}>',
- '{{view.parentView.secondary}}</button>{{/if}}',
- '</p>'
- ].join(''))
- }),
- bodyClass: Ember.View.extend({
- template: Ember.Handlebars.compile([
- '<form class="form-horizontal pre-scrollable">{{#each view.parentView.content.configs}}',
- '{{#if isVisible}}',
- '<div class="row-fluid control-group">',
- ' <div {{bindAttr class="errorMessage:error :control-label-span :span4"}}>',
- ' <label>{{displayName}}</label>',
- ' </div>',
- ' <div {{bindAttr class="errorMessage:error :control-group :span8"}}>',
- ' {{view viewClass serviceConfigBinding="this" categoryConfigsBinding="view.categoryConfigs" }}',
- ' <span class="help-inline">{{errorMessage}}</span>',
- ' </div>',
- '</div>',
- '{{/if}}',
- '{{/each}}</form>'
- ].join(''))
- }),
- /**
- * Insert extra config in popup according to queue
- *
- * the mapred.queue.default.acl-administer-jobs turns into two implicit configs:
- * "Admin Users" field and "Admin Groups" field
- * the mapred.queue.default.acl-submit-job turns into two implicit configs:
- * "Users" field and "Groups" field
- * Add implicit config that contain "Queue Name"
- * @param content
- * @return {*}
- */
- insertExtraConfigs: function(content){
- var that = this;
- var admin = content.configs.findProperty('name', 'mapred.queue.' + content.name + '.acl-administer-jobs').get('value');
- var submit = content.configs.findProperty('name', 'mapred.queue.' + content.name + '.acl-submit-job').get('value');
- admin = (admin) ? admin.split(' ') : [''];
- submit = (submit) ? submit.split(' ') : [''];
- if(admin.length < 2){
- admin.push('');
- }
- if(submit.length < 2){
- submit.push('');
- }
- var newField = App.ServiceConfigProperty.create({
- name: 'queueName',
- displayName: Em.I18n.t('services.mapReduce.extraConfig.queue.name'),
- description: Em.I18n.t('services.mapReduce.description.queue.name'),
- value: (content.name == '<queue-name>') ? '' : content.name,
- validate: function(){
- var queueNames = self.get('queues').mapProperty('name');
- var value = this.get('value');
- var isError = false;
- var regExp = /^[a-z]([\_\-a-z0-9]{0,50})\$?$/i;
- if(value == ''){
- if (this.get('isRequired')) {
- this.set('errorMessage', 'This is required');
- isError = true;
- } else {
- return;
- }
- }
- if(!isError){
- if((queueNames.indexOf(value) !== -1) && (value != content.name)){
- this.set('errorMessage', 'Queue name is already used');
- isError = true;
- }
- }
- if(!isError){
- if(!regExp.test(value)){
- this.set('errorMessage', 'Incorrect input');
- isError = true;
- }
- }
- if (!isError) {
- this.set('errorMessage', '');
- }
- }.observes('value'),
- isRequired: true,
- isVisible: true,
- isEditable: self.get('canEdit'),
- index: 0
- });
- newField.validate();
- content.configs.unshift(newField);
- var submitUser = App.ServiceConfigProperty.create({
- name: 'mapred.queue.' + content.name + '.acl-submit-job',
- displayName: Em.I18n.t('common.users'),
- value: submit[0],
- description: Em.I18n.t('services.mapReduce.description.queue.submit.user'),
- isRequired: true,
- isVisible: true,
- type: 'USERS',
- displayType: "UNIXList",
- isEditable: self.get('canEdit'),
- index: 3
- });
- var submitGroup = App.ServiceConfigProperty.create({
- name: 'mapred.queue.' + content.name + '.acl-submit-job',
- displayName: Em.I18n.t('services.mapReduce.config.queue.groups'),
- description: Em.I18n.t('services.mapReduce.description.queue.submit.group'),
- value: submit[1],
- isRequired: true,
- isVisible: true,
- "displayType": "UNIXList",
- type: 'GROUPS',
- isEditable: self.get('canEdit'),
- index: 4
- });
- var adminUser = App.ServiceConfigProperty.create({
- name: 'mapred.queue.' + content.name + '.acl-administer-jobs',
- displayName: Em.I18n.t('services.mapReduce.config.queue.adminUsers'),
- description: Em.I18n.t('services.mapReduce.description.queue.admin.user'),
- value: admin[0],
- isRequired: true,
- isVisible: true,
- type: 'USERS',
- displayType: "UNIXList",
- isEditable: self.get('canEdit'),
- index: 5
- });
- var adminGroup = App.ServiceConfigProperty.create({
- name: 'mapred.queue.' + content.name + '.acl-administer-jobs',
- displayName: Em.I18n.t('services.mapReduce.config.queue.adminGroups'),
- value: admin[1],
- description: Em.I18n.t('services.mapReduce.description.queue.admin.group'),
- isRequired: true,
- isVisible: true,
- "displayType": "UNIXList",
- type: 'GROUPS',
- isEditable: self.get('canEdit'),
- index: 6
- });
- submitUser.reopen({
- validate: function(){
- that.userGroupValidation(this, submitGroup);
- }.observes('value')
- });
- submitGroup.reopen({
- validate: function(){
- that.userGroupValidation(this, submitUser);
- }.observes('value')
- });
- adminUser.reopen({
- validate: function(){
- that.userGroupValidation(this, adminGroup);
- }.observes('value')
- });
- adminGroup.reopen({
- validate: function(){
- that.userGroupValidation(this, adminUser);
- }.observes('value')
- });
- submitUser.validate();
- adminUser.validate();
- content.configs.push(submitUser);
- content.configs.push(submitGroup);
- content.configs.push(adminUser);
- content.configs.push(adminGroup);
- return content;
- },
- /**
- * sort properties of queue by index
- * @param configs
- * @return {Array}
- */
- sortQueueProperties: function(configs){
- var sortedConfigs = [];
- var skippedConfigs = [];
- configs.forEach(function(_config){
- if(isFinite(_config.index)){
- sortedConfigs[_config.index] = _config;
- } else {
- skippedConfigs.push(_config);
- }
- });
- return sortedConfigs.concat(skippedConfigs);
- },
- /**
- * Validate by follow rules:
- * Users can be blank. If this is blank, Groups must not be blank.
- * Groups can be blank. If this is blank, Users must not be blank.
- * @param context
- * @param boundConfig
- */
- userGroupValidation: function(context, boundConfig){
- if(context.get('value') == ''){
- if(boundConfig.get('value') == ''){
- context._super();
- } else {
- boundConfig.validate();
- }
- } else {
- if(boundConfig.get('value') == ''){
- boundConfig.set('errorMessage', '');
- }
- context._super();
- }
- }
- })
- }
- });
|