Return-Path: X-Original-To: apmail-incubator-ambari-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-ambari-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 61F9C10DF4 for ; Thu, 14 Nov 2013 16:22:11 +0000 (UTC) Received: (qmail 6282 invoked by uid 500); 14 Nov 2013 16:22:09 -0000 Delivered-To: apmail-incubator-ambari-commits-archive@incubator.apache.org Received: (qmail 6194 invoked by uid 500); 14 Nov 2013 16:22:03 -0000 Mailing-List: contact ambari-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@incubator.apache.org Delivered-To: mailing list ambari-commits@incubator.apache.org Received: (qmail 6186 invoked by uid 99); 14 Nov 2013 16:22:02 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 14 Nov 2013 16:22:02 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 3C9948A99CD; Thu, 14 Nov 2013 16:22:02 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: akovalenko@apache.org To: ambari-commits@incubator.apache.org Message-Id: <8d91d0e5c3144036b92e8d0da512296c@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: AMBARI-3767. Provide basic config-group management dialog. (akovalenko) Date: Thu, 14 Nov 2013 16:22:02 +0000 (UTC) Updated Branches: refs/heads/trunk a948d6b77 -> ef55a79c2 AMBARI-3767. Provide basic config-group management dialog. (akovalenko) Project: http://git-wip-us.apache.org/repos/asf/incubator-ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ambari/commit/ef55a79c Tree: http://git-wip-us.apache.org/repos/asf/incubator-ambari/tree/ef55a79c Diff: http://git-wip-us.apache.org/repos/asf/incubator-ambari/diff/ef55a79c Branch: refs/heads/trunk Commit: ef55a79c264fdc14c99dca62fa83da9fc050a038 Parents: a948d6b Author: Aleksandr Kovalenko Authored: Thu Nov 14 18:20:32 2013 +0200 Committer: Aleksandr Kovalenko Committed: Thu Nov 14 18:20:32 2013 +0200 ---------------------------------------------------------------------- ambari-web/app/controllers.js | 1 + ambari-web/app/controllers/main/service/item.js | 19 +++ .../service/manage_config_groups_controller.js | 144 +++++++++++++++++++ ambari-web/app/messages.js | 10 +- ambari-web/app/models/config_group.js | 84 ++++++----- ambari-web/app/styles/application.less | 6 + .../manage_configuration_groups_popup.hbs | 63 ++++++++ ambari-web/app/utils/ajax.js | 3 + ambari-web/app/views.js | 1 + ambari-web/app/views/main/service/item.js | 1 + .../main/service/manage_config_groups_view.js | 48 +++++++ 11 files changed, 344 insertions(+), 36 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/controllers.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers.js b/ambari-web/app/controllers.js index 80bfac9..37610be 100644 --- a/ambari-web/app/controllers.js +++ b/ambari-web/app/controllers.js @@ -72,6 +72,7 @@ require('controllers/main/service/reassign/step3_controller'); require('controllers/main/service/reassign/step4_controller'); require('controllers/main/service/reassign/step5_controller'); require('controllers/main/service/reassign/step6_controller'); +require('controllers/main/service/manage_config_groups_controller'); require('controllers/main/host'); require('controllers/main/host/details'); require('controllers/main/host/configs_service'); http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/controllers/main/service/item.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/service/item.js b/ambari-web/app/controllers/main/service/item.js index c24c4f9..ca9ca35 100644 --- a/ambari-web/app/controllers/main/service/item.js +++ b/ambari-web/app/controllers/main/service/item.js @@ -215,6 +215,25 @@ App.MainServiceItemController = Em.Controller.extend({ App.router.transitionTo('reassign'); }, + manageConfigurationGroups: function () { + var serviceName = this.get('content.serviceName'); + var displayName = this.get('content.displayName'); + App.ModalPopup.show({ + header: Em.I18n.t('services.service.config_groups_popup.header').format(displayName), + bodyClass: App.MainServiceManageConfigGroupView.extend({ + serviceName: serviceName, + controllerBinding: 'App.router.manageConfigGroupsController' + }), + classNames: ['sixty-percent-width-modal', 'manage-configuration-group-popup'], + primary: Em.I18n.t('common.save'), + onPrimary: function() { + this.hide(); + }, + secondary : Em.I18n.t('common.cancel'), + didInsertElement: function () {} + }); + }, + /** * On click callback for action dropdown menu * Calls runSmokeTest, runRebalancer, runCompaction or reassignMaster depending on context http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/controllers/main/service/manage_config_groups_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/service/manage_config_groups_controller.js b/ambari-web/app/controllers/main/service/manage_config_groups_controller.js new file mode 100644 index 0000000..549a1cb --- /dev/null +++ b/ambari-web/app/controllers/main/service/manage_config_groups_controller.js @@ -0,0 +1,144 @@ +/** + * 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.ManageConfigGroupsController = App.WizardController.extend({ + + name: 'manageConfigGroupsController', + + isLoaded: false, + + serviceName: null, + + configGroups: [], + + selectedConfigGroup: null, + + loadConfigGroups: function (serviceName) { + this.set('serviceName', serviceName); + App.ajax.send({ + name: 'service.load_config_groups', + sender: this, + data: { + serviceName: serviceName + }, + success: 'onLoadConfigGroupsSuccess', + error: 'onLoadConfigGroupsError' + }); + }, + + onLoadConfigGroupsSuccess: function (data) { + var usedHosts = []; + var unusedHosts = []; + var defaultConfigGroup = App.ConfigGroup.create({ + name: "Default", + description: "Default cluster level " + this.get('serviceName') + " configuration", + isDefault: true, + parentConfigGroup: null, + service: this.get('content'), + configSiteTags: [] + }); + if (data && data.items) { + var groupToTypeToTagMap = {}; + var configGroups = []; + data.items.forEach(function (configGroup) { + configGroup = configGroup.ConfigGroup; + var newConfigGroup = App.ConfigGroup.create({ + id: configGroup.id, + name: configGroup.group_name, + description: configGroup.description, + isDefault: false, + parentConfigGroup: defaultConfigGroup, + service: App.Service.find().findProperty('serviceName', configGroup.tag), + hosts: configGroup.hosts.mapProperty('host_name'), + configSiteTags: [], + properties: [] + }); + usedHosts = usedHosts.concat(newConfigGroup.get('hosts')); + configGroups.push(newConfigGroup); + configGroup.desired_configs.forEach(function (config) { + if (!groupToTypeToTagMap[configGroup.group_name]) { + groupToTypeToTagMap[configGroup.group_name] = {} + } + groupToTypeToTagMap[configGroup.group_name][config.type] = config.tag; + }); + }, this); + unusedHosts = App.Host.find().mapProperty('hostName'); + usedHosts.uniq().forEach(function (host) { + unusedHosts = unusedHosts.without(host); + }, this); + defaultConfigGroup.set('childConfigGroups', configGroups); + defaultConfigGroup.set('hosts', unusedHosts); + this.set('configGroups', [defaultConfigGroup].concat(configGroups)); + this.loadProperties(groupToTypeToTagMap); + this.set('isLoaded', true); + } + }, + + onLoadConfigGroupsError: function () { + console.error('Unable to load config groups for service.'); + }, + + loadProperties: function (groupToTypeToTagMap) { + var typeTagToGroupMap = {}; + var urlParams = []; + for (var group in groupToTypeToTagMap) { + var overrideTypeTags = groupToTypeToTagMap[group]; + for (var type in overrideTypeTags) { + var tag = overrideTypeTags[type]; + typeTagToGroupMap[type + "///" + tag] = group; + urlParams.push('(type=' + type + '&tag=' + tag + ')'); + } + } + var params = urlParams.join('|'); + if (urlParams.length) { + App.ajax.send({ + name: 'config.host_overrides', + sender: this, + data: { + params: params, + typeTagToGroupMap: typeTagToGroupMap + }, + success: 'onLoadPropertiesSuccess' + }); + } + }, + + onLoadPropertiesSuccess: function (data, opt, params) { + data.items.forEach(function (configs) { + var typeTagConfigs = []; + App.config.loadedConfigurationsCache[configs.type + "_" + configs.tag] = configs.properties; + var group = params.typeTagToGroupMap[configs.type + "///" + configs.tag]; + for (var config in configs.properties) { + typeTagConfigs.push({ + name: config, + value: configs.properties[config] + }); + } + this.get('configGroups').findProperty('name', group).get('properties').pushObjects(typeTagConfigs); + }, this); + }, + + showProperties: function () { + var properies = this.get('selectedConfigGroup.propertiesList'); + if (properies) { + App.showAlertPopup(Em.I18n.t('services.service.config_groups_popup.properties'), properies); + } + } +}); http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index ead756f..1e2f49d 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -156,6 +156,8 @@ Em.I18n.translations = { 'common.allServices':'All Services', 'common.move':'Move', 'common.change': 'Change', + 'common.overrides': 'Overrides', + 'common.properties': 'properties', 'requestInfo.installComponents':'Install Components', 'requestInfo.installServices':'Install Services', @@ -953,6 +955,7 @@ Em.I18n.translations = { 'services.service.actions.run.smoke':'Run Smoke Test', 'services.service.actions.reassign.master':'Reassign {0}', 'services.service.actions.reassign.master.hive':'Reassign HiveServer2, WebHCat Server, MySQL Server', + 'services.service.actions.manage_configuration_groups':'Manage Configuration Groups...', 'services.service.actions.serviceActions':'Service Actions...', 'services.service.summary.unknown':'unknown', 'services.service.summary.notRunning':'Not Running', @@ -1111,7 +1114,12 @@ Em.I18n.translations = { 'services.service.add':'Add Service', 'services.service.startAll':'Start All', 'services.service.stopAll':'Stop All', - + 'services.service.config_groups_popup.header':'Manage {0} Configuration Groups', + 'services.service.config_groups_popup.notice':'Manage configuration groups of this service. Groups can be created, renamed and deleted and from here. Host memberships can also be changed. A host can belong to only one configuration group.', + 'services.service.config_groups_popup.config_groups':'Configuration Groups', + 'services.service.config_groups_popup.rename':'Rename', + 'services.service.config_groups_popup.duplicate':'Duplicate', + 'services.service.config_groups_popup.properties':'Properties', 'services.reassign.closePopup':'Reassign {0} wizard is in progress. It\'s necessary to complete the wizard for Ambari to be in usable state. If you choose to quit, you must follow manual instructions to complete or revert reassign {0} wizard as documented in the Ambari User Guide. Are you sure you want to exit the wizard ?', 'services.reassign.step1.header':'Get Started', http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/models/config_group.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/config_group.js b/ambari-web/app/models/config_group.js index d789793..2a70ce4 100644 --- a/ambari-web/app/models/config_group.js +++ b/ambari-web/app/models/config_group.js @@ -19,80 +19,94 @@ var App = require('app'); /** - * Represents a configuration-group on the cluster. + * Represents a configuration-group on the cluster. * A configuration-group is a collection of hosts * on which a collection of configurations are applied. - * - * Configuration group hierarchy is at 2 levels. For + * + * Configuration group hierarchy is at 2 levels. For * each service there is a 'Default' configuration group * containing all hosts not belonging to any group of that - * service. - * + * service. + * * A default configuration group has child configuration * groups which contain configuration overrides (deltas) - * for a bunch of hosts. This allows different configurations + * for a bunch of hosts. This allows different configurations * for different hosts in a heterogeneous cluster environment. */ App.ConfigGroup = Ember.Object.extend({ - id: DS.attr('number'), - name: DS.attr('string'), - description: DS.attr('string'), - isDefault: DS.attr('boolean'), - + id: null, + name: null, + description: null, + isDefault: null, + /** * Parent configuration group for this group. * When {@link #isDefault} is true, this value is null * When {@link #isDefault} is false, this represents the configuration * deltas that are applied on the default. */ - parentConfigGroup: DS.belongsTo('App.ConfigGroup'), - + parentConfigGroup: null, + /** * Children configuration groups for this group. * When {@link #isDefault} is false, this value is null * When {@link #isDefault} is true, this represents the various * configuration groups that override the default. */ - childConfigGroups: DS.hasMany('App.ConfigGroup'), - + childConfigGroups: [], + /** - * Service for which this configuration-group + * Service for which this configuration-group * is applicable. */ - service: DS.belongsTo('App.Service'), - + service: null, + /** - * Hosts on which this configuration-group - * is to be applied. For a service, a host can + * Hosts on which this configuration-group + * is to be applied. For a service, a host can * belong to only one non-default configuration-group. - * + * * When {#isDefault} is false, this contains hosts * for which the overrides will apply. - * - * When {#isDefault} is true, this value is empty, as + * + * When {#isDefault} is true, this value is empty, as * it dynamically reflects hosts not belonging to other * non-default groups. - * + * */ - hosts: DS.hasMany('App.Host'), - + hosts: [], + + displayName: function () { + return this.get('name') + ' (' + this.get('hosts.length') + ')'; + }.property('name', 'hosts.length'), + /** - * Provides hosts which are available for inclusion in - * non-default configuration groups. + * Provides hosts which are available for inclusion in + * non-default configuration groups. */ - availableHosts: function() { - + availableHosts: function () { + }.property('isDefault', 'parentConfigGroup', 'childConfigGroups'), - + /** * Collection of (site, tag) pairs representing properties. - * - * When {#isDefault} is true, this represents the + * + * When {#isDefault} is true, this represents the * default cluster configurations for that service. - * + * * When {#isDefault} is false, this represents the * configuration overrides on top of the cluster default for the * hosts identified by 'hosts'. */ - configSiteTags: DS.hasMany('App.ConfigSiteTag') + configSiteTags: [], + + properties: [], + + propertiesList: function () { + var result = ''; + this.get('properties').forEach(function (item) { + result += item.name + " : " + item.value + '\n'; + }, this); + return result; + }.property('properties.length') }); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/styles/application.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less index 8b00c90..a8be260 100644 --- a/ambari-web/app/styles/application.less +++ b/ambari-web/app/styles/application.less @@ -4870,3 +4870,9 @@ i.icon-asterisks { } } } + +.manage-configuration-group-popup { + .group-select { + width: 100% + } +} http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/templates/main/service/manage_configuration_groups_popup.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/main/service/manage_configuration_groups_popup.hbs b/ambari-web/app/templates/main/service/manage_configuration_groups_popup.hbs new file mode 100644 index 0000000..073a8d1 --- /dev/null +++ b/ambari-web/app/templates/main/service/manage_configuration_groups_popup.hbs @@ -0,0 +1,63 @@ +{{! +* 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. +}} +
{{t services.service.config_groups_popup.notice}}
+
+
+ {{t services.service.config_groups_popup.config_groups}} +
+
+ {{view Em.Select + contentBinding="configGroups" + optionLabelPath="content.displayName" + selectionBinding="view.selectedConfigGroup" + multiple="multiple" + class="group-select" + }} + +
+
+
+
{{t common.hosts}}
+
+ {{view Em.Select + contentBinding="selectedConfigGroup.hosts" + multiple="multiple" + class="group-select" + }} +
+
+ + + - +
+
+ +
+
+
+
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/utils/ajax.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ajax.js b/ambari-web/app/utils/ajax.js index 91654d3..45da260 100644 --- a/ambari-web/app/utils/ajax.js +++ b/ambari-web/app/utils/ajax.js @@ -90,6 +90,9 @@ var urls = { }; } }, + 'service.load_config_groups': { + 'real': '/clusters/{clusterName}/config_groups?ConfigGroup/tag={serviceName}&fields=*' + }, 'reassign.stop_services': { 'real': '/clusters/{clusterName}/services', 'mock': '', http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/views.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js index c7980cb..2e53b86 100644 --- a/ambari-web/app/views.js +++ b/ambari-web/app/views.js @@ -196,6 +196,7 @@ require('views/main/service/reassign/step3_view'); require('views/main/service/reassign/step4_view'); require('views/main/service/reassign/step5_view'); require('views/main/service/reassign/step6_view'); +require('views/main/service/manage_config_groups_view'); require('views/main/charts/menu'); require('views/main/charts/heatmap'); require('views/main/charts/heatmap/heatmap_rack'); http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/views/main/service/item.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/service/item.js b/ambari-web/app/views/main/service/item.js index 76d0712..3352e62 100644 --- a/ambari-web/app/views/main/service/item.js +++ b/ambari-web/app/views/main/service/item.js @@ -43,6 +43,7 @@ App.MainServiceItemView = Em.View.extend({ } default: options.push({action: 'runSmokeTest', 'label': Em.I18n.t('services.service.actions.run.smoke'), disabled:disabled}); + options.push({action: 'manageConfigurationGroups', 'label': Em.I18n.t('services.service.actions.manage_configuration_groups'), disabled:false}); } return options; }.property('controller.content', 'controller.isStopDisabled'), http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/ef55a79c/ambari-web/app/views/main/service/manage_config_groups_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/service/manage_config_groups_view.js b/ambari-web/app/views/main/service/manage_config_groups_view.js new file mode 100644 index 0000000..9a50d10 --- /dev/null +++ b/ambari-web/app/views/main/service/manage_config_groups_view.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. + */ + +var App = require('app'); + +App.MainServiceManageConfigGroupView = Em.View.extend({ + + templateName: require('templates/main/service/manage_configuration_groups_popup'), + + selectedConfigGroup: null, + + onGroupSelect: function () { + var selectedConfigGroup = this.get('selectedConfigGroup'); + // to unable user select more than one config group at a time + if (selectedConfigGroup.length) { + this.set('controller.selectedConfigGroup', selectedConfigGroup[selectedConfigGroup.length - 1]); + } + if (selectedConfigGroup.length > 1) { + this.set('selectedConfigGroup', selectedConfigGroup[selectedConfigGroup.length - 1]); + } + }.observes('selectedConfigGroup'), + + onLoad: function () { + if (this.get('controller.isLoaded')) { + this.set('selectedConfigGroup', this.get('controller.configGroups')[0]) + } + }.observes('controller.isLoaded', 'controller.configGroups'), + + didInsertElement: function () { + this.get('controller').loadConfigGroups(this.get('serviceName')); + $('.properties-link').tooltip(); + } +});