Forráskód Böngészése

AMBARI-2423. Improvements to running Ambari Server as non-root. (Dmitry Lysnichenko via smohanty)

git-svn-id: https://svn.apache.org/repos/asf/incubator/ambari/trunk@1495625 13f79535-47bb-0310-9956-ffa450edef68
Sumit Mohanty 12 éve
szülő
commit
b49b75314b

+ 29 - 24
ambari-server/src/main/python/ambari-server.py

@@ -78,7 +78,7 @@ ambari_provider_module_option = ""
 ambari_provider_module = os.environ.get('AMBARI_PROVIDER_MODULE')
 
 # Non-root user setup commands
-NR_USER_PROPERTY = "ambari.user"
+NR_USER_PROPERTY = "ambari-server.user"
 NR_USER_COMMENT =  "Ambari user"
 NR_GET_OWNER_CMD = 'stat -c "%U" {0}'
 NR_USERADD_CMD = 'useradd -M -g {0} --comment "{1}" ' \
@@ -634,8 +634,6 @@ def create_custom_user():
                       "finished with {2}: \n{3}".format(user, command, retcode, err))
     return retcode, None
 
-
-
   print_info_msg("User/group configuration is done.")
   return 0, user
 
@@ -643,18 +641,27 @@ def create_custom_user():
 def check_ambari_user():
   try:
     user = read_ambari_user()
+    create_user = False
+    update_user_setting = False
     if user is not None:
-      print_info_msg("Detected custom user {0}".format(user))
-    else: # user is not configured yet or server is running under root
-      ok = get_YN_input("Create a separate user for ambari-server "
+      create_user = get_YN_input("Ambari-server process is configured run under user {0}."
+                        " Change this setting [y/n] (n)? ".format(user), False)
+      update_user_setting = create_user # Only if we will create another user
+    else: # user is not configured yet
+      update_user_setting = True # Write configuration anyway
+      create_user = get_YN_input("Create a separate user for ambari-server "
                    "daemon [y/n] (n)? ", False)
-      if ok:
-        (retcode, user) = create_custom_user()
-        if retcode != 0:
-          return retcode
-      else:
+      if not create_user:
         user = "root"
+
+    if create_user:
+      (retcode, user) = create_custom_user()
+      if retcode != 0:
+        return retcode
+
+    if update_user_setting:
       write_property(NR_USER_PROPERTY, user)
+
     adjust_directory_permissions(user)
   except OSError:
     print_error_msg("Failed: %s" % OSError.message)
@@ -666,8 +673,6 @@ def check_ambari_user():
 
 
 
-
-
 #
 # Checks iptables
 #
@@ -1922,6 +1927,17 @@ def reset(args):
 # Starts the Ambari Server.
 #
 def start(args):
+  current_user = getpass.getuser()
+  ambari_user = read_ambari_user()
+  if ambari_user is None:
+    err = "Can not detect a system user for Ambari. " \
+          "Please run \"setup\" command to create such user "
+    raise FatalException(1, err)
+  if current_user != ambari_user and not is_root():
+    err = "Can not start ambari-server as user {0}. Please either run \"start\" " \
+          "command as root or as user {1}".format(current_user, ambari_user)
+    raise FatalException(1, err)
+
   parse_properties_file(args)
   if os.path.exists(PID_DIR + os.sep + PID_NAME):
     f = open(PID_DIR + os.sep + PID_NAME, "r")
@@ -1934,17 +1950,6 @@ def start(args):
     except OSError as e:
       print_info_msg("Server is not running...")
 
-  current_user = getpass.getuser()
-  ambari_user = read_ambari_user()
-  if ambari_user is None:
-    err = "Can not detect a system user for Ambari. " \
-                    "Please run \"setup\" command to create such user "
-    raise FatalException(1, err)
-  if current_user != ambari_user and not is_root():
-    err = "Can not start ambari-server as user {0}. Please either run \"start\" " \
-          "command as root or as user {1}".format(current_user, ambari_user)
-    raise FatalException(1, err)
-
   conf_dir = get_conf_dir()
   jdk_path = find_jdk()
   if jdk_path is None:

+ 90 - 3
ambari-server/src/test/python/TestAmbaryServer.py

@@ -743,17 +743,56 @@ class TestAmbariServer(TestCase):
             adjust_directory_permissions_mock, write_property_mock,
             create_custom_user_mock, get_YN_input_mock, read_ambari_user_mock):
 
-    # Scenario: user is already defined
+    # Scenario: user is already defined, user does not want to reconfigure it
     read_ambari_user_mock.return_value = "dummy-user"
