浏览代码

AMBARI-8317 Refactor the OS-dependent Ambari Server Windows components - Part 1.4

+Further decomposing ambari-server.py: Moved setup, reset and upgrade into their own files
+Made them OS-independent - now the same routines are being used in Windows too (save upgrade, which is not active in Windows yet)
+Merged the OS-dependent code for JDBC & JDK setup, database interface creation, firewall checks
+Refactored the database setup: split the supported DBMSes into distinct objects
+Replaced recursive calls in the user input routines
Florian Barca 10 年之前
父节点
当前提交
49955a3597
共有 23 个文件被更改,包括 3234 次插入4887 次删除
  1. 73 17
      ambari-common/src/main/python/ambari_commons/firewall.py
  2. 3 3
      ambari-common/src/main/python/ambari_commons/inet_utils.py
  3. 15 1
      ambari-common/src/main/python/ambari_commons/logging_utils.py
  4. 15 2
      ambari-server/conf/unix/ambari.properties
  5. 1 1
      ambari-server/conf/windows/ambari.properties
  6. 18 33
      ambari-server/src/main/python/ambari-server-windows.py
  7. 108 2162
      ambari-server/src/main/python/ambari-server.py
  8. 352 80
      ambari-server/src/main/python/ambari_server/dbConfiguration.py
  9. 708 592
      ambari-server/src/main/python/ambari_server/dbConfiguration_linux.py
  10. 124 174
      ambari-server/src/main/python/ambari_server/dbConfiguration_windows.py
  11. 401 48
      ambari-server/src/main/python/ambari_server/serverConfiguration.py
  12. 673 283
      ambari-server/src/main/python/ambari_server/serverSetup.py
  13. 0 793
      ambari-server/src/main/python/ambari_server/serverSetup_linux.py
  14. 0 300
      ambari-server/src/main/python/ambari_server/serverSetup_windows.py
  15. 305 0
      ambari-server/src/main/python/ambari_server/serverUpgrade.py
  16. 3 1
      ambari-server/src/main/python/ambari_server/setupActions.py
  17. 76 199
      ambari-server/src/main/python/ambari_server/setupSecurity.py
  18. 18 11
      ambari-server/src/main/python/ambari_server/userInput.py
  19. 1 1
      ambari-server/src/main/resources/custom_actions/scripts/check_host.py
  20. 2 2
      ambari-server/src/main/resources/stacks/HDPWIN/2.1/hooks/before-ANY/scripts/setup_jdk.py
  21. 2 2
      ambari-server/src/main/resources/stacks/HDPWIN/2.1/services/YARN/package/scripts/mapred_service_check.py
  22. 332 179
      ambari-server/src/test/python/TestAmbariServer.py
  23. 4 3
      ambari-server/src/test/python/TestOSCheck.py

+ 73 - 17
ambari-common/src/main/python/ambari_commons/firewall.py

@@ -18,9 +18,14 @@ See the License for the specific language governing permissions and
 limitations under the License.
 limitations under the License.
 '''
 '''
 
 
+import subprocess
+import shlex
 from ambari_commons import OSCheck, OSConst
 from ambari_commons import OSCheck, OSConst
+from ambari_commons.logging_utils import print_warning_msg
+from ambari_commons.os_family_impl import OsFamilyImpl
 from ambari_commons.os_utils import run_os_command
 from ambari_commons.os_utils import run_os_command
 
 
+
 class Firewall(object):
 class Firewall(object):
   def __init__(self):
   def __init__(self):
     # OS info
     # OS info
@@ -28,6 +33,16 @@ class Firewall(object):
     self.OS_TYPE = OSCheck.get_os_type()
     self.OS_TYPE = OSCheck.get_os_type()
     self.OS_FAMILY = OSCheck.get_os_family()
     self.OS_FAMILY = OSCheck.get_os_family()
 
 
+  def getFirewallObject(self):
+    pass
+
+@OsFamilyImpl(os_family=OSConst.WINSRV_FAMILY)
+class FirewallWindows(Firewall):
+  def getFirewallObject(self):
+    return WindowsFirewallChecks()
+
+@OsFamilyImpl(os_family=OsFamilyImpl.DEFAULT)
+class FirewallLinux(Firewall):
   def getFirewallObject(self):
   def getFirewallObject(self):
     if self.OS_TYPE == OSConst.OS_UBUNTU:
     if self.OS_TYPE == OSConst.OS_UBUNTU:
       return UbuntuFirewallChecks()
       return UbuntuFirewallChecks()
@@ -47,23 +62,31 @@ class FirewallChecks(object):
     self.returncode = None
     self.returncode = None
     self.stdoutdata = None
     self.stdoutdata = None
     self.stderrdata = None
     self.stderrdata = None
+    # stdout message
+    self.MESSAGE_CHECK_FIREWALL = 'Checking iptables...'
 
 
   def get_command(self):
   def get_command(self):
     return "%s %s %s" % (self.SERVICE_CMD, self.FIREWALL_SERVICE_NAME, self.SERVICE_SUBCMD)
     return "%s %s %s" % (self.SERVICE_CMD, self.FIREWALL_SERVICE_NAME, self.SERVICE_SUBCMD)
 
 
-  def check_result(self, retcode, out, err):
+  def check_result(self):
     result = False
     result = False
-    if retcode == 3:
+    if self.returncode == 3:
       result = False
       result = False
-    elif retcode == 0:
-      if "Table: filter" in out:
+    elif self.returncode == 0:
+      if "Table: filter" in self.stdoutdata:
         result = True
         result = True
     return result
     return result
 
 
+  def run_command(self):
+    retcode, out, err = run_os_command(self.get_command())
+    self.returncode = retcode
+    self.stdoutdata = out
+    self.stderrdata = err
+
   def check_iptables(self):
   def check_iptables(self):
     try:
     try:
-      self.returncode, self.stdoutdata, self.stderrdata = run_os_command(self.get_command())
-      return self.check_result(self.returncode, self.stdoutdata, self.stderrdata)
+      self.run_command()
+      return self.check_result()
     except OSError:
     except OSError:
       return False
       return False
 
 
@@ -76,13 +99,13 @@ class UbuntuFirewallChecks(FirewallChecks):
   def get_command(self):
   def get_command(self):
     return "%s %s" % (self.FIREWALL_SERVICE_NAME, self.SERVICE_SUBCMD)
     return "%s %s" % (self.FIREWALL_SERVICE_NAME, self.SERVICE_SUBCMD)
 
 
-  def check_result(self, retcode, out, err):
+  def check_result(self):
     # On ubuntu, the status command returns 0 whether running or not
     # On ubuntu, the status command returns 0 whether running or not
     result = False
     result = False
-    if retcode == 0:
-      if "Status: inactive" in out:
+    if self.returncode == 0:
+      if "Status: inactive" in self.stdoutdata:
         result = False
         result = False
-      elif "Status: active" in out:
+      elif "Status: active" in self.stdoutdata:
         result = True
         result = True
     return result
     return result
 
 
@@ -93,10 +116,10 @@ class Fedora18FirewallChecks(FirewallChecks):
   def get_command(self):
   def get_command(self):
     return "systemctl is-active %s" % (self.FIREWALL_SERVICE_NAME)
     return "systemctl is-active %s" % (self.FIREWALL_SERVICE_NAME)
 
 
-  def check_result(self, retcode, out, err):
+  def check_result(self):
     result = False
     result = False
-    if retcode == 0:
-      if "active" in out:
+    if self.returncode == 0:
+      if "active" in self.stdoutdata:
         result = True
         result = True
     return result
     return result
 
 
@@ -108,11 +131,44 @@ class SuseFirewallChecks(FirewallChecks):
   def get_command(self):
   def get_command(self):
     return "%s %s" % (self.FIREWALL_SERVICE_NAME, self.SERVICE_SUBCMD)
     return "%s %s" % (self.FIREWALL_SERVICE_NAME, self.SERVICE_SUBCMD)
 
 
-  def check_result(self, retcode, out, err):
+  def check_result(self):
     result = False
     result = False
-    if retcode == 0:
-      if "SuSEfirewall2 not active" in out:
+    if self.returncode == 0:
+      if "SuSEfirewall2 not active" in self.stdoutdata:
         result = False
         result = False
-      elif "### iptables" in out:
+      elif "### iptables" in self.stdoutdata:
         result = True
         result = True
     return result
     return result
+
+
+class WindowsFirewallChecks(FirewallChecks):
+  def __init__(self):
+    super(WindowsFirewallChecks, self).__init__()
+    self.MESSAGE_CHECK_FIREWALL = 'Checking firewall status...'
+
+  def run_command(self):
+    from ambari_commons.os_windows import run_powershell_script, CHECK_FIREWALL_SCRIPT
+
+    retcode, out, err = run_powershell_script(CHECK_FIREWALL_SCRIPT)
+    self.returncode = retcode
+    self.stdoutdata = out
+    self.stderrdata = err
+
+  def check_result(self):
+    if self.returncode != 0:
+      print_warning_msg("Unable to check firewall status:{0}".format(self.stderrdata))
+      return False
+    profiles_status = [i for i in self.stdoutdata.split("\n") if not i == ""]
+    if "1" in profiles_status:
+      enabled_profiles = []
+      if profiles_status[0] == "1":
+        enabled_profiles.append("DomainProfile")
+      if profiles_status[1] == "1":
+        enabled_profiles.append("StandardProfile")
+      if profiles_status[2] == "1":
+        enabled_profiles.append("PublicProfile")
+      print_warning_msg(
+        "Following firewall profiles are enabled:{0}. Make sure that the firewall is properly configured.".format(
+          ",".join(enabled_profiles)))
+      return False
+    return True

+ 3 - 3
ambari-common/src/main/python/ambari_commons/inet_utils.py

@@ -56,7 +56,7 @@ def find_range_components(meta):
     if len(range_comp1) > 1:
     if len(range_comp1) > 1:
       range_comp2 = range_comp1[0].split(' ') #split away the "bytes" prefix
       range_comp2 = range_comp1[0].split(' ') #split away the "bytes" prefix
       if len(range_comp2) == 0:
       if len(range_comp2) == 0:
-        raise FatalException(12, 'Malformed Content-Range response header: "{}".' % hdr_range)
+        raise FatalException(12, 'Malformed Content-Range response header: "{0}".' % hdr_range)
       range_comp3 = range_comp2[1].split('-')
       range_comp3 = range_comp2[1].split('-')
       seek_pos = int(range_comp3[0])
       seek_pos = int(range_comp3[0])
       if range_comp1[1] != '*': #'*' == unknown length
       if range_comp1[1] != '*': #'*' == unknown length
