Quellcode durchsuchen

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 vor 10 Jahren
Ursprung
Commit
49955a3597
23 geänderte Dateien mit 3234 neuen und 4887 gelöschten Zeilen
  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.
 '''
 
+import subprocess
+import shlex
 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
 
+
 class Firewall(object):
   def __init__(self):
     # OS info
@@ -28,6 +33,16 @@ class Firewall(object):
     self.OS_TYPE = OSCheck.get_os_type()
     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):
     if self.OS_TYPE == OSConst.OS_UBUNTU:
       return UbuntuFirewallChecks()
@@ -47,23 +62,31 @@ class FirewallChecks(object):
     self.returncode = None
     self.stdoutdata = None
     self.stderrdata = None
+    # stdout message
+    self.MESSAGE_CHECK_FIREWALL = 'Checking iptables...'
 
   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):
+  def check_result(self):
     result = False
-    if retcode == 3:
+    if self.returncode == 3:
       result = False
-    elif retcode == 0:
-      if "Table: filter" in out:
+    elif self.returncode == 0:
+      if "Table: filter" in self.stdoutdata:
         result = True
     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):
     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:
       return False
 
@@ -76,13 +99,13 @@ class UbuntuFirewallChecks(FirewallChecks):
   def get_command(self):
     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
     result = False
-    if retcode == 0:
-      if "Status: inactive" in out:
+    if self.returncode == 0:
+      if "Status: inactive" in self.stdoutdata:
         result = False
-      elif "Status: active" in out:
+      elif "Status: active" in self.stdoutdata:
         result = True
     return result
 
@@ -93,10 +116,10 @@ class Fedora18FirewallChecks(FirewallChecks):
   def get_command(self):
     return "systemctl is-active %s" % (self.FIREWALL_SERVICE_NAME)
 
-  def check_result(self, retcode, out, err):
+  def check_result(self):
     result = False
-    if retcode == 0:
-      if "active" in out:
+    if self.returncode == 0:
+      if "active" in self.stdoutdata:
         result = True
     return result
 
@@ -108,11 +131,44 @@ class SuseFirewallChecks(FirewallChecks):
   def get_command(self):
     return "%s %s" % (self.FIREWALL_SERVICE_NAME, self.SERVICE_SUBCMD)
 
-  def check_result(self, retcode, out, err):
+  def check_result(self):
     result = False
-    if retcode == 0:
-      if "SuSEfirewall2 not active" in out:
+    if self.returncode == 0:
+      if "SuSEfirewall2 not active" in self.stdoutdata:
         result = False
-      elif "### iptables" in out:
+      elif "### iptables" in self.stdoutdata:
         result = True
     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:
       range_comp2 = range_comp1[0].split(' ') #split away the "bytes" prefix
       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('-')
       seek_pos = int(range_comp3[0])
       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):
     #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)
 
   (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
   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)
 
   # 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
 _SILENT = False
-_DEBUG_MODE = False
+_DEBUG_MODE = 0
 
 # terminal styles
 BOLD_ON = '\033[1m'
@@ -50,6 +50,20 @@ def set_debug_mode(newVal):
   global _DEBUG_MODE
   _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.
 #

+ 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
 shared.resources.dir = /usr/lib/ambari-server/lib/ambari_commons/resources
 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
-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
-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
 common.services.path=/var/lib/ambari-server/resources/common-services
 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
 #java.releases=jdk1.8.20,jdk1.6.31
 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.dest-file=jdk-7u67-windows-x64.exe
 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.exceptions import FatalException, NonFatalException
 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_windows import SvcStatusCallback
 
 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.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, \
-  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, \
   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
@@ -73,16 +74,12 @@ SERVER_START_CMD_DEBUG = \
                        " -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,"\
                        "server=y,suspend={1} -cp {0}" +\
                        " org.apache.ambari.server.controller.AmbariServer"
-SERVER_SEARCH_PATTERN = "org.apache.ambari.server.controller.AmbariServer"
 
 SERVER_INIT_TIMEOUT = 5
 SERVER_START_TIMEOUT = 10
 
-PID_NAME = "ambari-server.pid"
 EXITCODE_NAME = "ambari-server.exitcode"
 
-SERVER_VERSION_FILE_PATH = "server.version.file"
-
 # linux open-file limit
 ULIMIT_OPEN_FILES_KEY = 'ulimit.open.files'
 ULIMIT_OPEN_FILES_DEFAULT = 10000
@@ -182,16 +179,9 @@ def svcstart():
   pass
 
 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:
-    global SUSPEND_START_MODE
-    SUSPEND_START_MODE = options.suspend_start
+    set_debug_mode_from_options(options)
   except AttributeError:
     pass
 
@@ -236,10 +226,15 @@ def server_process_main(options, scmStatus=None):
   if conf_dir.find(' ') != -1:
     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)
-  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)
   if not os.path.exists(configDefaults.PID_DIR):
     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
 #If the timeout has been reached, bail out with exception
 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):
     raise FatalException(-1, "JDBC driver is not installed. Run ambari-server setup and try again.")
 
@@ -317,9 +313,6 @@ def svcstop():
 
 ### Stack upgrade ###
 
-#def upgrade_stack(args, stack_id, repo_url=None, repo_url_os=None):
-
-
 def get_resources_location(properties):
   res_location = properties[RESOURCES_DIR_PROPERTY]
   if res_location is None:
@@ -327,13 +320,6 @@ def get_resources_location(properties):
   return res_location
 #  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.
@@ -465,7 +451,6 @@ def main():
 
   if are_cmd_line_db_args_blank(options):
     options.must_set_database_options = True
-    #TODO Silent is invalid here, right?
 
   elif not are_cmd_line_db_args_valid(options):
     parser.error('All database options should be set. Please see help for the options.')

Datei-Diff unterdrückt, da er zu groß ist
+ 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
 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.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
@@ -31,77 +36,76 @@ DB_STATUS_RUNNING_DEFAULT = "running"
 SETUP_DB_CONNECT_TIMEOUT = 5
 SETUP_DB_CONNECT_ATTEMPTS = 3
 
-DATABASE_INDEX = 0
 USERNAME_PATTERN = "^[a-zA-Z_][a-zA-Z0-9_\-]*$"
 PASSWORD_PATTERN = "^[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']
+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
 #
 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
     """
-    self.persistence_type = 'remote'
+    self.persistence_type = storage_type
     self.dbms = ""
-    self.driver_name = ""
+    self.driver_class_name = ""
+    self.driver_file_name = ""
+    self.driver_symlink_name = ""
     self.database_host = ""
     self.database_port = ""
     self.database_name = ""
     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.
   #
-  def configure_database(self, args, properties):
+  def configure_database(self, properties):
     result = self._prompt_db_properties()
     if result:
       #DB setup should be done last after doing any setup.
@@ -122,7 +126,7 @@ class DBMSConfig(object):
     return result
 
   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.
     if self._is_local_database():
@@ -132,43 +136,71 @@ class DBMSConfig(object):
     pass
 
   def reset_database(self):
-    print 'Resetting {} database...'.format(self.db_title)
-
     if self._is_local_database():
       self._reset_local_database()
     else:
       self._reset_remote_database()
     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:
-      (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 self._install_jdbc_driver(args, properties):
+      if self._install_jdbc_driver(properties, result):
         return True
     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
   #
 
+  @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
   #
   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):
     #if WINDOWS
@@ -197,15 +229,255 @@ class DBMSConfig(object):
     pass
 
   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
 
   def ensure_dbms_is_running(self, options, properties, scmStatus=None):
     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
 limitations under the License.
 '''
