serverUpgrade.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #!/usr/bin/env python
  2. '''
  3. Licensed to the Apache Software Foundation (ASF) under one
  4. or more contributor license agreements. See the NOTICE file
  5. distributed with this work for additional information
  6. regarding copyright ownership. The ASF licenses this file
  7. to you under the Apache License, Version 2.0 (the
  8. "License"); you may not use this file except in compliance
  9. with the License. You may obtain a copy of the License at
  10. http://www.apache.org/licenses/LICENSE-2.0
  11. Unless required by applicable law or agreed to in writing, software
  12. distributed under the License is distributed on an "AS IS" BASIS,
  13. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. See the License for the specific language governing permissions and
  15. limitations under the License.
  16. '''
  17. import json
  18. import os
  19. import shutil
  20. from ambari_commons.exceptions import FatalException
  21. from ambari_commons.logging_utils import print_info_msg, print_warning_msg, print_error_msg
  22. from ambari_commons.os_utils import is_root, run_os_command
  23. from ambari_server.dbConfiguration import DBMSConfigFactory, check_jdbc_drivers
  24. from ambari_server.properties import Properties
  25. from ambari_server.serverConfiguration import configDefaults, \
  26. check_database_name_property, get_ambari_properties, get_ambari_version, get_full_ambari_classpath, \
  27. get_java_exe_path, get_stack_location, parse_properties_file, read_ambari_user, update_ambari_properties, \
  28. update_database_name_property, \
  29. AMBARI_PROPERTIES_FILE, IS_LDAP_CONFIGURED, LDAP_PRIMARY_URL_PROPERTY, RESOURCES_DIR_PROPERTY, \
  30. SETUP_OR_UPGRADE_MSG
  31. from ambari_server.setupSecurity import adjust_directory_permissions
  32. # constants
  33. from ambari_server.utils import compare_versions
  34. STACK_NAME_VER_SEP = "-"
  35. SCHEMA_UPGRADE_HELPER_CMD = "{0} -cp {1} " + \
  36. "org.apache.ambari.server.upgrade.SchemaUpgradeHelper" + \
  37. " > " + configDefaults.SERVER_OUT_FILE + " 2>&1"
  38. STACK_UPGRADE_HELPER_CMD = "{0} -cp {1} " + \
  39. "org.apache.ambari.server.upgrade.StackUpgradeHelper" + \
  40. " {2} {3} > " + configDefaults.SERVER_OUT_FILE + " 2>&1"
  41. #
  42. # Stack upgrade
  43. #
  44. def upgrade_stack(args, stack_id, repo_url=None, repo_url_os=None):
  45. if not is_root():
  46. err = 'Ambari-server upgradestack should be run with ' \
  47. 'root-level privileges'
  48. raise FatalException(4, err)
  49. check_database_name_property()
  50. stack_name, stack_version = stack_id.split(STACK_NAME_VER_SEP)
  51. retcode = run_stack_upgrade(stack_name, stack_version, repo_url, repo_url_os)
  52. if not retcode == 0:
  53. raise FatalException(retcode, 'Stack upgrade failed.')
  54. return retcode
  55. def load_stack_values(version, filename):
  56. import xml.etree.ElementTree as ET
  57. values = {}
  58. root = ET.parse(filename).getroot()
  59. for ostag in root:
  60. ostype = ostag.attrib['type']
  61. for repotag in ostag:
  62. reponametag = repotag.find('reponame')
  63. repoidtag = repotag.find('repoid')
  64. baseurltag = repotag.find('baseurl')
  65. if reponametag is not None and repoidtag is not None and baseurltag is not None:
  66. key = "repo:/" + reponametag.text
  67. key += "/" + version
  68. key += "/" + ostype
  69. key += "/" + repoidtag.text
  70. key += ":baseurl"
  71. values[key] = baseurltag.text
  72. return values
  73. def run_stack_upgrade(stackName, stackVersion, repo_url, repo_url_os):
  74. jdk_path = get_java_exe_path()
  75. if jdk_path is None:
  76. print_error_msg("No JDK found, please run the \"setup\" "
  77. "command to install a JDK automatically or install any "
  78. "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
  79. return 1
  80. stackId = {}
  81. stackId[stackName] = stackVersion
  82. if repo_url is not None:
  83. stackId['repo_url'] = repo_url
  84. if repo_url_os is not None:
  85. stackId['repo_url_os'] = repo_url_os
  86. command = STACK_UPGRADE_HELPER_CMD.format(jdk_path, get_full_ambari_classpath(),
  87. "updateStackId",
  88. "'" + json.dumps(stackId) + "'")
  89. (retcode, stdout, stderr) = run_os_command(command)
  90. print_info_msg("Return code from stack upgrade command, retcode = " + str(retcode))
  91. if retcode > 0:
  92. print_error_msg("Error executing stack upgrade, please check the server logs.")
  93. return retcode
  94. def run_metainfo_upgrade(keyValueMap=None):
  95. jdk_path = get_java_exe_path()
  96. if jdk_path is None:
  97. print_error_msg("No JDK found, please run the \"setup\" "
  98. "command to install a JDK automatically or install any "
  99. "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
  100. retcode = 1
  101. if keyValueMap:
  102. command = STACK_UPGRADE_HELPER_CMD.format(jdk_path, get_full_ambari_classpath(),
  103. 'updateMetaInfo',
  104. "'" + json.dumps(keyValueMap) + "'")
  105. (retcode, stdout, stderr) = run_os_command(command)
  106. print_info_msg("Return code from stack upgrade command, retcode = " + str(retcode))
  107. if retcode > 0:
  108. print_error_msg("Error executing metainfo upgrade, please check the "
  109. "server logs.")
  110. return retcode
  111. #
  112. # Repo upgrade
  113. #
  114. def change_objects_owner(args):
  115. print 'Fixing database objects owner'
  116. properties = Properties() #Dummy, args contains the dbms name and parameters already
  117. factory = DBMSConfigFactory()
  118. dbms = factory.create(args, properties)
  119. dbms.change_db_files_owner()
  120. def upgrade_local_repo(args):
  121. properties = get_ambari_properties()
  122. if properties == -1:
  123. print_error_msg("Error getting ambari properties")
  124. return -1
  125. stack_location = get_stack_location(properties)
  126. stack_root_local = os.path.join(stack_location, "HDPLocal")
  127. if not os.path.exists(stack_root_local):
  128. print_info_msg("HDPLocal stack directory does not exist, skipping")
  129. return
  130. stack_root = os.path.join(stack_location, "HDP")
  131. if not os.path.exists(stack_root):
  132. print_info_msg("HDP stack directory does not exist, skipping")
  133. return
  134. for stack_version_local in os.listdir(stack_root_local):
  135. repo_file_local = os.path.join(stack_root_local, stack_version_local, "repos", "repoinfo.xml.rpmsave")
  136. if not os.path.exists(repo_file_local):
  137. repo_file_local = os.path.join(stack_root_local, stack_version_local, "repos", "repoinfo.xml")
  138. repo_file = os.path.join(stack_root, stack_version_local, "repos", "repoinfo.xml")
  139. print_info_msg("Local repo file: " + repo_file_local)
  140. print_info_msg("Repo file: " + repo_file_local)
  141. metainfo_update_items = {}
  142. if os.path.exists(repo_file_local) and os.path.exists(repo_file):
  143. local_values = load_stack_values(stack_version_local, repo_file_local)
  144. repo_values = load_stack_values(stack_version_local, repo_file)
  145. for k, v in local_values.iteritems():
  146. if repo_values.has_key(k):
  147. local_url = local_values[k]
  148. repo_url = repo_values[k]
  149. if repo_url != local_url:
  150. metainfo_update_items[k] = local_url
  151. run_metainfo_upgrade(metainfo_update_items)
  152. #
  153. # Schema upgrade
  154. #
  155. def run_schema_upgrade():
  156. jdk_path = get_java_exe_path()
  157. if jdk_path is None:
  158. print_error_msg("No JDK found, please run the \"setup\" "
  159. "command to install a JDK automatically or install any "
  160. "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
  161. return 1
  162. print 'Upgrading database schema'
  163. command = SCHEMA_UPGRADE_HELPER_CMD.format(jdk_path, get_full_ambari_classpath())
  164. (retcode, stdout, stderr) = run_os_command(command)
  165. print_info_msg("Return code from schema upgrade command, retcode = " + str(retcode))
  166. if retcode > 0:
  167. print_error_msg("Error executing schema upgrade, please check the server logs.")
  168. else:
  169. print_info_msg('Schema upgrade completed')
  170. return retcode
  171. #
  172. # Upgrades the Ambari Server.
  173. #
  174. def move_user_custom_actions():
  175. print_info_msg('Moving *.py files from custom_actions to custom_actions/scripts')
  176. properties = get_ambari_properties()
  177. if properties == -1:
  178. err = "Error getting ambari properties"
  179. print_error_msg(err)
  180. raise FatalException(-1, err)
  181. try:
  182. resources_dir = properties[RESOURCES_DIR_PROPERTY]
  183. except (KeyError), e:
  184. conf_file = properties.fileName
  185. err = 'Property ' + str(e) + ' is not defined at ' + conf_file
  186. print_error_msg(err)
  187. raise FatalException(1, err)
  188. custom_actions_dir_path = os.path.join(resources_dir, 'custom_actions')
  189. custom_actions_scripts_dir_path = os.path.join(custom_actions_dir_path, 'scripts')
  190. print_info_msg('Moving *.py files from %s to %s' % (custom_actions_dir_path, custom_actions_scripts_dir_path))
  191. try:
  192. for custom_action_file_name in os.listdir(custom_actions_dir_path):
  193. custom_action_file_path = os.path.join(custom_actions_dir_path, custom_action_file_name)
  194. if os.path.isfile(custom_action_file_path) and custom_action_file_path.endswith('.py'):
  195. print_info_msg('Moving %s to %s' % (custom_action_file_path, custom_actions_scripts_dir_path))
  196. shutil.move(custom_action_file_path, custom_actions_scripts_dir_path)
  197. except (OSError, shutil.Error) as e:
  198. err = 'Upgrade failed. Can not move *.py files from %s to %s. ' % (custom_actions_dir_path, custom_actions_scripts_dir_path) + str(e)
  199. print_error_msg(err)
  200. raise FatalException(1, err)
  201. def upgrade(args):
  202. if not is_root():
  203. err = configDefaults.MESSAGE_ERROR_UPGRADE_NOT_ROOT
  204. raise FatalException(4, err)
  205. print 'Updating properties in ' + AMBARI_PROPERTIES_FILE + ' ...'
  206. retcode = update_ambari_properties()
  207. if not retcode == 0:
  208. err = AMBARI_PROPERTIES_FILE + ' file can\'t be updated. Exiting'
  209. raise FatalException(retcode, err)
  210. try:
  211. update_database_name_property(upgrade=True)
  212. except FatalException:
  213. return -1
  214. # Ignore the server version & database options passed via command-line arguments
  215. parse_properties_file(args)
  216. #TODO check database version
  217. change_objects_owner(args)
  218. retcode = run_schema_upgrade()
  219. if not retcode == 0:
  220. print_error_msg("Ambari server upgrade failed. Please look at {0}, for more details.".format(configDefaults.SERVER_LOG_FILE))
  221. raise FatalException(11, 'Schema upgrade failed.')
  222. user = read_ambari_user()
  223. if user is None:
  224. warn = "Can not determine custom ambari user.\n" + SETUP_OR_UPGRADE_MSG
  225. print_warning_msg(warn)
  226. else:
  227. adjust_directory_permissions(user)
  228. # local repo
  229. upgrade_local_repo(args)
  230. # create jdbc symlinks if jdbc drivers are available in resources
  231. check_jdbc_drivers(args)
  232. properties = get_ambari_properties()
  233. if properties == -1:
  234. err = "Error getting ambari properties"
  235. print_error_msg(err)
  236. raise FatalException(-1, err)
  237. # Move *.py files from custom_actions to custom_actions/scripts
  238. # This code exists for historic reasons in which custom action python scripts location changed from Ambari 1.7.0 to 2.0.0
  239. ambari_version = get_ambari_version(properties)
  240. if ambari_version is None:
  241. args.warnings.append("*.py files were not moved from custom_actions to custom_actions/scripts.")
  242. elif compare_versions(ambari_version, "2.0.0") == 0:
  243. move_user_custom_actions()
  244. # check if ambari has obsolete LDAP configuration
  245. if properties.get_property(LDAP_PRIMARY_URL_PROPERTY) and not properties.get_property(IS_LDAP_CONFIGURED):
  246. args.warnings.append("Existing LDAP configuration is detected. You must run the \"ambari-server setup-ldap\" command to adjust existing LDAP configuration.")