@@ -77,7 +77,7 @@ def force_download_file(link, destination, chunk_size = 16 * 1024, progress_func
 
 
   if os.path.exists(destination) and not os.path.isfile(destination):
   if os.path.exists(destination) and not os.path.isfile(destination):
     #Directory specified as target? Must be a mistake. Bail out, don't assume anything.
     #Directory specified as target? Must be a mistake. Bail out, don't assume anything.
-    err = 'Download target {} is a directory.' % destination
+    err = 'Download target {0} is a directory.' % destination
     raise FatalException(1, err)
     raise FatalException(1, err)
 
 
   (dest_path, file_name) = os.path.split(destination)
   (dest_path, file_name) = os.path.split(destination)
@@ -138,7 +138,7 @@ def force_download_file(link, destination, chunk_size = 16 * 1024, progress_func
 
 
   downloaded_size = os.stat(temp_dest).st_size
   downloaded_size = os.stat(temp_dest).st_size
   if downloaded_size != file_size:
   if downloaded_size != file_size:
-    err = 'Size of downloaded file {} is {} bytes, it is probably damaged or incomplete' % (destination, downloaded_size)
+    err = 'Size of downloaded file {0} is {1} bytes, it is probably damaged or incomplete' % (destination, downloaded_size)
     raise FatalException(1, err)
     raise FatalException(1, err)
 
 
   # when download is complete -> mv temp_dest destination
   # when download is complete -> mv temp_dest destination

+ 15 - 1
ambari-common/src/main/python/ambari_commons/logging_utils.py

@@ -20,7 +20,7 @@ limitations under the License.
 
 
 _VERBOSE = False
 _VERBOSE = False
 _SILENT = False
 _SILENT = False
-_DEBUG_MODE = False
+_DEBUG_MODE = 0
 
 
 # terminal styles
 # terminal styles
 BOLD_ON = '\033[1m'
 BOLD_ON = '\033[1m'
@@ -50,6 +50,20 @@ def set_debug_mode(newVal):
   global _DEBUG_MODE
   global _DEBUG_MODE
   _DEBUG_MODE = newVal
   _DEBUG_MODE = newVal
 
 
+def set_debug_mode_from_options(options):
+  debug_mode = 0
+  try:
+    if options.debug:
+      debug_mode = 1
+  except AttributeError:
+    pass
+  try:
+    if options.suspend_start:
+      debug_mode = debug_mode | 2
+  except AttributeError:
+    pass
+  set_debug_mode(debug_mode)
+
 #
 #
 # Prints an "info" messsage.
 # Prints an "info" messsage.
 #
 #

+ 15 - 2
ambari-server/conf/unix/ambari.properties

@@ -22,10 +22,23 @@ security.server.keys_dir = /var/lib/ambari-server/keys
 resources.dir = /var/lib/ambari-server/resources
 resources.dir = /var/lib/ambari-server/resources
 shared.resources.dir = /usr/lib/ambari-server/lib/ambari_commons/resources
 shared.resources.dir = /usr/lib/ambari-server/lib/ambari_commons/resources
 custom.action.definitions = /var/lib/ambari-server/resources/custom_action_definitions
 custom.action.definitions = /var/lib/ambari-server/resources/custom_action_definitions
+
+java.releases=jdk1.7,jdk1.6
+jdk1.6.desc=Oracle JDK 1.6
 jdk1.6.url=http://public-repo-1.hortonworks.com/ARTIFACTS/jdk-6u31-linux-x64.bin
 jdk1.6.url=http://public-repo-1.hortonworks.com/ARTIFACTS/jdk-6u31-linux-x64.bin
-jce_policy1.6.url=http://public-repo-1.hortonworks.com/ARTIFACTS/jce_policy-6.zip
+jdk1.6.dest-file=jdk-6u31-linux-x64.bin
+jdk1.6.jcpol-url=http://public-repo-1.hortonworks.com/ARTIFACTS/jce_policy-6.zip
+jdk1.6.jcpol-file=jce_policy-6.zip
+jdk1.6.home=/usr/jdk64/
+jdk1.6.re=Creating (jdk.*)/jre
+jdk1.7.desc=Oracle JDK 1.7
 jdk1.7.url=http://public-repo-1.hortonworks.com/ARTIFACTS/jdk-7u67-linux-x64.tar.gz
 jdk1.7.url=http://public-repo-1.hortonworks.com/ARTIFACTS/jdk-7u67-linux-x64.tar.gz
-jce_policy1.7.url=http://public-repo-1.hortonworks.com/ARTIFACTS/UnlimitedJCEPolicyJDK7.zip
+jdk1.7.dest-file=jdk-7u67-linux-x64.tar.gz
+jdk1.7.jcpol-url=http://public-repo-1.hortonworks.com/ARTIFACTS/UnlimitedJCEPolicyJDK7.zip
+jdk1.7.jcpol-file=UnlimitedJCEPolicyJDK7.zip
+jdk1.7.home=/usr/jdk64/
+jdk1.7.re=(jdk.*)/jre
+
 metadata.path=/var/lib/ambari-server/resources/stacks
 metadata.path=/var/lib/ambari-server/resources/stacks
 common.services.path=/var/lib/ambari-server/resources/common-services
 common.services.path=/var/lib/ambari-server/resources/common-services
 server.version.file=/var/lib/ambari-server/resources/version
 server.version.file=/var/lib/ambari-server/resources/version

+ 1 - 1
ambari-server/conf/windows/ambari.properties

@@ -24,7 +24,7 @@ custom.action.definitions=resources\\custom_action_definitions
 #Comma-separated list of JDK versions
 #Comma-separated list of JDK versions
 #java.releases=jdk1.8.20,jdk1.6.31
 #java.releases=jdk1.8.20,jdk1.6.31
 java.releases=jdk1.7.67
 java.releases=jdk1.7.67
-jdk1.7.67.desc=Oracle JDK 1.7.67
+jdk1.7.67.desc=Oracle JDK 1.7
 jdk1.7.67.url=http://public-repo-1.hortonworks.com/ARTIFACTS/jdk-7u67-windows-x64.exe
 jdk1.7.67.url=http://public-repo-1.hortonworks.com/ARTIFACTS/jdk-7u67-windows-x64.exe
 jdk1.7.67.dest-file=jdk-7u67-windows-x64.exe
 jdk1.7.67.dest-file=jdk-7u67-windows-x64.exe
 jdk1.7.67.jcpol-url=http://public-repo-1.hortonworks.com/ARTIFACTS/UnlimitedJCEPolicyJDK7.zip
 jdk1.7.67.jcpol-url=http://public-repo-1.hortonworks.com/ARTIFACTS/UnlimitedJCEPolicyJDK7.zip

+ 18 - 33
ambari-server/src/main/python/ambari-server-windows.py

@@ -26,18 +26,19 @@ import subprocess
 from ambari_commons.ambari_service import AmbariService
 from ambari_commons.ambari_service import AmbariService
 from ambari_commons.exceptions import FatalException, NonFatalException
 from ambari_commons.exceptions import FatalException, NonFatalException
 from ambari_commons.logging_utils import print_info_msg, print_warning_msg, print_error_msg, \
 from ambari_commons.logging_utils import print_info_msg, print_warning_msg, print_error_msg, \
-  get_verbose, set_verbose, get_silent, set_silent, get_debug_mode, set_debug_mode
+  get_verbose, set_verbose, get_silent, set_silent, get_debug_mode, set_debug_mode_from_options
 from ambari_commons.os_utils import remove_file, set_open_files_limit
 from ambari_commons.os_utils import remove_file, set_open_files_limit
 from ambari_commons.os_windows import SvcStatusCallback
 from ambari_commons.os_windows import SvcStatusCallback
 
 
 from ambari_server import utils
 from ambari_server import utils
-from ambari_server.dbConfiguration import DBMSConfig
+from ambari_server.dbConfiguration import DBMSConfigFactory
 from ambari_server.resourceFilesKeeper import ResourceFilesKeeper, KeeperException
 from ambari_server.resourceFilesKeeper import ResourceFilesKeeper, KeeperException
 from ambari_server.serverConfiguration import find_jdk, get_ambari_classpath, get_ambari_properties, get_conf_dir, \
 from ambari_server.serverConfiguration import find_jdk, get_ambari_classpath, get_ambari_properties, get_conf_dir, \
   get_value_from_properties, configDefaults, DEBUG_MODE_KEY, RESOURCES_DIR_DEFAULT, RESOURCES_DIR_PROPERTY, \
   get_value_from_properties, configDefaults, DEBUG_MODE_KEY, RESOURCES_DIR_DEFAULT, RESOURCES_DIR_PROPERTY, \
-  SERVER_OUT_FILE_KEY, STACK_LOCATION_DEFAULT, STACK_LOCATION_KEY, SUSPEND_START_MODE_KEY, VERBOSE_OUTPUT_KEY
-from ambari_server.serverSetup import setup, reset, is_server_running, upgrade
-from ambari_server.serverSetup_windows import SERVICE_PASSWORD_KEY, SERVICE_USERNAME_KEY
+  SERVER_OUT_FILE_KEY, SERVICE_PASSWORD_KEY, SERVICE_USERNAME_KEY, \
+  SUSPEND_START_MODE_KEY, VERBOSE_OUTPUT_KEY, PID_NAME, get_java_exe_path
+from ambari_server.serverSetup import setup, reset, is_server_running
+from ambari_server.serverUpgrade import upgrade
 from ambari_server.setupActions import SETUP_ACTION, START_ACTION, PSTART_ACTION, STOP_ACTION, RESET_ACTION, \
 from ambari_server.setupActions import SETUP_ACTION, START_ACTION, PSTART_ACTION, STOP_ACTION, RESET_ACTION, \
   STATUS_ACTION, UPGRADE_ACTION, UPGRADE_STACK_ACTION, LDAP_SETUP_ACTION, SETUP_SECURITY_ACTION, ACTION_REQUIRE_RESTART
   STATUS_ACTION, UPGRADE_ACTION, UPGRADE_STACK_ACTION, LDAP_SETUP_ACTION, SETUP_SECURITY_ACTION, ACTION_REQUIRE_RESTART
 from ambari_server.setupSecurity import setup_ambari_krb5_jaas, setup_https, setup_ldap, setup_master_key
 from ambari_server.setupSecurity import setup_ambari_krb5_jaas, setup_https, setup_ldap, setup_master_key
@@ -73,16 +74,12 @@ SERVER_START_CMD_DEBUG = \
                        " -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,"\
                        " -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,"\
                        "server=y,suspend={1} -cp {0}" +\
                        "server=y,suspend={1} -cp {0}" +\
                        " org.apache.ambari.server.controller.AmbariServer"
                        " org.apache.ambari.server.controller.AmbariServer"
-SERVER_SEARCH_PATTERN = "org.apache.ambari.server.controller.AmbariServer"
 
 
 SERVER_INIT_TIMEOUT = 5
 SERVER_INIT_TIMEOUT = 5
 SERVER_START_TIMEOUT = 10
 SERVER_START_TIMEOUT = 10
 
 
-PID_NAME = "ambari-server.pid"
 EXITCODE_NAME = "ambari-server.exitcode"
 EXITCODE_NAME = "ambari-server.exitcode"
 
 
-SERVER_VERSION_FILE_PATH = "server.version.file"
-
 # linux open-file limit
 # linux open-file limit
 ULIMIT_OPEN_FILES_KEY = 'ulimit.open.files'
 ULIMIT_OPEN_FILES_KEY = 'ulimit.open.files'
 ULIMIT_OPEN_FILES_DEFAULT = 10000
 ULIMIT_OPEN_FILES_DEFAULT = 10000
@@ -182,16 +179,9 @@ def svcstart():
   pass
   pass
 
 
 def server_process_main(options, scmStatus=None):
 def server_process_main(options, scmStatus=None):
-  # debug mode
-  try:
-    set_debug_mode(options.debug)
-  except AttributeError:
-    pass
-
-  # stop Java process at startup?
+  # debug mode, including stop Java process at startup
   try:
   try:
-    global SUSPEND_START_MODE
-    SUSPEND_START_MODE = options.suspend_start
+    set_debug_mode_from_options(options)
   except AttributeError:
   except AttributeError:
     pass
     pass
 
 
@@ -236,10 +226,15 @@ def server_process_main(options, scmStatus=None):
   if conf_dir.find(' ') != -1:
   if conf_dir.find(' ') != -1:
     conf_dir = '"' + conf_dir + '"'
     conf_dir = '"' + conf_dir + '"'
 
 
-  java_exe = jdk_path + os.sep + configDefaults.JAVA_EXE_SUBPATH
+  java_exe = get_java_exe_path()
   pidfile = os.path.join(configDefaults.PID_DIR, PID_NAME)
   pidfile = os.path.join(configDefaults.PID_DIR, PID_NAME)
-  command_base = SERVER_START_CMD_DEBUG if (get_debug_mode() or SERVER_START_DEBUG) else SERVER_START_CMD
-  suspend_mode = 'y' if SUSPEND_START_MODE else 'n'
+
+  debug_mode = get_debug_mode()
+  debug_start = (debug_mode & 1) or SERVER_START_DEBUG
+  suspend_start = (debug_mode & 2) or SUSPEND_START_MODE
+
+  command_base = SERVER_START_CMD_DEBUG if debug_start else SERVER_START_CMD
+  suspend_mode = 'y' if suspend_start else 'n'
   command = command_base.format(conf_dir, suspend_mode)
   command = command_base.format(conf_dir, suspend_mode)
   if not os.path.exists(configDefaults.PID_DIR):
   if not os.path.exists(configDefaults.PID_DIR):
     os.makedirs(configDefaults.PID_DIR, 0755)
     os.makedirs(configDefaults.PID_DIR, 0755)
@@ -285,7 +280,8 @@ def server_process_main(options, scmStatus=None):
 #Wait until the status is 'started' or a configured timeout elapses
 #Wait until the status is 'started' or a configured timeout elapses
 #If the timeout has been reached, bail out with exception
 #If the timeout has been reached, bail out with exception
 def ensure_dbms_is_running(options, properties, scmStatus):
 def ensure_dbms_is_running(options, properties, scmStatus):
-  dbms = DBMSConfig.create(options, properties, "Ambari")
+  factory = DBMSConfigFactory()
+  dbms = factory.create(options, properties, "Ambari")
   if not dbms._is_jdbc_driver_installed(properties):
   if not dbms._is_jdbc_driver_installed(properties):
     raise FatalException(-1, "JDBC driver is not installed. Run ambari-server setup and try again.")
     raise FatalException(-1, "JDBC driver is not installed. Run ambari-server setup and try again.")
 
 
@@ -317,9 +313,6 @@ def svcstop():
 
 
 ### Stack upgrade ###
 ### Stack upgrade ###
 
 
-#def upgrade_stack(args, stack_id, repo_url=None, repo_url_os=None):
-
-
 def get_resources_location(properties):
 def get_resources_location(properties):
   res_location = properties[RESOURCES_DIR_PROPERTY]
   res_location = properties[RESOURCES_DIR_PROPERTY]
   if res_location is None:
   if res_location is None:
@@ -327,13 +320,6 @@ def get_resources_location(properties):
   return res_location
   return res_location
 #  pass
 #  pass
 
 
-def get_stack_location(properties):
-  stack_location = properties[STACK_LOCATION_KEY]
-  if stack_location is None:
-    stack_location = STACK_LOCATION_DEFAULT
-  return stack_location
-#  pass
-
 
 
 #
 #
 # The Ambari Server status.
 # The Ambari Server status.
@@ -465,7 +451,6 @@ def main():
 
 
   if are_cmd_line_db_args_blank(options):
   if are_cmd_line_db_args_blank(options):
     options.must_set_database_options = True
     options.must_set_database_options = True
-    #TODO Silent is invalid here, right?
 
 
   elif not are_cmd_line_db_args_valid(options):
   elif not are_cmd_line_db_args_valid(options):
     parser.error('All database options should be set. Please see help for the options.')
     parser.error('All database options should be set. Please see help for the options.')

文件差异内容过多而无法显示
+ 108 - 2162
ambari-server/src/main/python/ambari-server.py


+ 352 - 80
ambari-server/src/main/python/ambari_server/dbConfiguration.py

@@ -17,12 +17,17 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 See the License for the specific language governing permissions and
 limitations under the License.
 limitations under the License.
 '''
 '''
+import os
 
 
-from ambari_commons import OSCheck
+from ambari_commons import OSConst
 from ambari_commons.exceptions import FatalException
 from ambari_commons.exceptions import FatalException
-from ambari_commons.logging_utils import print_error_msg
-from ambari_server.setupSecurity import SECURITY_IS_ENCRYPTION_ENABLED
-from serverConfiguration import get_ambari_properties
+from ambari_commons.logging_utils import get_silent, print_error_msg, print_info_msg, print_warning_msg, set_silent
+from ambari_commons.os_family_impl import OsFamilyImpl
+from ambari_server.serverConfiguration import decrypt_password_for_alias, get_value_from_properties, get_is_secure, \
+  is_alias_string, \
+  JDBC_PASSWORD_PROPERTY, JDBC_RCA_PASSWORD_ALIAS, PRESS_ENTER_MSG, get_ambari_properties, update_properties, \
+  RESOURCES_DIR_PROPERTY
+from ambari_server.userInput import get_validated_string_input
 
 
 
 
 #Database settings
 #Database settings
@@ -31,77 +36,76 @@ DB_STATUS_RUNNING_DEFAULT = "running"
 SETUP_DB_CONNECT_TIMEOUT = 5
 SETUP_DB_CONNECT_TIMEOUT = 5
 SETUP_DB_CONNECT_ATTEMPTS = 3
 SETUP_DB_CONNECT_ATTEMPTS = 3
 
 
-DATABASE_INDEX = 0
 USERNAME_PATTERN = "^[a-zA-Z_][a-zA-Z0-9_\-]*$"
 USERNAME_PATTERN = "^[a-zA-Z_][a-zA-Z0-9_\-]*$"
 PASSWORD_PATTERN = "^[a-zA-Z0-9_-]*$"
 PASSWORD_PATTERN = "^[a-zA-Z0-9_-]*$"
 DATABASE_NAMES = ["postgres", "oracle", "mysql"]
 DATABASE_NAMES = ["postgres", "oracle", "mysql"]
-DATABASE_STORAGE_NAMES = ["Database", "Service", "Database"]
-DATABASE_PORTS = ["5432", "1521", "3306"]
-DATABASE_DRIVER_NAMES = ["org.postgresql.Driver", "oracle.jdbc.driver.OracleDriver", "com.mysql.jdbc.Driver"]
-DATABASE_CONNECTION_STRINGS = [
-                  "jdbc:postgresql://{0}:{1}/{2}",
-                  "jdbc:oracle:thin:@{0}:{1}/{2}",
-                  "jdbc:mysql://{0}:{1}/{2}"]
-DATABASE_CONNECTION_STRINGS_ALT = [
-                  "jdbc:postgresql://{0}:{1}/{2}",
-                  "jdbc:oracle:thin:@{0}:{1}:{2}",
-                  "jdbc:mysql://{0}:{1}/{2}"]
-ORACLE_SID_PATTERN = "jdbc:oracle:thin:@.+:.+/.+"
-ORACLE_SNAME_PATTERN = "jdbc:oracle:thin:@.+:.+:.+"
-
-DATABASE_CLI_TOOLS = [["psql"], ["sqlplus", "sqlplus64"], ["mysql"]]
-DATABASE_CLI_TOOLS_DESC = ["psql", "sqlplus", "mysql"]
-DATABASE_CLI_TOOLS_USAGE = ['su -postgres --command=psql -f {0} -v username=\'"{1}"\' -v password="\'{2}\'"',
-                            'sqlplus {1}/{2} < {0} ',
-                            'mysql --user={1} --password={2} {3}<{0}']
-
-MYSQL_INIT_SCRIPT = '/var/lib/ambari-server/resources/Ambari-DDL-MySQL-CREATE.sql'
-DATABASE_INIT_SCRIPTS = ['/var/lib/ambari-server/resources/Ambari-DDL-Postgres-CREATE.sql',
-                         '/var/lib/ambari-server/resources/Ambari-DDL-Oracle-CREATE.sql',
-                         MYSQL_INIT_SCRIPT]
-DATABASE_DROP_SCRIPTS = ['/var/lib/ambari-server/resources/Ambari-DDL-Postgres-DROP.sql',
-                         '/var/lib/ambari-server/resources/Ambari-DDL-Oracle-DROP.sql',
-                         '/var/lib/ambari-server/resources/Ambari-DDL-MySQL-DROP.sql']
+DATABASE_FULL_NAMES = {"oracle": "Oracle", "mysql": "MySQL", "postgres": "PostgreSQL"}
+
+AMBARI_DATABASE_NAME = "ambari"
+AMBARI_DATABASE_TITLE = "ambari"
+
+STORAGE_TYPE_LOCAL = 'local'
+STORAGE_TYPE_REMOTE = 'remote'
+
+DEFAULT_USERNAME = "ambari"
+DEFAULT_PASSWORD = "bigdata"
+
+#
+# Database configuration helper classes
+#
+class DBMSDesc:
+  def __init__(self, i_dbms_key, i_storage_key, i_dbms_name, i_storage_name, i_fn_create_config):
+    self.dbms_key = i_dbms_key
+    self.storage_key = i_storage_key
+    self.dbms_name = i_dbms_name
+    self.storage_name = i_storage_name
+    self.fn_create_config = i_fn_create_config
+
+  def create_config(self, options, properties, dbId):
+    return self.fn_create_config(options, properties, self.storage_key, dbId)
+
+class DbPropKeys:
+  def __init__(self, i_dbms_key, i_driver_key, i_server_key, i_port_key, i_db_name_key, i_db_url_key):
+    self.dbms_key = i_dbms_key
+    self.driver_key = i_driver_key
+    self.server_key = i_server_key
+    self.port_key = i_port_key
+    self.db_name_key = i_db_name_key
+    self.db_url_key = i_db_url_key
+
+class DbAuthenticationKeys:
+  def __init__(self, i_user_name_key, i_password_key, i_password_alias, i_password_filename):
+    self.user_name_key = i_user_name_key
+    self.password_key = i_password_key
+    self.password_alias = i_password_alias
+    self.password_filename = i_password_filename
+
 #
 #
 # Database configuration base class
 # Database configuration base class
 #
 #
 class DBMSConfig(object):
 class DBMSConfig(object):
-  def __init__(self, options, properties):
+  def __init__(self, options, properties, storage_type):
     """
     """
     #Just load the defaults. The derived classes will be able to modify them later
     #Just load the defaults. The derived classes will be able to modify them later
     """
     """
-    self.persistence_type = 'remote'
+    self.persistence_type = storage_type
     self.dbms = ""
     self.dbms = ""
-    self.driver_name = ""
+    self.driver_class_name = ""
+    self.driver_file_name = ""
+    self.driver_symlink_name = ""
     self.database_host = ""
     self.database_host = ""
     self.database_port = ""
     self.database_port = ""
     self.database_name = ""
     self.database_name = ""
     self.database_username = ""
     self.database_username = ""
-    self.password_file = None
 
 
-    self.silent = options.silent
+    self.db_title = AMBARI_DATABASE_TITLE
 
 
-    isSecureProp = properties.get_property(SECURITY_IS_ENCRYPTION_ENABLED)
-    self.isSecure = True if isSecureProp and isSecureProp.lower() == 'true' else False
-    pass
+    self.must_set_database_options = DBMSConfig._init_member_with_default(options, "must_set_database_options", False)
 
 
+    self.JDBC_DRIVER_INSTALL_MSG = 'Before starting Ambari Server, you must install the JDBC driver.'
 
 
-  @staticmethod
-  # properties = property bag that will ultimately define the type of database. Since
-  #   right now in Windows we only support SQL Server, this argument is not yet used.
-  # dbId = additional information, that helps distinguish between various database connections
-  #   (Ambari vs. Metrics is a prime example)
-  def create(options, properties, dbId = "Ambari"):
-    #if OSCheck.is_windows_family():
-    if dbId == "Ambari":
-      return SQLServerAmbariDBConfig(options, properties)
-    else:
-      raise FatalException(-1, "Invalid database requested: " + str(dbId))
-    #else:
-    #  go the classic Linux way
-    #return PGConfig(properties, dbId)
-    #return MySQLConfig(properties, dbId)
-    #return OracleConfig(properties, dbId)
+    self.isSecure = get_is_secure(properties)
+    pass
 
 
 
 
   #
   #
@@ -111,7 +115,7 @@ class DBMSConfig(object):
   #
   #
   # Main method. Configures the database according to the options and the existing properties.
   # Main method. Configures the database according to the options and the existing properties.
   #
   #
-  def configure_database(self, args, properties):
+  def configure_database(self, properties):
     result = self._prompt_db_properties()
     result = self._prompt_db_properties()
     if result:
     if result:
       #DB setup should be done last after doing any setup.
       #DB setup should be done last after doing any setup.
@@ -122,7 +126,7 @@ class DBMSConfig(object):
     return result
     return result
 
 
   def setup_database(self):
   def setup_database(self):
-    print 'Configuring {} database...'.format(self.db_title)
+    print 'Configuring {0} database...'.format(self.db_title)
 
 
     #DB setup should be done last after doing any setup.
     #DB setup should be done last after doing any setup.
     if self._is_local_database():
     if self._is_local_database():
@@ -132,43 +136,71 @@ class DBMSConfig(object):
     pass
     pass
 
 
   def reset_database(self):
   def reset_database(self):
-    print 'Resetting {} database...'.format(self.db_title)
-
     if self._is_local_database():
     if self._is_local_database():
       self._reset_local_database()
       self._reset_local_database()
     else:
     else:
       self._reset_remote_database()
       self._reset_remote_database()
     pass
     pass
 
 
-  def ensure_jdbc_driver_installed(self, args, properties):
-    result = self._is_jdbc_driver_installed(properties)
+  def ensure_jdbc_driver_installed(self, properties):
+    (result, msg) = self._prompt_jdbc_driver_install(properties)
     if result == -1:
     if result == -1:
-      (result, msg) = self._prompt_jdbc_driver_install(properties)
-      if result == -1:
-        print_error_msg(msg)
-        raise FatalException(-1, msg)
+      print_error_msg(msg)
+      raise FatalException(-1, msg)
 
 
     if result != 1:
     if result != 1:
-      if self._install_jdbc_driver(args, properties):
+      if self._install_jdbc_driver(properties, result):
         return True
         return True
     return False
     return False
 
 
+  def change_db_files_owner(self):
+    if self._is_local_database():
+      retcode = self._change_db_files_owner()
+      if not retcode == 0:
+        raise FatalException(20, 'Unable to change owner of database objects')
 
 
   #
   #
   # Private implementation
   # Private implementation
   #
   #
 
 
+  @staticmethod
+  def _read_password_from_properties(properties):
+    database_password = DEFAULT_PASSWORD
+    password_file = get_value_from_properties(properties, JDBC_PASSWORD_PROPERTY, "")
+    if password_file:
+      if is_alias_string(password_file):
+        database_password = decrypt_password_for_alias(properties, JDBC_RCA_PASSWORD_ALIAS)
+      else:
+        if os.path.isabs(password_file) and os.path.exists(password_file):
+          with open(password_file, 'r') as file:
+            database_password = file.read()
+    return database_password
+
+  @staticmethod
+  def _init_member_with_default(options, attr_name, default_val):
+    options_val = getattr(options, attr_name, None)
+    val = options_val if options_val is not None and options_val is not "" else default_val
+    return val
+
+  @staticmethod
+  def _init_member_with_properties(options, attr_name, properties, property_key):
+    options_val = getattr(options, attr_name, None)
+    if options_val is None or options_val is "":
+      options_val = get_value_from_properties(properties, property_key, None)
+    return options_val
+
+  @staticmethod
+  def _init_member_with_prop_default(options, attr_name, properties, property_key, default_val):
+    val = DBMSConfig._init_member_with_properties(options, attr_name, properties, property_key)
+    if val is None or val is "":
+      val = default_val
+    return val
+
   #
   #
   # Checks if options determine local DB configuration
   # Checks if options determine local DB configuration
   #
   #
   def _is_local_database(self):
   def _is_local_database(self):
-    return self.persistence_type == 'local'
-
-  def _is_jdbc_driver_installed(self, properties):
-    return 1
-
-  def configure_database_password(showDefault=True):
-    pass
+    return self.persistence_type == STORAGE_TYPE_LOCAL
 
 
   def _prompt_db_properties(self):
   def _prompt_db_properties(self):
     #if WINDOWS
     #if WINDOWS
@@ -197,15 +229,255 @@ class DBMSConfig(object):
     pass
     pass
 
 
   def _prompt_jdbc_driver_install(self, properties):
   def _prompt_jdbc_driver_install(self, properties):
-    return (False, "")
+    result = self._is_jdbc_driver_installed(properties)
+    if result == -1:
+      if get_silent():
+        print_error_msg(self.JDBC_DRIVER_INSTALL_MSG)
+      else:
+        print_warning_msg(self.JDBC_DRIVER_INSTALL_MSG)
+        raw_input(PRESS_ENTER_MSG)
+        result = self._is_jdbc_driver_installed(properties)
+    return (result, self.JDBC_DRIVER_INSTALL_MSG)
+
+  def _is_jdbc_driver_installed(self, properties):
+    return 1
 
 
-  def _install_jdbc_driver(self, options, properties):
+  def _install_jdbc_driver(self, properties, files_list):
     return False
     return False
 
 
   def ensure_dbms_is_running(self, options, properties, scmStatus=None):
   def ensure_dbms_is_running(self, options, properties, scmStatus=None):
     pass
     pass
 
 
-if OSCheck.is_windows_family():
-  from ambari_server.dbConfiguration_windows import SQLServerAmbariDBConfig
-#else:
-#  from ambari_server.dbConfiguration_linux import PostgreSQLConfig #and potentially MySQLConfig, OracleConfig
+  def _change_db_files_owner(self, args):
+    return 0
+
+
+#
+# Database configuration factory base class
+#
+class DBMSConfigFactory(object):
+  def select_dbms(self, options):
+    '''
+    # Base declaration of the DBMS selection method.
+    :return: DBMS index in the descriptor table
+    '''
+    pass
+
+  def create(self, options, properties, dbId = "Ambari"):
+    """
+    # Base declaration of the factory method. The outcome of the derived implementations
+    #  is expected to be a subclass of DBMSConfig.
+    # properties = property bag that will ultimately define the type of database. Since
+    #   right now in Windows we only support SQL Server, this argument is not yet used.
+    # dbId = additional information, that helps distinguish between various database connections, if applicable
+    """
+    pass
+
+#
+# Database configuration factory for Windows
+#
+@OsFamilyImpl(os_family=OSConst.WINSRV_FAMILY)
+class DBMSConfigFactoryWindows(DBMSConfigFactory):
+  def __init__(self):
+    from ambari_server.dbConfiguration_windows import DATABASE_DBMS_SQLSERVER
+
+    self.DBMS_KEYS_LIST = [
+      DATABASE_DBMS_SQLSERVER
+    ]
+
+  def select_dbms(self, options):
+    # For now, we only support SQL Server in Windows, in remote mode.
+    return 0
+
+  def create(self, options, properties, dbId = "Ambari"):
+    """
+    # Windows implementation of the factory method. The outcome of the derived implementations
+    #  is expected to be a subclass of DBMSConfig.
+    # properties = property bag that will ultimately define the type of database. Since
+    #   right now in Windows we only support SQL Server, this argument is not yet used.
+    # dbId = additional information, that helps distinguish between various database connections, if applicable
+    """
+    from ambari_server.dbConfiguration_windows import createSQLServerConfig
+    return createSQLServerConfig(options, properties, STORAGE_TYPE_REMOTE, dbId)
+
+  def get_supported_jdbc_drivers(self):
+    return self.DBMS_KEYS_LIST
+
+#
+# Database configuration factory for Linux
+#
+@OsFamilyImpl(os_family=OsFamilyImpl.DEFAULT)
+class DBMSConfigFactoryLinux(DBMSConfigFactory):
+  def __init__(self):
+    from ambari_server.dbConfiguration_linux import createPGConfig, createOracleConfig, createMySQLConfig
+
+    self.DBMS_KEYS_LIST = [
+      'embedded',
+      'oracle',
+      'mysql',
+      'postgres'
+    ]
+
+    self.DRIVER_KEYS_LIST = [
+      'oracle',
+      'mysql',
+      'postgres',
+      'mssql'
+    ]
+
+    self.DBMS_LIST = [
+      DBMSDesc(self.DBMS_KEYS_LIST[3], STORAGE_TYPE_LOCAL, 'PostgreSQL', 'Embedded', createPGConfig),
+      DBMSDesc(self.DBMS_KEYS_LIST[1], STORAGE_TYPE_REMOTE, 'Oracle', '', createOracleConfig),
+      DBMSDesc(self.DBMS_KEYS_LIST[2], STORAGE_TYPE_REMOTE, 'MySQL', '', createMySQLConfig),
+      DBMSDesc(self.DBMS_KEYS_LIST[3], STORAGE_TYPE_REMOTE, 'PostgreSQL', '', createPGConfig)
+    ]
+
+    self.DBMS_DICT = \
+    {
+      '-' : 0,
+      '-' + STORAGE_TYPE_LOCAL : 0,
+      self.DBMS_KEYS_LIST[0] + '-' : 0,
+      self.DBMS_KEYS_LIST[2] + '-'  : 2,
+      self.DBMS_KEYS_LIST[2] + '-' + STORAGE_TYPE_REMOTE : 2,
+      self.DBMS_KEYS_LIST[1] + '-' : 1,
+      self.DBMS_KEYS_LIST[1] + '-' + STORAGE_TYPE_REMOTE : 1,
+      self.DBMS_KEYS_LIST[3] + '-' : 3,
+      self.DBMS_KEYS_LIST[3] + '-' + STORAGE_TYPE_LOCAL : 0,
+      self.DBMS_KEYS_LIST[3] + '-' + STORAGE_TYPE_REMOTE : 3,
+    }
+
+    self.DBMS_PROMPT_PATTERN = "[{0}] - {1}{2}\n"
+    self.DBMS_CHOICE_PROMPT_PATTERN = "==============================================================================\n" \
+                                      "Enter choice ({0}): "
+    self.JDK_VALID_CHOICES_PATTERN = "^[{0}]$"
+
+  def select_dbms(self, options):
+    try:
+      dbms_index = options.database_index
+    except AttributeError:
+      dbms_index = self._get_default_dbms_index(options)
+
+    if options.must_set_database_options:
+      n_dbms = 1
+      dbms_choice_prompt = "==============================================================================\n" \
+                           "Choose one of the following options:\n"
+      dbms_choices = ''
+      for desc in self.DBMS_LIST:
+        if len(desc.storage_name) > 0:
+          dbms_storage = " ({0})".format(desc.storage_name)
+        else:
+          dbms_storage = ""
+        dbms_choice_prompt += self.DBMS_PROMPT_PATTERN.format(n_dbms, desc.dbms_name, dbms_storage)
+        dbms_choices += str(n_dbms)
+        n_dbms += 1
+
+      database_num = str(dbms_index + 1)
+      dbms_choice_prompt += self.DBMS_CHOICE_PROMPT_PATTERN.format(database_num)
+      dbms_valid_choices = self.JDK_VALID_CHOICES_PATTERN.format(dbms_choices)
+
+      database_num = get_validated_string_input(
+        dbms_choice_prompt,
+        database_num,
+        dbms_valid_choices,
+        "Invalid number.",
+        False
+      )
+
+      dbms_index = int(database_num) - 1
+      if dbms_index >= n_dbms:
+        print_info_msg('Unknown db option, default to {0} {1}.'.format(
+          self.DBMS_LIST[0].storage_name, self.DBMS_LIST[0].dbms_name))
+        dbms_index = 0
+
+    return dbms_index
+
+  def create(self, options, properties, dbId = "Ambari"):
+    """
+    # Linux implementation of the factory method. The outcome of the derived implementations
+    #  is expected to be a subclass of DBMSConfig.
+    # properties = property bag that will ultimately define the type of database. Supported types are
+    #   MySQL, Oracle and PostgreSQL.
+    # dbId = additional information, that helps distinguish between various database connections, if applicable
+    """
+
+    try:
+      index = options.database_index
+    except AttributeError:
+      index = options.database_index = self._get_default_dbms_index(options)
+
+    desc = self.DBMS_LIST[index]
+    options.persistence_type = desc.storage_key
+    dbmsConfig = desc.create_config(options, properties, dbId)
+    return dbmsConfig
+
+  def get_supported_dbms(self):
+    return self.DBMS_KEYS_LIST
+
+  def get_supported_jdbc_drivers(self):
+    return self.DRIVER_KEYS_LIST
+
+  def _get_default_dbms_index(self, options):
+    try:
+      dbms_name = options.dbms
+      if not dbms_name:
+        dbms_name = ""
+    except AttributeError:
+      dbms_name = ""
+    try:
+      persistence_type = options.persistence_type
+      if not persistence_type:
+        persistence_type = ""
+    except AttributeError:
+      persistence_type = ""
+
+    try:
+      def_index = self.DBMS_DICT[dbms_name + "-" + persistence_type]
+    except KeyError:
+      # Unsupported database type (e.g. local Oracle or MySQL)
+      raise FatalException(15, "Invalid database selection: {0} {1}".format(
+          getattr(options, "persistence_type", ""), getattr(options, "options.dbms", "")))
+
+    return def_index
+
+
+def check_jdbc_drivers(args):
+  # create jdbc symlinks if jdbc drivers are available in resources
+  properties = get_ambari_properties()
+  if properties == -1:
+    err = "Error getting ambari properties"
+    print_error_msg(err)
+    raise FatalException(-1, err)
+  conf_file = properties.fileName
+
+  try:
+    resources_dir = properties[RESOURCES_DIR_PROPERTY]
+  except (KeyError), e:
+    err = 'Property ' + str(e) + ' is not defined at ' + conf_file
+    raise FatalException(1, err)
+
+  try:
+    db_idx_orig = args.database_index
+  except AttributeError:
+    db_idx_orig = None
+
+  factory = DBMSConfigFactory()
+
+  # AMBARI-5696 Validate the symlinks for each supported driver, in case various back-end HDP services happen to
+  #  use different DBMSes
+  # This is skipped on Windows
+  db_idx = 1
+
+  try:
+    while db_idx < len(factory.get_supported_dbms()):
+      args.database_index = db_idx
+      dbms = factory.create(args, properties)
+      if dbms.driver_symlink_name:
+        jdbc_file_path = os.path.join(resources_dir, dbms.driver_file_name)
+        if os.path.isfile(jdbc_file_path):
+          jdbc_symlink = os.path.join(resources_dir, dbms.driver_symlink_name)
+          if os.path.lexists(jdbc_symlink):
+            os.remove(jdbc_symlink)
+          os.symlink(jdbc_file_path, jdbc_symlink)
+      db_idx += 1
+  finally:
+    args.database_index = db_idx_orig

+ 708 - 592
ambari-server/src/main/python/ambari_server/dbConfiguration_linux.py

@@ -17,210 +17,184 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 See the License for the specific language governing permissions and
 limitations under the License.
 limitations under the License.
 '''
 '''
-
+import fileinput
+import glob
+import os
+import re
 import shutil
 import shutil
+import socket
+import subprocess
+import sys
+import time
+
+from ambari_commons import OSCheck, OSConst
+from ambari_commons.logging_utils import get_silent, get_verbose, print_error_msg, print_info_msg, print_warning_msg
+from ambari_commons.exceptions import NonFatalException, FatalException
+from ambari_commons.os_utils import copy_files, remove_file, run_os_command, find_in_path
+from ambari_server.dbConfiguration import DBMSConfig, USERNAME_PATTERN, SETUP_DB_CONNECT_ATTEMPTS, \
+    SETUP_DB_CONNECT_TIMEOUT, STORAGE_TYPE_LOCAL, DEFAULT_USERNAME, DEFAULT_PASSWORD
+from ambari_server.serverConfiguration import get_ambari_properties, get_value_from_properties, configDefaults, \
+    OS_TYPE, AMBARI_PROPERTIES_FILE, RESOURCES_DIR_PROPERTY, \
+    JDBC_DATABASE_PROPERTY, JDBC_DATABASE_NAME_PROPERTY, JDBC_POSTGRES_SCHEMA_PROPERTY, \
+    JDBC_HOSTNAME_PROPERTY, JDBC_PORT_PROPERTY, \
+    JDBC_USER_NAME_PROPERTY, JDBC_PASSWORD_PROPERTY, JDBC_PASSWORD_FILENAME, \
+    JDBC_DRIVER_PROPERTY, JDBC_URL_PROPERTY, \
+    JDBC_RCA_USER_NAME_PROPERTY, JDBC_RCA_PASSWORD_ALIAS, JDBC_RCA_PASSWORD_FILE_PROPERTY, \
+    JDBC_RCA_DRIVER_PROPERTY, JDBC_RCA_URL_PROPERTY, \
+    PERSISTENCE_TYPE_PROPERTY
+from ambari_server.setupSecurity import read_password, store_password_file, encrypt_password
+from ambari_server.userInput import get_YN_input, get_validated_string_input
+from ambari_server.utils import get_postgre_hba_dir, get_postgre_running_status
+
+ORACLE_DB_ID_TYPES = ["Service Name", "SID"]
+ORACLE_SNAME_PATTERN = "jdbc:oracle:thin:@.+:.+:.+"
+
+JDBC_PROPERTIES_PREFIX = "server.jdbc.properties."
+
+class LinuxDBMSConfig(DBMSConfig):
+  def __init__(self, options, properties, storage_type):
+    super(LinuxDBMSConfig, self).__init__(options, properties, storage_type)
 
 
-from ambari_commons import OSConst
-from ambari_commons.logging_utils import *
-from exceptions import *
-from dbConfiguration import *
-from utils import *
-
-import utils
-
-# PostgreSQL settings
-PG_JDBC_CONNECTION_STRING = "jdbc:postgresql://{0}:{1}/{2}"
-PG_JDBC_CONNECTION_STRING_ALT = "jdbc:postgresql://{0}:{1}/{2}"
-
-UBUNTU_PG_HBA_ROOT = "/etc/postgresql"
-PG_HBA_ROOT_DEFAULT = "/var/lib/pgsql/data"
-
-SETUP_DB_CMD = ['su', '-', 'postgres',
-        '--command=psql -f {0} -v username=\'"{1}"\' -v password="\'{2}\'" -v dbname="{3}"']
-UPGRADE_STACK_CMD = ['su', 'postgres',
-        '--command=psql -f {0} -v stack_name="\'{1}\'"  -v stack_version="\'{2}\'" -v dbname="{3}"']
-
-CHANGE_OWNER_COMMAND = ['su', '-', 'postgres',
-                        '--command=/var/lib/ambari-server/resources/scripts/change_owner.sh -d {0} -s {1} -o {2}']
-
-PG_ERROR_BLOCKED = "is being accessed by other users"
-PG_STATUS_RUNNING = get_running_status()
-PG_DEFAULT_PASSWORD = "bigdata"
-SERVICE_CMD = "/usr/bin/env service"
-PG_SERVICE_NAME = "postgresql"
-PG_HBA_DIR = utils.get_postgre_hba_dir()
-
-PG_ST_CMD = "%s %s status" % (SERVICE_CMD, PG_SERVICE_NAME)
-if os.path.isfile("/usr/bin/postgresql-setup"):
-    PG_INITDB_CMD = "/usr/bin/postgresql-setup initdb"
-else:
-    PG_INITDB_CMD = "%s %s initdb" % (SERVICE_CMD, PG_SERVICE_NAME)
-
-PG_START_CMD = "%s %s start" % (SERVICE_CMD, PG_SERVICE_NAME)
-PG_RESTART_CMD = "%s %s restart" % (SERVICE_CMD, PG_SERVICE_NAME)
-PG_HBA_RELOAD_CMD = "%s %s reload" % (SERVICE_CMD, PG_SERVICE_NAME)
-
-PG_HBA_CONF_FILE = os.path.join(PG_HBA_DIR, "pg_hba.conf")
-PG_HBA_CONF_FILE_BACKUP = os.path.join(PG_HBA_DIR, "pg_hba_bak.conf.old")
-POSTGRESQL_CONF_FILE = os.path.join(PG_HBA_DIR, "postgresql.conf")
-
-
-# Set database properties to default values
-def load_default_db_properties(args):
-  args.persistence_type = 'local'
-  args.dbms = DATABASE_NAMES[DATABASE_INDEX]
-  args.database_host = "localhost"
-  args.database_port = DATABASE_PORTS[DATABASE_INDEX]
-  args.database_name = DEFAULT_DB_NAME
-  args.database_username = "ambari"
-  args.database_password = "bigdata"
-  args.sid_or_sname = "sname"
-  pass
-
-def configure_database_password(showDefault=True):
-  passwordDefault = PG_DEFAULT_PASSWORD
-  if showDefault:
-    passwordPrompt = 'Enter Database Password (' + passwordDefault + '): '
-  else:
-    passwordPrompt = 'Enter Database Password: '
-  passwordPattern = "^[a-zA-Z0-9_-]*$"
-  passwordDescr = "Invalid characters in password. Use only alphanumeric or "\
-                  "_ or - characters"
-
-  password = read_password(passwordDefault, passwordPattern, passwordPrompt,
-    passwordDescr)
-
-  return password
-
-# Ask user for database connection properties
-def prompt_linux_db_properties(args):
-  global DATABASE_INDEX
-
-  if args.must_set_database_options:
-    load_default_db_properties(args)
-    ok = get_YN_input("Enter advanced database configuration [y/n] (n)? ", False)
-    if ok:
-
-      print "=============================================================================="
-      print "Choose one of the following options:"
-
-      database_num = str(DATABASE_INDEX + 1)
-      database_num = get_validated_string_input(
-        "[1] - PostgreSQL (Embedded)\n[2] - Oracle\n[3] - MySQL\n[4] - PostgreSQL\n"
-        "==============================================================================\n"
-        "Enter choice (" + database_num + "): ",
-        database_num,
-        "^[1234]$",
-        "Invalid number.",
-        False
-      )
+    #Init the database configuration data here, if any
+    self.dbms_full_name = ""
+
+    # The values from options supersede the values from properties
+    self.database_host = DBMSConfig._init_member_with_prop_default(options, "database_host",
+                                                                   properties, JDBC_HOSTNAME_PROPERTY, "localhost")
+    #self.database_port is set in the subclasses
+    self.database_name = DBMSConfig._init_member_with_prop_default(options, "database_name",
+                                                                   properties, JDBC_DATABASE_NAME_PROPERTY, configDefaults.DEFAULT_DB_NAME)
+
+    self.database_username = DBMSConfig._init_member_with_prop_default(options, "database_username",
+                                                                       properties, JDBC_USER_NAME_PROPERTY, DEFAULT_USERNAME)
+    self.database_password = getattr(options, "database_password", "")
+    if not self.database_password:
+      self.database_password = DBMSConfig._read_password_from_properties(properties)
+
+    self.database_url_pattern = ""
+    self.database_url_pattern_alt = ""
+
+    self.database_storage_name = ""
+    self.sid_or_sname = "sname"
+
+    self.init_script_file = ""
+    self.drop_tables_script_file = ""
+    self.client_tool_usage_pattern = ""
+
+    self.jdbc_extra_params = []
+
+  def _prompt_db_properties(self):
+    if self.must_set_database_options:
+      if self.persistence_type != STORAGE_TYPE_LOCAL:
+        self.database_host = get_validated_string_input(
+            "Hostname (" + self.database_host + "): ",
+            self.database_host,
+            "^[a-zA-Z0-9.\-]*$",
+            "Invalid hostname.",
+            False
+        )
 
 
-      if int(database_num) == 1:
-        args.persistence_type = 'local'
-        args.database_index = 0
-      else:
-        args.persistence_type = 'remote'
-        selected_db_option = int(database_num)
-
-        if selected_db_option == 2:
-          args.database_index = 1
-        elif selected_db_option == 3:
-          args.database_index = 2
-        elif selected_db_option == 4:
-          args.database_index = 0
-        else:
-          print_info_msg('Unknown db option, default to embbeded postgres.')
-          args.database_index = 0
-        pass
-      pass
+        self.database_port = get_validated_string_input(
+            "Port (" + self.database_port + "): ",
+            self.database_port,
+            "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
+            "Invalid port.",
+            False
+        )
 
 
-      DATABASE_INDEX = args.database_index
-      args.dbms = DATABASE_NAMES[args.database_index]
+      if not self._configure_database_name():
+        return False
 
 
-      if args.persistence_type != 'local':
-        args.database_host = get_validated_string_input(
-          "Hostname (" + args.database_host + "): ",
-          args.database_host,
-          "^[a-zA-Z0-9.\-]*$",
-          "Invalid hostname.",
+      # Username is common for Oracle/MySQL/Postgres
+      self.database_username = get_validated_string_input(
+          'Username (' + self.database_username + '): ',
+          self.database_username,
+          USERNAME_PATTERN,
+          "Invalid characters in username. Start with _ or alpha "
+          "followed by alphanumeric or _ or - characters",
           False
           False
-        )
+      )
+      self.database_password = LinuxDBMSConfig._configure_database_password(True)
 
 
-        args.database_port = DATABASE_PORTS[DATABASE_INDEX]
-        args.database_port = get_validated_string_input(
-          "Port (" + args.database_port + "): ",
-          args.database_port,
-          "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
-          "Invalid port.",
-          False
-        )
+    self._display_db_properties()
+    return True
 
 
-        if args.dbms == "oracle":
-          # Oracle uses service name or service id
-          idType = "1"
-          idType = get_validated_string_input(
-            "Select Oracle identifier type:\n1 - " + ORACLE_DB_ID_TYPES[0] +
-            "\n2 - " + ORACLE_DB_ID_TYPES[1] + "\n(" + idType + "): ",
-            idType,
-            "^[12]$",
-            "Invalid number.",
-            False
-          )
+  # Supporting remote server for all the DB types. Supporting local server only for PostgreSQL.
+  def _setup_remote_server(self, args):
+    self._store_remote_properties(args)
 
 
-          if idType == "2":
-            args.sid_or_sname = "sid"
+  def _setup_remote_database(self):
+    properties = get_ambari_properties()
+    if properties == -1:
+      err = 'Error getting ambari properties'
+      print_error_msg(err)
+      raise FatalException(-1, err)
 
 
-          IDTYPE_INDEX = int(idType) - 1
-          args.database_name = get_validated_service_name(args.database_name,
-                                                          IDTYPE_INDEX)
-        elif args.dbms in ["mysql", "postgres"]:
-          args.database_name = get_validated_db_name(args.database_name)
+    if self.ensure_jdbc_driver_installed(properties):
+      print 'Configuring remote database connection properties...'
+      retcode = self._setup_remote_db()
+      if retcode == -1:
+        err = "Remote database setup aborted."
+        raise NonFatalException(err)
+      if not retcode == 0:
+        err = 'Error while configuring connection properties. Exiting'
+        raise FatalException(retcode, err)
 
 
-        else:
-          # other DB types
-          pass
-        pass
-      else:
-        args.database_host = "localhost"
-        args.database_port = DATABASE_PORTS[DATABASE_INDEX]
+  def _reset_remote_database(self):
+    client_usage_cmd_drop = self._get_remote_script_line(self.drop_tables_script_file)
+    client_usage_cmd_init = self._get_remote_script_line(self.init_script_file)
 
 
-        args.database_name = get_validated_db_name(args.database_name)
-        pass
+    print_warning_msg('To reset Ambari Server schema ' +
+                      'you must run the following DDL against the database to '
+                      + 'drop the schema:' + os.linesep + client_usage_cmd_drop
+                      + os.linesep + 'Then you must run the following DDL ' +
+                      'against the database to create the schema: ' + os.linesep +
+                      client_usage_cmd_init + os.linesep)
 
 
-      # Username is common for Oracle/MySQL/Postgres
-      args.database_username = get_validated_string_input(
-        'Username (' + args.database_username + '): ',
-        args.database_username,
-        USERNAME_PATTERN,
-        "Invalid characters in username. Start with _ or alpha "
-        "followed by alphanumeric or _ or - characters",
-        False
-      )
-      args.database_password = configure_database_password(True)
+  def _install_jdbc_driver(self, properties, files_list):
+    if type(files_list) is not int:
+      print 'Copying JDBC drivers to server resources...'
+      try:
+        resources_dir = properties[RESOURCES_DIR_PROPERTY]
+      except KeyError:
+        print_error_msg("There is no value for " + RESOURCES_DIR_PROPERTY + "in " + AMBARI_PROPERTIES_FILE)
+        return False
 
 
-    print_info_msg('Using database options: {database},{host},{port},{schema},{user},{password}'.format(
-      database=args.dbms,
-      host=args.database_host,
-      port=args.database_port,
-      schema=args.database_name,
-      user=args.database_username,
-      password=args.database_password
-    ))
+      db_name = self.dbms_full_name.lower()
+      symlink_name = db_name + "-jdbc-driver.jar"
+      jdbc_symlink = os.path.join(resources_dir, symlink_name)
+      db_default_driver_path = os.path.join(configDefaults.JAVA_SHARE_PATH, self.driver_file_name)
 
 
-# PostgreSQL configuration and setup
-class PGConfig(DBMSConfig):
-  def __init__(self):
-    #Init the database configuration data here, if any
-    pass
+      if os.path.lexists(jdbc_symlink):
+        os.remove(jdbc_symlink)
+
+      copy_status = copy_files(files_list, resources_dir)
+
+      if not copy_status == 0:
+        raise FatalException(-1, "Failed to copy JDBC drivers to server resources")
+
+      if db_default_driver_path in files_list:
+        os.symlink(os.path.join(resources_dir, self.driver_file_name), jdbc_symlink)
+    else:
+      if files_list == -1:
+        return False
+    return True
+
+  def _configure_database_name(self):
+    return True
 
 
-  def configure_database_password(showDefault=True):
-    passwordDefault = PG_DEFAULT_PASSWORD
+  def _get_remote_script_line(self, scriptFile):
+    return None
+
+  @staticmethod
+  def _configure_database_password(showDefault=True):
+    passwordDefault = DEFAULT_PASSWORD
     if showDefault:
     if showDefault:
       passwordPrompt = 'Enter Database Password (' + passwordDefault + '): '
       passwordPrompt = 'Enter Database Password (' + passwordDefault + '): '
     else:
     else:
       passwordPrompt = 'Enter Database Password: '
       passwordPrompt = 'Enter Database Password: '
     passwordPattern = "^[a-zA-Z0-9_-]*$"
     passwordPattern = "^[a-zA-Z0-9_-]*$"
-    passwordDescr = "Invalid characters in password. Use only alphanumeric or "\
+    passwordDescr = "Invalid characters in password. Use only alphanumeric or " \
                     "_ or - characters"
                     "_ or - characters"
 
 
     password = read_password(passwordDefault, passwordPattern, passwordPrompt,
     password = read_password(passwordDefault, passwordPattern, passwordPrompt,
@@ -228,513 +202,655 @@ class PGConfig(DBMSConfig):
 
 
     return password
     return password
 
 
-  #
-  # Private implementation
-  #
-  def _change_db_files_owner(args):
-    print 'Fixing database objects owner'
-    database_name = args.database_name
-    new_owner = args.database_username
-    if '"' not in new_owner:
-      #wrap to allow old username "ambari-server", postgres only
-      new_owner = '\'"{0}"\''.format(new_owner)
-      pass
+  @staticmethod
+  def _get_validated_db_name(database_storage_name, database_name):
+    return get_validated_string_input(
+        database_storage_name + " name ("
+        + database_name + "): ",
+        database_name,
+        ".*",
+        "Invalid " + database_storage_name.lower() + " name.",
+        False
+    )
 
 
-    command = CHANGE_OWNER_COMMAND[:]
-    command[-1] = command[-1].format(database_name, 'ambari', new_owner)
-    return run_os_command(command)
+  def _display_db_properties(self):
+    print_info_msg('Using database options: {database},{host},{port},{schema},{user},{password}'.format(
+        database=self.dbms,
+        host=self.database_host,
+        port=self.database_port,
+        schema=self.database_name,
+        user=self.database_username,
+        password=self.database_password
+    ))
 
 
-  def _configure_pg_hba_ambaridb_users(self):
-    args = optparse.Values()
-    configure_database_username_password(args)
+  #Check if required jdbc drivers present
+  @staticmethod
+  def _find_jdbc_driver(jdbc_pattern):
+    drivers = []
+    drivers.extend(glob.glob(configDefaults.JAVA_SHARE_PATH + os.sep + jdbc_pattern))
+    if drivers:
+      return drivers
+    return -1
 
 
-    with open(PG_HBA_CONF_FILE, "a") as pgHbaConf:
-      pgHbaConf.write("\n")
-      pgHbaConf.write("local  all  " + args.database_username +
-                      ",mapred md5")
-      pgHbaConf.write("\n")
-      pgHbaConf.write("host  all   " + args.database_username +
-                      ",mapred 0.0.0.0/0  md5")
-      pgHbaConf.write("\n")
-      pgHbaConf.write("host  all   " + args.database_username +
-                      ",mapred ::/0 md5")
-      pgHbaConf.write("\n")
-    retcode, out, err = run_os_command(PG_HBA_RELOAD_CMD)
-    if not retcode == 0:
-      raise FatalException(retcode, err)
+  # Let the console user initialize the remote database schema
+  def _setup_remote_db(self):
+    setup_msg = "Before starting Ambari Server, you must run the following DDL " \
+                "against the database to create the schema: {0}".format(self.init_script_file)
 
 
-  def _configure_pg_hba_postgres_user(self):
-    postgresString = "all   postgres"
-    for line in fileinput.input(PG_HBA_CONF_FILE, inplace=1):
-      print re.sub('all\s*all', postgresString, line),
-    os.chmod(PG_HBA_CONF_FILE, 0644)
+    print_warning_msg(setup_msg)
 
 
-  def _configure_postgresql_conf(self):
-    listenAddress = "listen_addresses = '*'        #"
-    for line in fileinput.input(POSTGRESQL_CONF_FILE, inplace=1):
-      print re.sub('#+listen_addresses.*?(#|$)', listenAddress, line),
-    os.chmod(POSTGRESQL_CONF_FILE, 0644)
+    proceed = get_YN_input("Proceed with configuring remote database connection properties [y/n] (y)? ", True)
+    retCode = 0 if proceed else -1
 
 
-  # Store set of properties for remote database connection
-  def _store_remote_properties(args):
-    properties = get_ambari_properties()
-    if properties == -1:
-      print_error_msg("Error getting ambari properties")
-      return -1
+    return retCode
 
 
-    isSecure = get_is_secure(properties)
+  def _store_password_property(self, properties, property_name):
+    properties.process_pair(property_name,
+                            store_password_file(self.database_password, JDBC_PASSWORD_FILENAME))
+    if self.isSecure:
+      encrypted_password = encrypt_password(JDBC_RCA_PASSWORD_ALIAS, self.database_password)
+      if encrypted_password != self.database_password:
+        properties.process_pair(property_name, encrypted_password)
 
 
-    properties.process_pair(PERSISTENCE_TYPE_PROPERTY, "remote")
+  # Store set of properties for remote database connection
+  def _store_remote_properties(self, properties):
+    properties.process_pair(PERSISTENCE_TYPE_PROPERTY, self.persistence_type)
 
 
-    properties.process_pair(JDBC_DATABASE_PROPERTY, args.dbms)
-    properties.process_pair(JDBC_HOSTNAME_PROPERTY, args.database_host)
-    properties.process_pair(JDBC_PORT_PROPERTY, args.database_port)
-    properties.process_pair(JDBC_SCHEMA_PROPERTY, args.database_name)
+    properties.process_pair(JDBC_DATABASE_PROPERTY, self.dbms)
+    properties.process_pair(JDBC_HOSTNAME_PROPERTY, self.database_host)
+    properties.process_pair(JDBC_PORT_PROPERTY, self.database_port)
+    properties.process_pair(JDBC_DATABASE_NAME_PROPERTY, self.database_name)
 
 
-    properties.process_pair(JDBC_DRIVER_PROPERTY, DBCN.get_driver_name())
+    properties.process_pair(JDBC_DRIVER_PROPERTY, self.driver_class_name)
     # fully qualify the hostname to make sure all the other hosts can connect
     # fully qualify the hostname to make sure all the other hosts can connect
     # to the jdbc hostname since its passed onto the agents for RCA
     # to the jdbc hostname since its passed onto the agents for RCA
-    jdbc_hostname = args.database_host
-    if (args.database_host == "localhost"):
+    jdbc_hostname = self.database_host
+    if (self.database_host == "localhost"):
       jdbc_hostname = socket.getfqdn()
       jdbc_hostname = socket.getfqdn()
 
 
-    #TODO: Implement the DBCN connection string generation
-    #connectionStringFormat = DATABASE_CONNECTION_STRINGS
-    #if args.sid_or_sname == "sid":
-    #  connectionStringFormat = DATABASE_CONNECTION_STRINGS_ALT
-    #properties.process_pair(JDBC_URL_PROPERTY, connectionStringFormat[DATABASE_INDEX].format(jdbc_hostname, args.database_port, args.database_name))
-    properties.process_pair(JDBC_URL_PROPERTY, DBCN.get_connection_string())
-    properties.process_pair(JDBC_USER_NAME_PROPERTY, args.database_username)
-    properties.process_pair(JDBC_PASSWORD_PROPERTY,
-        store_password_file(args.database_password, JDBC_PASSWORD_FILENAME))
+    connectionStringFormat = self.database_url_pattern
+    if self.sid_or_sname == "sid":
+      connectionStringFormat = self.database_url_pattern_alt
+    properties.process_pair(JDBC_URL_PROPERTY, connectionStringFormat.format(jdbc_hostname, self.database_port, self.database_name))
+    properties.process_pair(JDBC_USER_NAME_PROPERTY, self.database_username)
+
+    self._store_password_property(properties, JDBC_PASSWORD_PROPERTY)
 
 
     # save any other defined properties to pass to JDBC
     # save any other defined properties to pass to JDBC
-    if DATABASE_INDEX < len(DATABASE_JDBC_PROPERTIES):
-      for pair in DATABASE_JDBC_PROPERTIES[DATABASE_INDEX]:
-        properties.process_pair(JDBC_PROPERTIES_PREFIX + pair[0], pair[1])
-
-    if isSecure:
-      encrypted_password = encrypt_password(JDBC_RCA_PASSWORD_ALIAS, args.database_password)
-      if encrypted_password != args.database_password:
-        properties.process_pair(JDBC_PASSWORD_PROPERTY, encrypted_password)
-    pass
-
-    properties.process_pair(JDBC_RCA_DRIVER_PROPERTY, DBCN.get_driver_name())
-    properties.process_pair(JDBC_RCA_URL_PROPERTY, DBCN.get_connection_string())
-    properties.process_pair(JDBC_RCA_USER_NAME_PROPERTY, args.database_username)
-    properties.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY,
-        store_password_file(args.database_password, JDBC_PASSWORD_FILENAME))
-    if isSecure:
-      encrypted_password = encrypt_password(JDBC_RCA_PASSWORD_ALIAS, args.database_password)
-      if encrypted_password != args.database_password:
-        properties.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, encrypted_password)
-    pass
-
-    conf_file = properties.fileName
+    for pair in self.jdbc_extra_params:
+      properties.process_pair(JDBC_PROPERTIES_PREFIX + pair[0], pair[1])
 
 
-    try:
-      properties.store(open(conf_file, "w"))
-    except Exception, e:
-      print 'Could not write ambari config file "%s": %s' % (conf_file, e)
-      return -1
+    properties.process_pair(JDBC_RCA_DRIVER_PROPERTY, self.driver_class_name)
+    properties.process_pair(JDBC_RCA_URL_PROPERTY, self.database_url_pattern.format(jdbc_hostname, self.database_port, self.database_name))
+    properties.process_pair(JDBC_RCA_USER_NAME_PROPERTY, self.database_username)
 
 
-    return 0
+    self._store_password_property(properties, JDBC_RCA_PASSWORD_FILE_PROPERTY)
 
 
-  #
-  # Public methods
-  #
-  def configure_postgres(self):
-    if os.path.isfile(PG_HBA_CONF_FILE):
-      if not os.path.isfile(PG_HBA_CONF_FILE_BACKUP):
-        shutil.copyfile(PG_HBA_CONF_FILE, PG_HBA_CONF_FILE_BACKUP)
-      else:
-        #Postgres has been configured before, must not override backup
-        print "Backup for pg_hba found, reconfiguration not required"
-        return 0
-    self._configure_pg_hba_postgres_user()
-    self._configure_pg_hba_ambaridb_users()
-    os.chmod(PG_HBA_CONF_FILE, 0644)
-    self._configure_postgresql_conf()
-    #restart postgresql if already running
-    pg_status = get_postgre_status()
-    if pg_status == PG_STATUS_RUNNING:
-      retcode = restart_postgres()
-      return retcode
-    return 0
 
 
-  def configure_database(self, args):
-    prompt_db_properties(args)
-
-    #DB setup should be done last after doing any setup.
+# PostgreSQL configuration and setup
+class PGConfig(LinuxDBMSConfig):
+  # PostgreSQL settings
+  SETUP_DB_CMD = ['su', '-', 'postgres',
+                  '--command=psql -f {0} -v username=\'"{1}"\' -v password="\'{2}\'" -v dbname="{3}"']
+  UPGRADE_STACK_CMD = ['su', 'postgres',
+                       '--command=psql -f {0} -v stack_name="\'{1}\'"  -v stack_version="\'{2}\'" -v dbname="{3}"']
+
+  CHANGE_OWNER_COMMAND = ['su', '-', 'postgres',
+                          '--command=/var/lib/ambari-server/resources/scripts/change_owner.sh -d {0} -s {1} -o {2}']
+
+  PG_ERROR_BLOCKED = "is being accessed by other users"
+  PG_STATUS_RUNNING = get_postgre_running_status(OS_TYPE)
+  SERVICE_CMD = "/usr/bin/env service"
+  PG_SERVICE_NAME = "postgresql"
+  PG_HBA_DIR = get_postgre_hba_dir(OSCheck.get_os_family())
+
+  PG_ST_CMD = "%s %s status" % (SERVICE_CMD, PG_SERVICE_NAME)
+  if os.path.isfile("/usr/bin/postgresql-setup"):
+      PG_INITDB_CMD = "/usr/bin/postgresql-setup initdb"
+  else:
+      PG_INITDB_CMD = "%s %s initdb" % (SERVICE_CMD, PG_SERVICE_NAME)
 
 
-    if is_local_database(args):
-      #check if jdbc user is changed
-      is_user_changed = is_jdbc_user_changed(args)
+  PG_START_CMD = "%s %s start" % (SERVICE_CMD, PG_SERVICE_NAME)
+  PG_RESTART_CMD = "%s %s restart" % (SERVICE_CMD, PG_SERVICE_NAME)
+  PG_HBA_RELOAD_CMD = "%s %s reload" % (SERVICE_CMD, PG_SERVICE_NAME)
 
 
-      print 'Default properties detected. Using built-in database.'
-      store_local_properties(args)
+  PG_HBA_CONF_FILE = os.path.join(PG_HBA_DIR, "pg_hba.conf")
+  PG_HBA_CONF_FILE_BACKUP = os.path.join(PG_HBA_DIR, "pg_hba_bak.conf.old")
+  POSTGRESQL_CONF_FILE = os.path.join(PG_HBA_DIR, "postgresql.conf")
 
 
-      print 'Checking PostgreSQL...'
-      retcode = check_postgre_up()
-      if not retcode == 0:
-        err = 'Unable to start PostgreSQL server. Exiting'
-        raise FatalException(retcode, err)
+  POSTGRES_EMBEDDED_INIT_FILE = "/var/lib/ambari-server/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql"
+  POSTGRES_EMBEDDED_DROP_FILE = "/var/lib/ambari-server/resources/Ambari-DDL-Postgres-EMBEDDED-DROP.sql"
 
 
-      print 'Configuring local database...'
-      retcode, outdata, errdata = setup_db(args)
-      if not retcode == 0:
-        err = 'Running database init script was failed. Exiting.'
-        raise FatalException(retcode, err)
+  POSTGRES_INIT_FILE = "/var/lib/ambari-server/resources/Ambari-DDL-Postgres-CREATE.sql"
+  POSTGRES_DROP_FILE = "/var/lib/ambari-server/resources/Ambari-DDL-Postgres-DROP.sql"
 
 
-      if is_user_changed:
-        #remove backup for pg_hba in order to reconfigure postgres
-        remove_file(PG_HBA_CONF_FILE_BACKUP)
+  def __init__(self, options, properties, storage_type):
+    super(PGConfig, self).__init__(options, properties, storage_type)
 
 
-      print 'Configuring PostgreSQL...'
-      retcode = configure_postgres()
-      if not retcode == 0:
-        err = 'Unable to configure PostgreSQL server. Exiting'
-        raise FatalException(retcode, err)
+    #Init the database configuration data here, if any
+    self.dbms = "postgres"
+    self.dbms_full_name = "PostgreSQL"
+    self.driver_class_name = "org.postgresql.Driver"
+    self.driver_file_name = "postgresql-jdbc.jar"
 
 
-    else:
-      retcode = self._store_remote_properties(args)
-      if retcode != 0:
-        err = 'Unable to save config file'
-        raise FatalException(retcode, err)
+    self.database_storage_name = "Database"
 
 
-      check_jdbc_drivers(args)
+    # PostgreSQL seems to require additional schema coordinates
+    self.postgres_schema = DBMSConfig._init_member_with_prop_default(options, "postgres_schema",
+                                                                     properties, JDBC_POSTGRES_SCHEMA_PROPERTY, self.database_name)
+    self.database_port = DBMSConfig._init_member_with_prop_default(options, "database_port",
+                                                                   properties, JDBC_PORT_PROPERTY, "5432")
 
 
-      print 'Configuring remote database connection properties...'
-      retcode = setup_remote_db(args)
-      if retcode == -1:
-        err = "Remote database setup aborted."
-        raise NonFatalException(err)
+    self.database_url_pattern = "jdbc:postgresql://{0}:{1}/{2}"
+    self.database_url_pattern_alt = "jdbc:postgresql://{0}:{1}/{2}"
 
 
-      if not retcode == 0:
-        err = 'Error while configuring connection properties. Exiting'
-        raise FatalException(retcode, err)
-      check_jdbc_drivers(args)
+    self.JDBC_DRIVER_INSTALL_MSG = 'Before starting Ambari Server, ' \
+                                   'you must copy the {0} JDBC driver JAR file to {1}.'.format(
+        self.dbms_full_name, configDefaults.JAVA_SHARE_PATH)
 
 
+    self._is_user_changed = False
 
 
-  def configure_database_username_password(self, args):
-    properties = get_ambari_properties()
-    if properties == -1:
-      print_error_msg("Error getting ambari properties")
-      return -1
-
-    username = properties[JDBC_USER_NAME_PROPERTY]
-    passwordProp = properties[JDBC_PASSWORD_PROPERTY]
-    dbname = properties[JDBC_DATABASE_PROPERTY]
-
-    if username and passwordProp and dbname:
-      print_info_msg("Database username + password already configured")
-      args.database_username = username
-      args.database_name = dbname
-      if is_alias_string(passwordProp):
-        args.database_password = decrypt_password_for_alias(JDBC_RCA_PASSWORD_ALIAS)
-      else:
-        if os.path.exists(passwordProp):
-          with open(passwordProp, 'r') as file:
-            args.database_password = file.read()
-
-      return 1
+    if self.persistence_type == STORAGE_TYPE_LOCAL:
+      postgres_init_file_default = PGConfig.POSTGRES_EMBEDDED_INIT_FILE
+      postgres_drop_file_default = PGConfig.POSTGRES_EMBEDDED_DROP_FILE
     else:
     else:
-      print_error_msg("Connection properties not set in config file.")
-
-  def setup_db(self, args):
-    self.configure_database_username_password(args)
-
-    dbname = args.database_name
-    scriptFile = args.init_script_file
-    username = args.database_username
-    password = args.database_password
-
-    #setup DB
-    command = SETUP_DB_CMD[:]
-    command[-1] = command[-1].format(scriptFile, username, password, dbname)
-
-    for i in range(SETUP_DB_CONNECT_ATTEMPTS):
-      sys.stdout.write('Connecting to local database...')
-      retcode, outdata, errdata = run_os_command(command)
-      if retcode == 0:
-        print 'done.'
-        return retcode, outdata, errdata
-      timeOutMsg = 'connection timed out'
-      if (i+1) < SETUP_DB_CONNECT_ATTEMPTS:
-        timeOutMsg += '...retrying (%d)' % (i+1)
-        print timeOutMsg
-        time.sleep(SETUP_DB_CONNECT_TIMEOUT)
-
-    print 'unable to connect to database'
-    utils.print_error_msg(errdata)
-    return retcode, outdata, errdata
-
-  # Initialize remote database schema
-  def setup_remote_db(args):
-
-    setup_msg = "Before starting Ambari Server, you must run the following DDL " \
-                "against the database to create the schema: {0}".format(DATABASE_INIT_SCRIPTS[DATABASE_INDEX])
+      postgres_init_file_default = PGConfig.POSTGRES_INIT_FILE
+      postgres_drop_file_default = PGConfig.POSTGRES_DROP_FILE
+    self.init_script_file = DBMSConfig._init_member_with_default(options, "init_script_file",
+                                                                 postgres_init_file_default)
+    self.drop_tables_script_file = DBMSConfig._init_member_with_default(options, "drop_script_file",
+                                                                        postgres_drop_file_default)
+    self.client_tool_usage_pattern = 'su -postgres --command=psql -f {0} -v username=\'"{1}"\' -v password="\'{2}\'"'
 
 
-    print_warning_msg(setup_msg)
-
-    proceed = get_YN_input("Proceed with configuring remote database connection properties [y/n] (y)? ", True)
-    retCode = 0 if proceed else -1
+  #
+  # Public methods
+  #
 
 
-    return retCode
+  #
+  # Private implementation
+  #
+  # Supporting remote server for all the DB types. Supporting local server only for PostgreSQL.
+  def _setup_local_server(self, properties):
+    # check if jdbc user is changed
+    self._is_user_changed = PGConfig._is_jdbc_user_changed(self.database_username)
+    print 'Default properties detected. Using built-in database.'
+    self._store_local_properties(properties)
+
+  def _setup_local_database(self):
+    print 'Checking PostgreSQL...'
+    (pg_status, retcode, out, err) = PGConfig._check_postgre_up()
+    if not retcode == 0:
+      err = 'Unable to start PostgreSQL server. Exiting'
+      raise FatalException(retcode, err)
+    print 'Configuring local database...'
+    retcode, out, err = self._setup_db()
+    if not retcode == 0:
+      err = 'Running database init script failed. Exiting.'
+      raise FatalException(retcode, err)
+    if self._is_user_changed:
+      #remove backup for pg_hba in order to reconfigure postgres
+      remove_file(PGConfig.PG_HBA_CONF_FILE_BACKUP)
+    print 'Configuring PostgreSQL...'
+    retcode, out, err = self._configure_postgres()
+    if not retcode == 0:
+      err = 'Unable to configure PostgreSQL server. Exiting'
+      raise FatalException(retcode, err)
 
 
-  def change_db_files_owner(self, args):
-    if args.persistence_type == 'local':
-      retcode, stdout, stderr = self._change_db_files_owner(args)
-      if not retcode == 0:
-        raise FatalException(20, 'Unable to change owner of database objects')
+  def _reset_local_database(self):
+    #force reset if silent option provided
+    if get_silent():
+      default = "yes"
+    else:
+      default = "no"
 
 
-  def reset_remote_db(self, args):
-    client_usage_cmd_drop = DATABASE_CLI_TOOLS_USAGE[DATABASE_INDEX].format(DATABASE_DROP_SCRIPTS[DATABASE_INDEX], args.database_username,
-                                                     BLIND_PASSWORD, args.database_name)
-    client_usage_cmd_init = DATABASE_CLI_TOOLS_USAGE[DATABASE_INDEX].format(DATABASE_INIT_SCRIPTS[DATABASE_INDEX], args.database_username,
-                                                     BLIND_PASSWORD, args.database_name)
+    # Run automatic reset only for embedded DB
+    okToRun = get_YN_input("Confirm server reset [yes/no]({0})? ".format(default), get_silent())
+    if not okToRun:
+      err = "Ambari Server 'reset' cancelled"
+      raise FatalException(1, err)
 
 
-    print_warning_msg('To reset Ambari Server schema ' +
-                      'you must run the following DDL against the database to '
-                      + 'drop the schema:' + os.linesep + client_usage_cmd_drop
-                      + os.linesep + 'Then you must run the following DDL ' +
-                      'against the database to create the schema: ' + os.linesep +
-                      client_usage_cmd_init + os.linesep)
+    print "Resetting the Server database..."
 
 
-  def reset_local_db(args):
-    dbname = args.database_name
-    filename = args.drop_script_file
-    username = args.database_username
-    password = args.database_password
-    command = SETUP_DB_CMD[:]
+    dbname = self.database_name
+    filename = self.drop_tables_script_file
+    username = self.database_username
+    password = self.database_password
+    command = PGConfig.SETUP_DB_CMD[:]
     command[-1] = command[-1].format(filename, username, password, dbname)
     command[-1] = command[-1].format(filename, username, password, dbname)
     drop_retcode, drop_outdata, drop_errdata = run_os_command(command)
     drop_retcode, drop_outdata, drop_errdata = run_os_command(command)
     if not drop_retcode == 0:
     if not drop_retcode == 0:
       raise FatalException(1, drop_errdata)
       raise FatalException(1, drop_errdata)
-    if drop_errdata and PG_ERROR_BLOCKED in drop_errdata:
+    if drop_errdata and PGConfig.PG_ERROR_BLOCKED in drop_errdata:
       raise FatalException(1, "Database is in use. Please, make sure all connections to the database are closed")
       raise FatalException(1, "Database is in use. Please, make sure all connections to the database are closed")
     if drop_errdata and get_verbose():
     if drop_errdata and get_verbose():
       print_warning_msg(drop_errdata)
       print_warning_msg(drop_errdata)
     print_info_msg("About to run database setup")
     print_info_msg("About to run database setup")
-    retcode, outdata, errdata = setup_db(args)
+    retcode, outdata, errdata = self._setup_db()
     if errdata and get_verbose():
     if errdata and get_verbose():
       print_warning_msg(errdata)
       print_warning_msg(errdata)
     if (errdata and 'ERROR' in errdata.upper()) or (drop_errdata and 'ERROR' in drop_errdata.upper()):
     if (errdata and 'ERROR' in errdata.upper()) or (drop_errdata and 'ERROR' in drop_errdata.upper()):
+      err = "Non critical error in DDL"
       if not get_verbose():
       if not get_verbose():
-        raise NonFatalException("Non critical error in DDL, use --verbose for more information")
-      else:
-        raise NonFatalException("Non critical error in DDL")
+        err += ", use --verbose for more information"
+      raise NonFatalException(err)
 
 
-# PostgreSQL database
-class PGDatabase:
-  _driverName = ''
-  _connectionString = ''
+  def _reset_remote_database(self):
+    super(PGConfig, self)._reset_remote_database()
 
 
-  def __init__(self):
-    #Init the database connection here, if any
-    pass
-
-  #
-  # Private implementation
-  #
-
-  # Get database client executable path
-  def get_db_cli_tool(self, args):
-    for tool in DATABASE_CLI_TOOLS[DATABASE_INDEX]:
-      cmd = CHECK_COMMAND_EXIST_CMD.format(tool)
-      ret, out, err = run_in_shell(cmd)
-      if ret == 0:
-        return get_exec_path(tool)
-
-    return None
-
-  #
-  # Public interface
-  #
-  def get_driver_name(self):
-    return self._driverName
+    raise NonFatalException("Please set DB password to PGPASSWORD env variable before running DDL`s!")
 
 
-  def get_connection_string(self):
-    return self._connectionString
+  def _is_jdbc_driver_installed(self, properties):
+    return 0
 
 
-  def connect(self, args):
-    if args.persistence_type == "local":
-      return self.check_postgre_up()
-    else:
-      return 0
-
-  def get_running_status(self):
-    """Return postgre running status indicator"""
-    if OS_TYPE == OSConst.OS_UBUNTU:
-      return "%s/main" % PGDatabase.get_ubuntu_db_version()
-    else:
-      return DB_STATUS_RUNNING_DEFAULT
+  def _configure_database_name(self):
+    self.database_name = LinuxDBMSConfig._get_validated_db_name(self.database_storage_name, self.database_name)
+    self.postgres_schema = PGConfig._get_validated_db_schema(self.postgres_schema)
+    return True
+
+  def _get_remote_script_line(self, scriptFile):
+    os.environ["PGPASSWORD"] = self.database_password
+    return "psql -h {0} -p {1} -d {2} -U {3} -f {4} -v username='{3}'".format(
+      self.database_host,
+      self.database_port,
+      self.database_name,
+      self.database_username,
+      scriptFile
+    )
 
 
   @staticmethod
   @staticmethod
-  def get_hba_dir():
-    """Return postgre hba dir location depends on OS"""
-    if OS_TYPE == OSConst.OS_UBUNTU:
-      return "%s/%s/main" % (UBUNTU_PG_HBA_ROOT, PGDatabase.get_ubuntu_db_version())
-    else:
-      return PG_HBA_ROOT_DEFAULT
-
+  def _get_validated_db_schema(postgres_schema):
+    return get_validated_string_input(
+        "Postgres schema (" + postgres_schema + "): ",
+        postgres_schema,
+        "^[a-zA-Z0-9_\-]*$",
+        "Invalid schema name.",
+        False, allowEmpty=True
+    )
+
+  # Check if jdbc user is changed
   @staticmethod
   @staticmethod
-  def get_ubuntu_db_version():
-    """Return installed version of postgre server. In case of several
-    installed versions will be returned a more new one.
-    """
-    postgre_ver = ""
-
-    if os.path.isdir(UBUNTU_PG_HBA_ROOT):  # detect actual installed versions of PG and select a more new one
-      postgre_ver = sorted(
-      [fld for fld in os.listdir(UBUNTU_PG_HBA_ROOT) if os.path.isdir(os.path.join(UBUNTU_PG_HBA_ROOT, fld))], reverse=True)
-      if len(postgre_ver) > 0:
-        return postgre_ver[0]
-    return postgre_ver
+  def _is_jdbc_user_changed(database_username):
+    properties = get_ambari_properties()
+    if properties == -1:
+      print_error_msg("Error getting ambari properties")
+      return None
 
 
+    previos_user = get_value_from_properties(properties, JDBC_USER_NAME_PROPERTY, "")
 
 
-  def restart_postgres():
-    print "Restarting PostgreSQL"
-    process = subprocess.Popen(PG_RESTART_CMD.split(' '),
-                              stdout=subprocess.PIPE,
-                              stdin=subprocess.PIPE,
-                              stderr=subprocess.PIPE
-                               )
-    time.sleep(5)
-    result = process.poll()
-    if result is None:
-      print_info_msg("Killing restart PostgresSQL process")
-      process.kill()
-      pg_status = get_postgre_status()
-      # SUSE linux set status of stopped postgresql proc to unused
-      if pg_status == "unused" or pg_status == "stopped":
-        print_info_msg("PostgreSQL is stopped. Restarting ...")
-        retcode, out, err = run_os_command(PG_START_CMD)
-        return retcode
-    return 0
-
-  def execute_db_script(self, args, file):
-    #password access to ambari-server and mapred
-    configure_database_username_password(args)
-    dbname = args.database_name
-    username = args.database_username
-    password = args.database_password
-    command = SETUP_DB_CMD[:]
-    command[-1] = command[-1].format(file, username, password, dbname)
-    retcode, outdata, errdata = run_os_command(command)
-    if not retcode == 0:
-      print errdata
-    return retcode
+    if previos_user and database_username:
+      if previos_user != database_username:
+        return True
+      else:
+        return False
 
 
-  def execute_remote_script(self, args, scriptPath):
-    print_warning_msg("Deprecated method called.")
-    tool = get_db_cli_tool(args)
-    if not tool:
-      # args.warnings.append('{0} not found. Please, run DDL script manually'.format(DATABASE_CLI_TOOLS[DATABASE_INDEX]))
-      if get_verbose():
-        print_warning_msg('{0} not found'.format(DATABASE_CLI_TOOLS[DATABASE_INDEX]))
-      return -1, "Client wasn't found", "Client wasn't found"
-
-    os.environ["PGPASSWORD"] = args.database_password
-    retcode, out, err = run_in_shell('{0} {1}'.format(tool, POSTGRES_EXEC_ARGS.format(
-      args.database_host,
-      args.database_port,
-      args.database_name,
-      args.database_username,
-      scriptPath
-    )))
-    return retcode, out, err
-
-  def check_db_consistency(args, file):
-    #password access to ambari-server and mapred
-    configure_database_username_password(args)
-    dbname = args.database_name
-    username = args.database_username
-    password = args.database_password
-    command = SETUP_DB_CMD[:]
-    command[-1] = command[-1].format(file, username, password, dbname)
-    retcode, outdata, errdata = run_os_command(command)
-    if not retcode == 0:
-      print errdata
-      return retcode
-    else:
-      # Assumes that the output is of the form ...\n<count>
-      print_info_msg("Parsing output: " + outdata)
-      lines = outdata.splitlines()
-      if (lines[-1] == '3' or lines[-1] == '0'):
-        return 0
-    return -1
+    return None
 
 
+  # Store local database connection properties
+  def _store_local_properties(self, properties):
+    properties.removeOldProp(JDBC_DATABASE_PROPERTY)
+    properties.removeOldProp(JDBC_DATABASE_NAME_PROPERTY)
+    properties.removeOldProp(JDBC_POSTGRES_SCHEMA_PROPERTY)
+    properties.removeOldProp(JDBC_HOSTNAME_PROPERTY)
+    properties.removeOldProp(JDBC_RCA_DRIVER_PROPERTY)
+    properties.removeOldProp(JDBC_RCA_URL_PROPERTY)
+    properties.removeOldProp(JDBC_PORT_PROPERTY)
+    properties.removeOldProp(JDBC_DRIVER_PROPERTY)
+    properties.removeOldProp(JDBC_URL_PROPERTY)
+
+    # Store the properties
+    properties.process_pair(PERSISTENCE_TYPE_PROPERTY, self.persistence_type)
+    properties.process_pair(JDBC_DATABASE_PROPERTY, self.dbms)
+    properties.process_pair(JDBC_DATABASE_NAME_PROPERTY, self.database_name)
+    properties.process_pair(JDBC_POSTGRES_SCHEMA_PROPERTY, self.postgres_schema)
+    properties.process_pair(JDBC_USER_NAME_PROPERTY, self.database_username)
+
+    self._store_password_property(properties, JDBC_PASSWORD_PROPERTY)
 
 
-  def get_postgre_status():
-    retcode, out, err = run_os_command(PG_ST_CMD)
+  @staticmethod
+  def _get_postgre_status():
+    retcode, out, err = run_os_command(PGConfig.PG_ST_CMD)
     try:
     try:
       pg_status = re.search('(stopped|running)', out, re.IGNORECASE).group(0).lower()
       pg_status = re.search('(stopped|running)', out, re.IGNORECASE).group(0).lower()
     except AttributeError:
     except AttributeError:
       pg_status = None
       pg_status = None
-    return pg_status
+    return pg_status, retcode, out, err
 
 
-
-  def check_postgre_up():
-    pg_status = get_postgre_status()
-    if pg_status == PG_STATUS_RUNNING:
+  @staticmethod
+  def _check_postgre_up():
+    pg_status, retcode, out, err = PGConfig._get_postgre_status()
+    if pg_status == PGConfig.PG_STATUS_RUNNING:
       print_info_msg("PostgreSQL is running")
       print_info_msg("PostgreSQL is running")
-      return 0
+      return pg_status, 0, out, err
     else:
     else:
       # run initdb only on non ubuntu systems as ubuntu does not have initdb cmd.
       # run initdb only on non ubuntu systems as ubuntu does not have initdb cmd.
       if OS_TYPE != OSConst.OS_UBUNTU:
       if OS_TYPE != OSConst.OS_UBUNTU:
         print "Running initdb: This may take upto a minute."
         print "Running initdb: This may take upto a minute."
-        retcode, out, err = run_os_command(PG_INITDB_CMD)
+        retcode, out, err = run_os_command(PGConfig.PG_INITDB_CMD)
         if retcode == 0:
         if retcode == 0:
           print out
           print out
       print "About to start PostgreSQL"
       print "About to start PostgreSQL"
       try:
       try:
-        process = subprocess.Popen(PG_START_CMD.split(' '),
+        process = subprocess.Popen(PGConfig.PG_START_CMD.split(' '),
                                    stdout=subprocess.PIPE,
                                    stdout=subprocess.PIPE,
                                    stdin=subprocess.PIPE,
                                    stdin=subprocess.PIPE,
                                    stderr=subprocess.PIPE
                                    stderr=subprocess.PIPE
-                                   )
+        )
         if OS_TYPE == OSConst.OS_SUSE:
         if OS_TYPE == OSConst.OS_SUSE:
           time.sleep(20)
           time.sleep(20)
           result = process.poll()
           result = process.poll()
           print_info_msg("Result of postgres start cmd: " + str(result))
           print_info_msg("Result of postgres start cmd: " + str(result))
           if result is None:
           if result is None:
             process.kill()
             process.kill()
-            pg_status = get_postgre_status()
+            pg_status, retcode, out, err = PGConfig._get_postgre_status()
           else:
           else:
             retcode = result
             retcode = result
         else:
         else:
           out, err = process.communicate()
           out, err = process.communicate()
           retcode = process.returncode
           retcode = process.returncode
-        if pg_status == PG_STATUS_RUNNING:
+          pg_status, retcode, out, err = PGConfig._get_postgre_status()
+        if pg_status == PGConfig.PG_STATUS_RUNNING:
           print_info_msg("Postgres process is running. Returning...")
           print_info_msg("Postgres process is running. Returning...")
-          return 0
+          return pg_status, 0, out, err
       except (Exception), e:
       except (Exception), e:
-        pg_status = get_postgre_status()
-        if pg_status == PG_STATUS_RUNNING:
-          return 0
+        pg_status, retcode, out, err = PGConfig._get_postgre_status()
+        if pg_status == PGConfig.PG_STATUS_RUNNING:
+          return pg_status, 0, out, err
         else:
         else:
           print_error_msg("Postgres start failed. " + str(e))
           print_error_msg("Postgres start failed. " + str(e))
-          return 1
-      return retcode
+      return pg_status, retcode, out, err
 
 
+  def _setup_db(self):
+    #password access to ambari-server and mapred
+    dbname = self.database_name
+    scriptFile = PGConfig.POSTGRES_EMBEDDED_INIT_FILE
+    username = self.database_username
+    password = self.database_password
 
 
-  def get_validated_db_name(database_name):
-    return get_validated_string_input(
-          DATABASE_STORAGE_NAMES[DATABASE_INDEX] + " Name ("
-          + database_name + "): ",
-          database_name,
-          ".*",
-          "Invalid " + DATABASE_STORAGE_NAMES[DATABASE_INDEX] + " name.",
+    #setup DB
+    command = PGConfig.SETUP_DB_CMD[:]
+    command[-1] = command[-1].format(scriptFile, username, password, dbname)
+
+    for i in range(SETUP_DB_CONNECT_ATTEMPTS):
+      sys.stdout.write('Connecting to local database...')
+      retcode, outdata, errdata = run_os_command(command)
+      if retcode == 0:
+        print 'done.'
+        return retcode, outdata, errdata
+      timeOutMsg = 'connection timed out'
+      if (i+1) < SETUP_DB_CONNECT_ATTEMPTS:
+        timeOutMsg += '...retrying (%d)' % (i+1)
+        print timeOutMsg
+        time.sleep(SETUP_DB_CONNECT_TIMEOUT)
+
+    print 'unable to connect to database'
+    print_error_msg(errdata)
+    return retcode, outdata, errdata
+
+  @staticmethod
+  def _configure_pg_hba_ambaridb_users(conf_file, database_username):
+    with open(conf_file, "a") as pgHbaConf:
+      pgHbaConf.write("\n")
+      pgHbaConf.write("local  all  " + database_username +
+                      ",mapred md5")
+      pgHbaConf.write("\n")
+      pgHbaConf.write("host  all   " + database_username +
+                      ",mapred 0.0.0.0/0  md5")
+      pgHbaConf.write("\n")
+      pgHbaConf.write("host  all   " + database_username +
+                      ",mapred ::/0 md5")
+      pgHbaConf.write("\n")
+    retcode, out, err = run_os_command(PGConfig.PG_HBA_RELOAD_CMD)
+    if not retcode == 0:
+      raise FatalException(retcode, err)
+
+  @staticmethod
+  def _configure_pg_hba_postgres_user():
+    postgresString = "all   postgres"
+    for line in fileinput.input(PGConfig.PG_HBA_CONF_FILE, inplace=1):
+      print re.sub('all\s*all', postgresString, line),
+    os.chmod(PGConfig.PG_HBA_CONF_FILE, 0644)
+
+  @staticmethod
+  def _configure_postgresql_conf():
+    listenAddress = "listen_addresses = '*'        #"
+    for line in fileinput.input(PGConfig.POSTGRESQL_CONF_FILE, inplace=1):
+      print re.sub('#+listen_addresses.*?(#|$)', listenAddress, line),
+    os.chmod(PGConfig.POSTGRESQL_CONF_FILE, 0644)
+
+  def _configure_postgres(self):
+    if os.path.isfile(PGConfig.PG_HBA_CONF_FILE):
+      if not os.path.isfile(PGConfig.PG_HBA_CONF_FILE_BACKUP):
+        shutil.copyfile(PGConfig.PG_HBA_CONF_FILE, PGConfig.PG_HBA_CONF_FILE_BACKUP)
+      else:
+        #Postgres has been configured before, must not override backup
+        print "Backup for pg_hba found, reconfiguration not required"
+        return 0, "", ""
+    PGConfig._configure_pg_hba_postgres_user()
+    PGConfig._configure_pg_hba_ambaridb_users(PGConfig.PG_HBA_CONF_FILE, self.database_username)
+    os.chmod(PGConfig.PG_HBA_CONF_FILE, 0644)
+    PGConfig._configure_postgresql_conf()
+    #restart postgresql if already running
+    pg_status, retcode, out, err = PGConfig._get_postgre_status()
+    if pg_status == PGConfig.PG_STATUS_RUNNING:
+      retcode, out, err = PGConfig._restart_postgres()
+      return retcode, out, err
+    return 0, "", ""
+
+  @staticmethod
+  def _restart_postgres():
+    print "Restarting PostgreSQL"
+    process = subprocess.Popen(PGConfig.PG_RESTART_CMD.split(' '),
+                               stdout=subprocess.PIPE,
+                               stdin=subprocess.PIPE,
+                               stderr=subprocess.PIPE
+    )
+    time.sleep(5)
+    result = process.poll()
+    if result is None:
+      print_info_msg("Killing restart PostgresSQL process")
+      process.kill()
+      pg_status, retcode, out, err = PGConfig._get_postgre_status()
+      # SUSE linux set status of stopped postgresql proc to unused
+      if pg_status == "unused" or pg_status == "stopped":
+        print_info_msg("PostgreSQL is stopped. Restarting ...")
+        retcode, out, err = run_os_command(PGConfig.PG_START_CMD)
+        return retcode, out, err
+    return 0, "", ""
+
+  def _store_remote_properties(self, properties):
+    super(PGConfig, self)._store_remote_properties(properties)
+
+    properties.process_pair(JDBC_POSTGRES_SCHEMA_PROPERTY, self.postgres_schema)
+
+  def _change_db_files_owner(self):
+    database_name = self.database_name
+    new_owner = self.database_username
+    if '"' not in new_owner:
+      #wrap to allow old username "ambari-server", postgres only
+      new_owner = '\'"{0}"\''.format(new_owner)
+      pass
+
+    command = PGConfig.CHANGE_OWNER_COMMAND[:]
+    command[-1] = command[-1].format(database_name, 'ambari', new_owner)
+    retcode, stdout, stderr = run_os_command(command)
+    if not retcode == 0:
+      if get_verbose():
+        if stderr:
+          print_error_msg("stderr:\n" + stderr.strip())
+        if stdout:
+          print_error_msg("stdout:\n" + stdout.strip())
+    else:
+      print_info_msg('Fixed database objects owner')
+
+    return retcode
+
+def createPGConfig(options, properties, storage_type, dbId):
+    return PGConfig(options, properties, storage_type)
+
+class OracleConfig(LinuxDBMSConfig):
+  def __init__(self, options, properties, storage_type):
+    super(OracleConfig, self).__init__(options, properties, storage_type)
+
+    #Init the database configuration data here, if any
+    self.dbms = "oracle"
+    self.dbms_full_name = "Oracle"
+    self.driver_class_name = "oracle.jdbc.driver.OracleDriver"
+    self.driver_file_name = "ojdbc6.jar"
+    self.driver_symlink_name = "oracle-jdbc-driver.jar"
+
+    self.database_storage_name = "Service"
+
+    if (hasattr(options, 'sid_or_sname') and options.sid_or_sname == "sname") or \
+        (hasattr(options, 'jdbc_url') and options.jdbc_url and re.match(ORACLE_SNAME_PATTERN, options.jdbc_url)):
+      print_info_msg("using SERVICE_NAME instead of SID for Oracle")
+      self.sid_or_sname = "service_name"
+
+    self.database_port = DBMSConfig._init_member_with_prop_default(options, "database_port",
+                                                                   properties, JDBC_PORT_PROPERTY, "1521")
+
+    self.database_url_pattern = "jdbc:oracle:thin:@{0}:{1}/{2}"
+    self.database_url_pattern_alt = "jdbc:oracle:thin:@{0}:{1}:{2}"
+
+    self.JDBC_DRIVER_INSTALL_MSG = 'Before starting Ambari Server, ' \
+                                   'you must copy the {0} JDBC driver JAR file to {1}.'.format(
+        self.dbms_full_name, configDefaults.JAVA_SHARE_PATH)
+
+    self.init_script_file = "/var/lib/ambari-server/resources/Ambari-DDL-Oracle-CREATE.sql'"
+    self.drop_tables_script_file = "/var/lib/ambari-server/resources/Ambari-DDL-Oracle-DROP.sql"
+    self.client_tool_usage_pattern = 'sqlplus {1}/{2} < {0}'
+
+    self.jdbc_extra_params = [
+        ["oracle.net.CONNECT_TIMEOUT", "2000"], # socket level timeout
+        ["oracle.net.READ_TIMEOUT", "2000"], # socket level timeout
+        ["oracle.jdbc.ReadTimeout", "8000"] # query fetch timeout
+    ]
+
+  #
+  # Private implementation
+  #
+  def _reset_remote_database(self):
+    super(OracleConfig, self)._reset_remote_database()
+
+    raise NonFatalException("Please replace '*' symbols with password before running DDL`s!")
+
+  def _is_jdbc_driver_installed(self, properties):
+    return LinuxDBMSConfig._find_jdbc_driver("*ojdbc*.jar")
+
+  def _configure_database_name(self):
+    if self.persistence_type != STORAGE_TYPE_LOCAL:
+      # Oracle uses service name or service id
+      idType = "1"
+      idType = get_validated_string_input(
+          "Select Oracle identifier type:\n1 - " + ORACLE_DB_ID_TYPES[0] +
+          "\n2 - " + ORACLE_DB_ID_TYPES[1] + "\n(" + idType + "): ",
+          idType,
+          "^[12]$",
+          "Invalid number.",
           False
           False
-          )
+      )
 
 
+      if idType == "2":
+        self.sid_or_sname = "sid"
 
 
-  def get_validated_service_name(service_name, index):
+      IDTYPE_INDEX = int(idType) - 1
+      self.database_name = OracleConfig._get_validated_service_name(self.database_name,
+                                                                    IDTYPE_INDEX)
+    else:
+      self.database_name = LinuxDBMSConfig._get_validated_db_name(self.database_storage_name, self.database_name)
+
+    return True
+
+  def _get_remote_script_line(self, scriptFile):
+    # Detect the existing sqlplus flavor
+    try:
+      find_in_path("sqlplus64")
+      tool = "sqlplus64"
+    except:
+      tool = "sqlplus"
+
+    ORACLE_EXEC_ARGS = "{0} -S -L '{1}/{2}@(description=(address=(protocol=TCP)(host={3})(port={4}))(connect_data=({7}={5})))' @{6} {1}"
+
+    return ORACLE_EXEC_ARGS.format(
+      tool,
+      self.database_username,
+      self.database_password,
+      self.database_host,
+      self.database_port,
+      self.database_name,
+      scriptFile,
+      self.sid_or_sname
+    )
+
+  @staticmethod
+  def _get_validated_service_name(service_name, index):
     return get_validated_string_input(
     return get_validated_string_input(
-              ORACLE_DB_ID_TYPES[index] + " (" + service_name + "): ",
-              service_name,
-              ".*",
-              "Invalid " + ORACLE_DB_ID_TYPES[index] + ".",
-              False
-              )
+        ORACLE_DB_ID_TYPES[index] + " (" + service_name + "): ",
+        service_name,
+        ".*",
+        "Invalid " + ORACLE_DB_ID_TYPES[index] + ".",
+        False
+    )
+
+def createOracleConfig(options, properties, storage_type, dbId):
+  return OracleConfig(options, properties, storage_type)
+
+
+class MySQLConfig(LinuxDBMSConfig):
+  def __init__(self, options, properties, storage_type):
+    super(MySQLConfig, self).__init__(options, properties, storage_type)
+
+    #Init the database configuration data here, if any
+    self.dbms = "mysql"
+    self.dbms_full_name = "MySQL"
+    self.driver_class_name = "com.mysql.jdbc.Driver"
+    self.driver_file_name = "mysql-connector-java.jar"
+    self.driver_symlink_name = "mysql-jdbc-driver.jar"
+
+    self.database_storage_name = "Database"
+    self.database_port = DBMSConfig._init_member_with_prop_default(options, "database_port",
+                                                                   properties, JDBC_PORT_PROPERTY, "3306")
+
+    self.database_url_pattern = "jdbc:mysql://{0}:{1}/{2}"
+    self.database_url_pattern_alt = "jdbc:mysql://{0}:{1}/{2}"
+
+    self.JDBC_DRIVER_INSTALL_MSG = 'Before starting Ambari Server, ' \
+                                     'you must copy the {0} JDBC driver JAR file to {1}.'.format(
+    self.dbms_full_name, configDefaults.JAVA_SHARE_PATH)
+
+    self.init_script_file = "/var/lib/ambari-server/resources/Ambari-DDL-MySQL-CREATE.sql"
+    self.drop_tables_script_file = "/var/lib/ambari-server/resources/Ambari-DDL-MySQL-DROP.sql"
+    self.client_tool_usage_pattern = 'mysql --user={1} --password={2} {3}<{0}'
+
+  #
+  # Private implementation
+  #
+  def _reset_remote_database(self):
+    super(MySQLConfig, self)._reset_remote_database()
+
+    raise NonFatalException("Please replace '*' symbols with password before running DDL`s!")
+
+  def _is_jdbc_driver_installed(self, properties):
+    return LinuxDBMSConfig._find_jdbc_driver("*mysql*.jar")
+
+  def _configure_database_name(self):
+    self.database_name = LinuxDBMSConfig._get_validated_db_name(self.database_storage_name, self.database_name)
+    return True
+
+  def _get_remote_script_line(self, scriptFile):
+    MYSQL_INIT_SCRIPT = '/var/lib/ambari-server/resources/Ambari-DDL-MySQL-CREATE.sql'
+    MYSQL_EXEC_ARGS_WITH_USER_VARS = "mysql --host={0} --port={1} --user={2} --password={3} {4} " \
+                                     "-e\"set @schema=\'{4}\'; set @username=\'{2}\'; source {5};\""
+    MYSQL_EXEC_ARGS_WO_USER_VARS = "mysql --force --host={0} --port={1} --user={2} --password={3} --database={4} < {5} 2> /dev/null"
+
+    MYSQL_EXEC_ARGS = MYSQL_EXEC_ARGS_WO_USER_VARS if MYSQL_INIT_SCRIPT == scriptFile else MYSQL_EXEC_ARGS_WITH_USER_VARS
+    return MYSQL_EXEC_ARGS.format(
+      self.database_host,
+      self.database_port,
+      self.database_username,
+      self.database_password,
+      self.database_name,
+      scriptFile
+    )
+
+def createMySQLConfig(options, properties, storage_type, dbId):
+  return MySQLConfig(options, properties, storage_type)

+ 124 - 174
ambari-server/src/main/python/ambari_server/dbConfiguration_windows.py

@@ -21,12 +21,12 @@ limitations under the License.
 import os
 import os
 import socket
 import socket
 import string
 import string
-
 from ambari_commons.exceptions import FatalException
 from ambari_commons.exceptions import FatalException
 from ambari_commons.logging_utils import print_info_msg, print_warning_msg
 from ambari_commons.logging_utils import print_info_msg, print_warning_msg
 from ambari_commons.os_utils import search_file, run_os_command
 from ambari_commons.os_utils import search_file, run_os_command
 from ambari_commons.os_windows import WinServiceController
 from ambari_commons.os_windows import WinServiceController
 from ambari_commons.str_utils import compress_backslashes, ensure_double_backslashes
 from ambari_commons.str_utils import compress_backslashes, ensure_double_backslashes
+from ambari_server.dbConfiguration import AMBARI_DATABASE_NAME, DEFAULT_USERNAME, DBMSConfig, DbPropKeys, DbAuthenticationKeys
 from ambari_server.serverConfiguration import JDBC_DRIVER_PROPERTY, JDBC_DRIVER_PATH_PROPERTY, JDBC_URL_PROPERTY, \
 from ambari_server.serverConfiguration import JDBC_DRIVER_PROPERTY, JDBC_DRIVER_PATH_PROPERTY, JDBC_URL_PROPERTY, \
   JDBC_DATABASE_PROPERTY, JDBC_DATABASE_NAME_PROPERTY, \
   JDBC_DATABASE_PROPERTY, JDBC_DATABASE_NAME_PROPERTY, \
   JDBC_HOSTNAME_PROPERTY, JDBC_PORT_PROPERTY, JDBC_USE_INTEGRATED_AUTH_PROPERTY, JDBC_USER_NAME_PROPERTY, JDBC_PASSWORD_PROPERTY, \
   JDBC_HOSTNAME_PROPERTY, JDBC_PORT_PROPERTY, JDBC_USE_INTEGRATED_AUTH_PROPERTY, JDBC_USER_NAME_PROPERTY, JDBC_PASSWORD_PROPERTY, \
@@ -35,59 +35,35 @@ from ambari_server.serverConfiguration import JDBC_DRIVER_PROPERTY, JDBC_DRIVER_
   JDBC_RCA_HOSTNAME_PROPERTY, JDBC_RCA_PORT_PROPERTY, JDBC_RCA_USE_INTEGRATED_AUTH_PROPERTY, \
   JDBC_RCA_HOSTNAME_PROPERTY, JDBC_RCA_PORT_PROPERTY, JDBC_RCA_USE_INTEGRATED_AUTH_PROPERTY, \
   JDBC_RCA_USER_NAME_PROPERTY, JDBC_RCA_PASSWORD_FILE_PROPERTY, JDBC_RCA_PASSWORD_FILENAME, JDBC_RCA_PASSWORD_ALIAS, \
   JDBC_RCA_USER_NAME_PROPERTY, JDBC_RCA_PASSWORD_FILE_PROPERTY, JDBC_RCA_PASSWORD_FILENAME, JDBC_RCA_PASSWORD_ALIAS, \
   PERSISTENCE_TYPE_PROPERTY, \
   PERSISTENCE_TYPE_PROPERTY, \
-  PRESS_ENTER_MSG
+  get_value_from_properties, configDefaults
 from ambari_server.setupSecurity import encrypt_password, store_password_file
 from ambari_server.setupSecurity import encrypt_password, store_password_file
-from dbConfiguration import DBMSConfig, DB_STATUS_RUNNING_DEFAULT
-from userInput import get_validated_string_input
+from ambari_server.userInput import get_validated_string_input
 
 
-#Import the SQL Server libraries
 
 
 # SQL Server settings
 # SQL Server settings
-DBPATH = 'C:\\Program Files\\Microsoft SQL Server\\MSSQL12.SQLEXPRESS\\MSSQL\\DATA\\'
-# DBPATH = 'C:\\Program Files\\Microsoft SQL Server\\MSSQL10_50.MSSQLSERVER\\MSSQL\\DATA\\'
-
-DATABASE_DBMS = "sqlserver"
-DATABASE_DRIVER_NAME = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
-LOCAL_DATABASE_SERVER = "localhost\\SQLEXPRESS"
-AMBARI_DATABASE_NAME = "ambari"
-
-class DbPropKeys:
-  def __init__(self, i_dbms_key, i_driver_key, i_server_key, i_port_key, i_db_name_key, i_db_url_key):
-    self.reset(i_dbms_key, i_driver_key, i_server_key, i_port_key, i_db_name_key, i_db_url_key)
-    pass
-
-  def reset(self, i_dbms_key, i_driver_key, i_server_key, i_port_key, i_db_name_key, i_db_url_key):
-    self.dbms_key = i_dbms_key
-    self.driver_key = i_driver_key
-    self.server_key = i_server_key
-    self.port_key = i_port_key
-    self.db_name_key = i_db_name_key
-    self.db_url_key = i_db_url_key
-    pass
+DATABASE_DBMS_SQLSERVER = "sqlserver"
+DATABASE_DRIVER_NAME_SQLSERVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
+DATABASE_SERVER_SQLSERVER_DEFAULT = "localhost\\SQLEXPRESS"
 
 
-class AuthenticationKeys:
+class SqlServerAuthenticationKeys(DbAuthenticationKeys):
   def __init__(self, i_integrated_auth_key, i_user_name_key, i_password_key, i_password_alias, i_password_filename):
   def __init__(self, i_integrated_auth_key, i_user_name_key, i_password_key, i_password_alias, i_password_filename):
-    self.reset(i_integrated_auth_key, i_user_name_key, i_password_key, i_password_alias, i_password_filename)
-    pass
-
-  def reset(self, i_integrated_auth_key, i_user_name_key, i_password_key, i_password_alias, i_password_filename):
     self.integrated_auth_key = i_integrated_auth_key
     self.integrated_auth_key = i_integrated_auth_key
-    self.user_name_key = i_user_name_key
-    self.password_key = i_password_key
-    self.password_alias = i_password_alias
-    self.password_filename = i_password_filename
-    pass
+    DbAuthenticationKeys.__init__(self, i_user_name_key, i_password_key, i_password_alias, i_password_filename)
 
 
+#
 # SQL Server configuration and setup
 # SQL Server configuration and setup
+#
 class SQLServerConfig(DBMSConfig):
 class SQLServerConfig(DBMSConfig):
-  def __init__(self, options, properties):
-    super(SQLServerConfig, self).__init__(options, properties)
+  def __init__(self, options, properties, storage_type):
+    super(SQLServerConfig, self).__init__(options, properties, storage_type)
 
 
     """
     """
     #Just load the defaults. The derived classes will be able to modify them later
     #Just load the defaults. The derived classes will be able to modify them later
     """
     """
-    self.dbms = DATABASE_DBMS
-    self.driver_name = DATABASE_DRIVER_NAME
+    self.dbms = DATABASE_DBMS_SQLSERVER
+    self.driver_class_name = DATABASE_DRIVER_NAME_SQLSERVER
+
+    self.JDBC_DRIVER_INSTALL_MSG = 'Before starting Ambari Server, you must install the SQL Server JDBC driver.'
 
 
     # The values from options supersede the values from properties
     # The values from options supersede the values from properties
     self.database_host = options.database_host if options.database_host is not None and options.database_host is not "" else \
     self.database_host = options.database_host if options.database_host is not None and options.database_host is not "" else \
@@ -98,27 +74,26 @@ class SQLServerConfig(DBMSConfig):
       else:
       else:
         self.database_host = compress_backslashes(self.database_host)
         self.database_host = compress_backslashes(self.database_host)
     except:
     except:
-      self.database_host = "localhost\\SQLEXPRESS"
+      self.database_host = DATABASE_SERVER_SQLSERVER_DEFAULT
       pass
       pass
-    self.database_port = options.database_port if options.database_port is not None and options.database_port is not "" else \
-        properties.get_property(self.dbPropKeys.port_key)
-    self.database_name = options.database_name if options.database_name is not None and options.database_name is not "" else \
-        properties.get_property(self.dbPropKeys.db_name_key)
-
-    self.use_windows_authentication = options.database_windows_auth if options.database_windows_auth is True else \
-        properties.get_property(self.dbAuthKeys.integrated_auth_key)
-    self.database_username = options.database_username if options.database_username is not None and options.database_username is not "" \
-        else properties.get_property(self.dbAuthKeys.user_name_key)
+    self.database_port = DBMSConfig._init_member_with_prop_default(options, "database_port",
+                                                                   properties, self.dbPropKeys.port_key, "1433")
+    self.database_name = DBMSConfig._init_member_with_prop_default(options, "database_name",
+                                                                   properties, self.dbPropKeys.db_name_key, configDefaults.DEFAULT_DB_NAME)
+
+    self.use_windows_authentication = DBMSConfig._init_member_with_prop_default(options, "database_windows_auth",
+        properties, self.dbAuthKeys.integrated_auth_key, False)
+    self.database_username = DBMSConfig._init_member_with_prop_default(options, "database_username",
+                                                                       properties, self.dbAuthKeys.user_name_key, DEFAULT_USERNAME)
     self.database_password = options.database_password if options.database_password is not None and options.database_password is not "" \
     self.database_password = options.database_password if options.database_password is not None and options.database_password is not "" \
-        else ""
-    self.password_file = properties[self.dbAuthKeys.password_key]
+      else ""
+    if not self.database_password:
+      self.database_password = DBMSConfig._read_password_from_properties(properties)
 
 
     self.database_url = self._build_sql_server_connection_string()
     self.database_url = self._build_sql_server_connection_string()
 
 
     self.persistence_property = None
     self.persistence_property = None
 
 
-    self.db_title = ""
-
     self.env_var_db_name = ""
     self.env_var_db_name = ""
     self.env_var_db_log_name = ""
     self.env_var_db_log_name = ""
     self.env_var_db_owner = ""
     self.env_var_db_owner = ""
@@ -132,137 +107,113 @@ class SQLServerConfig(DBMSConfig):
   def _is_local_database(self):
   def _is_local_database(self):
     return False
     return False
 
 
-  def _is_jdbc_driver_installed(self, properties):
-    """
-    #Attempt to load the sqljdbc4.jar and sqljdbc_auth.dll. This will automatically scan the PATH.
-    :param None
-    :rtype : bool
-    """
-    paths = "." + os.pathsep + os.environ["PATH"]
-
-    # Find the jar by attempting to load it as a resource dll
-    driver_path = search_file("sqljdbc4.jar", paths)
-    if not driver_path:
-      return 0
-
-    auth_dll_path = search_file("sqljdbc_auth.dll", paths)
-    if not auth_dll_path:
-      return 0
-
-    try:
-      driver_path = properties[JDBC_DRIVER_PATH_PROPERTY]
-      if driver_path is None or driver_path is "":
-        return 0
-    except Exception:
-      # No such attribute set
-      return 0
-
-    return 1
-
-  def get_jdbc_driver_path(self):
-    paths = "." + os.pathsep + os.environ["PATH"]
-
-    # Find the jar by attempting to load it as a resource dll
-    driver_path = search_file("sqljdbc4.jar", paths)
-    return driver_path
-
-  def configure_database_password(showDefault=True):
+  def _configure_database_password(showDefault=True):
     #No password needed, using SQL Server integrated authentication
     #No password needed, using SQL Server integrated authentication
     pass
     pass
 
 
   def _prompt_db_properties(self):
   def _prompt_db_properties(self):
-    if self.silent:
-      # All the settings are supposed to be retrieved from the command-line parameters
-      return True
-
-    #prompt for SQL Server host and instance name
-    hostname_prompt = "SQL Server host and instance for the {} database: ({}) ".format(self.db_title, self.database_host)
-    self.database_host = get_validated_string_input(hostname_prompt, self.database_host, None, None, False, True)
-
-    #prompt for SQL Server authentication method
-    if (not self.use_windows_authentication is None and self.use_windows_authentication.lower() == "true") or \
-            self.database_username is None or self.database_username == "":
-      auth_option_default = '1'
-    else:
-      auth_option_default = '2'
-
-    user_prompt = \
-      "[1] - Use SQL Server integrated authentication\n[2] - Use username+password authentication\n" \
-      "Enter choice ({}): ".format(auth_option_default)
-    auth_option = get_validated_string_input(user_prompt,
-                                             auth_option_default,
-                                             "^[12]$",
-                                             "Invalid number.",
-                                             False
-    )
-    if str(auth_option) == '1':
-      self.use_windows_authentication = True
-      self.database_password = None
-    else:
-      self.use_windows_authentication = False
+    if self.must_set_database_options:
+      #prompt for SQL Server host and instance name
+      hostname_prompt = "SQL Server host and instance for the {0} database: ({1}) ".format(self.db_title, self.database_host)
+      self.database_host = get_validated_string_input(hostname_prompt, self.database_host, None, None, False, True)
+
+      #prompt for SQL Server authentication method
+      if (not self.use_windows_authentication is None and self.use_windows_authentication.lower() == "true") or \
+              self.database_username is None or self.database_username == "":
+        auth_option_default = '1'
+      else:
+        auth_option_default = '2'
+
+      user_prompt = \
+        "[1] - Use SQL Server integrated authentication\n[2] - Use username+password authentication\n" \
+        "Enter choice ({0}): ".format(auth_option_default)
+      auth_option = get_validated_string_input(user_prompt,
+                                               auth_option_default,
+                                               "^[12]$",
+                                               "Invalid number.",
+                                               False
+      )
+      if str(auth_option) == '1':
+        self.use_windows_authentication = True
+        self.database_password = None
+      else:
+        self.use_windows_authentication = False
 
 
-      user_prompt = "SQL Server user name for the {} database: ({}) ".format(self.db_title, self.database_username)
-      username = get_validated_string_input(user_prompt, self.database_username, None, "User name", False,
-                                            False)
-      self.database_username = username
+        user_prompt = "SQL Server user name for the {0} database: ({1}) ".format(self.db_title, self.database_username)
+        username = get_validated_string_input(user_prompt, self.database_username, None, "User name", False,
+                                              False)
+        self.database_username = username
 
 
-      user_prompt = "SQL Server password for the {} database: ".format(self.db_title)
-      password = get_validated_string_input(user_prompt, "", None, "Password", True, False)
-      self.database_password = password
+        user_prompt = "SQL Server password for the {0} database: ".format(self.db_title)
+        password = get_validated_string_input(user_prompt, "", None, "Password", True, False)
+        self.database_password = password
 
 
     self.database_url = self._build_sql_server_connection_string()
     self.database_url = self._build_sql_server_connection_string()
 
 
     return True
     return True
 
 
   def _setup_remote_server(self, properties):
   def _setup_remote_server(self, properties):
-    properties.removeOldProp(self.dbPropKeys.port_key)
-    properties.removeOldProp(self.dbAuthKeys.integrated_auth_key)
-    properties.removeOldProp(self.dbAuthKeys.user_name_key)
-    properties.removeOldProp(self.dbAuthKeys.password_key)
+    if self.ensure_jdbc_driver_installed(properties):
+      properties.removeOldProp(self.dbPropKeys.port_key)
+      properties.removeOldProp(self.dbAuthKeys.integrated_auth_key)
+      properties.removeOldProp(self.dbAuthKeys.user_name_key)
+      properties.removeOldProp(self.dbAuthKeys.password_key)
 
 
-    properties.process_pair(self.persistence_property, 'remote')
+      properties.process_pair(self.persistence_property, 'remote')
 
 
-    properties.process_pair(self.dbPropKeys.dbms_key, self.dbms)
-    properties.process_pair(self.dbPropKeys.driver_key, self.driver_name)
-    properties.process_pair(self.dbPropKeys.server_key, ensure_double_backslashes(self.database_host))
-    if self.database_port is not None and self.database_port != "":
-      properties.process_pair(self.dbPropKeys.port_key, self.database_port)
-    properties.process_pair(self.dbPropKeys.db_name_key, self.database_name)
+      properties.process_pair(self.dbPropKeys.dbms_key, self.dbms)
+      properties.process_pair(self.dbPropKeys.driver_key, self.driver_class_name)
+      properties.process_pair(self.dbPropKeys.server_key, ensure_double_backslashes(self.database_host))
+      if self.database_port is not None and self.database_port != "":
+        properties.process_pair(self.dbPropKeys.port_key, self.database_port)
+      properties.process_pair(self.dbPropKeys.db_name_key, self.database_name)
 
 
-    self._store_db_auth_config(properties, self.dbAuthKeys)
+      self._store_db_auth_config(properties, self.dbAuthKeys)
 
 
-    properties.process_pair(self.dbPropKeys.db_url_key, self.database_url)
+      properties.process_pair(self.dbPropKeys.db_url_key, self.database_url)
     pass
     pass
 
 
   def _setup_remote_database(self):
   def _setup_remote_database(self):
-    print 'Populating {} database structure...'.format(self.db_title)
+    print 'Populating the {0} database structure...'.format(self.db_title)
 
 
     self._populate_database_structure()
     self._populate_database_structure()
 
 
   def _reset_remote_database(self):
   def _reset_remote_database(self):
-    print 'Resetting {} database structure...'.format(self.db_title)
+    print 'Resetting the {0} database structure...'.format(self.db_title)
 
 
     self._populate_database_structure()
     self._populate_database_structure()
 
 
-  def _prompt_jdbc_driver_install(self, properties):
-    result = False
-    msg = 'Before starting Ambari Server, you must install the SQL Server JDBC driver.'
+  def _is_jdbc_driver_installed(self, properties):
+    """
+    #Attempt to find the sqljdbc4.jar and sqljdbc_auth.dll by scanning the PATH.
+    :param None
+    :rtype : bool
+    """
+    paths = "." + os.pathsep + os.environ["PATH"]
 
 
-    if not self.silent:
-      print_warning_msg(msg)
-      raw_input(PRESS_ENTER_MSG)
-      result = self._is_jdbc_driver_installed(properties)
-    return (result, msg)
+    # Find the jar by attempting to load it as a resource dll
+    driver_path = search_file("sqljdbc4.jar", paths)
+    if not driver_path:
+      return 0
+
+    auth_dll_path = search_file("sqljdbc_auth.dll", paths)
+    if not auth_dll_path:
+      return 0
 
 
-  def _install_jdbc_driver(self, options, properties):
     try:
     try:
       driver_path = properties[JDBC_DRIVER_PATH_PROPERTY]
       driver_path = properties[JDBC_DRIVER_PATH_PROPERTY]
+      if driver_path is None or driver_path is "":
+        return 0
     except Exception:
     except Exception:
       # No such attribute set
       # No such attribute set
-      driver_path = None
+      return 0
 
 
+    return 1
+
+  def _install_jdbc_driver(self, properties, files_list):
+    driver_path = get_value_from_properties(properties, JDBC_DRIVER_PATH_PROPERTY, None)
     if driver_path is None or driver_path == "":
     if driver_path is None or driver_path == "":
-      driver_path = self.get_jdbc_driver_path()
+      driver_path = self._get_jdbc_driver_path()
 
 
       properties.process_pair(JDBC_DRIVER_PATH_PROPERTY, driver_path)
       properties.process_pair(JDBC_DRIVER_PATH_PROPERTY, driver_path)
       return True
       return True
@@ -283,7 +234,7 @@ class SQLServerConfig(DBMSConfig):
       sql_svc_name = "MSSQL$" + db_host_components[1]
       sql_svc_name = "MSSQL$" + db_host_components[1]
 
 
     if db_machine == "localhost" or db_machine.lower() == os.getenv("COMPUTERNAME").lower() or \
     if db_machine == "localhost" or db_machine.lower() == os.getenv("COMPUTERNAME").lower() or \
-      db_machine.lower() == socket.getfqdn().lower():
+            db_machine.lower() == socket.getfqdn().lower():
       #TODO: Configure the SQL Server service name in ambari.properties
       #TODO: Configure the SQL Server service name in ambari.properties
       ret = WinServiceController.EnsureServiceIsStarted(sql_svc_name)
       ret = WinServiceController.EnsureServiceIsStarted(sql_svc_name)
       if 0 != ret:
       if 0 != ret:
@@ -298,11 +249,18 @@ class SQLServerConfig(DBMSConfig):
     pass
     pass
 
 
 
 
+  def _get_jdbc_driver_path(self):
+    paths = "." + os.pathsep + os.environ["PATH"]
+
+    # Find the jar in the PATH
+    driver_path = search_file("sqljdbc4.jar", paths)
+    return driver_path
+
   def _build_sql_server_connection_string(self):
   def _build_sql_server_connection_string(self):
-    databaseUrl = "jdbc:sqlserver://{}".format(ensure_double_backslashes(self.database_host))
+    databaseUrl = "jdbc:sqlserver://{0}".format(ensure_double_backslashes(self.database_host))
     if self.database_port is not None and self.database_port != "":
     if self.database_port is not None and self.database_port != "":
-      databaseUrl += ":{}".format(self.database_port)
-    databaseUrl += ";databaseName={}".format(self.database_name)
+      databaseUrl += ":{0}".format(self.database_port)
+    databaseUrl += ";databaseName={0}".format(self.database_name)
     if(self.use_windows_authentication):
     if(self.use_windows_authentication):
       databaseUrl += ";integratedSecurity=true"
       databaseUrl += ";integratedSecurity=true"
     #No need to append the username and password, the Ambari server adds them by itself when connecting to the database
     #No need to append the username and password, the Ambari server adds them by itself when connecting to the database
@@ -340,18 +298,20 @@ class SQLServerConfig(DBMSConfig):
 
 
   @staticmethod
   @staticmethod
   def _execute_db_script(databaseHost, databaseScript):
   def _execute_db_script(databaseHost, databaseScript):
-    dbCmd = 'sqlcmd -S {} -i {}'.format(databaseHost, databaseScript)
+    dbCmd = 'sqlcmd -S {0} -i {1}'.format(databaseHost, databaseScript)
     retCode, outData, errData = run_os_command(['cmd', '/C', dbCmd])
     retCode, outData, errData = run_os_command(['cmd', '/C', dbCmd])
     if not retCode == 0:
     if not retCode == 0:
-      err = 'Running database create script failed. Error output: {} Output: {} Exiting.'.format(errData, outData)
+      err = 'Running database create script failed. Error output: {0} Output: {1} Exiting.'.format(errData, outData)
       raise FatalException(retCode, err)
       raise FatalException(retCode, err)
     print_info_msg("sqlcmd output:")
     print_info_msg("sqlcmd output:")
     print_info_msg(outData)
     print_info_msg(outData)
     pass
     pass
 
 
+#
 # SQL Server Ambari database configuration and setup
 # SQL Server Ambari database configuration and setup
+#
 class SQLServerAmbariDBConfig(SQLServerConfig):
 class SQLServerAmbariDBConfig(SQLServerConfig):
-  def __init__(self, options, properties):
+  def __init__(self, options, properties, storage_type):
     self.dbPropKeys = DbPropKeys(
     self.dbPropKeys = DbPropKeys(
       JDBC_DATABASE_PROPERTY,
       JDBC_DATABASE_PROPERTY,
       JDBC_DRIVER_PROPERTY,
       JDBC_DRIVER_PROPERTY,
@@ -359,7 +319,7 @@ class SQLServerAmbariDBConfig(SQLServerConfig):
       JDBC_PORT_PROPERTY,
       JDBC_PORT_PROPERTY,
       JDBC_DATABASE_NAME_PROPERTY,
       JDBC_DATABASE_NAME_PROPERTY,
       JDBC_URL_PROPERTY)
       JDBC_URL_PROPERTY)
-    self.dbAuthKeys = AuthenticationKeys(
+    self.dbAuthKeys = SqlServerAuthenticationKeys(
       JDBC_USE_INTEGRATED_AUTH_PROPERTY,
       JDBC_USE_INTEGRATED_AUTH_PROPERTY,
       JDBC_USER_NAME_PROPERTY,
       JDBC_USER_NAME_PROPERTY,
       JDBC_PASSWORD_PROPERTY,
       JDBC_PASSWORD_PROPERTY,
@@ -367,15 +327,13 @@ class SQLServerAmbariDBConfig(SQLServerConfig):
       JDBC_PASSWORD_FILENAME
       JDBC_PASSWORD_FILENAME
     )
     )
 
 
-    super(SQLServerAmbariDBConfig, self).__init__(options, properties)
+    super(SQLServerAmbariDBConfig, self).__init__(options, properties, storage_type)
 
 
     if self.database_name is None or self.database_name is "":
     if self.database_name is None or self.database_name is "":
       self.database_name = AMBARI_DATABASE_NAME
       self.database_name = AMBARI_DATABASE_NAME
 
 
     self.persistence_property = PERSISTENCE_TYPE_PROPERTY
     self.persistence_property = PERSISTENCE_TYPE_PROPERTY
 
 
-    self.db_title = "ambari"
-
     self.env_var_db_name ='AMBARIDBNAME'
     self.env_var_db_name ='AMBARIDBNAME'
     self.env_var_db_log_name = 'AMBARIDBLOGNAME'
     self.env_var_db_log_name = 'AMBARIDBLOGNAME'
     self.env_var_db_owner = 'AMBARIDBOWNER'
     self.env_var_db_owner = 'AMBARIDBOWNER'
@@ -394,13 +352,12 @@ class SQLServerAmbariDBConfig(SQLServerConfig):
   def _setup_remote_server(self, properties):
   def _setup_remote_server(self, properties):
     super(SQLServerAmbariDBConfig, self)._setup_remote_server(properties)
     super(SQLServerAmbariDBConfig, self)._setup_remote_server(properties)
 
 
-    properties.process_pair(JDBC_RCA_DRIVER_PROPERTY, self.driver_name)
+    properties.process_pair(JDBC_RCA_DRIVER_PROPERTY, self.driver_class_name)
     properties.process_pair(JDBC_RCA_HOSTNAME_PROPERTY, ensure_double_backslashes(self.database_host))
     properties.process_pair(JDBC_RCA_HOSTNAME_PROPERTY, ensure_double_backslashes(self.database_host))
     if self.database_port is not None and self.database_port != "":
     if self.database_port is not None and self.database_port != "":
       properties.process_pair(JDBC_RCA_PORT_PROPERTY, self.database_port)
       properties.process_pair(JDBC_RCA_PORT_PROPERTY, self.database_port)
-    properties.process_pair(JDBC_RCA_SCHEMA_PROPERTY, self.database_name)
 
 
-    authKeys = AuthenticationKeys(
+    authKeys = SqlServerAuthenticationKeys(
       JDBC_RCA_USE_INTEGRATED_AUTH_PROPERTY,
       JDBC_RCA_USE_INTEGRATED_AUTH_PROPERTY,
       JDBC_RCA_USER_NAME_PROPERTY,
       JDBC_RCA_USER_NAME_PROPERTY,
       JDBC_RCA_PASSWORD_FILE_PROPERTY,
       JDBC_RCA_PASSWORD_FILE_PROPERTY,
@@ -412,13 +369,6 @@ class SQLServerAmbariDBConfig(SQLServerConfig):
     properties.process_pair(JDBC_RCA_URL_PROPERTY, self.database_url)
     properties.process_pair(JDBC_RCA_URL_PROPERTY, self.database_url)
     pass
     pass
 
 
-# SQL Server database
-class SQLServerDatabase:
-  def __init__(self):
-    #Init the database connection here
-    pass
 
 
-  def get_running_status(self):
-    #if the connection is active, return running
-    #else return stopped
-    return DB_STATUS_RUNNING_DEFAULT
+def createSQLServerConfig(options, properties, storage_type, dbId):
+  return SQLServerAmbariDBConfig(options, properties, storage_type)

+ 401 - 48
ambari-server/src/main/python/ambari_server/serverConfiguration.py

@@ -23,21 +23,27 @@ import glob
 import os
 import os
 import re
 import re
 import shutil
 import shutil
+import stat
 import string
 import string
+import sys
 import tempfile
 import tempfile
 
 
 from ambari_commons.exceptions import FatalException
 from ambari_commons.exceptions import FatalException
 from ambari_commons.os_check import OSCheck, OSConst
 from ambari_commons.os_check import OSCheck, OSConst
 from ambari_commons.os_family_impl import OsFamilyImpl
 from ambari_commons.os_family_impl import OsFamilyImpl
 from ambari_commons.os_utils import run_os_command, search_file
 from ambari_commons.os_utils import run_os_command, search_file
-from ambari_commons.logging_utils import print_warning_msg, print_info_msg, print_error_msg
-from properties import Properties
+from ambari_commons.logging_utils import get_debug_mode, print_info_msg, print_warning_msg, print_error_msg, \
+  set_debug_mode
+from ambari_server.properties import Properties
+from ambari_server.userInput import get_validated_string_input
+from ambari_server.utils import compare_versions, locate_file
 
 
 
 
 OS_VERSION = OSCheck().get_os_major_version()
 OS_VERSION = OSCheck().get_os_major_version()
 OS_TYPE = OSCheck.get_os_type()
 OS_TYPE = OSCheck.get_os_type()
 OS_FAMILY = OSCheck.get_os_family()
 OS_FAMILY = OSCheck.get_os_family()
 
 
+PID_NAME = "ambari-server.pid"
 
 
 # Non-root user setup commands
 # Non-root user setup commands
 NR_USER_PROPERTY = "ambari-server.user"
 NR_USER_PROPERTY = "ambari-server.user"
@@ -56,10 +62,6 @@ BOOTSTRAP_DIR_PROPERTY = "bootstrap.dir"
 
 
 AMBARI_CONF_VAR = "AMBARI_CONF_DIR"
 AMBARI_CONF_VAR = "AMBARI_CONF_DIR"
 AMBARI_PROPERTIES_FILE = "ambari.properties"
 AMBARI_PROPERTIES_FILE = "ambari.properties"
-if OSCheck.is_windows_family():
-  AMBARI_PROPERTIES_BACKUP_FILE = "ambari.properties.backup"
-else:
-  AMBARI_PROPERTIES_BACKUP_FILE = "ambari.properties.rpmsave"
 
 
 GET_FQDN_SERVICE_URL = "server.fqdn.service.url"
 GET_FQDN_SERVICE_URL = "server.fqdn.service.url"
 
 
@@ -85,10 +87,10 @@ JDK_NAMES = ["jdk-7u67-linux-x64.tar.gz", "jdk-6u31-linux-x64.bin"]
 
 
 #JCE Policy files
 #JCE Policy files
 JCE_POLICY_FILENAMES = ["UnlimitedJCEPolicyJDK7.zip", "jce_policy-6.zip"]
 JCE_POLICY_FILENAMES = ["UnlimitedJCEPolicyJDK7.zip", "jce_policy-6.zip"]
-JCE_DOWNLOAD_CMD = "curl -o {0} {1}"
-JCE_MIN_FILESIZE = 5000
 
 
 # JDBC
 # JDBC
+JDBC_PATTERNS = {"oracle": "*ojdbc*.jar", "mysql": "*mysql*.jar"}
+
 #TODO property used incorrectly in local case, it was meant to be dbms name, not postgres database name,
 #TODO property used incorrectly in local case, it was meant to be dbms name, not postgres database name,
 # has workaround for now, as we don't need dbms name if persistence_type=local
 # has workaround for now, as we don't need dbms name if persistence_type=local
 JDBC_DATABASE_PROPERTY = "server.jdbc.database"                 # E.g., embedded|oracle|mysql|postgres|sqlserver
 JDBC_DATABASE_PROPERTY = "server.jdbc.database"                 # E.g., embedded|oracle|mysql|postgres|sqlserver
@@ -105,6 +107,8 @@ JDBC_RCA_PASSWORD_FILENAME = "rca_password.dat"
 CLIENT_API_PORT_PROPERTY = "client.api.port"
 CLIENT_API_PORT_PROPERTY = "client.api.port"
 CLIENT_API_PORT = "8080"
 CLIENT_API_PORT = "8080"
 
 
+SERVER_VERSION_FILE_PATH = "server.version.file"
+
 PERSISTENCE_TYPE_PROPERTY = "server.persistence.type"
 PERSISTENCE_TYPE_PROPERTY = "server.persistence.type"
 JDBC_DRIVER_PROPERTY = "server.jdbc.driver"
 JDBC_DRIVER_PROPERTY = "server.jdbc.driver"
 JDBC_DRIVER_PATH_PROPERTY = "server.jdbc.driver.path"
 JDBC_DRIVER_PATH_PROPERTY = "server.jdbc.driver.path"
@@ -122,12 +126,16 @@ JDBC_RCA_PASSWORD_FILE_PROPERTY = "server.jdbc.rca.user.passwd"
 
 
 JDBC_RCA_PASSWORD_ALIAS = "ambari.db.password"
 JDBC_RCA_PASSWORD_ALIAS = "ambari.db.password"
 
 
-#Windows-specific settings
+### # Windows-specific # ###
 
 
 JDBC_USE_INTEGRATED_AUTH_PROPERTY = "server.jdbc.use.integrated.auth"
 JDBC_USE_INTEGRATED_AUTH_PROPERTY = "server.jdbc.use.integrated.auth"
 
 
 JDBC_RCA_USE_INTEGRATED_AUTH_PROPERTY = "server.jdbc.rca.use.integrated.auth"
 JDBC_RCA_USE_INTEGRATED_AUTH_PROPERTY = "server.jdbc.rca.use.integrated.auth"
 
 
+### # End Windows-specific # ###
+
+SERVICE_USERNAME_KEY = "TMP_AMBARI_USERNAME"
+SERVICE_PASSWORD_KEY = "TMP_AMBARI_PASSWORD"
 
 
 # resources repo configuration
 # resources repo configuration
 RESOURCES_DIR_PROPERTY = "resources.dir"
 RESOURCES_DIR_PROPERTY = "resources.dir"
@@ -135,11 +143,26 @@ RESOURCES_DIR_DEFAULT = "resources"
 
 
 # stack repo upgrade
 # stack repo upgrade
 STACK_LOCATION_KEY = 'metadata.path'
 STACK_LOCATION_KEY = 'metadata.path'
-STACK_LOCATION_DEFAULT = "resources" + os.sep + "stacks"
+
+# LDAP security
+IS_LDAP_CONFIGURED = "ambari.ldap.isConfigured"
+LDAP_MGR_PASSWORD_ALIAS = "ambari.ldap.manager.password"
+LDAP_MGR_PASSWORD_PROPERTY = "authentication.ldap.managerPassword"
+LDAP_MGR_PASSWORD_FILENAME = "ldap-password.dat"
+LDAP_MGR_USERNAME_PROPERTY = "authentication.ldap.managerDn"
+LDAP_PRIMARY_URL_PROPERTY = "authentication.ldap.primaryUrl"
+
+# SSL truststore
+SSL_TRUSTSTORE_PASSWORD_ALIAS = "ambari.ssl.trustStore.password"
+SSL_TRUSTSTORE_PATH_PROPERTY = "ssl.trustStore.path"
+SSL_TRUSTSTORE_PASSWORD_PROPERTY = "ssl.trustStore.password"
+SSL_TRUSTSTORE_TYPE_PROPERTY = "ssl.trustStore.type"
 
 
 # JDK
 # JDK
 JDK_RELEASES="java.releases"
 JDK_RELEASES="java.releases"
 
 
+VIEWS_DIR_PROPERTY = "views.dir"
+
 #Common setup or upgrade message
 #Common setup or upgrade message
 SETUP_OR_UPGRADE_MSG = "- If this is a new setup, then run the \"ambari-server setup\" command to create the user\n" \
 SETUP_OR_UPGRADE_MSG = "- If this is a new setup, then run the \"ambari-server setup\" command to create the user\n" \
                        "- If this is an upgrade of an existing setup, run the \"ambari-server upgrade\" command.\n" \
                        "- If this is an upgrade of an existing setup, run the \"ambari-server upgrade\" command.\n" \
@@ -147,7 +170,6 @@ SETUP_OR_UPGRADE_MSG = "- If this is a new setup, then run the \"ambari-server s
 
 
 DEFAULT_DB_NAME = "ambari"
 DEFAULT_DB_NAME = "ambari"
 
 
-
 class ServerConfigDefaults(object):
 class ServerConfigDefaults(object):
   def __init__(self):
   def __init__(self):
     self.JAVA_SHARE_PATH = "/usr/share/java"
     self.JAVA_SHARE_PATH = "/usr/share/java"
@@ -165,11 +187,14 @@ class ServerConfigDefaults(object):
     self.PID_DIR = os.sep + os.path.join("var", "run", "ambari-server")
     self.PID_DIR = os.sep + os.path.join("var", "run", "ambari-server")
     self.DEFAULT_LIBS_DIR = ""
     self.DEFAULT_LIBS_DIR = ""
 
 
+    self.AMBARI_PROPERTIES_BACKUP_FILE = ""
+
     # ownership/permissions mapping
     # ownership/permissions mapping
     # path - permissions - user - group - recursive
     # path - permissions - user - group - recursive
     # Rules are executed in the same order as they are listed
     # Rules are executed in the same order as they are listed
     # {0} in user/group will be replaced by customized ambari-server username
     # {0} in user/group will be replaced by customized ambari-server username
     self.NR_ADJUST_OWNERSHIP_LIST = []
     self.NR_ADJUST_OWNERSHIP_LIST = []
+    self.NR_USERADD_CMD = ""
 
 
     self.MASTER_KEY_FILE_PERMISSIONS = "600"
     self.MASTER_KEY_FILE_PERMISSIONS = "600"
     self.CREDENTIALS_STORE_FILE_PERMISSIONS = "600"
     self.CREDENTIALS_STORE_FILE_PERMISSIONS = "600"
@@ -177,11 +202,19 @@ class ServerConfigDefaults(object):
 
 
     self.DEFAULT_DB_NAME = "ambari"
     self.DEFAULT_DB_NAME = "ambari"
 
 
+    self.STACK_LOCATION_DEFAULT = ""
+
     self.DEFAULT_VIEWS_DIR = ""
     self.DEFAULT_VIEWS_DIR = ""
 
 
     #keytool commands
     #keytool commands
     self.keytool_bin = ""
     self.keytool_bin = ""
 
 
+    #Standard messages
+    self.MESSAGE_ERROR_SETUP_NOT_ROOT = ""
+    self.MESSAGE_ERROR_RESET_NOT_ROOT = ""
+    self.MESSAGE_ERROR_UPGRADE_NOT_ROOT = ""
+    self.MESSAGE_CHECK_FIREWALL = ""
+
 @OsFamilyImpl(os_family=OSConst.WINSRV_FAMILY)
 @OsFamilyImpl(os_family=OSConst.WINSRV_FAMILY)
 class ServerConfigDefaultsWindows(ServerConfigDefaults):
 class ServerConfigDefaultsWindows(ServerConfigDefaults):
   def __init__(self):
   def __init__(self):
@@ -194,6 +227,8 @@ class ServerConfigDefaultsWindows(ServerConfigDefaults):
     self.DEFAULT_CONF_DIR = "conf"
     self.DEFAULT_CONF_DIR = "conf"
     self.DEFAULT_LIBS_DIR = "lib"
     self.DEFAULT_LIBS_DIR = "lib"
 
 
+    self.AMBARI_PROPERTIES_BACKUP_FILE = "ambari.properties.backup"
+
     # ownership/permissions mapping
     # ownership/permissions mapping
     # path - permissions - user - group - recursive
     # path - permissions - user - group - recursive
     # Rules are executed in the same order as they are listed
     # Rules are executed in the same order as they are listed
@@ -218,12 +253,21 @@ class ServerConfigDefaultsWindows(ServerConfigDefaults):
       # Also, /etc/ambari-server/conf/password.dat
       # Also, /etc/ambari-server/conf/password.dat
       # is generated later at store_password_file
       # is generated later at store_password_file
     ]
     ]
+    self.NR_USERADD_CMD = "cmd /C net user {0} {1} /ADD"
+
+    self.STACK_LOCATION_DEFAULT = "resources\\stacks"
 
 
     self.DEFAULT_VIEWS_DIR = "resources\\views"
     self.DEFAULT_VIEWS_DIR = "resources\\views"
 
 
     #keytool commands
     #keytool commands
     self.keytool_bin = "keytool.exe"
     self.keytool_bin = "keytool.exe"
 
 
+    #Standard messages
+    self.MESSAGE_ERROR_SETUP_NOT_ROOT = "Ambari-server setup must be run with administrator-level privileges"
+    self.MESSAGE_ERROR_RESET_NOT_ROOT = "Ambari-server reset must be run with administrator-level privileges"
+    self.MESSAGE_ERROR_UPGRADE_NOT_ROOT = "Ambari-server upgrade must be run with administrator-level privileges"
+    self.MESSAGE_CHECK_FIREWALL = "Checking firewall status..."
+
 @OsFamilyImpl(os_family=OsFamilyImpl.DEFAULT)
 @OsFamilyImpl(os_family=OsFamilyImpl.DEFAULT)
 class ServerConfigDefaultsLinux(ServerConfigDefaults):
 class ServerConfigDefaultsLinux(ServerConfigDefaults):
   def __init__(self):
   def __init__(self):
@@ -237,6 +281,8 @@ class ServerConfigDefaultsLinux(ServerConfigDefaults):
     self.DEFAULT_CONF_DIR = "/etc/ambari-server/conf"
     self.DEFAULT_CONF_DIR = "/etc/ambari-server/conf"
     self.DEFAULT_LIBS_DIR = "/usr/lib/ambari-server"
     self.DEFAULT_LIBS_DIR = "/usr/lib/ambari-server"
 
 
+    self.AMBARI_PROPERTIES_BACKUP_FILE = "ambari.properties.rpmsave"
+
     # ownership/permissions mapping
     # ownership/permissions mapping
     # path - permissions - user - group - recursive
     # path - permissions - user - group - recursive
     # Rules are executed in the same order as they are listed
     # Rules are executed in the same order as they are listed
@@ -271,18 +317,48 @@ class ServerConfigDefaultsLinux(ServerConfigDefaults):
       # Also, /etc/ambari-server/conf/password.dat
       # Also, /etc/ambari-server/conf/password.dat
       # is generated later at store_password_file
       # is generated later at store_password_file
     ]
     ]