+    get_YN_input_mock.return_value = False
     result = ambari_server.check_ambari_user()
-    self.assertFalse(get_YN_input_mock.called)
+    self.assertTrue(get_YN_input_mock.called)
     self.assertFalse(write_property_mock.called)
+    self.assertFalse(create_custom_user_mock.called)
     self.assertTrue(adjust_directory_permissions_mock.called)
     self.assertEqual(result, 0)
 
     get_YN_input_mock.reset_mock()
     write_property_mock.reset_mock()
     adjust_directory_permissions_mock.reset_mock()
+    create_custom_user_mock.reset_mock()
+
+    # Scenario: user is already defined, but user wants to reconfigure it
+
+    read_ambari_user_mock.return_value = "dummy-user"
+    create_custom_user_mock.return_value = (0, "new-dummy-user")
+    get_YN_input_mock.return_value = True
+    result = ambari_server.check_ambari_user()
+    self.assertTrue(get_YN_input_mock.called)
+    self.assertTrue(write_property_mock.called)
+    self.assertTrue(write_property_mock.call_args[0][1] == "new-dummy-user")
+    self.assertTrue(create_custom_user_mock.called)
+    self.assertTrue(adjust_directory_permissions_mock.called)
+    self.assertEqual(result, 0)
+
+    get_YN_input_mock.reset_mock()
+    write_property_mock.reset_mock()
+    adjust_directory_permissions_mock.reset_mock()
+    create_custom_user_mock.reset_mock()
+
+    # Negative scenario: user is already defined, but user wants
+    # to reconfigure it, user creation failed
+
+    read_ambari_user_mock.return_value = "dummy-user"
+    create_custom_user_mock.return_value = (1, None)
+    get_YN_input_mock.return_value = True
+    result = ambari_server.check_ambari_user()
+    self.assertTrue(get_YN_input_mock.called)
+    self.assertTrue(create_custom_user_mock.called)
+    self.assertFalse(write_property_mock.called)
+    self.assertFalse(adjust_directory_permissions_mock.called)
+    self.assertEqual(result, 1)
+
+    get_YN_input_mock.reset_mock()
+    create_custom_user_mock.reset_mock()
+    write_property_mock.reset_mock()
+    adjust_directory_permissions_mock.reset_mock()
 
     # Scenario: user is not defined (setup process)
     read_ambari_user_mock.return_value = None
@@ -789,6 +828,23 @@ class TestAmbariServer(TestCase):
     write_property_mock.reset_mock()
     adjust_directory_permissions_mock.reset_mock()
 
+    # negative scenario: user is not defined (setup process), user creation failed
+
+    read_ambari_user_mock.return_value = None
+    get_YN_input_mock.return_value = True
+    create_custom_user_mock.return_value = (1, None)
+    result = ambari_server.check_ambari_user()
+    self.assertTrue(get_YN_input_mock.called)
+    self.assertTrue(create_custom_user_mock.called)
+    self.assertFalse(write_property_mock.called)
+    self.assertFalse(adjust_directory_permissions_mock.called)
+    self.assertEqual(result, 1)
+
+    get_YN_input_mock.reset_mock()
+    create_custom_user_mock.reset_mock()
+    write_property_mock.reset_mock()
+    adjust_directory_permissions_mock.reset_mock()
+
     # Scenario: user is not defined and left to be root
     read_ambari_user_mock.return_value = None
     get_YN_input_mock.return_value = False
@@ -1549,6 +1605,9 @@ class TestAmbariServer(TestCase):
       pass
     self.assertTrue(killMock.called)
 
+    killMock.reset_mock()
+    parse_properties_file_mock.reset_mock()
+
     pexistsMock.return_value = False
 
     # Checking situation when ambari user is not set up
@@ -1560,6 +1619,8 @@ class TestAmbariServer(TestCase):
       # Expected
       self.assertTrue('Can not detect a system user' in e.reason)
 
+    parse_properties_file_mock.reset_mock()
+
     # Checking start from non-root when current user is not the same as a
     # custom user
     read_ambari_user_mock.return_value = "dummy-user"
@@ -1571,6 +1632,9 @@ class TestAmbariServer(TestCase):
     except FatalException as e:
       # Expected
       self.assertTrue('Can not start ambari-server as user' in e.reason)
+      self.assertFalse(parse_properties_file_mock.called)
+
+    parse_properties_file_mock.reset_mock()
 
     # Checking "jdk not found"
     is_root_mock.return_value = True
