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)