+    self.NR_USERADD_CMD = 'useradd -M --comment "{1}" ' \
+                 '--shell %s -d /var/lib/ambari-server/keys/ {0}' % locate_file('nologin', '/sbin')
+
+    self.STACK_LOCATION_DEFAULT = "/var/lib/ambari-server/resources/stacks"
 
 
     self.DEFAULT_VIEWS_DIR = "/var/lib/ambari-server/resources/views"
     self.DEFAULT_VIEWS_DIR = "/var/lib/ambari-server/resources/views"
 
 
     #keytool commands
     #keytool commands
     self.keytool_bin = "keytool"
     self.keytool_bin = "keytool"
 
 
+    #Standard messages
+    self.MESSAGE_ERROR_SETUP_NOT_ROOT = "Ambari-server setup should be run with root-level privileges"
+    self.MESSAGE_ERROR_RESET_NOT_ROOT = "Ambari-server reset should be run with root-level privileges"
+    self.MESSAGE_ERROR_UPGRADE_NOT_ROOT = "Ambari-server upgrade must be run with root-level privileges"
+    self.MESSAGE_CHECK_FIREWALL = "Checking iptables..."
+
 configDefaults = ServerConfigDefaults()
 configDefaults = ServerConfigDefaults()
 
 
+# Security
+SECURITY_KEYS_DIR = "security.server.keys_dir"
+SECURITY_MASTER_KEY_LOCATION = "security.master.key.location"
+SECURITY_KEY_IS_PERSISTED = "security.master.key.ispersisted"
+SECURITY_KEY_ENV_VAR_NAME = "AMBARI_SECURITY_MASTER_KEY"
+SECURITY_MASTER_KEY_FILENAME = "master"
+SECURITY_IS_ENCRYPTION_ENABLED = "security.passwords.encryption.enabled"
+SECURITY_KERBEROS_JASS_FILENAME = "krb5JAASLogin.conf"
+
+SECURITY_PROVIDER_GET_CMD = "{0} -cp {1}" + \
+                            "org.apache.ambari.server.security.encryption" + \
+                            ".CredentialProvider GET {2} {3} {4} " + \
+                            "> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
+
+SECURITY_PROVIDER_PUT_CMD = "{0} -cp {1}" + \
+                            "org.apache.ambari.server.security.encryption" + \
+                            ".CredentialProvider PUT {2} {3} {4} " + \
+                            "> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
+
+SECURITY_PROVIDER_KEY_CMD = "{0} -cp {1}" + \
+                            "org.apache.ambari.server.security.encryption" + \
+                            ".MasterKeyServiceImpl {2} {3} {4} " + \
+                            "> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
 
 
-SCHEMA_UPGRADE_HELPER_CMD = "{0} -cp {1} " + \
-                            "org.apache.ambari.server.upgrade.SchemaUpgradeHelper" + \
-                            " > " + configDefaults.SERVER_OUT_FILE + " 2>&1"
 
 
 
 
 def get_conf_dir():
 def get_conf_dir():
