123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314 |
- /**
- * 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');
- var stringUtils = require('utils/string_utils');
- var hostsUtils = require('utils/hosts');
- 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 () {
- if(this.get('isNotEditable') === true) {
- this.set('canEdit', false);
- }
- this.$('.service-body').hide();
- $(".restart-required-property").tooltip({html: true});
- $(".icon-lock").tooltip({placement: 'right'});
- }
- });
- 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(),
- /**
- * Warn/prompt user to adjust Service props when changing user/groups in Misc
- * Is triggered when user ended editing text field
- */
- miscConfigChange: function (manuallyChangedProperty) {
- var changedProperty;
- if(manuallyChangedProperty.get("id")){
- changedProperty = [manuallyChangedProperty];
- }else{
- changedProperty = this.get("serviceConfigs").filterProperty("editDone", true);
- }
- if (changedProperty.length > 0) {
- changedProperty = changedProperty.objectAt(0);
- } else {
- return;
- }
- if (this.get('controller.selectedService.serviceName') == 'MISC') {
- var newValue = changedProperty.get("value");
- var stepConfigs = this.get("controller.stepConfigs");
- this.affectedProperties = [];
- var curConfigs = "";
- var affectedPropertyName = App.get('isHadoop2Stack') ? "dfs.permissions.superusergroup" : "dfs.permissions.supergroup";
- if (changedProperty.get("name") == "hdfs_user") {
- curConfigs = stepConfigs.findProperty("serviceName", "HDFS").get("configs");
- if (newValue != curConfigs.findProperty("name", affectedPropertyName).get("value")) {
- this.affectedProperties.push(
- {
- serviceName: "HDFS",
- propertyName: affectedPropertyName,
- propertyDisplayName: affectedPropertyName,
- newValue: newValue,
- curValue: curConfigs.findProperty("name", affectedPropertyName).get("value"),
- changedPropertyName: "hdfs_user"
- }
- );
- }
- if ($.trim(newValue) != $.trim(curConfigs.findProperty("name", "dfs.cluster.administrators").get("value"))) {
- this.affectedProperties.push(
- {
- serviceName: "HDFS",
- propertyName: "dfs.cluster.administrators",
- propertyDisplayName: "dfs.cluster.administrators",
- newValue: " " + $.trim(newValue),
- curValue: curConfigs.findProperty("name", "dfs.cluster.administrators").get("value"),
- changedPropertyName: "hdfs_user"
- }
- );
- }
- } else if (changedProperty.get("name") == "hbase_user" && !App.get('isHadoop2Stack')) {
- curConfigs = stepConfigs.findProperty("serviceName", "HDFS").get("configs");
- if (newValue != curConfigs.findProperty("name", "dfs.block.local-path-access.user").get("value")) {
- this.affectedProperties.push(
- {
- serviceName: "HDFS",
- propertyName: "dfs.block.local-path-access.user",
- propertyDisplayName: "dfs.block.local-path-access.user",
- newValue: newValue,
- curValue: curConfigs.findProperty("name", "dfs.block.local-path-access.user").get("value"),
- changedPropertyName: "hbase_user"
- }
- );
- }
- var hbaseCurConfigs = stepConfigs.findProperty("serviceName", "HBASE").get("configs");
- if (newValue != hbaseCurConfigs.findProperty("name", "hbase.superuser").get("value")) {
- this.affectedProperties.push(
- {
- serviceName: "HBASE",
- propertyName: "hbase.superuser",
- propertyDisplayName: "hbase.superuser",
- newValue: newValue,
- curValue: hbaseCurConfigs.findProperty("name", "hbase.superuser").get("value"),
- changedPropertyName: "hbase_user"
- }
- );
- }
- } else if (changedProperty.get("name") == "user_group") {
- if (!((this.get("controller.selectedServiceNames").indexOf("MAPREDUCE") >= 0) || (this.get("controller.selectedServiceNames").indexOf("YARN") >= 0))) {
- return;
- }
- if(this.get("controller.selectedServiceNames").indexOf("MAPREDUCE") >= 0) {
- curConfigs = stepConfigs.findProperty("serviceName", "MAPREDUCE").get("configs");
- if (newValue != curConfigs.findProperty("name", "mapreduce.tasktracker.group").get("value")) {
- this.affectedProperties.push(
- {
- serviceName: "MAPREDUCE",
- propertyName: "mapreduce.tasktracker.group",
- propertyDisplayName: "mapreduce.tasktracker.group",
- newValue: newValue,
- curValue: curConfigs.findProperty("name", "mapreduce.tasktracker.group").get("value"),
- changedPropertyName: "user_group"
- }
- )
- }
- if ($.trim(newValue) != $.trim(curConfigs.findProperty("name", "mapreduce.cluster.administrators").get("value"))) {
- this.affectedProperties.push(
- {
- serviceName: "MAPREDUCE",
- propertyName: "mapreduce.cluster.administrators",
- propertyDisplayName: "mapreduce.cluster.administrators",
- newValue: " " + $.trim(newValue),
- curValue: curConfigs.findProperty("name", "mapreduce.cluster.administrators").get("value"),
- changedPropertyName: "user_group"
- }
- );
- }
- }
- if(this.get("controller.selectedServiceNames").indexOf("MAPREDUCE2") >= 0) {
- curConfigs = stepConfigs.findProperty("serviceName", "MAPREDUCE2").get("configs");
- if ($.trim(newValue) != $.trim(curConfigs.findProperty("name", "mapreduce.cluster.administrators").get("value"))) {
- this.affectedProperties.push(
- {
- serviceName: "MAPREDUCE2",
- propertyName: "mapreduce.cluster.administrators",
- propertyDisplayName: "mapreduce.cluster.administrators",
- newValue: " " + $.trim(newValue),
- curValue: curConfigs.findProperty("name", "mapreduce.cluster.administrators").get("value"),
- changedPropertyName: "user_group"
- }
- );
- }
- }
- if (this.get("controller.selectedServiceNames").indexOf("YARN") >= 0) {
- curConfigs = stepConfigs.findProperty("serviceName", "YARN").get("configs");
- if (newValue != curConfigs.findProperty("name", "yarn.nodemanager.linux-container-executor.group").get("value")) {
- this.affectedProperties.push(
- {
- serviceName: "YARN",
- propertyName: "yarn.nodemanager.linux-container-executor.group",
- propertyDisplayName: "yarn.nodemanager.linux-container-executor.group",
- newValue: newValue,
- curValue: curConfigs.findProperty("name", "yarn.nodemanager.linux-container-executor.group").get("value"),
- changedPropertyName: "user_group"
- }
- )
- }
- }
- }
- if (this.affectedProperties.length > 0 && !this.get("controller.miscModalVisible")) {
- this.newAffectedProperties = this.affectedProperties;
- var self = this;
- return App.ModalPopup.show({
- classNames: ['modal-690px-width'],
- showCloseButton: false,
- header: "Warning: you must also change these Service properties",
- onApply: function () {
- self.get("newAffectedProperties").forEach(function (item) {
- self.get("controller.stepConfigs").findProperty("serviceName", item.serviceName).get("configs")
- .findProperty("name", item.propertyName).set("value", item.newValue);
- });
- self.get("controller").set("miscModalVisible", false);
- this.hide();
- },
- onIgnore: function () {
- self.get("controller").set("miscModalVisible", false);
- this.hide();
- },
- onUndo: function () {
- var affected = self.get("newAffectedProperties").objectAt(0);
- self.get("controller.stepConfigs").findProperty("serviceName", "MISC").get("configs")
- .findProperty("name", affected.changedPropertyName).set("value", $.trim(affected.curValue));
- self.get("controller").set("miscModalVisible", false);
- this.hide();
- },
- footerClass: Ember.View.extend({
- classNames: ['modal-footer'],
- template: Ember.Handlebars.compile([
- '<div class="pull-right">',
- '<button class="btn" {{action onUndo target="view.parentView"}}>Cancel</button>',
- '<button class="btn btn-warning" {{action onIgnore target="view.parentView"}}>Ignore</button>',
- '<button class="btn btn-success" {{action onApply target="view.parentView"}}>Apply</button>',
- '</div>'
- ].join(''))
- }),
- bodyClass: Ember.View.extend({
- templateName: require('templates/common/configs/propertyDependence'),
- controller: this,
- propertyChange: self.get("newAffectedProperties"),
- didInsertElement: function () {
- self.get("controller").set("miscModalVisible", true);
- }
- })
- });
- }
- }
- }.observes('categoryConfigs.@each.editDone'),
- /**
- * 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(c){
- c.set('isEditable', false);
- var overrides = c.get('overrides');
- if (overrides!=null) {
- overrides.setEach('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;
- });
- filteredResult = this.sortByIndex(filteredResult);
- return filteredResult;
- }.property('categoryConfigs', 'parentView.filter', 'parentView.columns.@each.selected'),
- /**
- * sort configs in current category by index
- * @param configs
- * @return {*}
- */
- sortByIndex: function (configs) {
- var sortedConfigs = [];
- var unSorted = [];
- if (!configs.someProperty('index')) {
- return configs;
- }
- configs.forEach(function (config) {
- var index = config.get('index');
- if ((index !== null) && isFinite(index)) {
- sortedConfigs[index] ? sortedConfigs.splice(index, 0, config) : sortedConfigs[index] = config;
- } else {
- unSorted.push(config);
- }
- });
- // remove undefined elements from array
- sortedConfigs = sortedConfigs.filter(function (config) {
- if (config !== undefined) return true;
- });
- return sortedConfigs.concat(unSorted);
- },
- /**
- * 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);
- var self = this;
- this.set('category.isCollapsed', isCollapsed);
- if (isCollapsed) {
- this.$('.accordion-body').hide();
- }
- this.updateReadOnlyFlags();
- Em.run.next(function() {
- self.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 configsOfFile = this.get('service.configs').filterProperty('filename', this.get('category.siteFileName'));
- var self =this;
- 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.get('configMapping').all().filterProperty('filename',self.get('category.siteFileName')).findProperty('name', name);
- if ((configMappingProperty == null) && (!configsOfFile.findProperty('name', 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 = App.config.get('preDefinedServiceConfigs');
- 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;
- serviceConfigObj.displayType = stringUtils.isSingleLine(serviceConfigObj.get('value')) ? 'advanced' : 'multiLine';
- var serviceConfigProperty = App.ServiceConfigProperty.create(serviceConfigObj);
- self.get('controller.secureConfigs').filterProperty('filename', self.get('category.siteFileName')).forEach(function (_secureConfig) {
- if (_secureConfig.name === serviceConfigProperty.get('name')) {
- serviceConfigProperty.set('isSecureConfig', true);
- }
- }, this);
- 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);
- }
- this.miscConfigChange(serviceConfigProperty);
- },
- createOverrideProperty: function (event) {
- var serviceConfigProperty = event.contexts[0];
- // Launch dialog to pick/create Config-group
- var serviceConfigGroups = [];
- App.config.launchConfigGroupSelectionCreationDialog(this.get('service.serviceName'),
- serviceConfigGroups, function(selectedConfigGroup){
- console.log("launchConfigGroupSelectionCreationDialog(): Selected/Created:", selectedConfigGroup);
- if (selectedConfigGroup) {
- // TODO - show configurations for this new config-group
- // 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);
- } else {
- // Cancelled dialog
- }
- });
- },
- 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');
- hostsUtils.launchHostsSelectionDialog(availableHosts, selectedHosts,
- false, validComponents, function(newSelectedHosts){
- if (newSelectedHosts!=null) {
- serviceConfigProperty.set('selectedHostOptions', newSelectedHosts);
- serviceConfigProperty.validate();
- } else {
- // Dialog cancelled
- // 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);
- }
- }
- });
- }
- });
- 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: function(){
- return App.config.get('preDefinedCustomConfigs');
- }.property('App.config.preDefinedCustomConfigs'),
- /**
- * 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: function(){
- if(App.get('isHadoop2Stack')){
- return ["yarn.scheduler.capacity.root.<queue-name>.user-limit-factor",
- "yarn.scheduler.capacity.root.<queue-name>.state"];
- }
- return [
- "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"
- ];
- }.property('App.isHadoop2Stack'),
- /**
- * 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)) {
- newConfig.value = config.defaultValue;
- }
- newConfig = App.ServiceConfigProperty.create(newConfig);
- newConfig.validate();
- emptyQueue.configs.push(newConfig);
- });
- this.set('emptyQueue', emptyQueue);
- },
- deriveQueueNames: function(configs){
- var queueNames = [];
- configs.mapProperty('name').forEach(function(name){
- var queueName;
- if(App.get('isHadoop2Stack')){
- queueName = /^yarn\.scheduler\.capacity\.root\.(.*?)\./.exec(name);
- } else {
- queueName = /^mapred\.capacity-scheduler\.queue\.(.*?)\./.exec(name);
- }
- if(queueName){
- queueNames.push(queueName[1]);
- }
- });
- return queueNames.uniq();
- },
- queues: function(){
- var configs = this.get('categoryConfigs').filterProperty('isQueue', true);
- var queueNames = this.deriveQueueNames(configs);
- var queues = [];
- queueNames.forEach(function(queueName){
- queues.push({
- name: queueName,
- color: this.generateColor(queueName),
- configs: this.groupConfigsByQueue(queueName, configs)
- })
- }, this);
- return queues;
- }.property('queueObserver'),
- /**
- * group configs by queue
- * @param queueName
- * @param configs
- */
- groupConfigsByQueue: function (queueName, configs) {
- var customConfigs = [];
- var queue = [];
- this.get('customConfigs').forEach(function(_config){
- var copy = $.extend({}, _config);
- copy.name = _config.name.replace('<queue-name>', queueName);
- customConfigs.push(copy);
- });
- configs.forEach(function (config) {
- var customConfig = customConfigs.findProperty('name', config.get('name'));
- 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('inTable', customConfig.inTable);
- config.set('index', customConfig.index);
- queue.push(config);
- }
- });
- if(queue.length < customConfigs.length){
- this.addMissingProperties(queue, customConfigs);
- }
- return queue;
- },
- /**
- * add missing properties to queue when they don't come from server
- * @param queue
- * @param customConfigs
- */
- addMissingProperties: function(queue, customConfigs){
- customConfigs.forEach(function(_config){
- var serviceConfigProperty;
- if(!queue.someProperty('name', _config.name)){
- _config.value = _config.defaultValue;
- serviceConfigProperty = App.ServiceConfigProperty.create(_config);
- serviceConfigProperty.validate();
- queue.push(serviceConfigProperty);
- }
- }, this);
- },
- /**
- * convert queues to table content
- */
- tableContent: function () {
- var result = [];
- this.get('queues').forEach(function (queue) {
- var usersAndGroups = queue.configs.findProperty('name', this.getUserAndGroupNames(queue.name)[0]).get('value');
- usersAndGroups = (usersAndGroups) ? usersAndGroups.split(' ') : [''];
- if (usersAndGroups.length == 1) {
- usersAndGroups.push('');
- }
- var queueObject = {
- name: queue.name,
- color: 'background-color:' + queue.color + ';',
- configs: this.sortByIndex(queue.configs.filterProperty('inTable'))
- };
- //push acl_submit_jobs users
- queueObject.configs.unshift({
- value: usersAndGroups[1],
- inTable: true,
- displayName: Em.I18n.t('common.users')
- });
- //push acl_submit_jobs groups
- queueObject.configs.unshift({
- value: usersAndGroups[0],
- inTable: true,
- displayName: Em.I18n.t('services.mapReduce.config.queue.groups')
- });
- result.push(queueObject);
- }, this);
- return result;
- }.property('queues'),
- /**
- * create headers depending on existed properties in queue
- */
- tableHeaders: function(){
- var headers = [
- Em.I18n.t('services.mapReduce.config.queue.name')
- ];
- return (this.get('tableContent').length) ?
- headers.concat(this.get('tableContent').objectAt(0).configs.filterProperty('inTable').mapProperty('displayName')):
- headers;
- }.property('tableContent'),
- queueObserver: null,
- /**
- * uses as template for adding new queue
- */
- emptyQueue: {},
- /**
- * get capacities sum of queues except of current
- * @param queueName
- * @return {Number}
- */
- getQueuesCapacitySum: function(queueName){
- var capacitySum = 0;
- this.get('queues').filter(function(queue){
- return queue.name !== queueName;
- }).forEach(function(queue){
- capacitySum = capacitySum + window.parseInt(queue.configs.find(function(config){
- return config.get('name').substr(-9, 9) === '.capacity';
- }).get('value'));
- });
- return capacitySum;
- },
- /**
- * get names of configs, for users and groups, which have different names in HDP1 and HDP2
- * @param queueName
- * @return {Array}
- */
- getUserAndGroupNames: function(queueName){
- queueName = queueName || '<queue-name>';
- if(App.config.get('isHDP2')){
- return ['yarn.scheduler.capacity.root.' + queueName + '.acl_submit_jobs',
- 'yarn.scheduler.capacity.root.' + queueName + '.acl_administer_jobs']
- }
- return ['mapred.queue.' + queueName + '.acl-submit-job',
- 'mapred.queue.' + queueName + '.acl-administer-jobs']
- },
- 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) {
- var adminName = this.getUserAndGroupNames()[1];
- var submitName = this.getUserAndGroupNames()[0];
- if(config.name == adminName){
- if (config.type == 'USERS') {
- admin[0] = config.value;
- }
- if (config.type == 'GROUPS') {
- admin[1] = config.value;
- }
- if (config.isQueue) {
- adminConfig = config;
- }
- }
- if(config.name == submitName){
- 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);
- }
- }, this);
- 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 = [];
- //comparison executes including 'queue.<queue-name>' to avoid false matches
- var queueNamePrefix = App.config.get('isHDP2') ? 'root.' : 'queue.';
- if (configNames.contains(_config.get('name'))) {
- if(configName == this.getUserAndGroupNames(queue.name)[0]){
- 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 == this.getUserAndGroupNames(queue.name)[1]){
- 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());
- }
- _config.set('name', configName.replace(queueNamePrefix + queue.name, queueNamePrefix + queue.configs.findProperty('name', 'queueName').get('value')));
- }
- }, this);
- 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) {
- var value = window.parseInt(queue.configs.find(function(_config){
- return _config.get('name').substr(-9, 9) === '.capacity';
- }).get('value'));
- data.push({
- label: queue.name,
- value: 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) {
- return !(config.name == self.getUserAndGroupNames(content.name)[0] ||
- config.name == self.getUserAndGroupNames(content.name)[1] &&
- config.isQueue);
- });
- 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 = [];
- // copy of queue configs
- content.configs.forEach(function (config, index) {
- if(config.get('name').substr(-9, 9) === '.capacity') {
- //added validation function for capacity property
- config.reopen({
- validate: function () {
- var value = this.get('value');
- var isError = false;
- var capacitySum = self.getQueuesCapacitySum(content.name);
- 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);
- }
- }
- if(config.name === 'yarn.scheduler.capacity.root.' + content.name + '.state'){
- config.reopen({
- validate: function(){
- var value = this.get('value');
- this._super();
- if(!this.get('errorMessage')){
- if(!(value === 'STOPPED' || value === 'RUNNING')){
- this.set('errorMessage', 'State value should be RUNNING or STOPPED');
- }
- }
- }.observes('value')
- })
- }
- configs[index] = App.ServiceConfigProperty.create(config);
- });
- content = {
- name: content.name,
- configs: configs
- };
- content = this.insertExtraConfigs(content);
- content.configs = self.sortByIndex(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" autocomplete="off">{{#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', self.getUserAndGroupNames(content.name)[1]).get('value');
- var submit = content.configs.findProperty('name', self.getUserAndGroupNames(content.name)[0]).get('value');
- admin = (admin) ? admin.split(' ') : [''];
- submit = (submit) ? submit.split(' ') : [''];
- if (admin.length < 2) {
- admin.push('');
- }
- if (submit.length < 2) {
- submit.push('');
- }
- var nameField = 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
- });
- nameField.validate();
- content.configs.unshift(nameField);
- var submitUser = App.ServiceConfigProperty.create({
- name: self.getUserAndGroupNames(content.name)[0],
- 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: self.getUserAndGroupNames(content.name)[0],
- 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: self.getUserAndGroupNames(content.name)[1],
- 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: self.getUserAndGroupNames(content.name)[1],
- 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;
- },
- /**
- * Validate by follow rules:
- * Users can be blank. If it is blank, Groups must not be blank.
- * Groups can be blank. If it 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();
- }
- }
- })
- }
- });
|