Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 2FB07200CD9 for ; Wed, 19 Jul 2017 14:38:59 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 2E14A16766E; Wed, 19 Jul 2017 12:38:59 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 08868167640 for ; Wed, 19 Jul 2017 14:38:56 +0200 (CEST) Received: (qmail 98244 invoked by uid 500); 19 Jul 2017 12:38:56 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 97612 invoked by uid 99); 19 Jul 2017 12:38:55 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Jul 2017 12:38:55 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id E20BDDFF9F; Wed, 19 Jul 2017 12:38:54 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rlevas@apache.org To: commits@ambari.apache.org Date: Wed, 19 Jul 2017 12:39:03 -0000 Message-Id: <91494abe381e405da6f3b9357a23dc9e@git.apache.org> In-Reply-To: <10abc9016e6d423db736811ec53621b1@git.apache.org> References: <10abc9016e6d423db736811ec53621b1@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [10/21] ambari git commit: AMBARI-21483. Add UID/GID related enhancements (echekanskiy) archived-at: Wed, 19 Jul 2017 12:38:59 -0000 AMBARI-21483. Add UID/GID related enhancements (echekanskiy) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f92d1219 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f92d1219 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f92d1219 Branch: refs/heads/branch-feature-AMBARI-20859 Commit: f92d12193b30d53dc06ab9642ef4b9d61b5bac1c Parents: 56462b2 Author: Eugene Chekanskiy Authored: Sun Jul 16 20:22:34 2017 +0300 Committer: Eugene Chekanskiy Committed: Sun Jul 16 20:22:34 2017 +0300 ---------------------------------------------------------------------- .../ambari/server/state/PropertyInfo.java | 2 + .../hooks/before-ANY/files/changeToSecureUid.sh | 13 +- .../before-ANY/scripts/shared_initialization.py | 45 ++- .../2.0.6/hooks/before-ANY/test_before_any.py | 294 +++++++++++-------- .../app/controllers/wizard/step7_controller.js | 67 +++++ .../configs/stack_config_properties_mapper.js | 14 +- ambari-web/app/styles/application.less | 15 + ...ontrols_service_config_usergroup_with_id.hbs | 27 ++ ambari-web/app/utils/config.js | 3 + .../configs/service_configs_by_category_view.js | 6 + ambari-web/app/views/common/controls_view.js | 39 +++ 11 files changed, 392 insertions(+), 133 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java index 62396e3..63c850e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/PropertyInfo.java @@ -281,7 +281,9 @@ public class PropertyInfo { public enum PropertyType { PASSWORD, USER, + UID, GROUP, + GID, TEXT, ADDITIONAL_USER_PROPERTY, NOT_MANAGED_HDFS_PATH, http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/files/changeToSecureUid.sh ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/files/changeToSecureUid.sh b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/files/changeToSecureUid.sh index 08542c4..4663f10 100644 --- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/files/changeToSecureUid.sh +++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/files/changeToSecureUid.sh @@ -21,6 +21,7 @@ username=$1 directories=$2 +newUid=$3 function find_available_uid() { for ((i=1001; i<=2000; i++)) @@ -34,7 +35,16 @@ function find_available_uid() { done } -find_available_uid +if [ -z $2 ]; then + test $(id -u ${username} 2>/dev/null) + if [ $? -ne 1 ]; then + newUid=`id -u ${username}` + else + find_available_uid + fi + echo $newUid + exit 0 +fi if [ $newUid -eq 0 ] then @@ -43,7 +53,6 @@ then fi set -e - dir_array=($(echo $directories | sed 's/,/\n/g')) old_uid=$(id -u $username) sudo_prefix="/var/lib/ambari-agent/ambari-sudo.sh -H -E" http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/scripts/shared_initialization.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/scripts/shared_initialization.py b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/scripts/shared_initialization.py index 39f5a47..bcc1a3a 100644 --- a/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/scripts/shared_initialization.py +++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/hooks/before-ANY/scripts/shared_initialization.py @@ -24,6 +24,7 @@ import tempfile from copy import copy from resource_management.libraries.functions.version import compare_versions from resource_management import * +from resource_management.core import shell def setup_users(): """ @@ -43,11 +44,17 @@ def setup_users(): ) for user in params.user_list: - User(user, - gid = params.user_to_gid_dict[user], - groups = params.user_to_groups_dict[user], - fetch_nonlocal_groups = params.fetch_nonlocal_groups - ) + if params.override_uid == "true": + User(user, + uid = get_uid(user), + gid = params.user_to_gid_dict[user], + groups = params.user_to_groups_dict[user], + ) + else: + User(user, + gid = params.user_to_gid_dict[user], + groups = params.user_to_groups_dict[user], + ) if params.override_uid == "true": set_uid(params.smoke_user, params.smoke_user_dirs) @@ -65,6 +72,7 @@ def setup_users(): create_parents = True, cd_access="a", ) + if params.override_uid == "true": set_uid(params.hbase_user, params.hbase_user_dirs) else: @@ -125,7 +133,7 @@ def create_users_and_groups(user_and_groups): Group(copy(groups_list), ) return groups_list - + def set_uid(user, user_dirs): """ user_dirs - comma separated directories @@ -136,9 +144,30 @@ def set_uid(user, user_dirs): content=StaticFile("changeToSecureUid.sh"), mode=0555) ignore_groupsusers_create_str = str(params.ignore_groupsusers_create).lower() - Execute(format("{tmp_dir}/changeUid.sh {user} {user_dirs}"), + uid = get_uid(user) + Execute(format("{tmp_dir}/changeUid.sh {user} {user_dirs} {uid}"), not_if = format("(test $(id -u {user}) -gt 1000) || ({ignore_groupsusers_create_str})")) - + +def get_uid(user): + import params + user_str = str(user) + "_uid" + service_env = [ serviceEnv for serviceEnv in params.config['configurations'] if user_str in params.config['configurations'][serviceEnv]] + + if service_env and params.config['configurations'][service_env[0]][user_str]: + service_env_str = str(service_env[0]) + uid = params.config['configurations'][service_env_str][user_str] + if len(service_env) > 1: + Logger.warning("Multiple values found for %s, using %s" % (user_str, uid)) + return uid + else: + if user == params.smoke_user: + return 0 + File(format("{tmp_dir}/changeUid.sh"), + content=StaticFile("changeToSecureUid.sh"), + mode=0555) + conde, newUid = shell.call((format("{tmp_dir}/changeUid.sh"), format("{user}")), sudo=True) + return newUid + def setup_hadoop_env(): import params stackversion = params.stack_version_unformatted http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-server/src/test/python/stacks/2.0.6/hooks/before-ANY/test_before_any.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/python/stacks/2.0.6/hooks/before-ANY/test_before_any.py b/ambari-server/src/test/python/stacks/2.0.6/hooks/before-ANY/test_before_any.py index 75c6543..1d2351f 100644 --- a/ambari-server/src/test/python/stacks/2.0.6/hooks/before-ANY/test_before_any.py +++ b/ambari-server/src/test/python/stacks/2.0.6/hooks/before-ANY/test_before_any.py @@ -21,6 +21,7 @@ limitations under the License. from stacks.utils.RMFTestCase import * from mock.mock import MagicMock, call, patch from resource_management import Hook +import itertools import getpass import os @@ -45,147 +46,201 @@ class TestHookBeforeInstall(RMFTestCase): self.executeScript("2.0.6/hooks/before-ANY/scripts/hook.py", classname="BeforeAnyHook", command="hook", - config_file="default.json" - ) - - self.assertResourceCalled('Group', 'hadoop', - ) - self.assertResourceCalled('Group', 'nobody', - ) - self.assertResourceCalled('Group', 'users', + config_file="default.json", + call_mocks=itertools.cycle([(0, "1000")]) ) + self.assertResourceCalled('Group', 'hadoop',) + self.assertResourceCalled('Group', 'nobody',) + self.assertResourceCalled('Group', 'users',) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'hive', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'oozie', - gid = 'hadoop', - groups = [u'users'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'users'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'nobody', - gid = 'hadoop', - groups = [u'nobody'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'nobody'], + ) self.assertResourceCalled('User', 'ambari-qa', - gid = 'hadoop', - groups = [u'users'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = 0, + groups = [u'users'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'flume', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'hdfs', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'storm', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'mapred', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'hbase', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'tez', - gid = 'hadoop', - groups = [u'users'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'users'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'zookeeper', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'falcon', - gid = 'hadoop', - groups = [u'users'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'users'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'sqoop', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'yarn', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) self.assertResourceCalled('User', 'hcat', - gid = 'hadoop', - groups = [u'hadoop'], - fetch_nonlocal_groups = True, - ) + gid = 'hadoop', + uid = '1000', + groups = [u'hadoop'], + ) self.assertResourceCalled('File', '/tmp/changeUid.sh', - content = StaticFile('changeToSecureUid.sh'), - mode = 0555, - ) - self.assertResourceCalled('Execute', '/tmp/changeUid.sh ambari-qa /tmp/hadoop-ambari-qa,/tmp/hsperfdata_ambari-qa,/home/ambari-qa,/tmp/ambari-qa,/tmp/sqoop-ambari-qa', - not_if = '(test $(id -u ambari-qa) -gt 1000) || (false)', - ) - self.assertResourceCalled('Directory', self.TMP_PATH, - owner = 'hbase', - mode = 0775, - create_parents = True, - cd_access='a' - ) + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) + self.assertResourceCalled('Execute', '/tmp/changeUid.sh ambari-qa /tmp/hadoop-ambari-qa,/tmp/hsperfdata_ambari-qa,/home/ambari-qa,/tmp/ambari-qa,/tmp/sqoop-ambari-qa 0', + not_if = '(test $(id -u ambari-qa) -gt 1000) || (false)', + ) + self.assertResourceCalled('Directory', '/tmp/hbase-hbase', + owner = 'hbase', + create_parents = True, + mode = 0775, + cd_access = 'a', + ) self.assertResourceCalled('File', '/tmp/changeUid.sh', - content = StaticFile('changeToSecureUid.sh'), - mode = 0555, - ) - self.assertResourceCalled('Execute', '/tmp/changeUid.sh hbase /home/hbase,/tmp/hbase,/usr/bin/hbase,/var/log/hbase,' + self.TMP_PATH, - not_if = '(test $(id -u hbase) -gt 1000) || (false)', - ) + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) + self.assertResourceCalled('File', '/tmp/changeUid.sh', + content = StaticFile('changeToSecureUid.sh'), + mode = 0555, + ) + self.assertResourceCalled('Execute', '/tmp/changeUid.sh hbase /home/hbase,/tmp/hbase,/usr/bin/hbase,/var/log/hbase,/tmp/hbase-hbase 1000', + not_if = '(test $(id -u hbase) -gt 1000) || (false)', + ) self.assertResourceCalled('User', 'test_user1', - fetch_nonlocal_groups = True, - ) + fetch_nonlocal_groups = True, + ) self.assertResourceCalled('User', 'test_user2', - fetch_nonlocal_groups = True, - ) - self.assertResourceCalled('Group', 'hdfs', - ) - self.assertResourceCalled('Group', 'test_group', - ) + fetch_nonlocal_groups = True, + ) + self.assertResourceCalled('Group', 'hdfs',) + self.assertResourceCalled('Group', 'test_group',) self.assertResourceCalled('User', 'hdfs', - groups = [u'hadoop', u'hdfs', u'test_group'], - fetch_nonlocal_groups = True, - ) + fetch_nonlocal_groups = True, + groups = [u'hadoop', u'hdfs', u'test_group'], + ) self.assertResourceCalled('Directory', '/etc/hadoop', - mode = 0755 - ) + mode = 0755, + ) self.assertResourceCalled('Directory', '/etc/hadoop/conf.empty', - owner = 'root', - group = 'hadoop', - create_parents = True, - ) + owner = 'root', + create_parents = True, + group = 'hadoop', + ) self.assertResourceCalled('Link', '/etc/hadoop/conf', - not_if = 'ls /etc/hadoop/conf', - to = '/etc/hadoop/conf.empty', - ) + not_if = 'ls /etc/hadoop/conf', + to = '/etc/hadoop/conf.empty', + ) self.assertResourceCalled('File', '/etc/hadoop/conf/hadoop-env.sh', - content = InlineTemplate(self.getConfig()['configurations']['hadoop-env']['content']), - owner = 'hdfs', - group = 'hadoop' + content = InlineTemplate(self.getConfig()['configurations']['hadoop-env']['content']), + owner = 'hdfs', + group = 'hadoop' ) self.assertResourceCalled('Directory', '/tmp/hadoop_java_io_tmpdir', owner = 'hdfs', group = 'hadoop', - mode = 01777 - ) - + mode = 01777, + ) self.assertResourceCalled('Directory', '/tmp/AMBARI-artifacts/', create_parents = True, ) @@ -198,20 +253,17 @@ class TestHookBeforeInstall(RMFTestCase): ) self.assertResourceCalled('Directory', '/usr/jdk64',) self.assertResourceCalled('Execute', ('chmod', 'a+x', u'/usr/jdk64'), - sudo = True - ) - self.assertResourceCalled('Execute', 'cd /tmp/jdk_tmp_dir && tar -xf /tmp/jdk-7u67-linux-x64.tar.gz && ambari-sudo.sh cp -rp /tmp/jdk_tmp_dir/* /usr/jdk64' + sudo = True, ) + self.assertResourceCalled('Execute', 'cd /tmp/jdk_tmp_dir && tar -xf /tmp/jdk-7u67-linux-x64.tar.gz && ambari-sudo.sh cp -rp /tmp/jdk_tmp_dir/* /usr/jdk64',) self.assertResourceCalled('Directory', '/tmp/jdk_tmp_dir', - action = ['delete'] + action = ['delete'], ) - self.assertResourceCalled('File', '/usr/jdk64/jdk1.7.0_45/bin/java', mode = 0755, - cd_access = "a", + cd_access = 'a', ) self.assertResourceCalled('Execute', ('chmod', '-R', '755', u'/usr/jdk64/jdk1.7.0_45'), - sudo = True, - ) - + sudo = True, + ) self.assertNoMoreResources() http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-web/app/controllers/wizard/step7_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step7_controller.js b/ambari-web/app/controllers/wizard/step7_controller.js index 9a897d0..6a90c26 100644 --- a/ambari-web/app/controllers/wizard/step7_controller.js +++ b/ambari-web/app/controllers/wizard/step7_controller.js @@ -531,6 +531,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E } var stepConfigs = this.createStepConfigs(); var serviceConfigs = this.renderConfigs(stepConfigs, configs); + this.addUidAndGidRepresentations(serviceConfigs); // if HA is enabled -> Make some reconfigurations if (this.get('wizardController.name') === 'addServiceController') { this.updateComponentActionConfigs(configs, serviceConfigs); @@ -802,6 +803,38 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E }, /** + * Set the uid property for user properties. The uid is later used to help map the user and uid values in adjacent columns + * @param {object} miscSvc + * @param {string} svcName + * @private + */ + _setUID: function (miscSvc, svcName) { + var user = miscSvc.configs.findProperty('name', svcName + '_user'); + if (user) { + var uid = miscSvc.configs.findProperty('name', user.value + '_uid'); + if (uid) { + user.set('ugid', uid); + } + } + }, + + /** + * Set the gid property for group properties. The gid is later used to help map the group and gid values in adjacent columns + * @param {object} miscSvc + * @param {string} svcName + * @private + */ + _setGID: function (miscSvc, svcName) { + var group = miscSvc.configs.findProperty('name', svcName + '_group'); + if (group) { + var gid = miscSvc.configs.findProperty('name', group.value + '_gid'); + if (gid) { + group.set('ugid', gid); + } + } + }, + + /** * render configs, distribute them by service * and wrap each in ServiceConfigProperty object * @param stepConfigs @@ -841,6 +874,11 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E this.updateHostOverrides(serviceConfigProperty, _config); if (this.get('wizardController.name') === 'addServiceController') { this._updateIsEditableFlagForConfig(serviceConfigProperty, true); + //since the override_uid and ignore_groupusers_create changes are not saved to the database post install, they should be editable only + //during initial cluster installation + if (['override_uid', 'ignore_groupsusers_create'].contains(serviceConfigProperty.get('name'))) { + serviceConfigProperty.set('isEditable', false); + } } if (!this.get('content.serviceConfigProperties.length') && !serviceConfigProperty.get('hasInitialValue')) { App.ConfigInitializer.initialValue(serviceConfigProperty, localDB, dependencies); @@ -860,6 +898,35 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, App.E return stepConfigs; }, + addUidAndGidRepresentations: function(serviceConfigs) { + //map the uids to the corresponding users + var miscSvc = serviceConfigs.findProperty('serviceName', 'MISC'); + if (miscSvc) { + //iterate through the list of users and groups and assign the uid/gid accordingly + //user properties are servicename_user + //uid properties are value of servicename_user + _uid + //group properties are servicename_group + //gid properties are value of servicename_group + _gid + //we will map the users/uids and groups/gids based on this assumption + this.get('selectedServiceNames').forEach(function (serviceName) { + this._setUID(miscSvc, serviceName.toLowerCase()); + this._setGID(miscSvc, serviceName.toLowerCase()); + }, this); + + //for zookeeper, the user property name does not follow the convention that users for other services do. i.e. the user property name is not servicename_user as is the case with other services + //the user property name is zk_user and not zookeeper_user, hence set the uid for zk_user separately + this._setUID(miscSvc, 'zk'); + //the user property name is mapred_user and not mapreduce2_user for mapreduce2 service, hence set the uid for mapred_user separately + this._setUID(miscSvc, 'mapred'); + //for haddop, the group property name does not follow the convention that groups for other services do. i.e. the group property name is not servicename_group as is the case with other services + //the group property name is user_group and not zookeeper_group, hence set the gid for user_group separately + this._setGID(miscSvc, 'user'); + + // uid/gid properties are displayed in a separate column, hence prevent the properties from showing up on a separate line + miscSvc.configs.filterProperty('displayType', 'uid_gid').setEach('isVisible', false); + } + }, + /** * Add host name properties to appropriate categories (for installer and add service) * http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-web/app/mappers/configs/stack_config_properties_mapper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/configs/stack_config_properties_mapper.js b/ambari-web/app/mappers/configs/stack_config_properties_mapper.js index 9b4b920..75a5564 100644 --- a/ambari-web/app/mappers/configs/stack_config_properties_mapper.js +++ b/ambari-web/app/mappers/configs/stack_config_properties_mapper.js @@ -197,9 +197,14 @@ App.stackConfigPropertiesMapper = App.QuickDataMapper.create({ * @param config */ handleSpecialProperties: function(config) { - if (!config.StackConfigurations.property_type.contains('ADDITIONAL_USER_PROPERTY')) { + var types = config.StackConfigurations.property_type; + if (!types.contains('ADDITIONAL_USER_PROPERTY')) { config.index = App.StackService.displayOrder.indexOf(config.StackConfigurations.service_name) + 1 || 30; } + // displayType from stack ignored, cause UID and GID should be shown along with service's user config + if (types.contains('UID') || types.contains('GID')) { + config.StackConfigurations.property_value_attributes.type = 'uid_gid'; + } config.StackConfigurations.service_name = 'MISC'; config.category = 'Users and Groups'; }, @@ -210,7 +215,12 @@ App.stackConfigPropertiesMapper = App.QuickDataMapper.create({ * @returns {Boolean} */ isMiscService: function(type) { - return type.length && (type.contains('USER') || type.contains('GROUP') || type.contains('ADDITIONAL_USER_PROPERTY')); + return type.length && + (type.contains('USER') + || type.contains('GROUP') + || type.contains('ADDITIONAL_USER_PROPERTY') + || type.contains('UID') + || type.contains('GID')); }, /** http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-web/app/styles/application.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less index 29788bc..a32275f 100644 --- a/ambari-web/app/styles/application.less +++ b/ambari-web/app/styles/application.less @@ -1147,6 +1147,21 @@ a:focus { } } +.serviceConfigUGIDLbl { + display: inline-block; + text-align: left; + margin-left: 92px; + width: 100px; +} + +.serviceConfigUGID { + width: 150px !important; +} + +.serviceConfigNoUGID { + width: 500px !important; +} + .chart-container { cursor: pointer; cursor: -moz-zoom-in; http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-web/app/templates/wizard/controls_service_config_usergroup_with_id.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/wizard/controls_service_config_usergroup_with_id.hbs b/ambari-web/app/templates/wizard/controls_service_config_usergroup_with_id.hbs new file mode 100644 index 0000000..24c785c --- /dev/null +++ b/ambari-web/app/templates/wizard/controls_service_config_usergroup_with_id.hbs @@ -0,0 +1,27 @@ +{{! +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +}} + +{{#if view.isUIDGIDVisible}} + {{view App.ServiceConfigTextField serviceConfigBinding="view.serviceConfig" class="serviceConfigUGID"}} + + {{view Ember.TextField valueBinding="view.serviceConfig.ugid.value" class="serviceConfigUGID"}} +{{else}} + {{view App.ServiceConfigTextField serviceConfigBinding="view.serviceConfig" class="serviceConfigNoUGID"}} +{{/if}} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-web/app/utils/config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js index 00cc2a3..7cfcb13 100644 --- a/ambari-web/app/utils/config.js +++ b/ambari-web/app/utils/config.js @@ -545,6 +545,9 @@ App.config = Em.Object.create({ */ getViewClass: function (displayType, dependentConfigPattern, unit) { switch (displayType) { + case 'user': + case 'group': + return App.ServiceConfigTextFieldUserGroupWithID; case 'checkbox': case 'boolean': return dependentConfigPattern ? App.ServiceConfigCheckboxWithDependencies : App.ServiceConfigCheckbox; http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-web/app/views/common/configs/service_configs_by_category_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/configs/service_configs_by_category_view.js b/ambari-web/app/views/common/configs/service_configs_by_category_view.js index 4058020..6cf9b99 100644 --- a/ambari-web/app/views/common/configs/service_configs_by_category_view.js +++ b/ambari-web/app/views/common/configs/service_configs_by_category_view.js @@ -50,6 +50,7 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.Persist, App.ConfigOverrid * @type {App.ServiceConfigProperty[]} */ serviceConfigs: null, + isUIDGIDVisible: true, /** * This is array of all the properties which apply @@ -744,6 +745,11 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.Persist, App.ConfigOverrid setRecommendedValue: function (event) { var serviceConfigProperty = event.contexts[0]; serviceConfigProperty.set('value', serviceConfigProperty.get('recommendedValue')); + + //in case of USER/GROUP fields, if they have uid/gid set, then these need to be reset to the recommended value as well + if (serviceConfigProperty.get('ugid')) { + serviceConfigProperty.set('ugid.value', serviceConfigProperty.get('ugid.recommendedValue')); + } serviceConfigProperty = null; }, http://git-wip-us.apache.org/repos/asf/ambari/blob/f92d1219/ambari-web/app/views/common/controls_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/controls_view.js b/ambari-web/app/views/common/controls_view.js index edeaf0a..4e926ba 100644 --- a/ambari-web/app/views/common/controls_view.js +++ b/ambari-web/app/views/common/controls_view.js @@ -247,6 +247,40 @@ App.ServiceConfigTextField = Ember.TextField.extend(App.ServiceConfigPopoverSupp }); /** + * Customized input control for user/group configs with corresponding uid/gid specified + * @type {Em.View} + */ +App.ServiceConfigTextFieldUserGroupWithID = Ember.View.extend(App.ServiceConfigPopoverSupport, { + valueBinding: 'serviceConfig.value', + placeholderBinding: 'serviceConfig.savedValue', + classNames: 'display-inline-block', + + templateName: require('templates/wizard/controls_service_config_usergroup_with_id'), + + isUIDGIDVisible: function () { + var overrideUidDisabled = this.get('parentView').serviceConfigs.findProperty('name', 'override_uid').value === 'false'; + //don't display the ugid field if there is no uid/gid for this property or override_uid is unchecked + if (Em.isNone(this.get('serviceConfig.ugid')) || overrideUidDisabled) { + return false; + } + + var serviceName = this.get('serviceConfig').name.substr(0, this.get('serviceConfig').name.indexOf('_')).toUpperCase(); + if (serviceName === 'ZK') { + serviceName = 'ZOOKEEPER'; + } + if (serviceName === 'MAPRED') { + serviceName = 'YARN'; + } + //addServiceController and service already installed or Hadoop user group + if (App.Service.find(serviceName).get('isLoaded') || serviceName === 'USER') { + return false; + } + + return this.get('parentView.isUIDGIDVisible'); + }.property('parentView.isUIDGIDVisible') +}); + +/** * Customized input control with Units type specified * @type {Em.View} */ @@ -415,6 +449,11 @@ var checkboxConfigView = Ember.Checkbox.extend(App.ServiceConfigPopoverSupport, this.set('serviceConfig.value', this.get(this.get('checked') + 'Value')); this.get('serviceConfig').set("editDone", true); this.sendRequestRorDependentConfigs(this.get('serviceConfig')); + + //if the checkbox being toggled is the 'Have Ambari manage UIDs' in Misc Tab, show/hide uid/gid column accordingly + if (this.get('serviceConfig.name') === 'override_uid') { + this.set('parentView.isUIDGIDVisible', this.get('checked')); + } } }.observes('checked'),