@@ -322,18 +398,12 @@ def read_ambari_user():
   '''
   '''
   Reads ambari user from properties file
   Reads ambari user from properties file
   '''
   '''
-  conf_file = find_properties_file()
-  try:
-    properties = Properties()
-    properties.load(open(conf_file))
+  properties = get_ambari_properties()
+  if properties != -1:
     user = properties[NR_USER_PROPERTY]
     user = properties[NR_USER_PROPERTY]
     if user:
     if user:
       return user
       return user
-    else:
-      return None
-  except Exception, e:
-    print_error_msg('Could not read "%s": %s' % (conf_file, e))
-    return None
+  return None
 
 
 def get_value_from_properties(properties, key, default=""):
 def get_value_from_properties(properties, key, default=""):
   try:
   try:
@@ -344,6 +414,32 @@ def get_value_from_properties(properties, key, default=""):
     return default
     return default
   return value
   return value
 
 
+def get_is_secure(properties):
+  isSecure = properties.get_property(SECURITY_IS_ENCRYPTION_ENABLED)
+  isSecure = True if isSecure and isSecure.lower() == 'true' else False
+  return isSecure
+
+def get_is_persisted(properties):
+  keyLocation = get_master_key_location(properties)
+  masterKeyFile = search_file(SECURITY_MASTER_KEY_FILENAME, keyLocation)
+  isPersisted = True if masterKeyFile else False
+
+  return (isPersisted, masterKeyFile)
+
+def get_credential_store_location(properties):
+  store_loc = properties[SECURITY_KEYS_DIR]
+  if store_loc is None or store_loc == "":
+    store_loc = "/var/lib/ambari-server/keys/credentials.jceks"
+  else:
+    store_loc += os.sep + "credentials.jceks"
+  return store_loc
+
+def get_master_key_location(properties):
+  keyLocation = properties[SECURITY_MASTER_KEY_LOCATION]
+  if keyLocation is None or keyLocation == "":
+    keyLocation = properties[SECURITY_KEYS_DIR]
+  return keyLocation
+
 # Copy file to /tmp and save with file.# (largest # is latest file)
 # Copy file to /tmp and save with file.# (largest # is latest file)
 def backup_file_in_temp(filePath):
 def backup_file_in_temp(filePath):
   if filePath is not None:
   if filePath is not None:
