You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by fb...@apache.org on 2015/01/24 02:37:10 UTC

[6/8] ambari git commit: AMBARI-8317 Refactor the OS-dependent Ambari Server Windows components - Part 1.4

http://git-wip-us.apache.org/repos/asf/ambari/blob/49955a35/ambari-server/src/main/python/ambari_server/dbConfiguration.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari_server/dbConfiguration.py b/ambari-server/src/main/python/ambari_server/dbConfiguration.py
index a200879..74bf194 100644
--- a/ambari-server/src/main/python/ambari_server/dbConfiguration.py
+++ b/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

http://git-wip-us.apache.org/repos/asf/ambari/blob/49955a35/ambari-server/src/main/python/ambari_server/dbConfiguration_linux.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari_server/dbConfiguration_linux.py b/ambari-server/src/main/python/ambari_server/dbConfiguration_linux.py
index 62853b7..04dbb61 100644
--- a/ambari-server/src/main/python/ambari_server/dbConfiguration_linux.py
+++ b/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)