@@ -1584,6 +1648,7 @@ class TestAmbariServer(TestCase):
 
     find_jdk_mock.return_value = "somewhere"
 
+    parse_properties_file_mock.reset_mock()
 
     ## Testing workflow under root
     is_root_mock.return_value = True
@@ -1601,6 +1666,7 @@ class TestAmbariServer(TestCase):
     self.assertFalse(check_postgre_up_mock.called)
 
     check_postgre_up_mock.reset_mock()
+    parse_properties_file_mock.reset_mock()
 
     # Local DB
     args.persistence_type="local"
@@ -1615,6 +1681,8 @@ class TestAmbariServer(TestCase):
       self.assertTrue('Unable to start PostgreSQL server' in e.reason)
       self.assertTrue(check_postgre_up_mock.called)
 
+    parse_properties_file_mock.reset_mock()
+
     # case: iptables failed to stop
     check_postgre_up_mock.return_value = 0
     check_iptables_mock.return_value = (1, ambari_server.IP_TBLS_ENABLED)
@@ -1625,6 +1693,8 @@ class TestAmbariServer(TestCase):
       # Expected
       self.assertTrue('Failed to stop iptables' in e.reason)
 
+    parse_properties_file_mock.reset_mock()
+
     check_iptables_mock.return_value = (0, None)
     # Case: custom user is "root"
     read_ambari_user_mock.return_value = "root"
@@ -1633,6 +1703,9 @@ class TestAmbariServer(TestCase):
     popen_arg = popenMock.call_args[0][0]
     self.assertTrue(popen_arg[0] == "/bin/sh")
     popenMock.reset_mock()
+
+    parse_properties_file_mock.reset_mock()
+
     # Case: custom user is  not "root"
     read_ambari_user_mock.return_value = "not-root-user"
     ambari_server.start(args)
@@ -1643,11 +1716,15 @@ class TestAmbariServer(TestCase):
     check_postgre_up_mock.reset_mock()
 
     popenMock.reset_mock()
+    parse_properties_file_mock.reset_mock()
 
     ## Testing workflow under non-root
     is_root_mock.return_value = False
     read_ambari_user_mock.return_value = "not-root-user"
     getuser_mock.return_value = read_ambari_user_mock.return_value
+
+    parse_properties_file_mock.reset_mock()
+
     # Local DB
     args.persistence_type="local"
 
@@ -1655,6 +1732,8 @@ class TestAmbariServer(TestCase):
 
     self.assertFalse(check_postgre_up_mock.called)
 
+    parse_properties_file_mock.reset_mock()
+
     # Remote DB
     args.persistence_type="remote"
 
@@ -1662,6 +1741,8 @@ class TestAmbariServer(TestCase):
 
     self.assertFalse(check_postgre_up_mock.called)
 
+    parse_properties_file_mock.reset_mock()
+
     # Checking call
     check_iptables_mock.reset_mock()
     check_iptables_mock.return_value = (0, None)
@@ -1671,6 +1752,8 @@ class TestAmbariServer(TestCase):
     self.assertTrue(popen_arg[0] == "/bin/sh")
     self.assertFalse(check_iptables_mock.called)
 
+    parse_properties_file_mock.reset_mock()
+
     # Test start under wrong user
     read_ambari_user_mock.return_value = "not-root-user"
     getuser_mock.return_value = "non_custom_user"
@@ -1681,6 +1764,8 @@ class TestAmbariServer(TestCase):
       # Expected
       self.assertTrue('Can not start ambari-server as user' in e.reason)
 
+    parse_properties_file_mock.reset_mock()
+
     # Check environ master key is set
     popenMock.reset_mock()
     get_ambari_properties_mock.return_value = \
@@ -1698,6 +1783,8 @@ class TestAmbariServer(TestCase):
     popen_arg = popenMock.call_args[1]['env']
     self.assertEquals(os_environ_mock.copy.return_value, popen_arg)
 
+    parse_properties_file_mock.reset_mock()
+
     # Check environ master key is not set
     popenMock.reset_mock()
     os_environ_mock.reset_mock()
@@ -2100,7 +2187,7 @@ class TestAmbariServer(TestCase):
       "server.jdbc.user.passwd=/etc/ambari-server/conf/password.dat\n",
       "java.home=/usr/jdk64/jdk1.6.0_31\n",
       "server.os_type=redhat6\n",
-      "ambari.user=ambari\n"]
+      "ambari-server.user=ambari\n"]
 
     NEW_PROPERTY = 'some_new_property=some_value\n'
     CHANGED_VALUE_PROPERTY = 'server.os_type=should_not_overwrite_value\n'