@@ -353,10 +449,99 @@ def backup_file_in_temp(filePath):
       shutil.copyfile(filePath, tmpDir + os.sep +
       shutil.copyfile(filePath, tmpDir + os.sep +
                       AMBARI_PROPERTIES_FILE + "." + str(back_up_file_count + 1))
                       AMBARI_PROPERTIES_FILE + "." + str(back_up_file_count + 1))
     except (Exception), e:
     except (Exception), e:
-      print_error_msg('Could not backup file in temp "%s": %s' % (str(
-        back_up_file_count, e)))
+      print_error_msg('Could not backup file in temp "%s": %s' % (
+        back_up_file_count, str(e)))
   return 0
   return 0
 
 
+def get_ambari_version(properties):
+  """
+  :param properties: Ambari properties
+  :return: Return a string of the ambari version. When comparing versions, please use "compare_versions" function.
+  """
+  version = None
+  try:
+    server_version_file_path = properties[SERVER_VERSION_FILE_PATH]
+    if server_version_file_path and os.path.exists(server_version_file_path):
+      with open(server_version_file_path, 'r') as file:
+        version = file.read().strip()
+  except:
+    print_error_msg("Error getting ambari version")
+  return version
+
+def get_db_type(properties):
+  db_type = None
+  if properties[JDBC_URL_PROPERTY]:
+    jdbc_url = properties[JDBC_URL_PROPERTY].lower()
+    if "postgres" in jdbc_url:
+      db_type = "postgres"
+    elif "oracle" in jdbc_url:
+      db_type = "oracle"
+    elif "mysql" in jdbc_url:
+      db_type = "mysql"
+    elif "derby" in jdbc_url:
+      db_type = "derby"
+
+  return db_type
+
+def check_database_name_property(upgrade=False):
+  """
+  :param upgrade: If Ambari is being upgraded.
+  :return:
+  """
+  properties = get_ambari_properties()
+  if properties == -1:
+    print_error_msg("Error getting ambari properties")
+    return -1
+
+  version = get_ambari_version(properties)
+  if upgrade and compare_versions(version, "1.7.0") == 0:
+    # This code exists for historic reasons in which property names changed from Ambari 1.6.1 to 1.7.0
+    persistence_type = properties[PERSISTENCE_TYPE_PROPERTY]
+    if persistence_type == "remote":
+      db_name = properties["server.jdbc.schema"]  # this was a property in Ambari 1.6.1, but not after 1.7.0
+      if db_name:
+        write_property(JDBC_DATABASE_NAME_PROPERTY, db_name)
+
+      # If DB type is missing, attempt to reconstruct it from the JDBC URL
+      db_type = properties[JDBC_DATABASE_PROPERTY]
+      if db_type is None or db_type.strip().lower() not in ["postgres", "oracle", "mysql", "derby"]:
+        db_type = get_db_type(properties)
+        if db_type:
+          write_property(JDBC_DATABASE_PROPERTY, db_type)
+
+      properties = get_ambari_properties()
+    elif persistence_type == "local":
+      # Ambari 1.6.1, had "server.jdbc.database" as the DB name, and the
+      # DB type was assumed to be "postgres" if was embedded ("local")
+      db_name = properties[JDBC_DATABASE_PROPERTY]
+      if db_name:
+        write_property(JDBC_DATABASE_NAME_PROPERTY, db_name)
+        write_property(JDBC_DATABASE_PROPERTY, "postgres")
+        properties = get_ambari_properties()
+
+  dbname = properties[JDBC_DATABASE_NAME_PROPERTY]
+  if dbname is None or dbname == "":
+    err = "DB Name property not set in config file.\n" + SETUP_OR_UPGRADE_MSG
+    raise FatalException(-1, err)
+
+def update_database_name_property(upgrade=False):
+  try:
+    check_database_name_property(upgrade)
+  except FatalException:
+    properties = get_ambari_properties()
+    if properties == -1:
+      err = "Error getting ambari properties"
+      raise FatalException(-1, err)
+    print_warning_msg(JDBC_DATABASE_NAME_PROPERTY + " property isn't set in " +
+                      AMBARI_PROPERTIES_FILE + ". Setting it to default value - " + configDefaults.DEFAULT_DB_NAME)
+    properties.process_pair(JDBC_DATABASE_NAME_PROPERTY, configDefaults.DEFAULT_DB_NAME)
+    conf_file = find_properties_file()
+    try:
+      properties.store(open(conf_file, "w"))
+    except Exception, e:
+      err = 'Could not write ambari config file "%s": %s' % (conf_file, e)
+      raise FatalException(-1, err)
+
 
 
 def is_alias_string(passwdStr):
 def is_alias_string(passwdStr):
   regex = re.compile("\$\{alias=[\w\.]+\}")
   regex = re.compile("\$\{alias=[\w\.]+\}")
@@ -367,9 +552,127 @@ def is_alias_string(passwdStr):
   else:
   else:
     return False
     return False
 
 
