blob: cec3fd71003828b3d2f97dd15fee97a384cbf821 [file] [log] [blame]
#!/usr/bin/env python3
'''
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
'''
import datetime
import glob
import os
import re
import shutil
import stat
import string
import sys
import tempfile
import getpass
import ambari_server.serverClassPath
from ambari_commons.exceptions import FatalException
from ambari_commons.os_check import OSCheck, OSConst
from ambari_commons.os_family_impl import OsFamilyImpl
from ambari_commons.os_utils import run_os_command, search_file, set_file_permissions, parse_log4j_file
from ambari_commons.logging_utils import get_debug_mode, print_info_msg, print_warning_msg, print_error_msg, \
set_debug_mode
from ambari_server.properties import Properties
from ambari_server.userInput import get_validated_string_input
from ambari_server.utils import compare_versions, locate_file, on_powerpc
from ambari_server.ambariPath import AmbariPath
from ambari_server.userInput import get_YN_input
OS_VERSION = OSCheck().get_os_major_version()
OS_TYPE = OSCheck.get_os_type()
OS_FAMILY = OSCheck.get_os_family()
PID_NAME = "ambari-server.pid"
# Non-root user setup commands
NR_USER_PROPERTY = "ambari-server.user"
BLIND_PASSWORD = "*****"
# Common messages
PRESS_ENTER_MSG = "Press <enter> to continue."
OS_FAMILY_PROPERTY = "server.os_family"
OS_TYPE_PROPERTY = "server.os_type"
BOOTSTRAP_DIR_PROPERTY = "bootstrap.dir"
RECOMMENDATIONS_DIR_PROPERTY = 'recommendations.dir'
AMBARI_CONF_VAR = "AMBARI_CONF_DIR"
AMBARI_PROPERTIES_FILE = "ambari.properties"
AMBARI_ENV_FILE = "ambari-env.sh"
AMBARI_KRB_JAAS_LOGIN_FILE = "krb5JAASLogin.conf"
GET_FQDN_SERVICE_URL = "server.fqdn.service.url"
SERVER_OUT_FILE_KEY = "ambari.output.file.path"
VERBOSE_OUTPUT_KEY = "ambari.output.verbose"
DEBUG_MODE_KEY = "ambari.server.debug"
SUSPEND_START_MODE_KEY = "ambari.server.debug.suspend.start"
# Environment variables
AMBARI_SERVER_LIB = "AMBARI_SERVER_LIB"
JAVA_HOME = "JAVA_HOME"
AMBARI_VERSION_VAR = "AMBARI_VERSION_VAR"
# JDK
JAVA_HOME_PROPERTY = "java.home"
JDK_NAME_PROPERTY = "jdk.name"
JCE_NAME_PROPERTY = "jce.name"
JDK_DOWNLOAD_SUPPORTED_PROPERTY = "jdk.download.supported"
JCE_DOWNLOAD_SUPPORTED_PROPERTY = "jce.download.supported"
# Stack JDK
STACK_JAVA_HOME_PROPERTY = "stack.java.home"
STACK_JDK_NAME_PROPERTY = "stack.jdk.name"
STACK_JCE_NAME_PROPERTY = "stack.jce.name"
STACK_JAVA_VERSION = "stack.java.version"
#TODO property used incorrectly in local case, it was meant to be dbms name, not postgres database name,
# has workaround for now, as we don't need dbms name if persistence_type=local
JDBC_DATABASE_PROPERTY = "server.jdbc.database" # E.g., embedded|oracle|mysql|mssql|postgres
JDBC_DATABASE_NAME_PROPERTY = "server.jdbc.database_name" # E.g., ambari. Not used on Windows.
JDBC_HOSTNAME_PROPERTY = "server.jdbc.hostname"
JDBC_PORT_PROPERTY = "server.jdbc.port"
JDBC_POSTGRES_SCHEMA_PROPERTY = "server.jdbc.postgres.schema" # Only for postgres, defaults to same value as DB name
JDBC_SQLA_SERVER_NAME = "server.jdbc.sqla.server_name"
JDBC_USER_NAME_PROPERTY = "server.jdbc.user.name"
JDBC_PASSWORD_PROPERTY = "server.jdbc.user.passwd"
JDBC_PASSWORD_FILENAME = "password.dat"
JDBC_RCA_PASSWORD_FILENAME = "rca_password.dat"
CLIENT_API_PORT_PROPERTY = "client.api.port"
CLIENT_API_PORT = "8080"
CLIENT_SECURITY = "client.security"
SERVER_VERSION_FILE_PATH = "server.version.file"
PERSISTENCE_TYPE_PROPERTY = "server.persistence.type"
JDBC_DRIVER_PROPERTY = "server.jdbc.driver"
JDBC_URL_PROPERTY = "server.jdbc.url"
# connection pool (age and time are in seconds)
JDBC_CONNECTION_POOL_TYPE = "server.jdbc.connection-pool"
JDBC_CONNECTION_POOL_ACQUISITION_SIZE = "server.jdbc.connection-pool.acquisition-size"
JDBC_CONNECTION_POOL_MAX_AGE = "server.jdbc.connection-pool.max-age"
JDBC_CONNECTION_POOL_MAX_IDLE_TIME = "server.jdbc.connection-pool.max-idle-time"
JDBC_CONNECTION_POOL_MAX_IDLE_TIME_EXCESS = "server.jdbc.connection-pool.max-idle-time-excess"
JDBC_CONNECTION_POOL_IDLE_TEST_INTERVAL = "server.jdbc.connection-pool.idle-test-interval"
JDBC_RCA_DATABASE_PROPERTY = "server.jdbc.database"
JDBC_RCA_HOSTNAME_PROPERTY = "server.jdbc.hostname"
JDBC_RCA_PORT_PROPERTY = "server.jdbc.port"
JDBC_RCA_SCHEMA_PROPERTY = "server.jdbc.schema"
JDBC_RCA_DRIVER_PROPERTY = "server.jdbc.rca.driver"
JDBC_RCA_URL_PROPERTY = "server.jdbc.rca.url"
JDBC_RCA_USER_NAME_PROPERTY = "server.jdbc.rca.user.name"
JDBC_RCA_PASSWORD_FILE_PROPERTY = "server.jdbc.rca.user.passwd"
DEFAULT_DBMS_PROPERTY = "server.setup.default.dbms"
JDBC_RCA_PASSWORD_ALIAS = "ambari.db.password"
### # Windows-specific # ###
JDBC_USE_INTEGRATED_AUTH_PROPERTY = "server.jdbc.use.integrated.auth"
JDBC_RCA_USE_INTEGRATED_AUTH_PROPERTY = "server.jdbc.rca.use.integrated.auth"
### # End Windows-specific # ###
# The user which will bootstrap embedded postgres database setup by creating the default schema and ambari user.
LOCAL_DATABASE_ADMIN_PROPERTY = "local.database.user"
# resources repo configuration
RESOURCES_DIR_PROPERTY = "resources.dir"
# stack repo upgrade
STACK_LOCATION_KEY = 'metadata.path'
# LDAP security
LDAP_MGR_PASSWORD_ALIAS = "ambari.ldap.manager.password"
LDAP_MGR_PASSWORD_PROPERTY = "ambari.ldap.connectivity.bind_password"
# SSL truststore
SSL_TRUSTSTORE_PASSWORD_ALIAS = "ambari.ssl.trustStore.password"
SSL_TRUSTSTORE_PATH_PROPERTY = "ssl.trustStore.path"
SSL_TRUSTSTORE_PASSWORD_PROPERTY = "ssl.trustStore.password"
SSL_TRUSTSTORE_TYPE_PROPERTY = "ssl.trustStore.type"
# SSL common
SSL_API = 'api.ssl'
SSL_API_PORT = 'client.api.ssl.port'
DEFAULT_SSL_API_PORT = 8443
# Kerberos
CHECK_AMBARI_KRB_JAAS_CONFIGURATION_PROPERTY = "kerberos.check.jaas.configuration"
# JDK
JDK_RELEASES="java.releases"
if on_powerpc():
JDK_RELEASES += ".ppc64le"
VIEWS_DIR_PROPERTY = "views.dir"
ACTIVE_INSTANCE_PROPERTY = "active.instance"
# web server startup timeout
WEB_SERVER_STARTUP_TIMEOUT = "server.startup.web.timeout"
#Common setup or upgrade message
SETUP_OR_UPGRADE_MSG = "- If this is a new setup, then run the \"ambari-server setup\" command to create the user\n" \
"- If this is an upgrade of an existing setup, run the \"ambari-server upgrade\" command.\n" \
"Refer to the Ambari documentation for more information on setup and upgrade."
GPL_LICENSE_PROMPT_TEXT = """GPL License for LZO: https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
Enable Ambari Server to download and install GPL Licensed LZO packages [y/n] (n)? """
DEFAULT_DB_NAME = "ambari"
SECURITY_KEYS_DIR = "security.server.keys_dir"
EXTENSION_PATH_PROPERTY = 'extensions.path'
COMMON_SERVICES_PATH_PROPERTY = 'common.services.path'
MPACKS_STAGING_PATH_PROPERTY = 'mpacks.staging.path'
WEBAPP_DIR_PROPERTY = 'webapp.dir'
SHARED_RESOURCES_DIR = 'shared.resources.dir'
BOOTSTRAP_SCRIPT = 'bootstrap.script'
CUSTOM_ACTION_DEFINITIONS = 'custom.action.definitions'
BOOTSTRAP_SETUP_AGENT_SCRIPT = 'bootstrap.setup_agent.script'
STACKADVISOR_SCRIPT = 'stackadvisor.script'
PID_DIR_PROPERTY = 'pid.dir'
SERVER_TMP_DIR_PROPERTY = "server.tmp.dir"
GPL_LICENSE_ACCEPTED_PROPERTY = 'gpl.license.accepted'
REQUIRED_PROPERTIES = [OS_FAMILY_PROPERTY, OS_TYPE_PROPERTY, COMMON_SERVICES_PATH_PROPERTY, SERVER_VERSION_FILE_PATH,
WEBAPP_DIR_PROPERTY, STACK_LOCATION_KEY, SECURITY_KEYS_DIR, JDBC_DATABASE_NAME_PROPERTY,
NR_USER_PROPERTY, JAVA_HOME_PROPERTY, JDBC_PASSWORD_PROPERTY, SHARED_RESOURCES_DIR,
JDBC_USER_NAME_PROPERTY, BOOTSTRAP_SCRIPT, RESOURCES_DIR_PROPERTY, CUSTOM_ACTION_DEFINITIONS,
BOOTSTRAP_SETUP_AGENT_SCRIPT, STACKADVISOR_SCRIPT, BOOTSTRAP_DIR_PROPERTY, PID_DIR_PROPERTY,
MPACKS_STAGING_PATH_PROPERTY]
# if these properties are available 'ambari-server setup -s' is not triggered again.
SETUP_DONE_PROPERTIES = [OS_FAMILY_PROPERTY, OS_TYPE_PROPERTY, JDK_NAME_PROPERTY, JDBC_DATABASE_PROPERTY,
NR_USER_PROPERTY, PERSISTENCE_TYPE_PROPERTY
]
def get_default_views_dir():
return AmbariPath.get("/var/lib/ambari-server/resources/views")
def get_conf_dir():
try:
conf_dir = os.environ[AMBARI_CONF_VAR]
return conf_dir
except KeyError:
default_conf_dir = AmbariPath.get("/etc/ambari-server/conf")
print_info_msg("{0} is not set, using default {1}".format(AMBARI_CONF_VAR, default_conf_dir))
return default_conf_dir
def find_properties_file():
conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
if conf_file is None:
err = 'File %s not found in search path $%s: %s' % (AMBARI_PROPERTIES_FILE,
AMBARI_CONF_VAR, get_conf_dir())
print_error_msg (err)
raise FatalException(1, err)
else:
print_info_msg('Loading properties from {0}'.format(conf_file))
return conf_file
# Load ambari properties and return dict with values
def get_ambari_properties():
conf_file = find_properties_file()
# Try to read ambari properties file. It is OK to fail.
# Return -1 on failure.
properties = None
try:
properties = Properties()
with open(conf_file) as hfR:
properties.load(hfR)
except (Exception) as e:
print_error_msg ('Could not read "%s": %s' % (conf_file, str(e)))
return -1
# Try to replace $ROOT with the value from the OS environment.
# OK to fail. Just print the exception and return the properties
# dictionary read above
try:
root_env = 'ROOT'
if root_env in os.environ:
root = os.environ["ROOT"].rstrip("/")
else:
root = ''
for k,v in properties.items():
properties.__dict__[k] = v.replace("$ROOT", root)
properties._props[k] = v.replace("$ROOT", root)
except (Exception) as e:
print_error_msg('Could not replace %s in "%s": %s' %(conf_file, root_env, str(e)))
return properties
class ServerDatabaseType(object):
internal = 0
remote = 1
class ServerDatabaseEntry(object):
def __init__(self, name, title, db_type, aliases=None):
"""
:type name str
:type title str
:type db_type int
:type aliases list
"""
self.__name = name
self.__title = title
self.__type = db_type
if aliases is None:
aliases = []
self.__aliases = aliases
@property
def name(self):
return self.__name
@property
def title(self):
return self.__title
@property
def dbtype(self):
return self.__type
def __str__(self):
return self.name
def __eq__(self, other):
if other is None:
return False
if isinstance(other, ServerDatabaseEntry):
return self.name == other.name and self.dbtype == other.dbtype
elif isinstance(other, str):
return self.name == other or other in self.__aliases
raise RuntimeError("Not compatible type")
class ServerDatabases(object):
postgres = ServerDatabaseEntry("postgres", "Postgres", ServerDatabaseType.remote)
oracle = ServerDatabaseEntry("oracle", "Oracle", ServerDatabaseType.remote)
mysql = ServerDatabaseEntry("mysql", "MySQL", ServerDatabaseType.remote)
mssql = ServerDatabaseEntry("mssql", "MSSQL", ServerDatabaseType.remote)
derby = ServerDatabaseEntry("derby", "Derby", ServerDatabaseType.remote)
sqlanywhere = ServerDatabaseEntry("sqlanywhere", "SQL Anywhere", ServerDatabaseType.remote)
postgres_internal = ServerDatabaseEntry("postgres", "Embedded Postgres", ServerDatabaseType.internal, aliases=['embedded'])
@staticmethod
def databases():
props = ServerDatabases.__dict__
r_props = []
for p in props:
if isinstance(props[p], ServerDatabaseEntry):
r_props.append(props[p].name)
return set(r_props)
@staticmethod
def match(name):
"""
:type name str
:rtype ServerDatabaseEntry
"""
props = ServerDatabases.__dict__
for p in props:
if isinstance(props[p], ServerDatabaseEntry):
if name == props[p]:
return props[p]
return None
class ServerConfigDefaults(object):
def __init__(self):
properties = get_ambari_properties()
if properties == -1:
print_error_msg("Error getting ambari properties")
self.JAVA_SHARE_PATH = "/usr/share/java"
self.SHARE_PATH = "/usr/share"
self.OUT_DIR = parse_log4j_file(get_conf_dir() + "/log4j.properties")['ambari.log.dir'].replace("//", "/")
self.SERVER_OUT_FILE = os.path.join(self.OUT_DIR, "ambari-server.out")
self.SERVER_LOG_FILE = os.path.join(self.OUT_DIR, "ambari-server.log")
self.DB_CHECK_LOG = os.path.join(self.OUT_DIR, "ambari-server-check-database.log")
self.ROOT_FS_PATH = os.sep
self.JDK_INSTALL_DIR = ""
self.JDK_SEARCH_PATTERN = ""
self.JAVA_EXE_SUBPATH = ""
self.JDK_SECURITY_DIR = os.path.join("jre", "lib", "security")
self.SERVER_RESOURCES_DIR = ""
# Configuration defaults
self.DEFAULT_CONF_DIR = ""
if properties == -1:
self.PID_DIR = AmbariPath.get(os.sep + os.path.join("var", "run", "ambari-server"))
self.BOOTSTRAP_DIR = AmbariPath.get(os.sep + os.path.join("var", "run", "ambari-server", "bootstrap"))
self.RECOMMENDATIONS_DIR = AmbariPath.get(os.sep + os.path.join("var", "run", "ambari-server", "stack-recommendations"))
else:
self.PID_DIR = properties.get_property(PID_DIR_PROPERTY)
self.BOOTSTRAP_DIR = properties.get_property(BOOTSTRAP_DIR_PROPERTY)
self.RECOMMENDATIONS_DIR = properties.get_property(RECOMMENDATIONS_DIR_PROPERTY)
# this directories should be pre-created by user and be writable.
self.check_if_directories_writable([self.OUT_DIR, self.PID_DIR])
self.DEFAULT_LIBS_DIR = ""
self.DEFAULT_VLIBS_DIR = ""
self.AMBARI_PROPERTIES_BACKUP_FILE = ""
self.AMBARI_ENV_BACKUP_FILE = ""
self.AMBARI_KRB_JAAS_LOGIN_BACKUP_FILE = ""
# ownership/permissions mapping
# path - permissions - user - group - recursive
# Rules are executed in the same order as they are listed
# {0} in user/group will be replaced by customized ambari-server username
self.NR_ADJUST_OWNERSHIP_LIST = []
self.NR_CHANGE_OWNERSHIP_LIST = []
self.NR_USERADD_CMD = ""
self.MASTER_KEY_FILE_PERMISSIONS = "640"
self.CREDENTIALS_STORE_FILE_PERMISSIONS = "640"
self.TRUST_STORE_LOCATION_PERMISSIONS = "644"
self.DEFAULT_DB_NAME = "ambari"
self.STACK_LOCATION_DEFAULT = ""
self.EXTENSION_LOCATION_DEFAULT = ""
self.COMMON_SERVICES_LOCATION_DEFAULT = ""
self.MPACKS_STAGING_LOCATION_DEFAULT = ""
self.SERVER_TMP_DIR_DEFAULT = ""
self.DASHBOARD_DIRNAME = "dashboards"
self.DEFAULT_VIEWS_DIR = ""
#keytool commands
self.keytool_bin_subpath = ""
#Standard messages
self.MESSAGE_SERVER_RUNNING_AS_ROOT = ""
self.MESSAGE_WARN_SETUP_NOT_ROOT = ""
self.MESSAGE_ERROR_RESET_NOT_ROOT = ""
self.MESSAGE_ERROR_UPGRADE_NOT_ROOT = ""
self.MESSAGE_CHECK_FIREWALL = ""
def check_if_directories_writable(self, directories):
for directory in directories:
if not os.path.isdir(directory):
try:
os.makedirs(directory, 0o755)
except Exception as ex:
# permission denied here is expected when ambari runs as non-root
print_error_msg("Could not create {0}. Reason: {1}".format(directory, str(ex)))
if not os.path.isdir(directory) or not os.access(directory, os.W_OK):
raise FatalException(-1, "Unable to access {0} directory. Confirm the directory is created and is writable by Ambari Server user account '{1}'".format(directory, getpass.getuser()))
@OsFamilyImpl(os_family=OSConst.WINSRV_FAMILY)
class ServerConfigDefaultsWindows(ServerConfigDefaults):
def __init__(self):
super(ServerConfigDefaultsWindows, self).__init__()
self.JDK_INSTALL_DIR = "C:\\"
self.JDK_SEARCH_PATTERN = "j[2se|dk|re]*"
self.JAVA_EXE_SUBPATH = "bin\\java.exe"
# Configuration defaults
self.DEFAULT_CONF_DIR = "conf"
self.DEFAULT_LIBS_DIR = "lib"
self.AMBARI_PROPERTIES_BACKUP_FILE = "ambari.properties.backup"
self.AMBARI_KRB_JAAS_LOGIN_BACKUP_FILE = "" # ToDo: should be adjusted later
# ownership/permissions mapping
# path - permissions - user - group - recursive
# Rules are executed in the same order as they are listed
# {0} in user/group will be replaced by customized ambari-server username
# The permissions are icacls
self.NR_ADJUST_OWNERSHIP_LIST = [
(self.OUT_DIR, "M", "{0}", True), #0110-0100-0100 rw-r-r
(self.OUT_DIR, "F", "{0}", False), #0111-0101-0101 rwx-rx-rx
(self.PID_DIR, "M", "{0}", True),
(self.PID_DIR, "F", "{0}", False),
("bootstrap", "F", "{0}", False),
("ambari-env.cmd", "F", "{0}", False),
("keystore", "M", "{0}", True),
("keystore", "F", "{0}", False),
("keystore\\db", "700", "{0}", False),
("keystore\\db\\newcerts", "700", "{0}", False),
("resources\\stacks", "755", "{0}", True),
("resources\\custom_actions", "755", "{0}", True),
("conf", "644", "{0}", True),
("conf", "755", "{0}", False),
("conf\\password.dat", "640", "{0}", False),
# Also, /etc/ambari-server/conf/password.dat
# is generated later at store_password_file
]
self.NR_USERADD_CMD = "cmd /C net user {0} {1} /ADD"
self.SERVER_RESOURCES_DIR = "resources"
self.STACK_LOCATION_DEFAULT = "resources\\stacks"
self.EXTENSION_LOCATION_DEFAULT = "resources\\extensions"
self.COMMON_SERVICES_LOCATION_DEFAULT = "resources\\common-services"
self.MPACKS_STAGING_LOCATION_DEFAULT = "resources\\mpacks"
self.SERVER_TMP_DIR_DEFAULT = "data\\tmp"
self.DEFAULT_VIEWS_DIR = "resources\\views"
#keytool commands
self.keytool_bin_subpath = "bin\\keytool.exe"
#Standard messages
self.MESSAGE_SERVER_RUNNING_AS_ROOT = "Ambari Server running with 'root' privileges."
self.MESSAGE_WARN_SETUP_NOT_ROOT = "Ambari-server setup is run with root-level privileges, passwordless sudo access for some commands commands may be required"
self.MESSAGE_ERROR_RESET_NOT_ROOT = "Ambari-server reset must be run with administrator-level privileges"
self.MESSAGE_ERROR_UPGRADE_NOT_ROOT = "Ambari-server upgrade must be run with administrator-level privileges"
self.MESSAGE_CHECK_FIREWALL = "Checking firewall status..."
@OsFamilyImpl(os_family=OsFamilyImpl.DEFAULT)
class ServerConfigDefaultsLinux(ServerConfigDefaults):
def __init__(self):
super(ServerConfigDefaultsLinux, self).__init__()
# JDK
self.JDK_INSTALL_DIR = AmbariPath.get("/usr/jdk64")
self.JDK_SEARCH_PATTERN = "jdk*"
self.JAVA_EXE_SUBPATH = "bin/java"
# Configuration defaults
self.DEFAULT_CONF_DIR = AmbariPath.get("/etc/ambari-server/conf")
self.DEFAULT_LIBS_DIR = AmbariPath.get("/usr/lib/ambari-server")
self.DEFAULT_VLIBS_DIR = AmbariPath.get("/var/lib/ambari-server")
self.AMBARI_PROPERTIES_BACKUP_FILE = "ambari.properties.rpmsave"
self.AMBARI_ENV_BACKUP_FILE = "ambari-env.sh.rpmsave"
self.AMBARI_KRB_JAAS_LOGIN_BACKUP_FILE = "krb5JAASLogin.conf.rpmsave"
# ownership/permissions mapping
# path - permissions - user - group - recursive
# Rules are executed in the same order as they are listed
# {0} in user/group will be replaced by customized ambari-server username
self.NR_ADJUST_OWNERSHIP_LIST = [
(self.OUT_DIR + "/*", "644", "{0}", True),
(self.OUT_DIR, "755", "{0}", False),
(self.PID_DIR + "/*", "644", "{0}", True),
(self.PID_DIR, "755", "{0}", False),
(self.BOOTSTRAP_DIR, "755", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/ambari-env.sh"), "700", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/ambari-sudo.sh"), "700", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/keys/*"), "600", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/keys/"), "700", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/keys/db/"), "700", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/keys/db/newcerts/"), "700", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/keys/.ssh"), "700", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/resources/common-services/"), "755", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/resources/stacks/"), "755", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/resources/extensions/"), "755", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/resources/dashboards/"), "755", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/resources/mpacks/"), "755", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/resources/custom_actions/"), "755", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/resources/host_scripts/"), "755", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/resources/views/*"), "644", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/resources/views/"), "755", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/resources/views/work/"), "755", "{0}", True),
(AmbariPath.get("/etc/ambari-server/conf/*"), "644", "{0}", True),
(AmbariPath.get("/etc/ambari-server/conf/"), "755", "{0}", False),
(AmbariPath.get("/etc/ambari-server/conf/password.dat"), "640", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/keys/pass.txt"), "600", "{0}", False),
(AmbariPath.get("/etc/ambari-server/conf/ldap-password.dat"), "640", "{0}", False),
(self.RECOMMENDATIONS_DIR, "744", "{0}", True),
(self.RECOMMENDATIONS_DIR, "755", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/resources/data/"), "644", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/resources/data/"), "755", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/data/tmp/*"), "644", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/data/tmp/"), "755", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/data/cache/"), "600", "{0}", True),
(AmbariPath.get("/var/lib/ambari-server/data/cache/"), "700", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/resources/common-services/STORM/0.9.1/package/files/wordCount.jar"), "644", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/resources/stacks/HDP/2.1.GlusterFS/services/STORM/package/files/wordCount.jar"), "644", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/resources/stack-hooks/before-START/files/fast-hdfs-resource.jar"), "644", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/resources/stacks/HDP/2.1/services/SMARTSENSE/package/files/view/smartsense-ambari-view-1.4.0.0.60.jar"), "644", "{0}", False),
(AmbariPath.get("/var/lib/ambari-server/resources/stacks/HDP/3.0/hooks/before-START/files/fast-hdfs-resource.jar"), "644", "{0}", False),
# Also, /etc/ambari-server/conf/password.dat
# is generated later at store_password_file
]
self.NR_CHANGE_OWNERSHIP_LIST = [
(AmbariPath.get("/var/lib/ambari-server"), "{0}", True),
(AmbariPath.get("/usr/lib/ambari-server"), "{0}", True),
(self.OUT_DIR, "{0}", True),
(self.PID_DIR, "{0}", True),
(AmbariPath.get("/etc/ambari-server"), "{0}", True),
]
self.NR_USERADD_CMD = 'useradd -M --comment "{1}" ' \
'--shell %s ' % locate_file('nologin', '/sbin') + ' -d ' + AmbariPath.get('/var/lib/ambari-server/keys/') + ' {0}'
self.SERVER_RESOURCES_DIR = AmbariPath.get("/var/lib/ambari-server/resources")
self.STACK_LOCATION_DEFAULT = AmbariPath.get("/var/lib/ambari-server/resources/stacks")
self.EXTENSION_LOCATION_DEFAULT = AmbariPath.get("/var/lib/ambari-server/resources/extensions")
self.COMMON_SERVICES_LOCATION_DEFAULT = AmbariPath.get("/var/lib/ambari-server/resources/common-services")
self.MPACKS_STAGING_LOCATION_DEFAULT = AmbariPath.get("/var/lib/ambari-server/resources/mpacks")
self.SERVER_TMP_DIR_DEFAULT = AmbariPath.get("/var/lib/ambari-server/data/tmp")
self.DEFAULT_VIEWS_DIR = AmbariPath.get("/var/lib/ambari-server/resources/views")
#keytool commands
self.keytool_bin_subpath = "bin/keytool"
#Standard messages
self.MESSAGE_SERVER_RUNNING_AS_ROOT = "Ambari Server running with administrator privileges."
self.MESSAGE_WARN_SETUP_NOT_ROOT = "Ambari-server setup is run with root-level privileges, passwordless sudo access for some commands commands may be required"
self.MESSAGE_ERROR_RESET_NOT_ROOT = "Ambari-server reset should be run with root-level privileges"
self.MESSAGE_ERROR_UPGRADE_NOT_ROOT = "Ambari-server upgrade must be run with root-level privileges"
self.MESSAGE_CHECK_FIREWALL = "Checking firewall status..."
configDefaults = ServerConfigDefaults()
# Security
SECURITY_MASTER_KEY_LOCATION = "security.master.key.location"
SECURITY_KEY_IS_PERSISTED = "security.master.key.ispersisted"
SECURITY_KEY_ENV_VAR_NAME = "AMBARI_SECURITY_MASTER_KEY"
SECURITY_MASTER_KEY_FILENAME = "master"
SECURITY_IS_ENCRYPTION_ENABLED = "security.passwords.encryption.enabled"
SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED = "security.server.encrypt_sensitive_data"
SECURITY_KERBEROS_JASS_FILENAME = "krb5JAASLogin.conf"
SECURITY_PROVIDER_GET_CMD = "{0} -cp {1} " + \
"org.apache.ambari.server.security.encryption" + \
".CredentialProvider GET {2} {3} {4} " + \
"> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
SECURITY_PROVIDER_PUT_CMD = "{0} -cp {1} " + \
"org.apache.ambari.server.security.encryption" + \
".CredentialProvider PUT {2} {3} {4} " + \
"> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
SECURITY_PROVIDER_KEY_CMD = "{0} -cp {1} " + \
"org.apache.ambari.server.security.encryption" + \
".MasterKeyServiceImpl {2} {3} {4} " + \
"> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
SECURITY_SENSITIVE_DATA_ENCRYPTON_CMD = "{0} -cp {1} " + \
"org.apache.ambari.server.security.encryption.SensitiveDataEncryption" + \
" {2} " + \
"> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
def read_ambari_user():
'''
Reads ambari user from properties file
'''
properties = get_ambari_properties()
if properties != -1:
user = properties[NR_USER_PROPERTY]
if user:
return user
return None
def get_is_active_instance():
# active.instance, if missing, will be considered to be true;
# if present, it should be explicitly set to "true" to set this as the active instance;
# any other value will be taken as a "false"
properties = get_ambari_properties()
# Get the value of active.instance.
active_instance_value = None
if properties != -1:
if ACTIVE_INSTANCE_PROPERTY in properties.propertyNames():
active_instance_value = properties[ACTIVE_INSTANCE_PROPERTY]
if active_instance_value is None: # property is missing
is_active_instance = True
elif (active_instance_value == 'true'): # property is explicitly set to true
is_active_instance = True
else: # any other value
is_active_instance = False
return is_active_instance
def get_value_from_properties(properties, key, default=""):
try:
value = properties.get_property(key)
if not value:
value = default
except:
return default
return value
def get_views_dir(properties):
views_dir = properties.get_property(VIEWS_DIR_PROPERTY)
if views_dir is None or views_dir == "":
views_dirs = glob.glob(AmbariPath.get("/var/lib/ambari-server/resources/views/work"))
else:
views_dirs = glob.glob(views_dir + "/work")
return views_dirs
def get_admin_views_dir(properties):
views_dir = properties.get_property(VIEWS_DIR_PROPERTY)
if views_dir is None or views_dir == "":
views_dirs = glob.glob(AmbariPath.get("/var/lib/ambari-server/resources/views/work/ADMIN_VIEW*"))
else:
views_dirs = glob.glob(views_dir + "/work/ADMIN_VIEW*")
return views_dirs
def get_views_jars(properties):
views_dir = properties.get_property(VIEWS_DIR_PROPERTY)
if views_dir is None or views_dir == "":
views_jars = glob.glob(AmbariPath.get("/var/lib/ambari-server/resources/views/*.jar"))
else:
views_jars = glob.glob(views_dir + "/*.jar")
return views_jars
def get_is_secure(properties):
isSecure = properties.get_property(SECURITY_IS_ENCRYPTION_ENABLED)
isSecure = True if isSecure and isSecure.lower() == 'true' else False
return isSecure
def get_is_persisted(properties):
keyLocation = get_master_key_location(properties)
masterKeyFile = search_file(SECURITY_MASTER_KEY_FILENAME, keyLocation)
isPersisted = True if masterKeyFile else False
return (isPersisted, masterKeyFile)
def get_credential_store_location(properties):
store_loc = properties[SECURITY_KEYS_DIR]
if store_loc is None or store_loc == "":
store_loc = AmbariPath.get("/var/lib/ambari-server/keys/credentials.jceks")
else:
store_loc += os.sep + "credentials.jceks"
return store_loc
def get_master_key_location(properties):
keyLocation = properties[SECURITY_MASTER_KEY_LOCATION]
if keyLocation is None or keyLocation == "":
keyLocation = properties[SECURITY_KEYS_DIR]
return keyLocation
def get_ambari_server_ui_port(properties):
ambari_server_ui_port = CLIENT_API_PORT
client_api_port = properties.get_property(CLIENT_API_PORT_PROPERTY)
if client_api_port:
ambari_server_ui_port = client_api_port
api_ssl = properties.get_property(SSL_API)
if api_ssl and str(api_ssl).lower() == "true":
ambari_server_ui_port = DEFAULT_SSL_API_PORT
ssl_api_port = properties.get_property(SSL_API_PORT)
if ssl_api_port:
ambari_server_ui_port = ssl_api_port
return ambari_server_ui_port
# Copy file to /tmp and save with file.# (largest # is latest file)
def backup_file_in_temp(filePath):
if filePath is not None:
tmpDir = tempfile.gettempdir()
back_up_file_count = len(glob.glob1(tmpDir, AMBARI_PROPERTIES_FILE + "*"))
try:
shutil.copyfile(filePath, tmpDir + os.sep +
AMBARI_PROPERTIES_FILE + "." + str(back_up_file_count + 1))
except (Exception) as e:
print_error_msg('Could not backup file in temp "%s": %s' % (
back_up_file_count, str(e)))
return 0
def get_ambari_version(properties):
"""
:param properties: Ambari properties
:return: Return a string of the ambari version. When comparing versions, please use "compare_versions" function.
"""
version = None
try:
server_version_file_path = properties[SERVER_VERSION_FILE_PATH]
if server_version_file_path and os.path.exists(server_version_file_path):
with open(server_version_file_path, 'r') as file:
version = file.read().strip()
except:
print_error_msg("Error getting ambari version")
return version
def get_db_type(properties):
"""
:rtype ServerDatabaseEntry
"""
db_type = None
persistence_type = properties[PERSISTENCE_TYPE_PROPERTY]
if properties[JDBC_DATABASE_PROPERTY]:
db_type = ServerDatabases.match(properties[JDBC_DATABASE_PROPERTY])
if db_type == ServerDatabases.postgres and persistence_type == "local":
db_type = ServerDatabases.postgres_internal
if properties[JDBC_URL_PROPERTY] and db_type is None:
jdbc_url = properties[JDBC_URL_PROPERTY].lower()
if str(ServerDatabases.postgres) in jdbc_url:
db_type = ServerDatabases.postgres
elif str(ServerDatabases.oracle) in jdbc_url:
db_type = ServerDatabases.oracle
elif str(ServerDatabases.mysql) in jdbc_url:
db_type = ServerDatabases.mysql
elif str(ServerDatabases.mssql) in jdbc_url:
db_type = ServerDatabases.mssql
elif str(ServerDatabases.derby) in jdbc_url:
db_type = ServerDatabases.derby
elif str(ServerDatabases.sqlanywhere) in jdbc_url:
db_type = ServerDatabases.sqlanywhere
if persistence_type == "local" and db_type is None:
db_type = ServerDatabases.postgres_internal
return db_type
def check_database_name_property(upgrade=False):
"""
:param upgrade: If Ambari is being upgraded.
:return:
"""
properties = get_ambari_properties()
if properties == -1:
print_error_msg("Error getting ambari properties")
return -1
version = get_ambari_version(properties)
if upgrade and (properties[JDBC_DATABASE_PROPERTY] not in ServerDatabases.databases()
or JDBC_RCA_SCHEMA_PROPERTY in properties):
# This code exists for historic reasons in which property names changed from Ambari 1.6.1 to 1.7.0
persistence_type = properties[PERSISTENCE_TYPE_PROPERTY]
if persistence_type == "remote":
db_name = properties[JDBC_RCA_SCHEMA_PROPERTY] # this was a property in Ambari 1.6.1, but not after 1.7.0
if db_name:
write_property(JDBC_DATABASE_NAME_PROPERTY, db_name)
# If DB type is missing, attempt to reconstruct it from the JDBC URL
db_type = properties[JDBC_DATABASE_PROPERTY]
if db_type is None or db_type.strip().lower() not in ServerDatabases.databases():
db_type = get_db_type(properties).name
if db_type:
write_property(JDBC_DATABASE_PROPERTY, db_type)
properties = get_ambari_properties()
elif persistence_type == "local":
# Ambari 1.6.1, had "server.jdbc.database" as the DB name, and the
# DB type was assumed to be "postgres" if was embedded ("local")
db_name = properties[JDBC_DATABASE_PROPERTY]
if db_name:
write_property(JDBC_DATABASE_NAME_PROPERTY, db_name)
write_property(JDBC_DATABASE_PROPERTY, "postgres")
properties = get_ambari_properties()
dbname = properties[JDBC_DATABASE_NAME_PROPERTY]
if dbname is None or dbname == "":
err = "DB Name property not set in config file.\n" + SETUP_OR_UPGRADE_MSG
raise FatalException(-1, err)
def update_database_name_property(upgrade=False):
try:
check_database_name_property(upgrade)
except FatalException:
properties = get_ambari_properties()
if properties == -1:
err = "Error getting ambari properties"
raise FatalException(-1, err)
print_warning_msg("{0} property isn't set in {1} . Setting it to default value - {2}".format(JDBC_DATABASE_NAME_PROPERTY, AMBARI_PROPERTIES_FILE, configDefaults.DEFAULT_DB_NAME))
properties.process_pair(JDBC_DATABASE_NAME_PROPERTY, configDefaults.DEFAULT_DB_NAME)
conf_file = find_properties_file()
try:
with open(conf_file, "w") as hfW:
properties.store(hfW)
except Exception as e:
err = 'Could not write ambari config file "%s": %s' % (conf_file, e)
raise FatalException(-1, err)
def encrypt_password(alias, password, options):
properties = get_ambari_properties()
if properties == -1:
raise FatalException(1, None)
return get_encrypted_password(alias, password, properties, options)
def get_encrypted_password(alias, password, properties, options):
isSecure = get_is_secure(properties)
(isPersisted, masterKeyFile) = get_is_persisted(properties)
if isSecure:
masterKey = None
if not masterKeyFile:
# Encryption enabled but no master key file found
masterKey = get_original_master_key(properties, options)
retCode = save_passwd_for_alias(alias, password, masterKey)
if retCode != 0:
print_error_msg ('Failed to save secure password!')
return password
else:
return get_alias_string(alias)
return password
def is_alias_string(passwdStr):
regex = re.compile("\$\{alias=[\w\.]+\}")
# Match implies string at beginning of word
r = regex.match(passwdStr)
if r is not None:
return True
else:
return False
def get_alias_string(alias):
return "${alias=" + alias + "}"
def get_alias_from_alias_string(aliasStr):
return aliasStr[8:-1]
def read_passwd_for_alias(alias, masterKey="", options=None):
if alias:
jdk_path = find_jdk()
if jdk_path is None:
print_error_msg("No JDK found, please run the \"setup\" "
"command to install a JDK automatically or install any "
"JDK manually to {0}".format(configDefaults.JDK_INSTALL_DIR))
return 1
tempFileName = "ambari.passwd"
passwd = ""
tempDir = tempfile.gettempdir()
#create temporary file for writing
tempFilePath = tempDir + os.sep + tempFileName
with open(tempFilePath, 'w+'):
os.chmod(tempFilePath, stat.S_IREAD | stat.S_IWRITE)
if options is not None and hasattr(options, 'master_key') and options.master_key:
masterKey = options.master_key
if not masterKey:
masterKey = "None"
serverClassPath = ambari_server.serverClassPath.ServerClassPath(get_ambari_properties(), None)
command = SECURITY_PROVIDER_GET_CMD.format(get_java_exe_path(),
serverClassPath.get_full_ambari_classpath_escaped_for_shell(), alias, tempFilePath, masterKey)
(retcode, stdout, stderr) = run_os_command(command)
print_info_msg("Return code from credential provider get passwd: {0}".format(str(retcode)))
if retcode != 0:
print_error_msg ('ERROR: Unable to read password from store. alias = {0}'.format(alias))
else:
with open(tempFilePath, 'r') as hfRTemp:
passwd = hfRTemp.read()
# Remove temporary file
os.remove(tempFilePath)
return passwd
else:
print_error_msg("Alias is unreadable.")
def decrypt_password_for_alias(properties, alias, options=None):
isSecure = get_is_secure(properties)
if isSecure:
masterKey = None
(isPersisted, masterKeyFile) = get_is_persisted(properties)
if not masterKeyFile:
# Encryption enabled but no master key file found
masterKey = get_original_master_key(properties, options)
return read_passwd_for_alias(alias, masterKey, options)
else:
return alias
def save_passwd_for_alias(alias, passwd, masterKey=""):
if alias and passwd:
jdk_path = find_jdk()
if jdk_path is None:
print_error_msg("No JDK found, please run the \"setup\" "
"command to install a JDK automatically or install any "
"JDK manually to {0}".format(configDefaults.JDK_INSTALL_DIR))
return 1
if masterKey is None or masterKey == "":
masterKey = "None"
serverClassPath = ambari_server.serverClassPath.ServerClassPath(get_ambari_properties(), None)
command = SECURITY_PROVIDER_PUT_CMD.format(get_java_exe_path(),
serverClassPath.get_full_ambari_classpath_escaped_for_shell(), alias, passwd, masterKey)
(retcode, stdout, stderr) = run_os_command(command)
print_info_msg("Return code from credential provider save passwd: {0}".format(str(retcode)))
return retcode
else:
print_error_msg("Alias or password is unreadable.")
def get_pass_file_path(conf_file, filename):
return os.path.join(os.path.dirname(conf_file), filename)
def store_password_file(password, filename):
conf_file = find_properties_file()
passFilePath = get_pass_file_path(conf_file, filename)
with open(passFilePath, 'w+') as passFile:
passFile.write(password)
print_info_msg("Adjusting filesystem permissions")
ambari_user = read_ambari_user()
if ambari_user: # at the first install ambari_user can be None. Which is fine since later on password.dat is chowned with the correct ownership.
set_file_permissions(passFilePath, "660", ambari_user, False)
#Windows paths need double backslashes, otherwise the Ambari server deserializer will think the single \ are escape markers
return passFilePath.replace('\\', '\\\\')
def remove_password_file(filename):
passFilePath = os.path.join(get_conf_dir(), filename)
if os.path.exists(passFilePath):
try:
os.remove(passFilePath)
except Exception as e:
print_warning_msg('Unable to remove password file: {0}'.format(str(e)))
return 1
pass
return 0
def get_web_server_startup_timeout(properties):
"""
Gets the time, in seconds, that the startup script should wait for the web server to bind to
the configured port. If this value is too low, then the startup script will return an
error code even though Ambari is actually starting up.
:param properties:
:return: The timeout value, in seconds. The default is 90.
"""
# get the timeout property and strip it if it exists
timeout = properties[WEB_SERVER_STARTUP_TIMEOUT]
timeout = None if timeout is None else timeout.strip()
if timeout is None or timeout == "":
timeout = 90
else:
timeout = int(timeout)
return timeout
def get_original_master_key(properties, options = None):
input = True
masterKey = None
env_master_key = os.environ.get(SECURITY_KEY_ENV_VAR_NAME)
while(input):
# Find an alias that exists
alias = None
property = properties.get_property(JDBC_PASSWORD_PROPERTY)
if property and is_alias_string(property):
alias = JDBC_RCA_PASSWORD_ALIAS
if not alias:
property = properties.get_property(LDAP_MGR_PASSWORD_PROPERTY)
if property and is_alias_string(property):
alias = LDAP_MGR_PASSWORD_ALIAS
if not alias:
property = properties.get_property(SSL_TRUSTSTORE_PASSWORD_PROPERTY)
if property and is_alias_string(property):
alias = SSL_TRUSTSTORE_PASSWORD_ALIAS
# Decrypt alias with master to validate it, if no master return
password = None
if alias and env_master_key and env_master_key != "" and env_master_key != "None":
password = read_passwd_for_alias(alias, env_master_key, options)
if not password:
try:
if options is not None and hasattr(options, 'master_key') and options.master_key:
masterKey = options.master_key
if not masterKey:
masterKey = get_validated_string_input('Enter current Master Key: ',
"", ".*", "", True, True)
if options is not None:
options.master_key = masterKey
except KeyboardInterrupt:
print_warning_msg('Exiting...')
sys.exit(1)
if alias and masterKey:
password = read_passwd_for_alias(alias, masterKey, options)
if not password:
masterKey = None
if options is not None:
options.master_key = None
print_error_msg ("ERROR: Master key does not match")
continue
input = False
return masterKey
# Load database connection properties from conf file
def parse_properties_file(args):
properties = get_ambari_properties()
if properties == -1:
print_error_msg("Error getting ambari properties")
return -1
args.server_version_file_path = properties[SERVER_VERSION_FILE_PATH]
args.persistence_type = properties[PERSISTENCE_TYPE_PROPERTY]
args.jdbc_url = properties[JDBC_URL_PROPERTY]
args.dbms = properties[JDBC_DATABASE_PROPERTY]
if not args.persistence_type:
args.persistence_type = "local"
if args.persistence_type == 'remote':
args.database_host = properties[JDBC_HOSTNAME_PROPERTY]
args.database_port = properties[JDBC_PORT_PROPERTY]
args.database_name = properties[JDBC_DATABASE_NAME_PROPERTY]
args.database_username = properties[JDBC_USER_NAME_PROPERTY]
args.postgres_schema = properties[JDBC_POSTGRES_SCHEMA_PROPERTY] \
if JDBC_POSTGRES_SCHEMA_PROPERTY in properties.propertyNames() else None
args.database_password_file = properties[JDBC_PASSWORD_PROPERTY]
if args.database_password_file:
if not is_alias_string(args.database_password_file):
with open(properties[JDBC_PASSWORD_PROPERTY]) as hfDbPwd:
args.database_password = hfDbPwd.read()
else:
args.database_password = args.database_password_file
return 0
def is_jaas_keytab_exists(conf_file):
with open(conf_file, "r") as f:
lines = f.read()
match = re.search("keyTab=(.*)$", lines, re.MULTILINE)
return os.path.exists(match.group(1).strip("\"").strip())
def update_krb_jaas_login_properties():
"""
Update configuration files
:return: int -2 - skipped, -1 - error, 0 - successful
"""
prev_conf_file = search_file(configDefaults.AMBARI_KRB_JAAS_LOGIN_BACKUP_FILE, get_conf_dir())
conf_file = search_file(AMBARI_KRB_JAAS_LOGIN_FILE, get_conf_dir())
# check if source and target files exists, if not - skip copy action
if prev_conf_file is None or conf_file is None:
return -2
# if rpmsave file contains invalid keytab, we can skip restoring
if not is_jaas_keytab_exists(prev_conf_file):
return -2
try:
# restore original file, destination arg for rename func shouldn't exists
os.remove(conf_file)
os.rename(prev_conf_file, conf_file)
print_warning_msg("Original file %s kept" % AMBARI_KRB_JAAS_LOGIN_FILE)
except OSError as e:
print_error_msg ("Couldn't move %s file: %s" % (prev_conf_file, str(e)))
return -1
return 0
def update_ambari_env():
prev_env_file = search_file(configDefaults.AMBARI_ENV_BACKUP_FILE, configDefaults.DEFAULT_VLIBS_DIR)
env_file = search_file(AMBARI_ENV_FILE, configDefaults.DEFAULT_VLIBS_DIR)
# Previous env file does not exist
if (not prev_env_file) or (prev_env_file is None):
print(("INFO: Can not find %s file from previous version, skipping restore of environment settings. "
"%s may not include any user customization.") % (configDefaults.AMBARI_ENV_BACKUP_FILE, AMBARI_ENV_FILE))
return 0
try:
if env_file is not None:
os.remove(env_file)
os.rename(prev_env_file, env_file)
print(("INFO: Original file %s kept") % (AMBARI_ENV_FILE))
except OSError as e:
print_error_msg ( "Couldn't move %s file: %s" % (prev_env_file, str(e)))
return -1
return 0
def set_property(key, value, rewrite=True):
properties = get_ambari_properties()
if properties == -1:
err = "Error getting ambari properties"
raise FatalException(-1, err)
if not rewrite and key in properties.keys():
return
properties.process_pair(key, value)
update_properties(properties)
# default should be false / not accepted
def write_gpl_license_accepted(default_prompt_value = False, text = GPL_LICENSE_PROMPT_TEXT):
properties = get_ambari_properties()
if properties == -1:
err = "Error getting ambari properties"
raise FatalException(-1, err)
if GPL_LICENSE_ACCEPTED_PROPERTY in properties.keys() and properties.get_property(GPL_LICENSE_ACCEPTED_PROPERTY).lower() == "true":
return True
result = get_YN_input(text, default_prompt_value)
set_property(GPL_LICENSE_ACCEPTED_PROPERTY, str(result).lower())
return result
def update_ambari_properties():
prev_conf_file = search_file(configDefaults.AMBARI_PROPERTIES_BACKUP_FILE, get_conf_dir())
conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
# Previous config file does not exist
if (not prev_conf_file) or (prev_conf_file is None):
print_warning_msg("Can not find %s file from previous version, skipping import of settings" % configDefaults.AMBARI_PROPERTIES_BACKUP_FILE)
return 0
# ambari.properties file does not exists
if conf_file is None:
print_error_msg("Can't find %s file" % AMBARI_PROPERTIES_FILE)
return -1
with open(prev_conf_file) as hfOld:
try:
old_properties = Properties()
old_properties.load(hfOld)
except Exception as e:
print_error_msg ('Could not read "%s": %s' % (prev_conf_file, str(e)))
return -1
try:
new_properties = Properties()
with open(conf_file) as hfNew:
new_properties.load(hfNew)
for prop_key, prop_value in old_properties.getPropertyDict().items():
prop_value = prop_value.replace("/usr/lib/python2.6/site-packages", "/usr/lib/ambari-server/lib")
if "agent.fqdn.service.url" == prop_key:
# what is agent.fqdn property in ambari.props?
new_properties.process_pair(GET_FQDN_SERVICE_URL, prop_value)
elif "server.os_type" == prop_key:
new_properties.process_pair(OS_TYPE_PROPERTY, OS_FAMILY + OS_VERSION)
elif JDK_RELEASES == prop_key:
# don't replace new jdk releases with old releases, because they can be updated
pass
else:
new_properties.process_pair(prop_key, prop_value)
# Adding custom user name property if it is absent
# In previous versions without custom user support server was started as
# "root" anyway so it's a reasonable default
if NR_USER_PROPERTY not in new_properties.keys():
new_properties.process_pair(NR_USER_PROPERTY, "root")
# update the os. In case os detection routine changed
new_properties.process_pair(OS_FAMILY_PROPERTY, OS_FAMILY + OS_VERSION)
with open(conf_file, 'w') as hfW:
new_properties.store(hfW)
except Exception as e:
print_error_msg ('Could not write "%s": %s' % (conf_file, str(e)))
return -1
timestamp = datetime.datetime.now()
fmt = '%Y%m%d%H%M%S'
new_conf_file = prev_conf_file + '.' + timestamp.strftime(fmt)
try:
os.rename(prev_conf_file, new_conf_file)
except Exception as e:
print_error_msg ('Could not rename "%s" to "%s": %s' % (prev_conf_file, new_conf_file, str(e)))
#Not critical, move on
return 0
# update properties in a section-less properties file
# Cannot use ConfigParser due to bugs in version 2.6
def update_properties(propertyMap):
conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
backup_file_in_temp(conf_file)
if propertyMap is not None and conf_file is not None:
properties = Properties()
try:
with open(conf_file, 'r') as file:
properties.load(file)
except (Exception) as e:
print_error_msg('Could not read "%s": %s' % (conf_file, e))
return -1
for key in propertyMap.keys():
properties.removeOldProp(key)
properties.process_pair(key, str(propertyMap[key]))
for key in properties.keys():
if not propertyMap.__contains__(key):
properties.removeOldProp(key)
with open(conf_file, 'w') as file:
properties.store_ordered(file)
return 0
def update_properties_2(properties, propertyMap):
conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
backup_file_in_temp(conf_file)
if conf_file is not None:
if propertyMap is not None:
for key in propertyMap.keys():
properties.removeOldProp(key)
properties.process_pair(key, str(propertyMap[key]))
pass
with open(conf_file, 'w') as file:
properties.store_ordered(file)
pass
pass
def write_property(key, value):
conf_file = find_properties_file()
properties = Properties()
try:
with open(conf_file, "r") as hfR:
properties.load(hfR)
except Exception as e:
print_error_msg('Could not read ambari config file "%s": %s' % (conf_file, e))
return -1
properties.process_pair(key, value)
try:
with open(conf_file, 'w') as hfW:
properties.store(hfW)
except Exception as e:
print_error_msg('Could not write ambari config file "%s": %s' % (conf_file, e))
return -1
return 0
#
# Checks if options determine local DB configuration
#
def is_local_database(args):
try:
return args.persistence_type == 'local'
except AttributeError:
return False
def update_debug_mode():
debug_mode = get_debug_mode()
# The command-line settings supersede the ones in ambari.properties
if not debug_mode & 1:
properties = get_ambari_properties()
if properties == -1:
print_error_msg("Error getting ambari properties")
return -1
if get_value_from_properties(properties, DEBUG_MODE_KEY, False):
debug_mode = debug_mode | 1
if get_value_from_properties(properties, SUSPEND_START_MODE_KEY, False):
debug_mode = debug_mode | 2
set_debug_mode(debug_mode)
#
### JDK ###
#
#
# Describes the JDK configuration data, necessary for download and installation
#
class JDKRelease:
name = ""
desc = ""
url = ""
dest_file = ""
jcpol_url = "http://public-repo-1.hortonworks.com/ARTIFACTS/UnlimitedJCEPolicyJDK7.zip"
dest_jcpol_file = ""
inst_dir = ""
def __init__(self, i_name, i_desc, i_url, i_dest_file, i_jcpol_url, i_dest_jcpol_file, i_inst_dir, i_reg_exp):
if i_name is None or i_name == "":
raise FatalException(-1, "Invalid JDK name: " + (i_desc or ""))
self.name = i_name
if i_desc is None or i_desc == "":
self.desc = self.name
else:
self.desc = i_desc
if i_url is None or i_url == "":
raise FatalException(-1, "Invalid URL for JDK " + i_name)
self.url = i_url
if i_dest_file is None or i_dest_file == "":
self.dest_file = i_name + ".exe"
else:
self.dest_file = i_dest_file
if not (i_jcpol_url is None or i_jcpol_url == ""):
self.jcpol_url = i_jcpol_url
if i_dest_jcpol_file is None or i_dest_jcpol_file == "":
self.dest_jcpol_file = "jcpol-" + i_name + ".zip"
else:
self.dest_jcpol_file = i_dest_jcpol_file
if i_inst_dir is None or i_inst_dir == "":
self.inst_dir = os.path.join(configDefaults.JDK_INSTALL_DIR, i_desc)
else:
self.inst_dir = i_inst_dir
if i_reg_exp is None or i_reg_exp == "":
raise FatalException(-1, "Invalid output parsing regular expression for JDK " + i_name)
self.reg_exp = i_reg_exp
@classmethod
def from_properties(cls, properties, section_name):
(desc, url, dest_file, jcpol_url, jcpol_file, inst_dir, reg_exp) = JDKRelease.__load_properties(properties, section_name)
cls = JDKRelease(section_name, desc, url, dest_file, jcpol_url, jcpol_file, inst_dir, reg_exp)
return cls
@staticmethod
def __load_properties(properties, section_name):
if section_name is None or section_name == "":
raise FatalException(-1, "Invalid properties section: " + ("(empty)" if section_name is None else ""))
if(properties.__contains__(section_name + ".desc")): #Not critical
desc = properties[section_name + ".desc"]
else:
desc = section_name
if not properties.__contains__(section_name + ".url"):
raise FatalException(-1, "Invalid JDK URL in the properties section: " + section_name)
url = properties[section_name + ".url"] #Required
if not properties.__contains__(section_name + ".re"):
raise FatalException(-1, "Invalid JDK output parsing regular expression in the properties section: " + section_name)
reg_exp = properties[section_name + ".re"] #Required
if(properties.__contains__(section_name + ".dest-file")): #Not critical
dest_file = properties[section_name + ".dest-file"]
else:
dest_file = section_name + ".exe"
if(properties.__contains__(section_name + ".jcpol-url")): #Not critical
jcpol_url = properties[section_name + ".jcpol-url"]
else:
jcpol_url = None
if(properties.__contains__(section_name + ".jcpol-file")): #Not critical
jcpol_file = properties[section_name + ".jcpol-file"]
else:
jcpol_file = None
if(properties.__contains__(section_name + ".home")): #Not critical
inst_dir = properties[section_name + ".home"]
else:
inst_dir = "C:\\" + section_name
return (desc, url, dest_file, jcpol_url, jcpol_file, inst_dir, reg_exp)
pass
def get_JAVA_HOME():
properties = get_ambari_properties()
if properties == -1:
print_error_msg("Error getting ambari properties")
return None
java_home = properties[JAVA_HOME_PROPERTY]
if (not 0 == len(java_home)) and (os.path.exists(java_home)):
return java_home
return None
#
# Checks jdk path for correctness
#
def validate_jdk(jdk_path):
if jdk_path:
if os.path.exists(jdk_path):
java_exe_path = os.path.join(jdk_path, configDefaults.JAVA_EXE_SUBPATH)
if os.path.exists(java_exe_path) and os.path.isfile(java_exe_path):
return True
return False
#
# Finds the available JDKs.
#
def find_jdk():
jdkPath = get_JAVA_HOME()
if jdkPath:
if validate_jdk(jdkPath):
return jdkPath
print("INFO: Looking for available JDKs at {0}".format(configDefaults.JDK_INSTALL_DIR))
jdks = glob.glob(os.path.join(configDefaults.JDK_INSTALL_DIR, configDefaults.JDK_SEARCH_PATTERN))
#[fbarca] Use the newest JDK
jdks.sort(reverse=True)
print_info_msg("Found: {0}".format(str(jdks)))
if len(jdks) == 0:
return
for jdkPath in jdks:
print("INFO: Trying to use JDK {0}".format(jdkPath))
if validate_jdk(jdkPath):
print("INFO: Selected JDK {0}".format(jdkPath))
return jdkPath
else:
print_error_msg ("JDK {0} is invalid".format(jdkPath))
return
def get_java_exe_path():
jdkPath = find_jdk()
if jdkPath:
java_exe = os.path.join(jdkPath, configDefaults.JAVA_EXE_SUBPATH)
return java_exe
return
#
# Server resource files location
#
def get_resources_location(properties):
err = 'Invalid directory'
try:
resources_dir = properties[RESOURCES_DIR_PROPERTY]
if not resources_dir:
resources_dir = configDefaults.SERVER_RESOURCES_DIR
except (KeyError) as e:
err = 'Property ' + str(e) + ' is not defined at ' + properties.fileName
resources_dir = configDefaults.SERVER_RESOURCES_DIR
if not os.path.exists(os.path.abspath(str(resources_dir))):
msg = 'Resources dir ' + resources_dir + ' is incorrectly configured: ' + err
raise FatalException(1, msg)
return resources_dir
#
# Stack location
#
def get_stack_location(properties):
stack_location = properties[STACK_LOCATION_KEY]
if not stack_location:
stack_location = configDefaults.STACK_LOCATION_DEFAULT
return stack_location
#
# Extension location
#
def get_extension_location(properties):
extension_location = properties[EXTENSION_PATH_PROPERTY]
if not extension_location:
extension_location = configDefaults.EXTENSION_LOCATION_DEFAULT
return extension_location
#
# Common services location
#
def get_common_services_location(properties):
common_services_location = properties[COMMON_SERVICES_PATH_PROPERTY]
if not common_services_location:
common_services_location = configDefaults.COMMON_SERVICES_LOCATION_DEFAULT
return common_services_location
#
# Management packs staging location
#
def get_mpacks_staging_location(properties):
mpacks_staging_location = properties[MPACKS_STAGING_PATH_PROPERTY]
if not mpacks_staging_location:
mpacks_staging_location = configDefaults.MPACKS_STAGING_LOCATION_DEFAULT
return mpacks_staging_location
#
# Dashboard location
#
def get_dashboard_location(properties):
resources_dir = get_resources_location(properties)
dashboard_location = os.path.join(str(resources_dir), configDefaults.DASHBOARD_DIRNAME)
return dashboard_location
#
# Server temp location
#
def get_server_temp_location(properties):
server_tmp_dir = properties[SERVER_TMP_DIR_PROPERTY]
if not server_tmp_dir:
server_tmp_dir = configDefaults.SERVER_TMP_DIR_DEFAULT
return server_tmp_dir
def get_missing_properties(properties, property_set=REQUIRED_PROPERTIES):
missing_propertiers = []
for property in property_set:
value = properties[property]
if not value:
missing_propertiers.append(property)
return missing_propertiers