Repository: ambari Updated Branches: refs/heads/trunk 3cf2ee4d4 -> bd28cd9e8
AMBARI-7214. Upgrade to Ambari 1.7.0 requires updating server.jdbc.database_name property in ambari.properties (alejandro) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/bd28cd9e Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/bd28cd9e Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/bd28cd9e Branch: refs/heads/trunk Commit: bd28cd9e80dc6026e7c4dfa768b4f14318185644 Parents: 3cf2ee4 Author: Alejandro Fernandez <afernan...@hortonworks.com> Authored: Thu Sep 11 16:21:42 2014 -0700 Committer: Alejandro Fernandez <afernan...@hortonworks.com> Committed: Fri Sep 12 10:22:50 2014 -0700 ---------------------------------------------------------------------- .../server/configuration/Configuration.java | 1 - ambari-server/src/main/python/ambari-server.py | 71 +++++++++++++++----- .../src/test/python/TestAmbariServer.py | 52 +++++++++++--- 3 files changed, 98 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/bd28cd9e/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java index a3a07b0..78fd7b6 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java @@ -106,7 +106,6 @@ public class Configuration { public static final String CLIENT_API_SSL_CRT_PASS_FILE_NAME_KEY = "client.api.ssl.cert_pass_file"; public static final String CLIENT_API_SSL_CRT_PASS_KEY = "client.api.ssl.crt_pass"; public static final String CLIENT_API_SSL_KEY_NAME_KEY = "client.api.ssl.key_name"; - public static final String SERVER_DB_TYPE_KEY = "server.jdbc.database"; // E.g., oracle|mysql|postgres public static final String SERVER_DB_NAME_KEY = "server.jdbc.database_name"; public static final String SERVER_DB_NAME_DEFAULT = "ambari"; public static final String SERVER_JDBC_POSTGRES_SCHEMA_NAME = "server.jdbc.postgres.schema"; http://git-wip-us.apache.org/repos/asf/ambari/blob/bd28cd9e/ambari-server/src/main/python/ambari-server.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/python/ambari-server.py b/ambari-server/src/main/python/ambari-server.py index 35ba17b..50420b2 100755 --- a/ambari-server/src/main/python/ambari-server.py +++ b/ambari-server/src/main/python/ambari-server.py @@ -304,7 +304,7 @@ DATABASE_INDEX = 0 PROMPT_DATABASE_OPTIONS = False USERNAME_PATTERN = "^[a-zA-Z_][a-zA-Z0-9_\-]*$" PASSWORD_PATTERN = "^[a-zA-Z0-9_-]*$" -DATABASE_NAMES = ["postgres", "oracle", "mysql"] +DATABASE_TYPES = ["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"] @@ -838,8 +838,6 @@ def restart_postgres(): return 0, "", "" -# todo: check if the scheme is already exist - def write_property(key, value): conf_file = find_properties_file() properties = Properties() @@ -1087,7 +1085,7 @@ def get_pass_file_path(conf_file): # Set database properties to default values def load_default_db_properties(args): args.persistence_type = 'local' - args.dbms = DATABASE_NAMES[DATABASE_INDEX] + args.dbms = DATABASE_TYPES[DATABASE_INDEX] args.database_host = "localhost" args.database_port = DATABASE_PORTS[DATABASE_INDEX] args.database_name = DEFAULT_DB_NAME @@ -1141,7 +1139,7 @@ def prompt_db_properties(args): pass DATABASE_INDEX = args.database_index - args.dbms = DATABASE_NAMES[args.database_index] + args.dbms = DATABASE_TYPES[args.database_index] if args.persistence_type != 'local': args.database_host = get_validated_string_input( @@ -1386,12 +1384,48 @@ def configure_database_password(showDefault=True): return password -def check_database_name_property(): +def get_ambari_version(properties): + """ + :param properties: Ambari properties + :return: Return a string of the ambari version. When comparing versions, please use "compare_versions" function. + """ + version = None + try: + server_version_file_path = properties[SERVER_VERSION_FILE_PATH] + if server_version_file_path and os.path.exists(server_version_file_path): + with open(server_version_file_path, 'r') as file: + version = file.read().strip() + except: + print_error_msg("Error getting ambari version") + return version + + +def check_database_name_property(args, upgrade=False): + """ + :param upgrade: If Ambari is being upgraded. + :return: + """ properties = get_ambari_properties() if properties == -1: print_error_msg("Error getting ambari properties") return -1 + version = get_ambari_version(properties) + if upgrade and compare_versions(version, "1.7.0") >= 0: + + expected_db_name = properties[JDBC_DATABASE_NAME_PROPERTY] + # The existing ambari config file is probably from an earlier version of Ambari, and needs to be transformed. + if expected_db_name is None or expected_db_name == "": + db_name = properties[JDBC_DATABASE_PROPERTY] + + if db_name: + write_property(JDBC_DATABASE_NAME_PROPERTY, db_name) + remove_property(JDBC_DATABASE_PROPERTY) + properties = get_ambari_properties() + else: + err = "DB Name property not set in config file.\n" + SETUP_OR_UPGRADE_MSG + raise FatalException(-1, "Upgrade to version %s cannot transform config file." % str(version)) + dbname = properties[JDBC_DATABASE_NAME_PROPERTY] if dbname is None or dbname == "": err = "DB Name property not set in config file.\n" + SETUP_OR_UPGRADE_MSG @@ -1523,7 +1557,7 @@ def parse_properties_file(args): args.database_port = properties[JDBC_PORT_PROPERTY] global DATABASE_INDEX try: - DATABASE_INDEX = DATABASE_NAMES.index(args.dbms) + DATABASE_INDEX = DATABASE_TYPES.index(args.dbms) except ValueError: pass @@ -2297,7 +2331,7 @@ def reset(args): err = "Ambari Server 'reset' cancelled" raise FatalException(1, err) - check_database_name_property() + check_database_name_property(args) parse_properties_file(args) if args.persistence_type == "remote": @@ -2370,7 +2404,7 @@ def start(args): "command as root, as sudo or as user \"{1}\"".format(current_user, ambari_user) raise FatalException(1, err) - check_database_name_property() + check_database_name_property(args) parse_properties_file(args) status, pid = is_server_runing() @@ -2540,7 +2574,7 @@ def upgrade_stack(args, stack_id, repo_url=None, repo_url_os=None): err = 'Ambari-server upgradestack should be run with ' \ 'root-level privileges' raise FatalException(4, err) - check_database_name_property() + check_database_name_property(args) stack_name, stack_version = stack_id.split(STACK_NAME_VER_SEP) retcode = run_stack_upgrade(stack_name, stack_version, repo_url, repo_url_os) @@ -2726,7 +2760,7 @@ def upgrade(args): raise FatalException(retcode, err) try: - check_database_name_property() + check_database_name_property(args, upgrade=True) except FatalException: properties = get_ambari_properties() if properties == -1: @@ -4170,12 +4204,12 @@ def main(): options.database_index = 0 DATABASE_INDEX = 0 pass - elif options.dbms is not None and options.dbms not in DATABASE_NAMES: + elif options.dbms is not None and options.dbms not in DATABASE_TYPES: parser.print_help() parser.error("Unsupported Database " + options.dbms) elif options.dbms is not None: options.dbms = options.dbms.lower() - DATABASE_INDEX = DATABASE_NAMES.index(options.dbms) + DATABASE_INDEX = DATABASE_TYPES.index(options.dbms) #correct port if options.database_port is not None: @@ -4339,6 +4373,9 @@ class Properties(object): self.process_pair(key, value) def process_pair(self, key, value): + """ + Adds or overrides the property with the given key. + """ oldkey = key oldvalue = value keyparts = self.bspacere.split(key) @@ -4407,7 +4444,9 @@ class Properties(object): def store(self, out, header=""): """ Write the properties list to the stream 'out' along - with the optional 'header' """ + with the optional 'header' + This function will attempt to close the file handler once it's done. + """ if out.mode[0] != 'w': raise ValueError, 'Steam should be opened in write mode!' try: @@ -4420,9 +4459,11 @@ class Properties(object): for prop, val in self._origprops.items(): if val is not None: out.write(''.join((prop, '=', val, '\n'))) - out.close() except IOError: raise + finally: + if out: + out.close() if __name__ == "__main__": try: http://git-wip-us.apache.org/repos/asf/ambari/blob/bd28cd9e/ambari-server/src/test/python/TestAmbariServer.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/python/TestAmbariServer.py b/ambari-server/src/test/python/TestAmbariServer.py index 53f0ba1..ebd691d 100644 --- a/ambari-server/src/test/python/TestAmbariServer.py +++ b/ambari-server/src/test/python/TestAmbariServer.py @@ -27,6 +27,7 @@ import stat import datetime import operator import json +from optparse import OptionParser import platform import shutil from pwd import getpwnam @@ -43,7 +44,7 @@ with patch("platform.linux_distribution", return_value = ('Suse','11','Final')): FatalException = ambari_server.FatalException NonFatalException = ambari_server.NonFatalException - +CURR_AMBARI_VERSION = "1.7.0" class TestAmbariServer(TestCase): def setUp(self): @@ -3176,6 +3177,32 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV self.assertEquals(os_symlink_mock.call_args_list[0][0][1], os.path.join("somewhere","postgres-jdbc-driver.jar")) + @patch.object(ambari_server, "write_property") + @patch.object(ambari_server, "find_properties_file") + @patch.object(ambari_server, "is_root") + @patch.object(ambari_server, "get_ambari_version") + @patch.object(ambari_server, "get_ambari_properties") + def test_upgrade_from_161(self, get_ambari_properties_mock, get_ambari_version_mock, is_root_mock, find_properties_file_mock, + write_property_mock): + args = MagicMock() + args.dbms = "postgres" + is_root_mock.return_value = True + + # In Ambari 1.6.1, the DB name was actually stored in JDBC_DATABASE_PROPERTY, and the JDBC_DATABASE_NAME_PROPERTY + # property didn't exist. When upgrading to Ambari 1.7.0, the ambari.properties file should be transformed. + get_ambari_version_mock.return_value = "1.7.0" + + properties = ambari_server.Properties() + properties.process_pair(ambari_server.JDBC_DATABASE_PROPERTY, "ambari") + get_ambari_properties_mock.return_value = properties + + try: + ambari_server.upgrade(args) + except FatalException as fe: + self.fail("Did not expect failure: " + str(fe)) + else: + self.assertTrue(write_property_mock.called) + @patch("__builtin__.open") @patch("os.path.isfile") @@ -3190,11 +3217,12 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV @patch.object(ambari_server, "run_schema_upgrade") @patch.object(ambari_server, "update_ambari_properties") @patch.object(ambari_server, "parse_properties_file") + @patch.object(ambari_server, "get_ambari_version") @patch.object(ambari_server, "is_root") @patch.object(ambari_server, "get_ambari_properties") @patch.object(ambari_server, "upgrade_local_repo") def test_upgrade(self, upgrade_local_repo_mock, - get_ambari_properties_mock, is_root_mock, + get_ambari_properties_mock, is_root_mock, get_ambari_version_mock, parse_properties_file_mock, update_ambari_properties_mock, run_schema_upgrade_mock, read_ambari_user_mock, print_warning_msg_mock, @@ -3204,10 +3232,10 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV args = MagicMock() check_database_name_property_mock = MagicMock() - update_ambari_properties_mock.return_value = 0 run_schema_upgrade_mock.return_value = 0 isfile_mock.return_value = False + get_ambari_version_mock.return_value = CURR_AMBARI_VERSION # Testing call under non-root is_root_mock.return_value = False @@ -3262,7 +3290,7 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV p = MagicMock() get_ambari_properties_mock.reset_mock() get_ambari_properties_mock.return_value = p - p.__getitem__.side_effect = ["something", KeyError("test exception")] + p.__getitem__.side_effect = ["something", "something", KeyError("test exception")] fail = False try: @@ -3271,9 +3299,9 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV fail = True self.assertTrue(fail) - # test if some drivers are available in reources, and symlink available too + # test if some drivers are available in resources, and symlink available too p.reset_mock() - p.__getitem__.side_effect = ["something", "resources"] + p.__getitem__.side_effect = ["something", "something", "resources"] lexists_mock.return_value = True isfile_mock.side_effect = [True, False, False] ambari_server.upgrade(args) @@ -3281,8 +3309,8 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV self.assertEquals(os_remove_mock.call_count, 1) self.assertEquals(os_remove_mock.call_args[0][0], os.path.join("resources", "oracle-jdbc-driver.jar")) self.assertEquals(os_symlink_mock.call_count, 1) - self.assertEquals(os_symlink_mock.call_args[0][0], os.path.join("resources","ojdbc6.jar")) - self.assertEquals(os_symlink_mock.call_args[0][1], os.path.join("resources","oracle-jdbc-driver.jar")) + self.assertEquals(os_symlink_mock.call_args[0][0], os.path.join("resources", "ojdbc6.jar")) + self.assertEquals(os_symlink_mock.call_args[0][1], os.path.join("resources", "oracle-jdbc-driver.jar")) def test_print_info_msg(self): @@ -4898,10 +4926,14 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV @patch.object(ambari_server, "get_ambari_properties") def test_check_database_name_property(self, get_ambari_properties_mock): + parser = OptionParser() + parser.add_option('--database', default=None, help="Database to use embedded|oracle|mysql|postgres", dest="dbms") + args = parser.parse_args() + # negative case get_ambari_properties_mock.return_value = {ambari_server.JDBC_DATABASE_NAME_PROPERTY: ""} try: - result = ambari_server.check_database_name_property() + result = ambari_server.check_database_name_property(args) self.fail("Should fail with exception") except FatalException as e: self.assertTrue('DB Name property not set in config file.' in e.reason) @@ -4911,7 +4943,7 @@ MIIFHjCCAwYCCQDpHKOBI+Lt0zANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJV get_ambari_properties_mock.reset_mock() get_ambari_properties_mock.return_value = {ambari_server.JDBC_DATABASE_NAME_PROPERTY: dbname} try: - result = ambari_server.check_database_name_property() + result = ambari_server.check_database_name_property(args) except FatalException: self.fail("Setup should be successful")