+def read_passwd_for_alias(alias, masterKey=""):
+  if alias:
+    jdk_path = find_jdk()
+    if jdk_path is None:
+      print_error_msg("No JDK found, please run the \"setup\" "
+                      "command to install a JDK automatically or install any "
+                      "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
+      return 1
+
+    tempFileName = "ambari.passwd"
+    passwd = ""
+    tempDir = tempfile.gettempdir()
+    #create temporary file for writing
+    tempFilePath = tempDir + os.sep + tempFileName
+    file = open(tempFilePath, 'w+')
+    os.chmod(tempFilePath, stat.S_IREAD | stat.S_IWRITE)
+    file.close()
+
+    if masterKey is None or masterKey == "":
+      masterKey = "None"
+
+    command = SECURITY_PROVIDER_GET_CMD.format(get_java_exe_path(),
+                                               get_full_ambari_classpath(), alias, tempFilePath, masterKey)
+    (retcode, stdout, stderr) = run_os_command(command)
+    print_info_msg("Return code from credential provider get passwd: " +
+                   str(retcode))
+    if retcode != 0:
+      print 'ERROR: Unable to read password from store. alias = ' + alias
+    else:
+      passwd = open(tempFilePath, 'r').read()
+      # Remove temporary file
+    os.remove(tempFilePath)
+    return passwd
+  else:
+    print_error_msg("Alias is unreadable.")
+
+def decrypt_password_for_alias(properties, alias):
+  isSecure = get_is_secure(properties)
+  if isSecure:
+    masterKey = None
+    (isPersisted, masterKeyFile) = get_is_persisted(properties)
+    if not masterKeyFile:
+      # Encryption enabled but no master key file found
+      masterKey = get_original_master_key(properties)
+
+    return read_passwd_for_alias(alias, masterKey)
+  else:
+    return alias
+
+def get_original_master_key(properties):
+  input = True
+  while(input):
+    try:
+      masterKey = get_validated_string_input('Enter current Master Key: ',
+                                             "", ".*", "", True, False)
+    except KeyboardInterrupt:
+      print 'Exiting...'
+      sys.exit(1)
+
+    # Find an alias that exists
+    alias = None
+    property = properties.get_property(JDBC_PASSWORD_PROPERTY)
+    if property and is_alias_string(property):
+      alias = JDBC_RCA_PASSWORD_ALIAS
+
+    if not alias:
+      property = properties.get_property(LDAP_MGR_PASSWORD_PROPERTY)
+      if property and is_alias_string(property):
+        alias = LDAP_MGR_PASSWORD_ALIAS
+
+    if not alias:
+      property = properties.get_property(SSL_TRUSTSTORE_PASSWORD_PROPERTY)
+      if property and is_alias_string(property):
+        alias = SSL_TRUSTSTORE_PASSWORD_ALIAS
+
+    # Decrypt alias with master to validate it, if no master return
+    if alias and masterKey:
+      password = read_passwd_for_alias(alias, masterKey)
+      if not password:
+        print "ERROR: Master key does not match."
+        continue
+
+    input = False
+
+  return masterKey
+
+
+# Load database connection properties from conf file
+def parse_properties_file(args):
+  properties = get_ambari_properties()
+  if properties == -1:
+    print_error_msg("Error getting ambari properties")
+    return -1
+
+  args.server_version_file_path = properties[SERVER_VERSION_FILE_PATH]
+  args.persistence_type = properties[PERSISTENCE_TYPE_PROPERTY]
+  args.jdbc_url = properties[JDBC_URL_PROPERTY]
+
+  args.dbms = properties[JDBC_DATABASE_PROPERTY]
+  if not args.persistence_type:
+    args.persistence_type = "local"
+
+  if args.persistence_type == 'remote':
+    args.database_host = properties[JDBC_HOSTNAME_PROPERTY]
+    args.database_port = properties[JDBC_PORT_PROPERTY]
+
+  args.database_name = properties[JDBC_DATABASE_NAME_PROPERTY]
+  args.database_username = properties[JDBC_USER_NAME_PROPERTY]
+  args.postgres_schema = properties[JDBC_POSTGRES_SCHEMA_PROPERTY] \
+    if JDBC_POSTGRES_SCHEMA_PROPERTY in properties.propertyNames() else None
+  args.database_password_file = properties[JDBC_PASSWORD_PROPERTY]
+  if args.database_password_file:
+    if not is_alias_string(args.database_password_file):
+      args.database_password = open(properties[JDBC_PASSWORD_PROPERTY]).read()
+    else:
+      args.database_password = args.database_password_file
+  return 0
+
 
 
 def update_ambari_properties():
 def update_ambari_properties():
-  prev_conf_file = search_file(AMBARI_PROPERTIES_BACKUP_FILE, get_conf_dir())
+  prev_conf_file = search_file(configDefaults.AMBARI_PROPERTIES_BACKUP_FILE, get_conf_dir())
   conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
   conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
 
 
   # Previous config file does not exist
   # Previous config file does not exist
@@ -482,27 +785,31 @@ def write_property(key, value):
     return -1
     return -1
   return 0
   return 0
 
 
-def remove_property(key):
-  conf_file = find_properties_file()
-  properties = Properties()
-  try:
-    properties.load(open(conf_file))
-  except Exception, e:
-    print_error_msg('Could not read ambari config file "%s": %s' % (conf_file, e))
-    return -1
-  properties.removeOldProp(key)
-  try:
-    properties.store(open(conf_file, "w"))
-  except Exception, e:
-    print_error_msg('Could not write ambari config file "%s": %s' % (conf_file, e))
-    return -1
-  return 0
-
 #
 #
 # Checks if options determine local DB configuration
 # Checks if options determine local DB configuration
 #
 #
 def is_local_database(args):
 def is_local_database(args):
-  return hasattr(args, 'persistence_type') and args.persistence_type == 'local'
+  try:
+    return args.persistence_type == 'local'
+  except AttributeError:
+    return False
+
+
+def update_debug_mode():
+  debug_mode = get_debug_mode()
+  # The command-line settings supersede the ones in ambari.properties
+  if not debug_mode & 1:
+    properties = get_ambari_properties()
+    if properties == -1:
+      print_error_msg("Error getting ambari properties")
+      return -1
+
+    if get_value_from_properties(properties, DEBUG_MODE_KEY, False):
+      debug_mode = debug_mode | 1
+    if get_value_from_properties(properties, SUSPEND_START_MODE_KEY, False):
+      debug_mode = debug_mode | 2
+
+    set_debug_mode(debug_mode)
 
 
 #
 #
 ### JDK ###
 ### JDK ###
@@ -520,7 +827,7 @@ class JDKRelease:
   dest_jcpol_file = ""
   dest_jcpol_file = ""
   inst_dir = ""
   inst_dir = ""
 
 
-  def __init__(self, i_name, i_desc, i_url, i_dest_file, i_jcpol_url, i_dest_jcpol_file, i_inst_dir):
+  def __init__(self, i_name, i_desc, i_url, i_dest_file, i_jcpol_url, i_dest_jcpol_file, i_inst_dir, i_reg_exp):
     if i_name is None or i_name is "":
     if i_name is None or i_name is "":
       raise FatalException(-1, "Invalid JDK name: " + (i_desc or ""))
       raise FatalException(-1, "Invalid JDK name: " + (i_desc or ""))
     self.name = i_name
     self.name = i_name
@@ -542,14 +849,17 @@ class JDKRelease:
     else:
     else:
       self.dest_jcpol_file = i_dest_jcpol_file
       self.dest_jcpol_file = i_dest_jcpol_file
     if i_inst_dir is None or i_inst_dir is "":
     if i_inst_dir is None or i_inst_dir is "":
-      self.inst_dir = "C:\\" + i_desc
+      self.inst_dir = os.path.join(configDefaults.JDK_INSTALL_DIR, i_desc)
     else:
     else:
       self.inst_dir = i_inst_dir
       self.inst_dir = i_inst_dir
+    if i_reg_exp is None or i_reg_exp is "":
+      raise FatalException(-1, "Invalid output parsing regular expression for JDK " + i_name)
+    self.reg_exp = i_reg_exp
 
 
   @classmethod
   @classmethod
   def from_properties(cls, properties, section_name):
   def from_properties(cls, properties, section_name):
-    (desc, url, dest_file, jcpol_url, jcpol_file, inst_dir) = JDKRelease.__load_properties(properties, section_name)
-    cls = JDKRelease(section_name, desc, url, dest_file, jcpol_url, jcpol_file, inst_dir)
+    (desc, url, dest_file, jcpol_url, jcpol_file, inst_dir, reg_exp) = JDKRelease.__load_properties(properties, section_name)
+    cls = JDKRelease(section_name, desc, url, dest_file, jcpol_url, jcpol_file, inst_dir, reg_exp)
     return cls
     return cls
 
 
   @staticmethod
   @staticmethod
@@ -563,6 +873,9 @@ class JDKRelease:
     if not properties.has_key(section_name + ".url"):
     if not properties.has_key(section_name + ".url"):
       raise FatalException(-1, "Invalid JDK URL in the properties section: " + section_name)
       raise FatalException(-1, "Invalid JDK URL in the properties section: " + section_name)
     url = properties[section_name + ".url"]      #Required
     url = properties[section_name + ".url"]      #Required
+    if not properties.has_key(section_name + ".re"):
+      raise FatalException(-1, "Invalid JDK output parsing regular expression in the properties section: " + section_name)
+    reg_exp = properties[section_name + ".re"]      #Required
     if(properties.has_key(section_name + ".dest-file")):   #Not critical
     if(properties.has_key(section_name + ".dest-file")):   #Not critical
       dest_file = properties[section_name + ".dest-file"]
       dest_file = properties[section_name + ".dest-file"]
     else:
     else:
@@ -579,7 +892,7 @@ class JDKRelease:
       inst_dir = properties[section_name + ".home"]
       inst_dir = properties[section_name + ".home"]
     else:
     else:
       inst_dir = "C:\\" + section_name
       inst_dir = "C:\\" + section_name
-    return (desc, url, dest_file, jcpol_url, jcpol_file, inst_dir)
+    return (desc, url, dest_file, jcpol_url, jcpol_file, inst_dir, reg_exp)
   pass
   pass
 
 
 def get_ambari_jars():
 def get_ambari_jars():
@@ -618,6 +931,14 @@ def get_ambari_classpath():
     ambari_cp = ambari_cp + os.pathsep + share_cp
     ambari_cp = ambari_cp + os.pathsep + share_cp
   return ambari_cp
   return ambari_cp
 
 
+def get_full_ambari_classpath(conf_dir = None):
+  if conf_dir is None:
+    conf_dir = get_conf_dir()
+  cp = conf_dir + os.pathsep + get_ambari_classpath()
+  if cp.find(' ') != -1:
+    cp = '"' + cp + '"'
+  return cp
+
 def get_JAVA_HOME():
 def get_JAVA_HOME():
   properties = get_ambari_properties()
   properties = get_ambari_properties()
   if properties == -1:
   if properties == -1:
@@ -665,3 +986,35 @@ def find_jdk():
     else:
     else:
       print "JDK {0} is invalid".format(jdkPath)
       print "JDK {0} is invalid".format(jdkPath)
   return
   return
+
+def get_java_exe_path():
+  jdkPath = find_jdk()
+  if jdkPath:
+    java_exe = os.path.join(jdkPath, configDefaults.JAVA_EXE_SUBPATH)
+    return java_exe
+  return
+
+#
+# JDBC
+#
+
+#Check if required jdbc drivers present
+def find_jdbc_driver(args):
+  if args.dbms in JDBC_PATTERNS.keys():
+    drivers = []
+    drivers.extend(glob.glob(os.path.join(configDefaults.JAVA_SHARE_PATH, JDBC_PATTERNS[args.dbms])))
+    if drivers:
+      return drivers
+    return -1
+  return 0
+
+
+#
+# Stack upgrade
+#
+
+def get_stack_location(properties):
+  stack_location = properties[STACK_LOCATION_KEY]
+  if stack_location is None:
+    stack_location = configDefaults.STACK_LOCATION_DEFAULT
+  return stack_location

文件差异内容过多而无法显示
+ 673 - 283
ambari-server/src/main/python/ambari_server/serverSetup.py


+ 0 - 793
ambari-server/src/main/python/ambari_server/serverSetup_linux.py

@@ -1,793 +0,0 @@
-#!/usr/bin/env python
-
-'''
-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.
-'''
-import glob
-import optparse
-
-import os
-import re
-import socket
-import subprocess
-import time
-
-from ambari_commons.exceptions import *
-from ambari_commons.logging_utils import *
-from ambari_commons.os_utils import run_os_command, copy_files
-from ambari_server.dbConfiguration_linux import SERVICE_CMD, PG_HBA_CONF_FILE_BACKUP
-from ambari_server.serverConfiguration import *
-from ambari_server.setupSecurity import *
-from ambari_server.userInput import get_YN_input, get_validated_string_input
-from ambari_server import utils
-
-# selinux commands
-GET_SE_LINUX_ST_CMD = utils.locate_file('sestatus', '/usr/sbin')
-SE_SETENFORCE_CMD = "setenforce 0"
-SE_STATUS_DISABLED = "disabled"
-SE_STATUS_ENABLED = "enabled"
-SE_MODE_ENFORCING = "enforcing"
-SE_MODE_PERMISSIVE = "permissive"
-
-# Non-root user setup commands
-NR_USER_COMMENT = "Ambari user"
-NR_GET_OWNER_CMD = 'stat -c "%U" {0}'
-NR_USERADD_CMD = 'useradd -M --comment "{1}" ' \
-                 '--shell %s -d /var/lib/ambari-server/keys/ {0}' % utils.locate_file('nologin', '/sbin')
-NR_SET_USER_COMMENT_CMD = 'usermod -c "{0}" {1}'
-
-NR_USER_CHANGE_PROMPT = "Ambari-server daemon is configured to run under user '{0}'. Change this setting [y/n] (n)? "
-NR_USER_CUSTOMIZE_PROMPT = "Customize user account for ambari-server daemon [y/n] (n)? "
-NR_DEFAULT_USER = "root"
-
-# jdk commands
-JDK_URL_PROPERTIES = ["jdk1.7.url", "jdk1.6.url"]
-JCE_URL_PROPERTIES = ["jce_policy1.7.url", "jce_policy1.6.url"]
-JDK_VERSION_REs = ["(jdk.*)/jre", "Creating (jdk.*)/jre"]
-JDK_CHOICE_PROMPT = "[1] - Oracle JDK 1.7\n[2] - Oracle JDK 1.6\n[3] - Custom JDK\n==============================================================================\nEnter choice ({0}): "
-JDK_VALID_CHOICES = "^[123]$"
-CUSTOM_JDK_NUMBER = "3"
-JDK_MIN_FILESIZE = 5000
-CREATE_JDK_DIR_CMD = "/bin/mkdir -p {0}"
-MAKE_FILE_EXECUTABLE_CMD = "chmod a+x {0}"
-
-JDK_DOWNLOAD_CMD = "curl --create-dirs -o {0} {1}"
-JDK_DOWNLOAD_SIZE_CMD = "curl -I {0}"
-
-# use --no-same-owner when running as root to prevent uucp as the user (AMBARI-6478)
-UNTAR_JDK_ARCHIVE = "tar --no-same-owner -xvf {0}"
-
-
-#JDBC
-DATABASE_INDEX = 0
-USERNAME_PATTERN = "^[a-zA-Z_][a-zA-Z0-9_\-]*$"
-DATABASE_NAMES = ["postgres", "oracle", "mysql"]
-DATABASE_STORAGE_NAMES = ["Database", "Service", "Database"]
-DATABASE_PORTS = ["5432", "1521", "3306"]
-DATABASE_DRIVER_NAMES = ["org.postgresql.Driver", "oracle.jdbc.driver.OracleDriver", "com.mysql.jdbc.Driver"]
-DATABASE_CONNECTION_STRINGS = [
-                  "jdbc:postgresql://{0}:{1}/{2}",
-                  "jdbc:oracle:thin:@{0}:{1}/{2}",
-                  "jdbc:mysql://{0}:{1}/{2}"]
-DATABASE_CONNECTION_STRINGS_ALT = [
-                  "jdbc:postgresql://{0}:{1}/{2}",
-                  "jdbc:oracle:thin:@{0}:{1}:{2}",
-                  "jdbc:mysql://{0}:{1}/{2}"]
-ORACLE_SID_PATTERN = "jdbc:oracle:thin:@.+:.+/.+"
-ORACLE_SNAME_PATTERN = "jdbc:oracle:thin:@.+:.+:.+"
-
-DATABASE_CLI_TOOLS = [["psql"], ["sqlplus", "sqlplus64"], ["mysql"]]
-DATABASE_CLI_TOOLS_DESC = ["psql", "sqlplus", "mysql"]
-DATABASE_CLI_TOOLS_USAGE = ['su -postgres --command=psql -f {0} -v username=\'"{1}"\' -v password="\'{2}\'"',
-                            'sqlplus {1}/{2} < {0} ',
-                            'mysql --user={1} --password={2} {3}<{0}']
-
-MYSQL_INIT_SCRIPT = '/var/lib/ambari-server/resources/Ambari-DDL-MySQL-CREATE.sql'
-DATABASE_INIT_SCRIPTS = ['/var/lib/ambari-server/resources/Ambari-DDL-Postgres-CREATE.sql',
-                         '/var/lib/ambari-server/resources/Ambari-DDL-Oracle-CREATE.sql',
-                         MYSQL_INIT_SCRIPT]
-DATABASE_DROP_SCRIPTS = ['/var/lib/ambari-server/resources/Ambari-DDL-Postgres-DROP.sql',
-                         '/var/lib/ambari-server/resources/Ambari-DDL-Oracle-DROP.sql',
-                         '/var/lib/ambari-server/resources/Ambari-DDL-MySQL-DROP.sql']
-
-JDBC_PROPERTIES_PREFIX = "server.jdbc.properties."
-DATABASE_JDBC_PROPERTIES = [
-                         [ ],
-                         [
-                           ["oracle.net.CONNECT_TIMEOUT", "2000"], # socket level timeout
-                           ["oracle.net.READ_TIMEOUT", "2000"], # socket level timeout
-                           ["oracle.jdbc.ReadTimeout", "8000"] # query fetch timeout
-                         ],
-                         [ ]
-                        ]
-
-POSTGRES_EXEC_ARGS = "-h {0} -p {1} -d {2} -U {3} -f {4} -v username='{3}'"
-ORACLE_EXEC_ARGS = "-S -L '{0}/{1}@(description=(address=(protocol=TCP)(host={2})(port={3}))(connect_data=({6}={4})))' @{5} {0}"
-MYSQL_EXEC_ARGS_WITH_USER_VARS = "--host={0} --port={1} --user={2} --password={3} {4} " \
-                 "-e\"set @schema=\'{4}\'; set @username=\'{2}\'; source {5};\""
-MYSQL_EXEC_ARGS_WO_USER_VARS = "--force --host={0} --port={1} --user={2} --password={3} --database={4} < {5} 2> /dev/null"
-MYSQL_UPGRADE_STACK_ARGS = "--host={0} --port={1} --user={2} --password={3} --database={4} " \
-                 "-e\"set @stackName=\'{6}\'; set @stackVersion=\'{7}\'; source {5};\""
-
-ORACLE_UPGRADE_STACK_ARGS = "-S -L '{0}/{1}@(description=(address=(protocol=TCP)(host={2})(port={3}))(connect_data=({6}={4})))' @{5} {7} {8}"
-
-JDBC_PATTERNS = {"oracle": "*ojdbc*.jar", "mysql": "*mysql*.jar"}
-DATABASE_FULL_NAMES = {"oracle": "Oracle", "mysql": "MySQL", "postgres": "PostgreSQL"}
-JDBC_DB_OPTION_VALUES = ["postgres", "mysql", "oracle"]
-JDBC_DB_DEFAULT_DRIVER = {"postgresql" : "postgresql-jdbc.jar", "mysql" : "mysql-connector-java.jar", "oracle" : "ojdbc6.jar"}
-ORACLE_DB_ID_TYPES = ["Service Name", "SID"]
-
-
-MESSAGE_ERROR_NOT_ROOT = 'Ambari-server setup should be run with root-level privileges'
-
-MESSAGE_CHECK_FIREWALL = 'Checking iptables...'
-
-class FirewallChecks(object):
-  def __init__(self):
-
-    self.FIREWALL_SERVICE_NAME = "iptables"
-    self.SERVICE_CMD = SERVICE_CMD
-    self.SERVICE_SUBCMD = "status"
-
-  def get_command(self):
-    return "%s %s %s" % (self.SERVICE_CMD, self.FIREWALL_SERVICE_NAME, self.SERVICE_SUBCMD)
-
-  def check_result(self, retcode, out, err):
-      return retcode == 0
-
-  def check_iptables(self):
-    retcode, out, err = run_os_command(self.get_command())
-    if err and len(err) > 0:
-      print err
-    if self.check_result(retcode, out, err):
-      print_warning_msg("%s is running. Confirm the necessary Ambari ports are accessible. " %
-                        self.FIREWALL_SERVICE_NAME +
-                        "Refer to the Ambari documentation for more details on ports.")
-      ok = get_YN_input("OK to continue [y/n] (y)? ", True)
-      if not ok:
-        raise FatalException(1, None)
-
-  def get_running_result(self):
-    # To support test code.  Expected ouput from run_os_command.
-    return (0, "", "")
-
-  def get_stopped_result(self):
-    # To support test code.  Expected output from run_os_command.
-    return (3, "", "")
-
-
-class UbuntuFirewallChecks(FirewallChecks):
-  def __init__(self):
-    super(UbuntuFirewallChecks, self).__init__()
-
-    self.FIREWALL_SERVICE_NAME = "ufw"
-    self.SERVICE_CMD = utils.locate_file('service', '/usr/sbin')
-
-  def check_result(self, retcode, out, err):
-    # On ubuntu, the status command returns 0 whether running or not
-    return out and len(out) > 0 and out.strip() != "ufw stop/waiting"
-
-  def get_running_result(self):
-    # To support test code.  Expected ouput from run_os_command.
-    return (0, "ufw start/running", "")
-
-  def get_stopped_result(self):
-    # To support test code.  Expected output from run_os_command.
-    return (0, "ufw stop/waiting", "")
-
-
-class Fedora18FirewallChecks(FirewallChecks):
-  def __init__(self):
-    self.FIREWALL_SERVICE_NAME = "firewalld.service"
-
-  def get_command(self):
-    return "systemctl is-active firewalld.service"
-
-
-class OpenSuseFirewallChecks(FirewallChecks):
-  def __init__(self):
-    self.FIREWALL_SERVICE_NAME = "SuSEfirewall2"
-
-  def get_command(self):
-    return "/sbin/SuSEfirewall2 status"
-
-
-def get_firewall_object():
-  if OS_TYPE == OSConst.OS_UBUNTU:
-    return UbuntuFirewallChecks()
-  elif OS_TYPE == OSConst.OS_FEDORA and int(OS_VERSION) >= 18:
-    return Fedora18FirewallChecks()
-  elif OS_TYPE == OSConst.OS_OPENSUSE:
-    return OpenSuseFirewallChecks()
-  else:
-    return FirewallChecks()
-
-
-def get_firewall_object_types():
-  # To support test code, so tests can loop through the types
-  return (FirewallChecks,
-          UbuntuFirewallChecks,
-          Fedora18FirewallChecks,
-          OpenSuseFirewallChecks)
-
-
-def os_check_firewall():
-  return get_firewall_object().check_iptables()
-
-
-#
-# Checks SELinux
-#
-def check_selinux():
-  try:
-    retcode, out, err = run_os_command(GET_SE_LINUX_ST_CMD)
-    se_status = re.search('(disabled|enabled)', out).group(0)
-    print "SELinux status is '" + se_status + "'"
-    if se_status == SE_STATUS_DISABLED:
-      return 0
-    else:
-      try:
-        se_mode = re.search('(enforcing|permissive)', out).group(0)
-      except AttributeError:
-        err = "Error determining SELinux mode. Exiting."
-        raise FatalException(1, err)
-      print "SELinux mode is '" + se_mode + "'"
-      if se_mode == SE_MODE_ENFORCING:
-        print "Temporarily disabling SELinux"
-        run_os_command(SE_SETENFORCE_CMD)
-      print_warning_msg(
-        "SELinux is set to 'permissive' mode and temporarily disabled.")
-      ok = get_YN_input("OK to continue [y/n] (y)? ", True)
-      if not ok:
-        raise FatalException(1, None)
-      return 0
-  except OSError:
-    print_warning_msg("Could not run {0}: OK".format(GET_SE_LINUX_ST_CMD))
-  return 0
-
-def disable_security_enhancements():
-  print 'Checking SELinux...'
-  err = ''
-  retcode = check_selinux()
-  if not retcode == 0:
-    err = 'Failed to disable SELinux. Exiting.'
-  return (retcode, err)
-
-
-#
-# User account creation
-#
-
-def os_create_custom_user():
-  user = get_validated_string_input(
-    "Enter user account for ambari-server daemon (root):",
-    "root",
-    "^[a-z_][a-z0-9_-]{1,31}$",
-    "Invalid username.",
-    False
-  )
-
-  print_info_msg("Trying to create user {0}".format(user))
-  command = NR_USERADD_CMD.format(user, NR_USER_COMMENT)
-  retcode, out, err = run_os_command(command)
-  if retcode == 9:  # 9 = username already in use
-    print_info_msg("User {0} already exists, "
-                      "skipping user creation".format(user))
-
-  elif retcode != 0:  # fail
-    print_warning_msg("Can't create user {0}. Command {1} "
-                      "finished with {2}: \n{3}".format(user, command, retcode, err))
-    return retcode, None
-
-  print_info_msg("User configuration is done.")
-  return 0, user
-
-
-#
-# JDK Setup
-#
-
-def os_install_jdk(java_inst_file, java_home_dir):
-  print "Installing JDK to {0}".format(java_home_dir)
-  retcode, out, err = run_os_command(CREATE_JDK_DIR_CMD.format(java_home_dir))
-  savedPath = os.getcwd()
-  os.chdir(java_home_dir)
-
-  if java_inst_file.endswith(".bin"):
-    retcode, out, err = run_os_command(MAKE_FILE_EXECUTABLE_CMD.format(java_inst_file))
-    retcode, out, err = run_os_command(java_inst_file + ' -noregister')
-  elif java_inst_file.endswith(".gz"):
-    retcode, out, err = run_os_command(UNTAR_JDK_ARCHIVE.format(java_inst_file))
-  else:
-    err = "JDK installation failed.Unknown file mask."
-    raise FatalException(1, err)
-
-  os.chdir(savedPath)
-
-  if retcode != 0:
-    err = "Installation of JDK returned exit code %s" % retcode
-    raise FatalException(retcode, err)
-
-  print "Successfully installed JDK to {0}".format(java_home_dir)
-  return (retcode, out)
-
-def os_ensure_java_home_env_var_is_set(java_home_var):
-  if not os.environ.has_key(JAVA_HOME) or os.environ[JAVA_HOME] != java_home_var:
-    os.system("SETX {0} {1} /M".format(JAVA_HOME, java_home_var))
-    os.environ[JAVA_HOME] = java_home_var
-    pass
-
-
-#
-# JDBC Setup
-#
-
-def os_check_jdbc_options(options):
-  return (options.jdbc_driver is not None and options.jdbc_db is not None)
-
-#Check if required jdbc drivers present
-def os_find_jdbc_driver(args):
-  if args.dbms in JDBC_PATTERNS.keys():
-    drivers = []
-    drivers.extend(glob.glob(configDefaults.JAVA_SHARE_PATH + os.sep + JDBC_PATTERNS[args.dbms]))
-    if drivers:
-      return drivers
-    return -1
-  return 0
-
-def os_setup_jdbc_drivers(args):
-  result = os_find_jdbc_driver(args)
-
-  msg = 'Before starting Ambari Server, ' \
-        'you must copy the {0} JDBC driver JAR file to {1}.'.format(
-        DATABASE_FULL_NAMES[args.dbms],
-        configDefaults.JAVA_SHARE_PATH)
-
-  if result == -1:
-    if get_silent():
-      print_error_msg(msg)
-      raise FatalException(-1, msg)
-    else:
-      print_warning_msg(msg)
-      raw_input(PRESS_ENTER_MSG)
-      result = os_find_jdbc_driver(args)
-      if result == -1:
-        print_error_msg(msg)
-        raise FatalException(-1, msg)
-
-  # Check if selected RDBMS requires drivers to copy
-  if type(result) is not int:
-    print 'Copying JDBC drivers to server resources...'
-    try:
-      resources_dir = args[RESOURCES_DIR_PROPERTY]
-    except KeyError:
-      print_error_msg("There is no value for " + RESOURCES_DIR_PROPERTY + "in " + AMBARI_PROPERTIES_FILE)
-      return -1
-
-    db_name = DATABASE_FULL_NAMES[args.dbms].lower()
-    jdbc_symlink = os.path.join(resources_dir, db_name + "-jdbc-driver.jar")
-    db_default_driver_path = os.path.join(configDefaults.JAVA_SHARE_PATH, JDBC_DB_DEFAULT_DRIVER[db_name])
-
-    if os.path.lexists(jdbc_symlink):
-      os.remove(jdbc_symlink)
-
-    copy_status = copy_files(result, resources_dir)
-
-    if not copy_status == 0:
-      raise FatalException(-1, "Failed to copy JDBC drivers to server resources")
-
-    if db_default_driver_path in result:
-      os.symlink(os.path.join(resources_dir, JDBC_DB_DEFAULT_DRIVER[db_name]), jdbc_symlink)
-
-def os_load_default_db_properties(args):
-  args.persistence_type = 'local'
-  args.dbms = DATABASE_NAMES[DATABASE_INDEX]
-  args.database_host = "localhost"
-  args.database_port = DATABASE_PORTS[DATABASE_INDEX]
-  args.database_name = DEFAULT_DB_NAME
-  args.database_username = "ambari"
-  args.database_password = "bigdata"
-  args.sid_or_sname = "sname"
-  pass
-
-# Check if jdbc user is changed
-def is_jdbc_user_changed(args):
-  properties = get_ambari_properties()
-  if properties == -1:
-    print_error_msg("Error getting ambari properties")
-    return None
-
-  previos_user = properties[JDBC_USER_NAME_PROPERTY]
-  new_user = args.database_username
-
-  if previos_user and new_user:
-    if previos_user != new_user:
-      return True
-    else:
-      return False
-
-  return None
-
-def os_setup_database(options):
-  if is_local_database(options):
-    os_setup_local_database(options)
-  else:
-    os_setup_remote_database(options)
-
-def os_setup_local_database(options):
-  #check if jdbc user is changed
-  is_user_changed = is_jdbc_user_changed(options)
-
-  print 'Default properties detected. Using built-in database.'
-  os_store_local_properties(options)
-
-  print 'Checking PostgreSQL...'
-  pg_status, retcode, out, err = check_postgre_up()
-  if not retcode == 0:
-    err = 'Unable to start PostgreSQL server. Status {0}. {1}.' \
-          ' Exiting'.format(pg_status, err)
-    raise FatalException(retcode, err)
-
-  print 'Configuring local database...'
-  retcode, outdata, errdata = setup_db(options)
-  if not retcode == 0:
-    err = 'Running database init script was failed. {0}. Exiting.'.format(errdata)
-    raise FatalException(retcode, err)
-
-  if is_user_changed:
-    #remove backup for pg_hba in order to reconfigure postgres
-    remove_file(PG_HBA_CONF_FILE_BACKUP)
-
-  print 'Configuring PostgreSQL...'
-  retcode, out, err = configure_postgres()
-  if not retcode == 0:
-    err = 'Unable to configure PostgreSQL server. {0} Exiting'.format(err)
-    raise FatalException(retcode, err)
-  pass
-
-def os_setup_remote_database(options):
-  retcode = os_store_remote_properties(options)
-  if retcode != 0:
-    err = 'Unable to save config file'
-    raise FatalException(retcode, err)
-
-    os_setup_jdbc_drivers(options)
-
-  print 'Configuring remote database connection properties...'
-  retcode = setup_remote_db(options)
-  if retcode == -1:
-    err = "Remote database setup aborted."
-    raise NonFatalException(err)
-
-  if not retcode == 0:
-    err = 'Error while configuring connection properties. Exiting'
-    raise FatalException(retcode, err)
-  pass
-
-def os_reset_database(options):
-  pass
-
-
-### Postgres ###
-
-
-def configure_pg_hba_ambaridb_users():
-  args = optparse.Values()
-  configure_database_username_password(args)
-
-  with open(PG_HBA_CONF_FILE, "a") as pgHbaConf:
-    pgHbaConf.write("\n")
-    pgHbaConf.write("local  all  " + args.database_username +
-                    ",mapred md5")
-    pgHbaConf.write("\n")
-    pgHbaConf.write("host  all   " + args.database_username +
-                    ",mapred 0.0.0.0/0  md5")
-    pgHbaConf.write("\n")
-    pgHbaConf.write("host  all   " + args.database_username +
-                    ",mapred ::/0 md5")
-    pgHbaConf.write("\n")
-  retcode, out, err = run_os_command(PG_HBA_RELOAD_CMD)
-  if not retcode == 0:
-    raise FatalException(retcode, err)
-
-
-def configure_pg_hba_postgres_user():
-  postgresString = "all   postgres"
-  for line in fileinput.input(PG_HBA_CONF_FILE, inplace=1):
-    print re.sub('all\s*all', postgresString, line),
-  os.chmod(PG_HBA_CONF_FILE, 0644)
-
-
-def configure_postgresql_conf():
-  listenAddress = "listen_addresses = '*'        #"
-  for line in fileinput.input(POSTGRESQL_CONF_FILE, inplace=1):
-    print re.sub('#+listen_addresses.*?(#|$)', listenAddress, line),
-  os.chmod(POSTGRESQL_CONF_FILE, 0644)
-
-
-def configure_postgres():
-  if os.path.isfile(PG_HBA_CONF_FILE):
-    if not os.path.isfile(PG_HBA_CONF_FILE_BACKUP):
-      shutil.copyfile(PG_HBA_CONF_FILE, PG_HBA_CONF_FILE_BACKUP)
-    else:
-      #Postgres has been configured before, must not override backup
-      print "Backup for pg_hba found, reconfiguration not required"
-      return 0, "", ""
-  configure_pg_hba_postgres_user()
-  configure_pg_hba_ambaridb_users()
-  os.chmod(PG_HBA_CONF_FILE, 0644)
-  configure_postgresql_conf()
-  #restart postgresql if already running
-  pg_status, retcode, out, err = get_postgre_status()
-  if pg_status == PG_STATUS_RUNNING:
-    retcode, out, err = restart_postgres()
-    return retcode, out, err
-  return 0, "", ""
-
-
-def restart_postgres():
-  print "Restarting PostgreSQL"
-  process = subprocess.Popen(PG_RESTART_CMD.split(' '),
-                            stdout=subprocess.PIPE,
-                            stdin=subprocess.PIPE,
-                            stderr=subprocess.PIPE
-                             )
-  time.sleep(5)
-  result = process.poll()
-  if result is None:
-    print_info_msg("Killing restart PostgresSQL process")
-    process.kill()
-    pg_status, retcode, out, err = get_postgre_status()
-    # SUSE linux set status of stopped postgresql proc to unused
-    if pg_status == "unused" or pg_status == "stopped":
-      print_info_msg("PostgreSQL is stopped. Restarting ...")
-      retcode, out, err = run_os_command(PG_START_CMD)
-      return retcode, out, err
-  return 0, "", ""
-
-
-# todo: check if the scheme is already exist
-
-
-def setup_db(args):
-  #password access to ambari-server and mapred
-  configure_database_username_password(args)
-  dbname = args.database_name
-  scriptFile = args.init_script_file
-  username = args.database_username
-  password = args.database_password
-
-  #setup DB
-  command = SETUP_DB_CMD[:]
-  command[-1] = command[-1].format(scriptFile, username, password, dbname)
-
-  for i in range(SETUP_DB_CONNECT_ATTEMPTS):
-    sys.stdout.write('Connecting to local database...')
-    retcode, outdata, errdata = run_os_command(command)
-    if retcode == 0:
-      print 'done.'
-      return retcode, outdata, errdata
-    timeOutMsg = 'connection timed out'
-    if (i+1) < SETUP_DB_CONNECT_ATTEMPTS:
-      timeOutMsg += '...retrying (%d)' % (i+1)
-      print timeOutMsg
-      time.sleep(SETUP_DB_CONNECT_TIMEOUT)
-
-  print 'unable to connect to database'
-  print_error_msg(errdata)
-  return retcode, outdata, errdata
-
-
-def execute_db_script(args, file):
-  #password access to ambari-server and mapred
-  configure_database_username_password(args)
-  dbname = args.database_name
-  username = args.database_username
-  password = args.database_password
-  command = SETUP_DB_CMD[:]
-  command[-1] = command[-1].format(file, username, password, dbname)
-  retcode, outdata, errdata = run_os_command(command)
-  if not retcode == 0:
-    print errdata
-  return retcode
-
-
-def check_db_consistency(args, file):
-  #password access to ambari-server and mapred
-  configure_database_username_password(args)
-  dbname = args.database_name
-  username = args.database_username
-  password = args.database_password
-  command = SETUP_DB_CMD[:]
-  command[-1] = command[-1].format(file, username, password, dbname)
-  retcode, outdata, errdata = run_os_command(command)
-  if not retcode == 0:
-    print errdata
-    return retcode
-  else:
-    # Assumes that the output is of the form ...\n<count>
-    print_info_msg("Parsing output: " + outdata)
-    lines = outdata.splitlines()
-    if (lines[-1] == '3' or lines[-1] == '0'):
-      return 0
-  return -1
-
-
-def get_postgre_status():
-  retcode, out, err = run_os_command(PG_ST_CMD)
-  try:
-    pg_status = re.search('(stopped|running)', out, re.IGNORECASE).group(0).lower()
-  except AttributeError:
-    pg_status = None
-  return pg_status, retcode, out, err
-
-
-def check_postgre_up():
-  pg_status, retcode, out, err = get_postgre_status()
-  if pg_status == PG_STATUS_RUNNING:
-    print_info_msg("PostgreSQL is running")
-    return pg_status, 0, out, err
-  else:
-    # run initdb only on non ubuntu systems as ubuntu does not have initdb cmd.
-    if OS_TYPE != OSConst.OS_UBUNTU:
-      print "Running initdb: This may take upto a minute."
-      retcode, out, err = run_os_command(PG_INITDB_CMD)
-      if retcode == 0:
-        print out
-    print "About to start PostgreSQL"
-    try:
-      process = subprocess.Popen(PG_START_CMD.split(' '),
-                                 stdout=subprocess.PIPE,
-                                 stdin=subprocess.PIPE,
-                                 stderr=subprocess.PIPE
-                                 )
-      if OS_TYPE == OSConst.OS_SUSE:
-        time.sleep(20)
-        result = process.poll()
-        print_info_msg("Result of postgres start cmd: " + str(result))
-        if result is None:
-          process.kill()
-          pg_status, retcode, out, err = get_postgre_status()
-        else:
-          retcode = result
-      else:
-        out, err = process.communicate()
-        retcode = process.returncode
-      if pg_status == PG_STATUS_RUNNING:
-        print_info_msg("Postgres process is running. Returning...")
-        return pg_status, 0, out, err
-    except (Exception), e:
-      pg_status, retcode, out, err = get_postgre_status()
-      if pg_status == PG_STATUS_RUNNING:
-        return pg_status, 0, out, err
-      else:
-        print_error_msg("Postgres start failed. " + str(e))
-    return pg_status, retcode, out, err
-
-def get_validated_db_name(database_name):
-  return get_validated_string_input(
-        DATABASE_STORAGE_NAMES[DATABASE_INDEX] + " Name ("
-        + database_name + "): ",
-        database_name,
-        ".*",
-        "Invalid " + DATABASE_STORAGE_NAMES[DATABASE_INDEX] + " name.",
-        False
-        )
-
-def get_validated_service_name(service_name, index):
-  return get_validated_string_input(
-            ORACLE_DB_ID_TYPES[index] + " (" + service_name + "): ",
-            service_name,
-            ".*",
-            "Invalid " + ORACLE_DB_ID_TYPES[index] + ".",
-            False
-            )
-
-def get_pass_file_path(conf_file):
-  return os.path.join(os.path.dirname(conf_file),
-                      JDBC_PASSWORD_FILENAME)
-
-# Store local database connection properties
-def os_store_local_properties(args):
-  properties = get_ambari_properties()
-  if properties == -1:
-    print_error_msg("Error getting ambari properties")
-    return -1
-
-  isSecure = get_is_secure(properties)
-
-  properties.removeOldProp(JDBC_POSTGRES_SCHEMA_PROPERTY)
-  properties.removeOldProp(JDBC_HOSTNAME_PROPERTY)
-  properties.removeOldProp(JDBC_RCA_DRIVER_PROPERTY)
-  properties.removeOldProp(JDBC_RCA_URL_PROPERTY)
-  properties.removeOldProp(JDBC_PORT_PROPERTY)
-  properties.removeOldProp(JDBC_DRIVER_PROPERTY)
-  properties.removeOldProp(JDBC_URL_PROPERTY)
-  properties.process_pair(PERSISTENCE_TYPE_PROPERTY, "local")
-  properties.process_pair(JDBC_DATABASE_PROPERTY, args.database_name)
-  properties.process_pair(JDBC_USER_NAME_PROPERTY, args.database_username)
-  properties.process_pair(JDBC_PASSWORD_PROPERTY,
-                          store_password_file(args.database_password, JDBC_PASSWORD_FILENAME))
-
-  if isSecure:
-    encrypted_password = encrypt_password(JDBC_RCA_PASSWORD_ALIAS, args.database_password)
-    if args.database_password != encrypted_password:
-      properties.process_pair(JDBC_PASSWORD_PROPERTY, encrypted_password)
-    pass
-  pass
-
-  return 0
-
-
-# Store set of properties for remote database connection
-def os_store_remote_properties(args):
-  properties = get_ambari_properties()
-  if properties == -1:
-    print_error_msg("Error getting ambari properties")
-    return -1
-
-  isSecure = get_is_secure(properties)
-
-  properties.process_pair(PERSISTENCE_TYPE_PROPERTY, "remote")
-
-  properties.process_pair(JDBC_DATABASE_PROPERTY, args.dbms)
-  properties.process_pair(JDBC_HOSTNAME_PROPERTY, args.database_host)
-  properties.process_pair(JDBC_PORT_PROPERTY, args.database_port)
-  properties.process_pair(JDBC_POSTGRES_SCHEMA_PROPERTY, args.database_name)
-
-  properties.process_pair(JDBC_DRIVER_PROPERTY, DATABASE_DRIVER_NAMES[DATABASE_INDEX])
-  # fully qualify the hostname to make sure all the other hosts can connect
-  # to the jdbc hostname since its passed onto the agents for RCA
-  jdbc_hostname = args.database_host
-  if (args.database_host == "localhost"):
-    jdbc_hostname = socket.getfqdn()
-
-  connectionStringFormat = DATABASE_CONNECTION_STRINGS
-  if args.sid_or_sname == "sid":
-    connectionStringFormat = DATABASE_CONNECTION_STRINGS_ALT
-  properties.process_pair(JDBC_URL_PROPERTY,
-                          connectionStringFormat[DATABASE_INDEX].format(jdbc_hostname, args.database_port,
-                                                                        args.database_name))
-  properties.process_pair(JDBC_USER_NAME_PROPERTY, args.database_username)
-  properties.process_pair(JDBC_PASSWORD_PROPERTY,
-                          store_password_file(args.database_password, JDBC_PASSWORD_FILENAME))
-
-  # save any other defined properties to pass to JDBC
-  if DATABASE_INDEX < len(DATABASE_JDBC_PROPERTIES):
-    for pair in DATABASE_JDBC_PROPERTIES[DATABASE_INDEX]:
-      properties.process_pair(JDBC_PROPERTIES_PREFIX + pair[0], pair[1])
-
-  if isSecure:
-    encrypted_password = encrypt_password(JDBC_RCA_PASSWORD_ALIAS, args.database_password)
-    if encrypted_password != args.database_password:
-      properties.process_pair(JDBC_PASSWORD_PROPERTY, encrypted_password)
-  pass
-
-  properties.process_pair(JDBC_RCA_DRIVER_PROPERTY, DATABASE_DRIVER_NAMES[DATABASE_INDEX])
-  properties.process_pair(JDBC_RCA_URL_PROPERTY,
-                          connectionStringFormat[DATABASE_INDEX].format(jdbc_hostname, args.database_port,
-                                                                        args.database_name))
-  properties.process_pair(JDBC_RCA_USER_NAME_PROPERTY, args.database_username)
-  properties.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY,
-                          store_password_file(args.database_password, JDBC_PASSWORD_FILENAME))
-  if isSecure:
-    encrypted_password = encrypt_password(JDBC_RCA_PASSWORD_ALIAS, args.database_password)
-    if encrypted_password != args.database_password:
-      properties.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, encrypted_password)
-  pass
-
-  return 0