-
+import fileinput
+import glob
+import os
+import re
 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
-        )
+      )
+      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:
       passwordPrompt = 'Enter Database Password (' + passwordDefault + '): '
     else:
       passwordPrompt = 'Enter Database Password: '
     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"
 
     password = read_password(passwordDefault, passwordPattern, passwordPrompt,
@@ -228,513 +202,655 @@ class PGConfig(DBMSConfig):
 
     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
     # 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()
 
-    #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
-    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:
-      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)
     drop_retcode, drop_outdata, drop_errdata = run_os_command(command)
     if not drop_retcode == 0:
       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")
     if drop_errdata and get_verbose():
       print_warning_msg(drop_errdata)
     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():
       print_warning_msg(errdata)
     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():
-        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
-  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
-  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:
       pg_status = re.search('(stopped|running)', out, re.IGNORECASE).group(0).lower()
     except AttributeError:
       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")
-      return 0
+      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)
+        retcode, out, err = run_os_command(PGConfig.PG_INITDB_CMD)
         if retcode == 0:
           print out
       print "About to start PostgreSQL"
       try:
-        process = subprocess.Popen(PG_START_CMD.split(' '),
+        process = subprocess.Popen(PGConfig.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 = get_postgre_status()
+            pg_status, retcode, out, err = PGConfig._get_postgre_status()
           else:
             retcode = result
         else:
           out, err = process.communicate()
           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...")
-          return 0
+          return pg_status, 0, out, err
       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:
           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
-          )
+      )
 