+ 0 - 300
ambari-server/src/main/python/ambari_server/serverSetup_windows.py

@@ -1,300 +0,0 @@
-#!/usr/bin/env python
-
-'''
-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.
-'''
-
-import optparse
-import os
-import socket
-import string
-
-from _winreg import (OpenKey, EnumValue, HKEY_LOCAL_MACHINE, KEY_READ, CloseKey, KEY_WRITE, QueryValueEx, SetValueEx,
-                     REG_EXPAND_SZ)
-
-from ambari_commons import os_utils
-
-from ambari_commons.exceptions import *
-from ambari_commons.logging_utils import *
-from ambari_commons.os_windows import run_powershell_script, UserHelper, CHECK_FIREWALL_SCRIPT
-from ambari_server.dbConfiguration import DBMSConfig
-from ambari_server.serverConfiguration import *
-from ambari_server.userInput import get_validated_string_input
-
-# Non-root user setup commands
-NR_USER_COMMENT = "Ambari user"
-NR_GET_OWNER_CMD = 'stat -c "%U" {0}'
-NR_USERADD_CMD = 'cmd /C net user {0} {1} /ADD'
-NR_SET_USER_COMMENT_CMD = 'usermod -c "{0}" {1}'
-
-NR_USER_CHANGE_PROMPT = "Ambari-server service is configured to run under user '{0}'. Change this setting [y/n] (n)? "
-NR_USER_CUSTOMIZE_PROMPT = "Customize user account for ambari-server service [y/n] (n)? "
-NR_DEFAULT_USER = "NT AUTHORITY\SYSTEM"
-
-SERVICE_USERNAME_KEY = "TMP_AMBARI_USERNAME"
-SERVICE_PASSWORD_KEY = "TMP_AMBARI_PASSWORD"
-
-# JDK setup choices
-JDK_DEFAULT_CONFIGS = [
-  JDKRelease("jdk7.67", "Oracle JDK 7.67",
-             "http://public-repo-1.hortonworks.com/ARTIFACTS/jdk-7u67-windows-x64.exe", "jdk-7u67-windows-x64.exe",
-             "http://public-repo-1.hortonworks.com/ARTIFACTS/UnlimitedJCEPolicyJDK7.zip", "UnlimitedJCEPolicyJDK7.zip",
-             None)
-]
-
-JDK_VERSION_REs = ["(jdk.*)/jre", "Creating (jdk.*)/jre"]
-JDK_PROMPT = "[{0}] {1}\n"
-JDK_CUSTOM_CHOICE_PROMPT = "[{0}] - Custom JDK\n==============================================================================\nEnter choice ({1}): "
-JDK_VALID_CHOICES = "^[{0}{1:d}]$"
-CUSTOM_JDK_NUMBER = "4"
-JDK_MIN_FILESIZE = 5000
-MAKE_FILE_EXECUTABLE_CMD = "chmod a+x {0}"
-
-JDK_DOWNLOAD_CMD = "curl --create-dirs -o {0} {1}"
-JDK_DOWNLOAD_SIZE_CMD = "curl -I {0}"
-
-# use --no-same-owner when running as root to prevent uucp as the user (AMBARI-6478)
-UNTAR_JDK_ARCHIVE = "tar --no-same-owner -xvf {0}"
-
-
-#JDBC
-USERNAME_PATTERN = "^[a-zA-Z_][a-zA-Z0-9_\-]*$"
-DATABASE_DBMS = "sqlserver"
-DATABASE_NAME = "ambari"
-DATABASE_SERVER = "localhost\\\\SQLEXPRESS"
-DATABASE_DRIVER_NAME = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
-
-JDBC_PATTERNS = {"sqlserver": "sqljdbc*.jar"}
-DATABASE_FULL_NAMES = {"sqlserver": "SQL Server"}
-JDBC_DB_OPTION_VALUES = ["sqlserver"]
-JDBC_DB_DEFAULT_DRIVER = {"sqlserver" : "sqljdbc4.jar"}
-
-
-ERROR_NOT_ROOT = 'Ambari-server setup should be run with administrator-level privileges'
-
-MESSAGE_CHECK_FIREWALL = 'Checking firewall status...'
-
-def os_check_firewall():
-  out = run_powershell_script(CHECK_FIREWALL_SCRIPT)
-  if out[0] != 0:
-    print_warning_msg("Unable to check firewall status:{0}".format(out[2]))
-    return False
-  profiles_status = [i for i in out[1].split("\n") if not i == ""]
-  if "1" in profiles_status:
-    enabled_profiles = []
-    if profiles_status[0] == "1":
-      enabled_profiles.append("DomainProfile")
-    if profiles_status[1] == "1":
-      enabled_profiles.append("StandardProfile")
-    if profiles_status[2] == "1":
-      enabled_profiles.append("PublicProfile")
-    print_warning_msg("Following firewall profiles enabled:{0}. Make sure that firewall properly configured.".format(",".join(enabled_profiles)))
-    return False
-  return True
-
-# No security enhancements in Windows
-def disable_security_enhancements():
-  retcode = 0
-  err = ''
-  return (retcode, err)
-
-
-#
-# User account creation
-#
-
-def os_create_custom_user():
-  user = get_validated_string_input(
-    "Enter user account for ambari-server service ({0}):".format(NR_DEFAULT_USER),
-    NR_DEFAULT_USER, None,
-    "Invalid username.",
-    False
-  )
-  if user == NR_DEFAULT_USER:
-    return 0, user
-  password = get_validated_string_input("Enter password for user {0}:".format(user), "", None, "Password", True, False)
-
-  uh = UserHelper()
-
-  status, message = uh.create_user(user,password)
-  if status == UserHelper.USER_EXISTS:
-    print_info_msg("User {0} already exists, make sure that you typed correct password for user, "
-                      "skipping user creation".format(user))
-
-  elif status == UserHelper.ACTION_FAILED:  # fail
-    print_warning_msg("Can't create user {0}. Failed with message {1}".format(user, message))
-    return UserHelper.ACTION_FAILED, None
-
-  # setting SeServiceLogonRight to user
-
-  status, message = uh.add_user_privilege(user, 'SeServiceLogonRight')
-  if status == UserHelper.ACTION_FAILED:
-    print_warning_msg("Can't add SeServiceLogonRight to user {0}. Failed with message {1}".format(user, message))
-    return UserHelper.ACTION_FAILED, None
-
-  print_info_msg("User configuration is done.")
-  print_warning_msg("When using non SYSTEM user make sure that your user have read\write access to log directories and "
-                    "all server directories. In case of integrated authentication for SQL Server make sure that your "
-                    "user properly configured to use ambari database.")
-  #storing username and password in os.environ temporary to pass them to service
-  os.environ[SERVICE_USERNAME_KEY] = user
-  os.environ[SERVICE_PASSWORD_KEY] = password
-  return 0, user
-
-
-#
-# JDK Setup
-#
-def populate_jdk_configs(properties, jdk_num):
-  if properties.has_key(JDK_RELEASES):
-    jdk_names = properties[JDK_RELEASES].split(',')
-    jdks = []
-    for jdk_name in jdk_names:
-      jdkR = JDKRelease.from_properties(properties, jdk_name)
-      jdks.append(jdkR)
-  else:
-    jdks = JDK_DEFAULT_CONFIGS
-
-  n_config = 1
-  jdk_choice_prompt = ''
-  jdk_choices = ''
-  for jdk in jdks:
-    jdk_choice_prompt += JDK_PROMPT.format(n_config, jdk.desc)
-    jdk_choices_tmp = '{0}{1:d}'.format(jdk_choices, n_config)
-    jdk_choices = jdk_choices_tmp
-    n_config += 1
-
-  jdk_choice_prompt += JDK_CUSTOM_CHOICE_PROMPT.format(n_config, jdk_num)
-  jdk_valid_choices = JDK_VALID_CHOICES.format(jdk_choices, n_config)
-
-  return (jdks, jdk_choice_prompt, jdk_valid_choices, n_config)
-
-
-def os_install_jdk(java_inst_file, java_home_dir):
-  print "Installing JDK to {0}".format(java_home_dir)
-
-  if not os.path.exists(java_home_dir):
-    os.makedirs(java_home_dir)
-
-  if java_inst_file.endswith(".exe"):
-    (dirname, filename) = os.path.split(java_inst_file)
-    installLogFilePath = os.path.join(configDefaults.OUT_DIR, filename + "-install.log")
-    #jre7u67.exe /s INSTALLDIR=<dir> STATIC=1 WEB_JAVA=0 /L \\var\\log\\ambari-server\\jre7u67.exe-install.log
-    installCmd = [
-      java_inst_file,
-      "/s",
-      "INSTALLDIR=" + java_home_dir,
-      "STATIC=1",
-      "WEB_JAVA=0",
-      "/L",
-      installLogFilePath
-    ]
-    retcode, out, err = run_os_command(installCmd)
-  #TODO: support .msi file installations
-    #msiexec.exe jre.msi /s INSTALLDIR=<dir> STATIC=1 WEB_JAVA=0 /L \\var\\log\\ambari-server\\jre7u67-install.log ?
-  else:
-    err = "JDK installation failed.Unknown file mask."
-    raise FatalException(1, err)
-
-  if retcode == 1603:
-    # JDK already installed
-    print "JDK already installed in {0}".format(java_home_dir)
-    retcode = 0
-  else:
-    if retcode != 0:
-      err = "Installation of JDK returned exit code %s" % retcode
-      raise FatalException(retcode, err)
-
-    print "Successfully installed JDK to {0}".format(java_home_dir)
-
-  # Don't forget to adjust the JAVA_HOME env var
-
-  return (retcode, out)
-
-def os_ensure_java_home_env_var_is_set(java_home_var):
-  if not os.environ.has_key(JAVA_HOME) or os.environ[JAVA_HOME] != java_home_var:
-    java_home_var_val = java_home_var.replace('\\\\', '\\')
-    os.system("SETX {0} {1} /M".format(JAVA_HOME, java_home_var_val))
-    os.environ[JAVA_HOME] = java_home_var
-    pass
-
-#
-# JDBC Setup
-#
-
-def os_check_jdbc_options(options):
-  #Only SQL Server supported, no point in checking options.jdbc_db
-  return (options.jdbc_driver is not None)
-
-def os_setup_jdbc_drivers(args):
-  properties = get_ambari_properties()
-  if properties == -1:
-    print_error_msg("Error getting ambari properties")
-    return -1
-
-  #Only support SQL Server
-  dbms = DBMSConfig.create(args, properties)
-  if dbms.ensure_jdbc_driver_installed(args, properties):
-    # Now save the properties file
-    update_properties(properties)
-  pass
-
-def os_setup_database(options):
-  properties = get_ambari_properties()
-  if properties == -1:
-    raise FatalException(-1, "Error getting ambari properties")
-
-  #Ensure the default database host is set
-  options.default_database_host = "localhost\\SQLEXPRESS"
-
-  #Only support SQL Server
-  dbmsAmbari = DBMSConfig.create(options, properties, "Ambari")
-  resultA = dbmsAmbari.configure_database(options, properties)
-
-  #By default, use the same server for Metrics
-  options.default_database_host = dbmsAmbari.database_host
-
-  # Now save the properties file
-  if resultA:
-    update_properties(properties)
-
-    dbmsAmbari.setup_database()
-
-def os_reset_database(options):
-  properties = get_ambari_properties()
-  if properties == -1:
-    raise FatalException(-1, "Error getting ambari properties")
-
-  if not (properties.getPropertyDict().has_key(JDBC_URL_PROPERTY) and
-            properties.getPropertyDict().has_key(JDBC_RCA_URL_PROPERTY)):
-    raise FatalException(-1, "Ambari Server not set up yet. Nothing to reset.")
-
-  empty_options = optparse.Values()
-  empty_options.silent = options.silent
-  empty_options.database_host = ""
-  empty_options.database_port = ""
-  empty_options.database_name = ""
-  empty_options.database_windows_auth = False
-  empty_options.database_username = ""
-  empty_options.database_password = ""
-  empty_options.init_db_script_file = ""
-  empty_options.cleanup_db_script_file = ""
-
-  #Only support SQL Server
-  dbmsAmbari = DBMSConfig.create(empty_options, properties, "Ambari")
-  dbmsAmbari.reset_database()
-  pass

+ 305 - 0
ambari-server/src/main/python/ambari_server/serverUpgrade.py

@@ -0,0 +1,305 @@
+#!/usr/bin/env python
+
+'''
+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.
+'''
+
+import json
+import os
+import shutil
+
+from ambari_commons.exceptions import FatalException
+from ambari_commons.logging_utils import print_info_msg, print_warning_msg, print_error_msg
+from ambari_commons.os_utils import is_root, run_os_command
+from ambari_server.dbConfiguration import DBMSConfigFactory, check_jdbc_drivers
+from ambari_server.properties import Properties
+from ambari_server.serverConfiguration import configDefaults, \
+  check_database_name_property, get_ambari_properties, get_ambari_version, get_full_ambari_classpath, \
+  get_java_exe_path, get_stack_location, parse_properties_file, read_ambari_user, update_ambari_properties, \
+  update_database_name_property, \
+  AMBARI_PROPERTIES_FILE, IS_LDAP_CONFIGURED, LDAP_PRIMARY_URL_PROPERTY, RESOURCES_DIR_PROPERTY, \
+  SETUP_OR_UPGRADE_MSG
+from ambari_server.setupSecurity import adjust_directory_permissions
+
+# constants
+from ambari_server.utils import compare_versions
+
+STACK_NAME_VER_SEP = "-"
+
+SCHEMA_UPGRADE_HELPER_CMD = "{0} -cp {1} " + \
+                            "org.apache.ambari.server.upgrade.SchemaUpgradeHelper" + \
+                            " > " + configDefaults.SERVER_OUT_FILE + " 2>&1"
+
+STACK_UPGRADE_HELPER_CMD = "{0} -cp {1} " + \
+                           "org.apache.ambari.server.upgrade.StackUpgradeHelper" + \
+                           " {2} {3} > " + configDefaults.SERVER_OUT_FILE + " 2>&1"
+
+
+#
+# Stack upgrade
+#
+
+def upgrade_stack(args, stack_id, repo_url=None, repo_url_os=None):
+  if not is_root():
+    err = 'Ambari-server upgradestack should be run with ' \
+          'root-level privileges'
+    raise FatalException(4, err)
+  check_database_name_property()
+
+  stack_name, stack_version = stack_id.split(STACK_NAME_VER_SEP)
+  retcode = run_stack_upgrade(stack_name, stack_version, repo_url, repo_url_os)
+
+  if not retcode == 0:
+    raise FatalException(retcode, 'Stack upgrade failed.')
+
+  return retcode
+
+def load_stack_values(version, filename):
+  import xml.etree.ElementTree as ET
+  values = {}
+  root = ET.parse(filename).getroot()
+  for ostag in root:
+    ostype = ostag.attrib['type']
+    for repotag in ostag:
+      reponametag = repotag.find('reponame')
+      repoidtag = repotag.find('repoid')
+      baseurltag = repotag.find('baseurl')
+      if reponametag is not None and repoidtag is not None and baseurltag is not None:
+        key = "repo:/" + reponametag.text
+        key += "/" + version
+        key += "/" + ostype
+        key += "/" + repoidtag.text
+        key += ":baseurl"
+        values[key] = baseurltag.text
+
+  return values
+
+
+def run_stack_upgrade(stackName, stackVersion, repo_url, repo_url_os):
+  jdk_path = get_java_exe_path()
+  if jdk_path is None:
+    print_error_msg("No JDK found, please run the \"setup\" "
+                    "command to install a JDK automatically or install any "
+                    "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
+    return 1
+  stackId = {}
+  stackId[stackName] = stackVersion
+  if repo_url is not None:
+    stackId['repo_url'] = repo_url
+  if repo_url_os is not None:
+    stackId['repo_url_os'] = repo_url_os
+
+  command = STACK_UPGRADE_HELPER_CMD.format(jdk_path, get_full_ambari_classpath(),
+                                            "updateStackId",
+                                            "'" + json.dumps(stackId) + "'")
+  (retcode, stdout, stderr) = run_os_command(command)
+  print_info_msg("Return code from stack upgrade command, retcode = " + str(retcode))
+  if retcode > 0:
+    print_error_msg("Error executing stack upgrade, please check the server logs.")
+  return retcode
+
+def run_metainfo_upgrade(keyValueMap=None):
+  jdk_path = get_java_exe_path()
+  if jdk_path is None:
+    print_error_msg("No JDK found, please run the \"setup\" "
+                    "command to install a JDK automatically or install any "
+                    "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
+
+  retcode = 1
+  if keyValueMap:
+    command = STACK_UPGRADE_HELPER_CMD.format(jdk_path, get_full_ambari_classpath(),
+                                              'updateMetaInfo',
+                                              "'" + json.dumps(keyValueMap) + "'")
+    (retcode, stdout, stderr) = run_os_command(command)
+    print_info_msg("Return code from stack upgrade command, retcode = " + str(retcode))
+    if retcode > 0:
+      print_error_msg("Error executing metainfo upgrade, please check the "
+                      "server logs.")
+
+  return retcode
+
+
+#
+# Repo upgrade
+#
+
+def change_objects_owner(args):
+  print 'Fixing database objects owner'
+
+  properties = Properties()   #Dummy, args contains the dbms name and parameters already
+
+  factory = DBMSConfigFactory()
+  dbms = factory.create(args, properties)
+
+  dbms.change_db_files_owner()
+
+def upgrade_local_repo(args):
+  properties = get_ambari_properties()
+  if properties == -1:
+    print_error_msg("Error getting ambari properties")
+    return -1
+
+  stack_location = get_stack_location(properties)
+  stack_root_local = os.path.join(stack_location, "HDPLocal")
+  if not os.path.exists(stack_root_local):
+    print_info_msg("HDPLocal stack directory does not exist, skipping")
+    return
+
+  stack_root = os.path.join(stack_location, "HDP")
+  if not os.path.exists(stack_root):
+    print_info_msg("HDP stack directory does not exist, skipping")
+    return
+
+  for stack_version_local in os.listdir(stack_root_local):
+    repo_file_local = os.path.join(stack_root_local, stack_version_local, "repos", "repoinfo.xml.rpmsave")
+    if not os.path.exists(repo_file_local):
+      repo_file_local = os.path.join(stack_root_local, stack_version_local, "repos", "repoinfo.xml")
+
+    repo_file = os.path.join(stack_root, stack_version_local, "repos", "repoinfo.xml")
+
+    print_info_msg("Local repo file: " + repo_file_local)
+    print_info_msg("Repo file: " + repo_file_local)
+
+    metainfo_update_items = {}
+
+    if os.path.exists(repo_file_local) and os.path.exists(repo_file):
+      local_values = load_stack_values(stack_version_local, repo_file_local)
+      repo_values = load_stack_values(stack_version_local, repo_file)
+      for k, v in local_values.iteritems():
+        if repo_values.has_key(k):
+          local_url = local_values[k]
+          repo_url = repo_values[k]
+          if repo_url != local_url:
+            metainfo_update_items[k] = local_url
+
+    run_metainfo_upgrade(metainfo_update_items)
+
+#
+# Schema upgrade
+#
+
+def run_schema_upgrade():
+  jdk_path = get_java_exe_path()
+  if jdk_path is None:
+    print_error_msg("No JDK found, please run the \"setup\" "
+                    "command to install a JDK automatically or install any "
+                    "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
+    return 1
+
+  print 'Upgrading database schema'
+
+  command = SCHEMA_UPGRADE_HELPER_CMD.format(jdk_path, get_full_ambari_classpath())
+  (retcode, stdout, stderr) = run_os_command(command)
+  print_info_msg("Return code from schema upgrade command, retcode = " + str(retcode))
+  if retcode > 0:
+    print_error_msg("Error executing schema upgrade, please check the server logs.")
+  else:
+    print_info_msg('Schema upgrade completed')
+  return retcode
+
+
+#
+# Upgrades the Ambari Server.
+#
+def move_user_custom_actions():
+  print_info_msg('Moving *.py files from custom_actions to custom_actions/scripts')
+  properties = get_ambari_properties()
+  if properties == -1:
+    err = "Error getting ambari properties"
+    print_error_msg(err)
+    raise FatalException(-1, err)
+
+  try:
+    resources_dir = properties[RESOURCES_DIR_PROPERTY]
+  except (KeyError), e:
+    conf_file = properties.fileName
+    err = 'Property ' + str(e) + ' is not defined at ' + conf_file
+    print_error_msg(err)
+    raise FatalException(1, err)
+
+  custom_actions_dir_path = os.path.join(resources_dir, 'custom_actions')
+  custom_actions_scripts_dir_path = os.path.join(custom_actions_dir_path, 'scripts')
+  print_info_msg('Moving *.py files from %s to %s' % (custom_actions_dir_path, custom_actions_scripts_dir_path))
+
+  try:
+    for custom_action_file_name in os.listdir(custom_actions_dir_path):
+      custom_action_file_path = os.path.join(custom_actions_dir_path, custom_action_file_name)
+      if os.path.isfile(custom_action_file_path) and custom_action_file_path.endswith('.py'):
+        print_info_msg('Moving %s to %s' % (custom_action_file_path, custom_actions_scripts_dir_path))
+        shutil.move(custom_action_file_path, custom_actions_scripts_dir_path)
+  except (OSError, shutil.Error) as e:
+    err = 'Upgrade failed. Can not move *.py files from %s to %s. ' % (custom_actions_dir_path, custom_actions_scripts_dir_path) + str(e)
+    print_error_msg(err)
+    raise FatalException(1, err)
+
+def upgrade(args):
+  if not is_root():
+    err = configDefaults.MESSAGE_ERROR_UPGRADE_NOT_ROOT
+    raise FatalException(4, err)
+
+  print 'Updating properties in ' + AMBARI_PROPERTIES_FILE + ' ...'
+  retcode = update_ambari_properties()
+  if not retcode == 0:
+    err = AMBARI_PROPERTIES_FILE + ' file can\'t be updated. Exiting'
+    raise FatalException(retcode, err)
+
+  try:
+    update_database_name_property(upgrade=True)
+  except FatalException:
+    return -1
+
+  # Ignore the server version & database options passed via command-line arguments
+  parse_properties_file(args)
+
+  #TODO check database version
+  change_objects_owner(args)
+
+  retcode = run_schema_upgrade()
+  if not retcode == 0:
+    print_error_msg("Ambari server upgrade failed. Please look at {0}, for more details.".format(configDefaults.SERVER_LOG_FILE))
+    raise FatalException(11, 'Schema upgrade failed.')
+
+  user = read_ambari_user()
+  if user is None:
+    warn = "Can not determine custom ambari user.\n" + SETUP_OR_UPGRADE_MSG
+    print_warning_msg(warn)
+  else:
+    adjust_directory_permissions(user)
+
+  # local repo
+  upgrade_local_repo(args)
+
+  # create jdbc symlinks if jdbc drivers are available in resources
+  check_jdbc_drivers(args)
+
+  properties = get_ambari_properties()
+  if properties == -1:
+    err = "Error getting ambari properties"
+    print_error_msg(err)
+    raise FatalException(-1, err)
+
+  # Move *.py files from custom_actions to custom_actions/scripts
+  # This code exists for historic reasons in which custom action python scripts location changed from Ambari 1.7.0 to 2.0.0
+  ambari_version = get_ambari_version(properties)
+  if ambari_version is None:
+    args.warnings.append("*.py files were not moved from custom_actions to custom_actions/scripts.")
+  elif compare_versions(ambari_version, "2.0.0") == 0:
+    move_user_custom_actions()
+
+  # check if ambari has obsolete LDAP configuration
+  if properties.get_property(LDAP_PRIMARY_URL_PROPERTY) and not properties.get_property(IS_LDAP_CONFIGURED):
+    args.warnings.append("Existing LDAP configuration is detected. You must run the \"ambari-server setup-ldap\" command to adjust existing LDAP configuration.")

+ 3 - 1
ambari-server/src/main/python/ambari_server/setupActions.py

@@ -30,10 +30,12 @@ REFRESH_STACK_HASH_ACTION = "refresh-stack-hash"
 STATUS_ACTION = "status"
 STATUS_ACTION = "status"
 SETUP_HTTPS_ACTION = "setup-https"
 SETUP_HTTPS_ACTION = "setup-https"
 LDAP_SETUP_ACTION = "setup-ldap"
 LDAP_SETUP_ACTION = "setup-ldap"
+LDAP_SYNC_ACTION = "sync-ldap"
 SETUP_GANGLIA_HTTPS_ACTION = "setup-ganglia-https"
 SETUP_GANGLIA_HTTPS_ACTION = "setup-ganglia-https"
-SETUP_NAGIOS_HTTPS_ACTION = "setup-nagios-https"
 ENCRYPT_PASSWORDS_ACTION = "encrypt-passwords"
 ENCRYPT_PASSWORDS_ACTION = "encrypt-passwords"
 SETUP_SECURITY_ACTION = "setup-security"
 SETUP_SECURITY_ACTION = "setup-security"
+BACKUP_ACTION = "backup"
+RESTORE_ACTION = "restore"
 
 
 ACTION_REQUIRE_RESTART = [RESET_ACTION, UPGRADE_ACTION, UPGRADE_STACK_ACTION,
 ACTION_REQUIRE_RESTART = [RESET_ACTION, UPGRADE_ACTION, UPGRADE_STACK_ACTION,
                           SETUP_SECURITY_ACTION, LDAP_SETUP_ACTION]
                           SETUP_SECURITY_ACTION, LDAP_SETUP_ACTION]

+ 76 - 199
ambari-server/src/main/python/ambari_server/setupSecurity.py

@@ -24,22 +24,27 @@ import random
 import re
 import re
 import shutil
 import shutil
 import socket
 import socket
-import stat
 import string
 import string
-import sys
 import tempfile
 import tempfile
 import urllib2
 import urllib2
+import time
 
 
 from ambari_commons.exceptions import NonFatalException, FatalException
 from ambari_commons.exceptions import NonFatalException, FatalException
 from ambari_commons.logging_utils import get_silent, print_warning_msg, print_error_msg, print_info_msg
 from ambari_commons.logging_utils import get_silent, print_warning_msg, print_error_msg, print_info_msg
-from ambari_commons.os_check import OSCheck, OSConst
+from ambari_commons.os_check import OSCheck
 from ambari_commons.os_utils import copy_file, is_root, is_valid_filepath, remove_file, set_file_permissions, \
 from ambari_commons.os_utils import copy_file, is_root, is_valid_filepath, remove_file, set_file_permissions, \
   run_os_command, search_file
   run_os_command, search_file
 from ambari_server.serverConfiguration import configDefaults, get_ambari_properties, read_ambari_user, \
 from ambari_server.serverConfiguration import configDefaults, get_ambari_properties, read_ambari_user, \
-  get_value_from_properties, find_jdk, get_ambari_classpath, get_conf_dir, is_alias_string, find_properties_file, \
+  get_value_from_properties, find_jdk, get_conf_dir, is_alias_string, find_properties_file, \
   update_properties_2, \
   update_properties_2, \
   JDBC_USE_INTEGRATED_AUTH_PROPERTY, JDBC_PASSWORD_PROPERTY, JDBC_PASSWORD_FILENAME, \
   JDBC_USE_INTEGRATED_AUTH_PROPERTY, JDBC_PASSWORD_PROPERTY, JDBC_PASSWORD_FILENAME, \
-  JDBC_RCA_PASSWORD_FILE_PROPERTY, JDBC_RCA_PASSWORD_ALIAS, BOOTSTRAP_DIR_PROPERTY, GET_FQDN_SERVICE_URL, BLIND_PASSWORD
+  JDBC_RCA_PASSWORD_FILE_PROPERTY, JDBC_RCA_PASSWORD_ALIAS, \
+  BOOTSTRAP_DIR_PROPERTY, GET_FQDN_SERVICE_URL, BLIND_PASSWORD, get_full_ambari_classpath, LDAP_MGR_PASSWORD_ALIAS, \
+  LDAP_MGR_PASSWORD_PROPERTY, LDAP_MGR_USERNAME_PROPERTY, decrypt_password_for_alias, read_passwd_for_alias, \
+  get_is_secure, get_master_key_location, get_credential_store_location, get_is_persisted, get_original_master_key, \
+  get_java_exe_path, SECURITY_PROVIDER_KEY_CMD, SECURITY_PROVIDER_PUT_CMD, SECURITY_IS_ENCRYPTION_ENABLED, \
+  SECURITY_KERBEROS_JASS_FILENAME, SECURITY_KEY_ENV_VAR_NAME, SECURITY_MASTER_KEY_FILENAME, \
+  SSL_TRUSTSTORE_PASSWORD_ALIAS, SSL_TRUSTSTORE_PASSWORD_PROPERTY, SSL_TRUSTSTORE_PATH_PROPERTY, SSL_TRUSTSTORE_TYPE_PROPERTY
 from setupActions import SETUP_ACTION, LDAP_SETUP_ACTION
 from setupActions import SETUP_ACTION, LDAP_SETUP_ACTION
 from ambari_server.userInput import get_YN_input, get_validated_string_input, get_validated_filepath_input, \
 from ambari_server.userInput import get_YN_input, get_validated_string_input, get_validated_filepath_input, \
   get_prompt_default
   get_prompt_default
@@ -63,28 +68,6 @@ KEYTOOL_IMPORT_CERT_CMD = "{0}" + os.sep + "bin" + os.sep + keytool_bin + " -imp
 KEYTOOL_DELETE_CERT_CMD = "{0}" + os.sep + "bin" + os.sep + keytool_bin + " -delete -alias '{1}' -storepass '{2}' -noprompt"
 KEYTOOL_DELETE_CERT_CMD = "{0}" + os.sep + "bin" + os.sep + keytool_bin + " -delete -alias '{1}' -storepass '{2}' -noprompt"
 KEYTOOL_KEYSTORE = " -keystore '{0}'"
 KEYTOOL_KEYSTORE = " -keystore '{0}'"
 
 
-java_bin = "java"
-if OSCheck.is_windows_family():
-  java_bin = "java.exe"
-
-SECURITY_PROVIDER_GET_CMD = "{0}" + os.sep + "bin" + os.sep + java_bin + " -cp {1}" +\
-                          os.pathsep + "{2} " +\
-                          "org.apache.ambari.server.security.encryption" +\
-                          ".CredentialProvider GET {3} {4} {5} " +\
-                          "> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
-
-SECURITY_PROVIDER_PUT_CMD = "{0}" + os.sep + "bin" + os.sep + java_bin + " -cp {1}" +\
-                          os.pathsep + "{2} " +\
-                          "org.apache.ambari.server.security.encryption" +\
-                          ".CredentialProvider PUT {3} {4} {5} " +\
-                          "> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
-
-SECURITY_PROVIDER_KEY_CMD = "{0}" + os.sep + "bin" + os.sep + java_bin + " -cp {1}" +\
-                          os.pathsep + "{2} " +\
-                          "org.apache.ambari.server.security.encryption" +\
-                          ".MasterKeyServiceImpl {3} {4} {5} " +\
-                          "> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
-
 SSL_KEY_DIR = 'security.server.keys_dir'
 SSL_KEY_DIR = 'security.server.keys_dir'
 SSL_API_PORT = 'client.api.ssl.port'
 SSL_API_PORT = 'client.api.ssl.port'
 SSL_API = 'api.ssl'
 SSL_API = 'api.ssl'
@@ -109,29 +92,12 @@ SRVR_TWO_WAY_SSL_PORT = "8441"
 SRVR_ONE_WAY_SSL_PORT_PROPERTY = "security.server.one_way_ssl.port"
 SRVR_ONE_WAY_SSL_PORT_PROPERTY = "security.server.one_way_ssl.port"
 SRVR_ONE_WAY_SSL_PORT = "8440"
 SRVR_ONE_WAY_SSL_PORT = "8440"
 
 
-SECURITY_KEYS_DIR = "security.server.keys_dir"
-SECURITY_MASTER_KEY_LOCATION = "security.master.key.location"
-SECURITY_KEY_IS_PERSISTED = "security.master.key.ispersisted"
-SECURITY_KEY_ENV_VAR_NAME = "AMBARI_SECURITY_MASTER_KEY"
-SECURITY_MASTER_KEY_FILENAME = "master"
-SECURITY_IS_ENCRYPTION_ENABLED = "security.passwords.encryption.enabled"
-SECURITY_KERBEROS_JASS_FILENAME = "krb5JAASLogin.conf"
-
 GANGLIA_HTTPS = 'ganglia.https'
 GANGLIA_HTTPS = 'ganglia.https'
 NAGIOS_HTTPS = 'nagios.https'
 NAGIOS_HTTPS = 'nagios.https'
 
 
-SSL_TRUSTSTORE_PASSWORD_ALIAS = "ambari.ssl.trustStore.password"
-SSL_TRUSTSTORE_PATH_PROPERTY = "ssl.trustStore.path"
-SSL_TRUSTSTORE_PASSWORD_PROPERTY = "ssl.trustStore.password"
-SSL_TRUSTSTORE_TYPE_PROPERTY = "ssl.trustStore.type"
-
 DEFAULT_PASSWORD = "bigdata"
 DEFAULT_PASSWORD = "bigdata"
 PASSWORD_PATTERN = "^[a-zA-Z0-9_-]*$"
 PASSWORD_PATTERN = "^[a-zA-Z0-9_-]*$"
 
 
-LDAP_MGR_PASSWORD_ALIAS = "ambari.ldap.manager.password"
-LDAP_MGR_PASSWORD_PROPERTY = "authentication.ldap.managerPassword"
-LDAP_MGR_USERNAME_PROPERTY = "authentication.ldap.managerDn"
-
 REGEX_IP_ADDRESS = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
 REGEX_IP_ADDRESS = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
 REGEX_HOSTNAME = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
 REGEX_HOSTNAME = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
 REGEX_HOSTNAME_PORT = "^(.*:[0-9]{1,5}$)"
 REGEX_HOSTNAME_PORT = "^(.*:[0-9]{1,5}$)"
@@ -420,7 +386,7 @@ def get_truststore_password(properties):
   isSecure = get_is_secure(properties)
   isSecure = get_is_secure(properties)
   if truststore_password:
   if truststore_password:
     if isSecure:
     if isSecure:
-      truststore_password = decrypt_password_for_alias(SSL_TRUSTSTORE_PASSWORD_ALIAS)
+      truststore_password = decrypt_password_for_alias(properties, SSL_TRUSTSTORE_PASSWORD_ALIAS)
   else:
   else:
     truststore_password = read_password("", ".*", "Password for TrustStore:", "Invalid characters in password")
     truststore_password = read_password("", ".*", "Password for TrustStore:", "Invalid characters in password")
     if truststore_password:
     if truststore_password:
@@ -429,40 +395,40 @@ def get_truststore_password(properties):
 
 
   return truststore_password
   return truststore_password
 
 
+def get_pass_file_path(conf_file, filename):
+  return os.path.join(os.path.dirname(conf_file), filename)
+
 def read_password(passwordDefault=DEFAULT_PASSWORD,
 def read_password(passwordDefault=DEFAULT_PASSWORD,
                   passwordPattern=PASSWORD_PATTERN,
                   passwordPattern=PASSWORD_PATTERN,
                   passwordPrompt=None,
                   passwordPrompt=None,
                   passwordDescr=None):
                   passwordDescr=None):
-  # setup password
-  if passwordPrompt is None:
-    passwordPrompt = 'Password (' + passwordDefault + '): '
-
-  if passwordDescr is None:
-    passwordDescr = "Invalid characters in password. Use only alphanumeric or " \
-                    "_ or - characters"
-
-  password = get_validated_string_input(passwordPrompt, passwordDefault,
-                                        passwordPattern, passwordDescr, True)
-
-  if not password:
-    print 'Password cannot be blank.'
-    return read_password(passwordDefault, passwordPattern, passwordPrompt,
-                   passwordDescr)
-
-  if password != passwordDefault:
-    password1 = get_validated_string_input("Re-enter password: ",
-                                           passwordDefault, passwordPattern, passwordDescr, True)
-    if password != password1:
-      print "Passwords do not match"
-      return read_password(passwordDefault, passwordPattern, passwordPrompt,
-                      passwordDescr)
 
 
-  return password
+  input = True
+  while(input):
+    # setup password
+    if passwordPrompt is None:
+      passwordPrompt = 'Password (' + passwordDefault + '): '
 
 
-def get_is_secure(properties):
-  isSecure = properties.get_property(SECURITY_IS_ENCRYPTION_ENABLED)
-  isSecure = True if isSecure and isSecure.lower() == 'true' else False
-  return isSecure
+    if passwordDescr is None:
+      passwordDescr = "Invalid characters in password. Use only alphanumeric or " \
+                      "_ or - characters"
+
+    password = get_validated_string_input(passwordPrompt, passwordDefault,
+                                          passwordPattern, passwordDescr, True)
+    if not password:
+      print 'Password cannot be blank.'
+      continue
+
+    if password != passwordDefault:
+      password1 = get_validated_string_input("Re-enter password: ",
+                                             passwordDefault, passwordPattern, passwordDescr, True)
+      if password != password1:
+        print "Passwords do not match"
+        continue
+
+    input = False
+
+  return password
 
 
 def encrypt_password(alias, password):
 def encrypt_password(alias, password):
   properties = get_ambari_properties()
   properties = get_ambari_properties()
@@ -494,59 +460,6 @@ def get_alias_string(alias):
 def get_alias_from_alias_string(aliasStr):
 def get_alias_from_alias_string(aliasStr):
   return aliasStr[8:-1]
   return aliasStr[8:-1]
 
 
-def read_passwd_for_alias(alias, masterKey=""):
-  if alias:
-    jdk_path = find_jdk()
-    if jdk_path is None:
-      print_error_msg("No JDK found, please run the \"setup\" "
-                      "command to install a JDK automatically or install any "
-                      "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
-      return 1
-
-    tempFileName = "ambari.passwd"
-    passwd = ""
-    tempDir = tempfile.gettempdir()
-    #create temporary file for writing
-    tempFilePath = tempDir + os.sep + tempFileName
-    file = open(tempFilePath, 'w+')
-    os.chmod(tempFilePath, stat.S_IREAD | stat.S_IWRITE)
-    file.close()
-
-    if masterKey is None or masterKey == "":
-      masterKey = "None"
-
-    command = SECURITY_PROVIDER_GET_CMD.format(jdk_path,
-      get_conf_dir(), get_ambari_classpath(), alias, tempFilePath, masterKey)
-    (retcode, stdout, stderr) = run_os_command(command)
-    print_info_msg("Return code from credential provider get passwd: " +
-                   str(retcode))
-    if retcode != 0:
-      print 'ERROR: Unable to read password from store. alias = ' + alias
-    else:
-      passwd = open(tempFilePath, 'r').read()
-      # Remove temporary file
-    os.remove(tempFilePath)
-    return passwd
-  else:
-    print_error_msg("Alias is unreadable.")
-
-def decrypt_password_for_alias(alias):
-  properties = get_ambari_properties()
-  if properties == -1:
-    raise FatalException(1, None)
-
-  isSecure = get_is_secure(properties)
-  (isPersisted, masterKeyFile) = get_is_persisted(properties)
-  if isSecure:
-    masterKey = None
-    if not masterKeyFile:
-      # Encryption enabled but no master key file found
-      masterKey = get_original_master_key(properties)
-
-    return read_passwd_for_alias(alias, masterKey)
-  else:
-    return alias
-
 def save_passwd_for_alias(alias, passwd, masterKey=""):
 def save_passwd_for_alias(alias, passwd, masterKey=""):
   if alias and passwd:
   if alias and passwd:
     jdk_path = find_jdk()
     jdk_path = find_jdk()
@@ -559,8 +472,8 @@ def save_passwd_for_alias(alias, passwd, masterKey=""):
     if masterKey is None or masterKey == "":
     if masterKey is None or masterKey == "":
       masterKey = "None"
       masterKey = "None"
 
 
-    command = SECURITY_PROVIDER_PUT_CMD.format(jdk_path, get_conf_dir(),
-      get_ambari_classpath(), alias, passwd, masterKey)
+    command = SECURITY_PROVIDER_PUT_CMD.format(get_java_exe_path(),
+      get_full_ambari_classpath(), alias, passwd, masterKey)
     (retcode, stdout, stderr) = run_os_command(command)
     (retcode, stdout, stderr) = run_os_command(command)
     print_info_msg("Return code from credential provider save passwd: " +
     print_info_msg("Return code from credential provider save passwd: " +
                    str(retcode))
                    str(retcode))
@@ -568,61 +481,6 @@ def save_passwd_for_alias(alias, passwd, masterKey=""):
   else:
   else:
     print_error_msg("Alias or password is unreadable.")
     print_error_msg("Alias or password is unreadable.")
 
 
-def get_is_persisted(properties):
-  keyLocation = get_master_key_location(properties)
-  masterKeyFile = search_file(SECURITY_MASTER_KEY_FILENAME, keyLocation)
-  isPersisted = True if masterKeyFile else False
-
-  return (isPersisted, masterKeyFile)
-
-def get_credential_store_location(properties):
-  store_loc = properties[SECURITY_KEYS_DIR]
-  if store_loc is None or store_loc == "":
-    store_loc = "/var/lib/ambari-server/keys/credentials.jceks"
-  else:
-    store_loc += os.sep + "credentials.jceks"
-  return store_loc
-
-def get_master_key_location(properties):
-  keyLocation = properties[SECURITY_MASTER_KEY_LOCATION]
-  if keyLocation is None or keyLocation == "":
-    keyLocation = properties[SECURITY_KEYS_DIR]
-  return keyLocation
-
-def get_original_master_key(properties):
-  try:
-    masterKey = get_validated_string_input('Enter current Master Key: ',
-                                             "", ".*", "", True, False)
-  except KeyboardInterrupt:
-    print 'Exiting...'
-    sys.exit(1)
-
-  # Find an alias that exists
-  alias = None
-  property = properties.get_property(JDBC_PASSWORD_PROPERTY)
-  if property and is_alias_string(property):
-    alias = JDBC_RCA_PASSWORD_ALIAS
-
-  alias = None
-  if not alias:
-    property = properties.get_property(LDAP_MGR_PASSWORD_PROPERTY)
-    if property and is_alias_string(property):
-      alias = LDAP_MGR_PASSWORD_ALIAS
-
-  if not alias:
-    property = properties.get_property(SSL_TRUSTSTORE_PASSWORD_PROPERTY)
-    if property and is_alias_string(property):
-      alias = SSL_TRUSTSTORE_PASSWORD_ALIAS
-
-  # Decrypt alias with master to validate it, if no master return
-  if alias and masterKey:
-    password = read_passwd_for_alias(alias, masterKey)
-    if not password:
-      print "ERROR: Master key does not match."
-      return get_original_master_key(properties)
-
-  return masterKey
-
 def read_master_key(isReset=False):
 def read_master_key(isReset=False):
   passwordPattern = ".*"
   passwordPattern = ".*"
   passwordPrompt = "Please provide master key for locking the credential store: "
   passwordPrompt = "Please provide master key for locking the credential store: "
@@ -632,19 +490,23 @@ def read_master_key(isReset=False):
   if isReset:
   if isReset:
     passwordPrompt = "Enter new Master Key: "
     passwordPrompt = "Enter new Master Key: "
 
 
-  masterKey = get_validated_string_input(passwordPrompt, passwordDefault,
-                            passwordPattern, passwordDescr, True, True)
+  input = True
+  while(input):
+    masterKey = get_validated_string_input(passwordPrompt, passwordDefault,
+                              passwordPattern, passwordDescr, True, True)
 
 
-  if not masterKey:
-    print "Master Key cannot be empty!"
-    return read_master_key()
+    if not masterKey:
+      print "Master Key cannot be empty!"
+      continue
 
 
-  masterKey2 = get_validated_string_input("Re-enter master key: ",
-      passwordDefault, passwordPattern, passwordDescr, True, True)
+    masterKey2 = get_validated_string_input("Re-enter master key: ",
+        passwordDefault, passwordPattern, passwordDescr, True, True)
 
 
-  if masterKey != masterKey2:
-    print "Master key did not match!"
-    return read_master_key()
+    if masterKey != masterKey2:
+      print "Master key did not match!"
+      continue
+
+    input = False
 
 
   return masterKey
   return masterKey
 
 
@@ -656,8 +518,8 @@ def save_master_key(master_key, key_location, persist=True):
                       "command to install a JDK automatically or install any "
                       "command to install a JDK automatically or install any "
                       "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
                       "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
       return 1
       return 1
-    command = SECURITY_PROVIDER_KEY_CMD.format(jdk_path,
-      get_ambari_classpath(), get_conf_dir(), master_key, key_location, persist)
+    command = SECURITY_PROVIDER_KEY_CMD.format(get_java_exe_path(),
+      get_full_ambari_classpath(), master_key, key_location, persist)
     (retcode, stdout, stderr) = run_os_command(command)
     (retcode, stdout, stderr) = run_os_command(command)
     print_info_msg("Return code from credential provider save KEY: " +
     print_info_msg("Return code from credential provider save KEY: " +
                    str(retcode))
                    str(retcode))
@@ -666,8 +528,7 @@ def save_master_key(master_key, key_location, persist=True):
 
 
 def store_password_file(password, filename):
 def store_password_file(password, filename):
   conf_file = find_properties_file()
   conf_file = find_properties_file()
-  passFilePath = os.path.join(os.path.dirname(conf_file),
-    filename)
+  passFilePath = get_pass_file_path(conf_file, filename)
 
 
   with open(passFilePath, 'w+') as passFile:
   with open(passFilePath, 'w+') as passFile:
     passFile.write(password)
     passFile.write(password)
@@ -694,10 +555,25 @@ def remove_password_file(filename):
 
 
 def adjust_directory_permissions(ambari_user):
 def adjust_directory_permissions(ambari_user):
   properties = get_ambari_properties()
   properties = get_ambari_properties()
-  bootstrap_dir = get_value_from_properties(properties, BOOTSTRAP_DIR_PROPERTY)
+
+  bootstrap_dir = os.path.abspath(get_value_from_properties(properties, BOOTSTRAP_DIR_PROPERTY))
   print_info_msg("Cleaning bootstrap directory ({0}) contents...".format(bootstrap_dir))
   print_info_msg("Cleaning bootstrap directory ({0}) contents...".format(bootstrap_dir))
+
   shutil.rmtree(bootstrap_dir, True) #Ignore the non-existent dir error
   shutil.rmtree(bootstrap_dir, True) #Ignore the non-existent dir error
-  os.makedirs(bootstrap_dir)
+  #Protect against directories lingering around
+  del_attempts = 0
+  while os.path.exists(bootstrap_dir) and del_attempts < 100:
+    time.sleep(50)
+    del_attempts += 1
+  if not os.path.exists(bootstrap_dir):
+    try:
+      os.makedirs(bootstrap_dir)
+    except Exception, ex:
+      print_warning_msg("Failed recreating the bootstrap directory: {0}".format(str(ex)))
+      pass
+  else:
+    print_warning_msg("Bootstrap directory lingering around after 5s. Unable to complete the cleanup.")
+
   # Add master key and credential store if exists
   # Add master key and credential store if exists
   keyLocation = get_master_key_location(properties)
   keyLocation = get_master_key_location(properties)
   masterKeyFile = search_file(SECURITY_MASTER_KEY_FILENAME, keyLocation)
   masterKeyFile = search_file(SECURITY_MASTER_KEY_FILENAME, keyLocation)
@@ -710,6 +586,7 @@ def adjust_directory_permissions(ambari_user):
   if trust_store_location:
   if trust_store_location:
     configDefaults.NR_ADJUST_OWNERSHIP_LIST.append((trust_store_location, configDefaults.TRUST_STORE_LOCATION_PERMISSIONS, "{0}", "{0}", False))
     configDefaults.NR_ADJUST_OWNERSHIP_LIST.append((trust_store_location, configDefaults.TRUST_STORE_LOCATION_PERMISSIONS, "{0}", "{0}", False))
   print "Adjusting ambari-server permissions and ownership..."
   print "Adjusting ambari-server permissions and ownership..."
+
   for pack in configDefaults.NR_ADJUST_OWNERSHIP_LIST:
   for pack in configDefaults.NR_ADJUST_OWNERSHIP_LIST:
     file = pack[0]
     file = pack[0]
     mod = pack[1]
     mod = pack[1]

+ 18 - 11
ambari-server/src/main/python/ambari_server/userInput.py

@@ -41,21 +41,28 @@ def get_choice_string_input(prompt, default, firstChoice, secondChoice):
   if get_silent():
   if get_silent():
     print(prompt)
     print(prompt)
     return default
     return default
-  choice = raw_input(prompt).lower()
-  if choice in firstChoice:
-    return True
-  elif choice in secondChoice:
-    return False
-  elif choice is "":  # Just enter pressed
-    return default
-  else:
-    print "input not recognized, please try again: "
-    return get_choice_string_input(prompt, default, firstChoice, secondChoice)
+
+  input = True
+  result = default
+  while input:
+    choice = raw_input(prompt).lower()
+    if choice in firstChoice:
+      result = True
+      input = False
+    elif choice in secondChoice:
+      result = False
+      input = False
+    elif choice is "":  # Just enter pressed
+      result = default
+      input = False
+    else:
+      print "input not recognized, please try again: "
+
+  return result
 
 
 
 
 def get_validated_string_input(prompt, default, pattern, description,
 def get_validated_string_input(prompt, default, pattern, description,
                                is_pass, allowEmpty=True, validatorFunction=None):
                                is_pass, allowEmpty=True, validatorFunction=None):
-
   input = ""
   input = ""
   while not input:
   while not input:
     if get_silent():
     if get_silent():

+ 1 - 1
ambari-server/src/main/resources/custom_actions/scripts/check_host.py

@@ -192,7 +192,7 @@ class CheckHost(Script):
         install_cmd = format("mkdir -p {java_dir} ; cd {java_dir} ; tar -xf {jdk_download_target} > /dev/null 2>&1")
         install_cmd = format("mkdir -p {java_dir} ; cd {java_dir} ; tar -xf {jdk_download_target} > /dev/null 2>&1")
         install_path = ["/bin","/usr/bin/"]
         install_path = ["/bin","/usr/bin/"]
       elif jdk_name.endswith(".exe"):
       elif jdk_name.endswith(".exe"):
-        install_cmd = "{} /s INSTALLDIR={} STATIC=1 WEB_JAVA=0 /L \\var\\log\\ambari-agent".format(
+        install_cmd = "{0} /s INSTALLDIR={1} STATIC=1 WEB_JAVA=0 /L \\var\\log\\ambari-agent".format(
           os_utils.quote_path(jdk_download_target), os_utils.quote_path(java64_home),
           os_utils.quote_path(jdk_download_target), os_utils.quote_path(java64_home),
         )
         )
         install_path = [java_dir]
         install_path = [java_dir]

+ 2 - 2
ambari-server/src/main/resources/stacks/HDPWIN/2.1/hooks/before-ANY/scripts/setup_jdk.py

@@ -24,7 +24,7 @@ from ambari_commons.inet_utils import download_file
 from resource_management import *
 from resource_management import *
 
 
 
 
-_install_cmd = '{} /s INSTALLDIR={} ADDLOCAL="ToolsFeature,SourceFeature"'
+_install_cmd = '{0} /s INSTALLDIR={1} ADDLOCAL="ToolsFeature,SourceFeature"'
 
 
 
 
 def _check_installed():
 def _check_installed():
@@ -42,7 +42,7 @@ def setup_jdk():
   if not os.path.exists(params.java_home):
   if not os.path.exists(params.java_home):
     os.makedirs(params.java_home)
     os.makedirs(params.java_home)
   jdk_setup_savepath = os.path.join(params.java_home, params.jdk_name)
   jdk_setup_savepath = os.path.join(params.java_home, params.jdk_name)
-  jdk_download_url = "{}/{}".format(params.jdk_location, params.jdk_name)
+  jdk_download_url = "{0}/{1}".format(params.jdk_location, params.jdk_name)
   download_file(jdk_download_url, jdk_setup_savepath)
   download_file(jdk_download_url, jdk_setup_savepath)
   Execute(_install_cmd.format(jdk_setup_savepath, params.java_home))
   Execute(_install_cmd.format(jdk_setup_savepath, params.java_home))
   if not _check_installed():
   if not _check_installed():

+ 2 - 2
ambari-server/src/main/resources/stacks/HDPWIN/2.1/services/YARN/package/scripts/mapred_service_check.py

@@ -40,11 +40,11 @@ class MapReduce2ServiceCheck(Script):
     validateStatusFileName = "validateYarnComponentStatus.py"
     validateStatusFileName = "validateYarnComponentStatus.py"
     validateStatusFilePath = os.path.join(os.path.dirname(params.hadoop_home), "temp", validateStatusFileName)
     validateStatusFilePath = os.path.join(os.path.dirname(params.hadoop_home), "temp", validateStatusFileName)
     python_executable = sys.executable
     python_executable = sys.executable
-    validateStatusCmd = "{} {} {} -p {} -s {}".format(
+    validateStatusCmd = "{0} {1} {2} -p {3} -s {4}".format(
       python_executable, validateStatusFilePath, component_type, component_address, params.hadoop_ssl_enabled)
       python_executable, validateStatusFilePath, component_type, component_address, params.hadoop_ssl_enabled)
 
 
     if params.security_enabled:
     if params.security_enabled:
-      kinit_cmd = "{} -kt {} {};".format(params.kinit_path_local, params.smoke_user_keytab, params.smokeuser)
+      kinit_cmd = "{0} -kt {1} {2};".format(params.kinit_path_local, params.smoke_user_keytab, params.smokeuser)
       smoke_cmd = kinit_cmd + validateStatusCmd
       smoke_cmd = kinit_cmd + validateStatusCmd
     else:
     else:
       smoke_cmd = validateStatusCmd
       smoke_cmd = validateStatusCmd

文件差异内容过多而无法显示
+ 332 - 179
ambari-server/src/test/python/TestAmbariServer.py


+ 4 - 3
ambari-server/src/test/python/TestOSCheck.py

@@ -38,7 +38,8 @@ with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
     with patch.object(utils, "get_postgre_hba_dir"):
     with patch.object(utils, "get_postgre_hba_dir"):
       ambari_server = __import__('ambari-server')
       ambari_server = __import__('ambari-server')
 
 
-      from ambari_server.serverConfiguration import update_ambari_properties
+      from ambari_server.serverConfiguration import update_ambari_properties, configDefaults
+
 
 
 class TestOSCheck(TestCase):
 class TestOSCheck(TestCase):
   @patch.object(OSCheck, "os_distribution")
   @patch.object(OSCheck, "os_distribution")
@@ -203,10 +204,10 @@ class TestOSCheck(TestCase):
 
 
     (tf1, fn1) = tempfile.mkstemp()
     (tf1, fn1) = tempfile.mkstemp()
     (tf2, fn2) = tempfile.mkstemp()
     (tf2, fn2) = tempfile.mkstemp()
-    serverConfiguration.AMBARI_PROPERTIES_BACKUP_FILE = fn1
+    configDefaults.AMBARI_PROPERTIES_BACKUP_FILE = fn1
     serverConfiguration.AMBARI_PROPERTIES_FILE = fn2
     serverConfiguration.AMBARI_PROPERTIES_FILE = fn2
 
 
-    with open(serverConfiguration.AMBARI_PROPERTIES_BACKUP_FILE, 'w') as f:
+    with open(configDefaults.AMBARI_PROPERTIES_BACKUP_FILE, 'w') as f:
       for line in properties:
       for line in properties:
         f.write(line)
         f.write(line)
 
 

部分文件因为文件数量过多而无法显示