+      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(
-              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 socket
 import string
-
 from ambari_commons.exceptions import FatalException
 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_windows import WinServiceController
 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, \
   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, \
@@ -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_USER_NAME_PROPERTY, JDBC_RCA_PASSWORD_FILE_PROPERTY, JDBC_RCA_PASSWORD_FILENAME, JDBC_RCA_PASSWORD_ALIAS, \
   PERSISTENCE_TYPE_PROPERTY, \
-  PRESS_ENTER_MSG
+  get_value_from_properties, configDefaults
 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
-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):
-    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.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
+#
 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
     """
-    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
     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:
         self.database_host = compress_backslashes(self.database_host)
     except:
-      self.database_host = "localhost\\SQLEXPRESS"
+      self.database_host = DATABASE_SERVER_SQLSERVER_DEFAULT
       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 "" \
-        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.persistence_property = None
 
-    self.db_title = ""
-
     self.env_var_db_name = ""
     self.env_var_db_log_name = ""
     self.env_var_db_owner = ""
@@ -132,137 +107,113 @@ class SQLServerConfig(DBMSConfig):
   def _is_local_database(self):
     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
     pass
 
   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()
 
     return True
 
   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
 
   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()
 
   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()
 
-  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:
       driver_path = properties[JDBC_DRIVER_PATH_PROPERTY]
+      if driver_path is None or driver_path is "":
+        return 0
     except Exception:
       # 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 == "":
-      driver_path = self.get_jdbc_driver_path()
+      driver_path = self._get_jdbc_driver_path()
 
       properties.process_pair(JDBC_DRIVER_PATH_PROPERTY, driver_path)
       return True
@@ -283,7 +234,7 @@ class SQLServerConfig(DBMSConfig):
       sql_svc_name = "MSSQL$" + db_host_components[1]
 
     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
       ret = WinServiceController.EnsureServiceIsStarted(sql_svc_name)
       if 0 != ret:
@@ -298,11 +249,18 @@ class SQLServerConfig(DBMSConfig):
     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):
-    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 != "":
-      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):
       databaseUrl += ";integratedSecurity=true"
     #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
   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])
     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)
     print_info_msg("sqlcmd output:")
     print_info_msg(outData)
     pass
 
+#
 # SQL Server Ambari database configuration and setup
+#
 class SQLServerAmbariDBConfig(SQLServerConfig):
-  def __init__(self, options, properties):
+  def __init__(self, options, properties, storage_type):
     self.dbPropKeys = DbPropKeys(
       JDBC_DATABASE_PROPERTY,
       JDBC_DRIVER_PROPERTY,
@@ -359,7 +319,7 @@ class SQLServerAmbariDBConfig(SQLServerConfig):
       JDBC_PORT_PROPERTY,
       JDBC_DATABASE_NAME_PROPERTY,
       JDBC_URL_PROPERTY)
-    self.dbAuthKeys = AuthenticationKeys(
+    self.dbAuthKeys = SqlServerAuthenticationKeys(
       JDBC_USE_INTEGRATED_AUTH_PROPERTY,
       JDBC_USER_NAME_PROPERTY,
       JDBC_PASSWORD_PROPERTY,
@@ -367,15 +327,13 @@ class SQLServerAmbariDBConfig(SQLServerConfig):
       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 "":
       self.database_name = AMBARI_DATABASE_NAME
 
     self.persistence_property = PERSISTENCE_TYPE_PROPERTY
 
-    self.db_title = "ambari"
-
     self.env_var_db_name ='AMBARIDBNAME'
     self.env_var_db_log_name = 'AMBARIDBLOGNAME'
     self.env_var_db_owner = 'AMBARIDBOWNER'
@@ -394,13 +352,12 @@ class SQLServerAmbariDBConfig(SQLServerConfig):
   def _setup_remote_server(self, 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))
     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_SCHEMA_PROPERTY, self.database_name)
 
-    authKeys = AuthenticationKeys(
+    authKeys = SqlServerAuthenticationKeys(
       JDBC_RCA_USE_INTEGRATED_AUTH_PROPERTY,
       JDBC_RCA_USER_NAME_PROPERTY,
       JDBC_RCA_PASSWORD_FILE_PROPERTY,
@@ -412,13 +369,6 @@ class SQLServerAmbariDBConfig(SQLServerConfig):
     properties.process_pair(JDBC_RCA_URL_PROPERTY, self.database_url)
     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 re
 import shutil
+import stat
 import string
+import sys
 import tempfile
 
 from ambari_commons.exceptions import FatalException
 from ambari_commons.os_check import OSCheck, OSConst
 from ambari_commons.os_family_impl import OsFamilyImpl
 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_TYPE = OSCheck.get_os_type()
 OS_FAMILY = OSCheck.get_os_family()
 
+PID_NAME = "ambari-server.pid"
 
 # Non-root user setup commands
 NR_USER_PROPERTY = "ambari-server.user"
@@ -56,10 +62,6 @@ BOOTSTRAP_DIR_PROPERTY = "bootstrap.dir"
 
 AMBARI_CONF_VAR = "AMBARI_CONF_DIR"
 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"
 
@@ -85,10 +87,10 @@ JDK_NAMES = ["jdk-7u67-linux-x64.tar.gz", "jdk-6u31-linux-x64.bin"]
 
 #JCE Policy files
 JCE_POLICY_FILENAMES = ["UnlimitedJCEPolicyJDK7.zip", "jce_policy-6.zip"]
-JCE_DOWNLOAD_CMD = "curl -o {0} {1}"
-JCE_MIN_FILESIZE = 5000
 
 # 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,
 # 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
@@ -105,6 +107,8 @@ JDBC_RCA_PASSWORD_FILENAME = "rca_password.dat"
 CLIENT_API_PORT_PROPERTY = "client.api.port"
 CLIENT_API_PORT = "8080"
 
+SERVER_VERSION_FILE_PATH = "server.version.file"
+
 PERSISTENCE_TYPE_PROPERTY = "server.persistence.type"
 JDBC_DRIVER_PROPERTY = "server.jdbc.driver"
 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"
 
-#Windows-specific settings
+### # Windows-specific # ###
 
 JDBC_USE_INTEGRATED_AUTH_PROPERTY = "server.jdbc.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_DIR_PROPERTY = "resources.dir"
@@ -135,11 +143,26 @@ RESOURCES_DIR_DEFAULT = "resources"
 
 # stack repo upgrade
 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_RELEASES="java.releases"
 
+VIEWS_DIR_PROPERTY = "views.dir"
+
 #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" \
                        "- 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"
 
-
 class ServerConfigDefaults(object):
   def __init__(self):
     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.DEFAULT_LIBS_DIR = ""
 
+    self.AMBARI_PROPERTIES_BACKUP_FILE = ""
+
     # ownership/permissions mapping
     # path - permissions - user - group - recursive
     # Rules are executed in the same order as they are listed
     # {0} in user/group will be replaced by customized ambari-server username
     self.NR_ADJUST_OWNERSHIP_LIST = []
+    self.NR_USERADD_CMD = ""
 
     self.MASTER_KEY_FILE_PERMISSIONS = "600"
     self.CREDENTIALS_STORE_FILE_PERMISSIONS = "600"
@@ -177,11 +202,19 @@ class ServerConfigDefaults(object):
 
     self.DEFAULT_DB_NAME = "ambari"
 
+    self.STACK_LOCATION_DEFAULT = ""
+
     self.DEFAULT_VIEWS_DIR = ""
 
     #keytool commands
     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)
 class ServerConfigDefaultsWindows(ServerConfigDefaults):
   def __init__(self):
@@ -194,6 +227,8 @@ class ServerConfigDefaultsWindows(ServerConfigDefaults):
     self.DEFAULT_CONF_DIR = "conf"
     self.DEFAULT_LIBS_DIR = "lib"
 
+    self.AMBARI_PROPERTIES_BACKUP_FILE = "ambari.properties.backup"
+
     # ownership/permissions mapping
     # path - permissions - user - group - recursive
     # 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
       # 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"
 
     #keytool commands
     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)
 class ServerConfigDefaultsLinux(ServerConfigDefaults):
   def __init__(self):
@@ -237,6 +281,8 @@ class ServerConfigDefaultsLinux(ServerConfigDefaults):
     self.DEFAULT_CONF_DIR = "/etc/ambari-server/conf"
     self.DEFAULT_LIBS_DIR = "/usr/lib/ambari-server"
 
+    self.AMBARI_PROPERTIES_BACKUP_FILE = "ambari.properties.rpmsave"
+
     # ownership/permissions mapping
     # path - permissions - user - group - recursive
     # 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
       # 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"
 
     #keytool commands
     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()
 
+# 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():
@@ -322,18 +398,12 @@ def read_ambari_user():
   '''
   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]
     if 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=""):
   try:
@@ -344,6 +414,32 @@ def get_value_from_properties(properties, key, default=""):
     return default
   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)
 def backup_file_in_temp(filePath):
   if filePath is not None:
@@ -353,10 +449,99 @@ def backup_file_in_temp(filePath):
       shutil.copyfile(filePath, tmpDir + os.sep +
                       AMBARI_PROPERTIES_FILE + "." + str(back_up_file_count + 1))
     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
 
+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):
   regex = re.compile("\$\{alias=[\w\.]+\}")
@@ -367,9 +552,127 @@ def is_alias_string(passwdStr):
   else:
     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():
-  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())
 
   # Previous config file does not exist
@@ -482,27 +785,31 @@ def write_property(key, value):
     return -1
   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
 #
 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 ###
@@ -520,7 +827,7 @@ class JDKRelease:
   dest_jcpol_file = ""
   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 "":
       raise FatalException(-1, "Invalid JDK name: " + (i_desc or ""))
     self.name = i_name
@@ -542,14 +849,17 @@ class JDKRelease:
     else:
       self.dest_jcpol_file = i_dest_jcpol_file
     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:
       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
   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
 
   @staticmethod
@@ -563,6 +873,9 @@ class JDKRelease:
     if not properties.has_key(section_name + ".url"):
       raise FatalException(-1, "Invalid JDK URL in the properties section: " + section_name)
     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
       dest_file = properties[section_name + ".dest-file"]
     else:
@@ -579,7 +892,7 @@ class JDKRelease:
       inst_dir = properties[section_name + ".home"]
     else:
       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
 
 def get_ambari_jars():
@@ -618,6 +931,14 @@ def get_ambari_classpath():
     ambari_cp = ambari_cp + os.pathsep + share_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():
   properties = get_ambari_properties()
   if properties == -1:
@@ -665,3 +986,35 @@ def find_jdk():
     else:
       print "JDK {0} is invalid".format(jdkPath)
   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

Datei-Diff unterdrückt, da er zu groß ist
+ 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"
 SETUP_HTTPS_ACTION = "setup-https"
 LDAP_SETUP_ACTION = "setup-ldap"
+LDAP_SYNC_ACTION = "sync-ldap"
 SETUP_GANGLIA_HTTPS_ACTION = "setup-ganglia-https"
-SETUP_NAGIOS_HTTPS_ACTION = "setup-nagios-https"
 ENCRYPT_PASSWORDS_ACTION = "encrypt-passwords"
 SETUP_SECURITY_ACTION = "setup-security"
+BACKUP_ACTION = "backup"
+RESTORE_ACTION = "restore"
 
 ACTION_REQUIRE_RESTART = [RESET_ACTION, UPGRADE_ACTION, UPGRADE_STACK_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 shutil
 import socket
-import stat
 import string
-import sys
 import tempfile
 import urllib2
+import time
 
 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.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, \
   run_os_command, search_file
 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, \
   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 ambari_server.userInput import get_YN_input, get_validated_string_input, get_validated_filepath_input, \
   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_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_API_PORT = 'client.api.ssl.port'
 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 = "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'
 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"
 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_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}$)"
@@ -420,7 +386,7 @@ def get_truststore_password(properties):
   isSecure = get_is_secure(properties)
   if truststore_password:
     if isSecure:
-      truststore_password = decrypt_password_for_alias(SSL_TRUSTSTORE_PASSWORD_ALIAS)
+      truststore_password = decrypt_password_for_alias(properties, SSL_TRUSTSTORE_PASSWORD_ALIAS)
   else:
     truststore_password = read_password("", ".*", "Password for TrustStore:", "Invalid characters in password")
     if truststore_password:
@@ -429,40 +395,40 @@ def get_truststore_password(properties):
 
   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,
                   passwordPattern=PASSWORD_PATTERN,
                   passwordPrompt=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):
   properties = get_ambari_properties()
@@ -494,59 +460,6 @@ def get_alias_string(alias):
 def get_alias_from_alias_string(aliasStr):
   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=""):
   if alias and passwd:
     jdk_path = find_jdk()
@@ -559,8 +472,8 @@ def save_passwd_for_alias(alias, passwd, masterKey=""):
     if masterKey is None or masterKey == "":
       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)
     print_info_msg("Return code from credential provider save passwd: " +
                    str(retcode))
@@ -568,61 +481,6 @@ def save_passwd_for_alias(alias, passwd, masterKey=""):
   else:
     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):
   passwordPattern = ".*"
   passwordPrompt = "Please provide master key for locking the credential store: "
@@ -632,19 +490,23 @@ def read_master_key(isReset=False):
   if isReset:
     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
 
@@ -656,8 +518,8 @@ def save_master_key(master_key, key_location, persist=True):
                       "command to install a JDK automatically or install any "
                       "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
       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)
     print_info_msg("Return code from credential provider save KEY: " +
                    str(retcode))
@@ -666,8 +528,7 @@ def save_master_key(master_key, key_location, persist=True):
 
 def store_password_file(password, filename):
   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:
     passFile.write(password)
@@ -694,10 +555,25 @@ def remove_password_file(filename):
 
 def adjust_directory_permissions(ambari_user):
   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))
+
   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
   keyLocation = get_master_key_location(properties)
   masterKeyFile = search_file(SECURITY_MASTER_KEY_FILENAME, keyLocation)
@@ -710,6 +586,7 @@ def adjust_directory_permissions(ambari_user):
   if trust_store_location:
     configDefaults.NR_ADJUST_OWNERSHIP_LIST.append((trust_store_location, configDefaults.TRUST_STORE_LOCATION_PERMISSIONS, "{0}", "{0}", False))
   print "Adjusting ambari-server permissions and ownership..."
+
   for pack in configDefaults.NR_ADJUST_OWNERSHIP_LIST:
     file = pack[0]
     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():
     print(prompt)
     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,
                                is_pass, allowEmpty=True, validatorFunction=None):
-
   input = ""
   while not input:
     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_path = ["/bin","/usr/bin/"]
       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),
         )
         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 *
 
 
-_install_cmd = '{} /s INSTALLDIR={} ADDLOCAL="ToolsFeature,SourceFeature"'
+_install_cmd = '{0} /s INSTALLDIR={1} ADDLOCAL="ToolsFeature,SourceFeature"'
 
 
 def _check_installed():
@@ -42,7 +42,7 @@ def setup_jdk():
   if not os.path.exists(params.java_home):
     os.makedirs(params.java_home)
   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)
   Execute(_install_cmd.format(jdk_setup_savepath, params.java_home))
   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"
     validateStatusFilePath = os.path.join(os.path.dirname(params.hadoop_home), "temp", validateStatusFileName)
     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)
 
     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
     else:
       smoke_cmd = validateStatusCmd

Datei-Diff unterdrückt, da er zu groß ist
+ 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"):
       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):
   @patch.object(OSCheck, "os_distribution")
@@ -203,10 +204,10 @@ class TestOSCheck(TestCase):
 
     (tf1, fn1) = tempfile.mkstemp()
     (tf2, fn2) = tempfile.mkstemp()
-    serverConfiguration.AMBARI_PROPERTIES_BACKUP_FILE = fn1
+    configDefaults.AMBARI_PROPERTIES_BACKUP_FILE = fn1
     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:
         f.write(line)
 

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.