blob: 8a435a31b86d5acee91aa3aff4b290777358d2ab [file] [log] [blame]
#!/usr/bin/env python2.6
'''
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 optparse
import shlex
import sys
import os
import signal
import subprocess
import re
import string
import glob
import platform
import shutil
import stat
import fileinput
import urllib2
import time
import getpass
# debug settings
VERBOSE = False
SILENT = False
SERVER_START_DEBUG = False
# action commands
SETUP_ACTION = "setup"
START_ACTION = "start"
STOP_ACTION = "stop"
RESET_ACTION = "reset"
UPGRADE_ACTION = "upgrade"
UPGRADE_STACK_ACTION = "upgradestack"
# selinux commands
GET_SE_LINUX_ST_CMD = "/usr/sbin/sestatus"
SE_SETENFORCE_CMD = "setenforce 0"
SE_STATUS_DISABLED = "disabled"
SE_STATUS_ENABLED = "enabled"
SE_MODE_ENFORCING = "enforcing"
SE_MODE_PERMISSIVE = "permissive"
# iptables commands
IP_TBLS_ST_CMD = "/sbin/service iptables status"
IP_TBLS_STOP_CMD = "/sbin/service iptables stop"
IP_TBLS_ENABLED = "Firewall is running"
IP_TBLS_DISABLED = "Firewall is stopped.\n"
IP_TBLS_SRVC_NT_FND = "iptables: unrecognized service"
# server commands
ambari_provider_module_option = ""
ambari_provider_module = os.environ.get('AMBARI_PROVIDER_MODULE')
# constants
STACK_NAME_VER_SEP = "-"
if ambari_provider_module is not None:
ambari_provider_module_option = "-Dprovider.module.class=" +\
ambari_provider_module + " "
SERVER_START_CMD="{0}" + os.sep + "bin" + os.sep +\
"java -server -XX:NewRatio=3 "\
"-XX:+UseConcMarkSweepGC " +\
"-XX:-UseGCOverheadLimit -XX:CMSInitiatingOccupancyFraction=60 " +\
ambari_provider_module_option +\
os.getenv('AMBARI_JVM_ARGS','-Xms512m -Xmx2048m') +\
" -cp {1}"+ os.pathsep + "{2}" +\
"/* org.apache.ambari.server.controller.AmbariServer "\
">/var/log/ambari-server/ambari-server.out 2>&1"
SERVER_START_CMD_DEBUG="{0}" + os.sep + "bin" + os.sep +\
"java -server -XX:NewRatio=2 -XX:+UseConcMarkSweepGC " +\
ambari_provider_module_option +\
os.getenv('AMBARI_JVM_ARGS','-Xms512m -Xmx2048m') +\
" -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,"\
"server=y,suspend=n -cp {1}"+ os.pathsep + ".." +\
os.sep + "lib" + os.sep + "ambari-server" +\
os.sep +\
"* org.apache.ambari.server.controller.AmbariServer"
AMBARI_CONF_VAR="AMBARI_CONF_DIR"
AMBARI_SERVER_LIB="AMBARI_SERVER_LIB"
JAVA_HOME="JAVA_HOME"
PID_DIR="/var/run/ambari-server"
PID_NAME="ambari-server.pid"
AMBARI_PROPERTIES_FILE="ambari.properties"
SETUP_DB_CMD = ['su', 'postgres',
'--command=psql -f {0} -v username=\'"{1}"\' -v password="\'{2}\'"']
UPGRADE_STACK_CMD = ['su', 'postgres',
'--command=psql -f {0} -v stack_name="\'{1}\'" -v stack_version="\'{2}\'"']
PG_ST_CMD = "/sbin/service postgresql status"
PG_START_CMD = "/sbin/service postgresql start"
PG_RESTART_CMD = "/sbin/service postgresql restart"
PG_STATUS_RUNNING = "running"
PG_HBA_DIR = "/var/lib/pgsql/data/"
PG_HBA_CONF_FILE = PG_HBA_DIR + "pg_hba.conf"
PG_HBA_CONF_FILE_BACKUP = PG_HBA_DIR + "pg_hba_bak.conf.old"
POSTGRESQL_CONF_FILE = PG_HBA_DIR + "postgresql.conf"
PG_HBA_RELOAD_CMD = "su postgres --command='pg_ctl -D {0} reload'"
PG_DEFAULT_PASSWORD = "bigdata"
JDBC_USER_NAME_PROPERTY = "server.jdbc.user.name"
JDBC_PASSWORD_FILE_PROPERTY = "server.jdbc.user.passwd"
JDBC_PASSWORD_FILENAME = "password.dat"
# jdk commands
JDK_LOCAL_FILENAME = "jdk-6u31-linux-x64.bin"
JDK_MIN_FILESIZE = 5000
JDK_INSTALL_DIR = "/usr/jdk64"
CREATE_JDK_DIR_CMD = "/bin/mkdir -p " + JDK_INSTALL_DIR
MAKE_FILE_EXECUTABLE_CMD = "chmod a+x {0}"
JAVA_HOME_PROPERTY = "java.home"
OS_TYPE_PROPERTY = "server.os_type"
JDK_DOWNLOAD_CMD = "curl --create-dirs -o {0} {1}"
JDK_DOWNLOAD_SIZE_CMD = "curl -I {0}"
def configure_pg_hba_ambaridb_users():
args = optparse.Values()
configure_postgres_username_password(args)
with open(PG_HBA_CONF_FILE, "a") as pgHbaConf:
pgHbaConf.write("\n")
pgHbaConf.write("local all " + args.postgres_username +
",mapred md5")
pgHbaConf.write("\n")
pgHbaConf.write("host all " + args.postgres_username +
",mapred 0.0.0.0/0 md5")
pgHbaConf.write("\n")
pgHbaConf.write("host all " + args.postgres_username +
",mapred ::/0 md5")
pgHbaConf.write("\n")
command = PG_HBA_RELOAD_CMD.format(PG_HBA_DIR)
retcode, out, err = run_os_command(command)
if not retcode == 0:
print err
sys.exit(retcode)
def configure_pg_hba_postgres_user():
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)
def configure_postgresql_conf():
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)
def configure_postgres():
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
configure_pg_hba_postgres_user()
configure_pg_hba_ambaridb_users()
os.chmod(PG_HBA_CONF_FILE, 0644)
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 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 run_os_command(cmd):
print_info_msg('about to run command: ' + str(cmd))
if type(cmd) == str:
cmd = shlex.split(cmd)
process = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE
)
(stdoutdata, stderrdata) = process.communicate()
return process.returncode, stdoutdata, stderrdata
# todo: check if the scheme is already exist
def write_property(key, value):
conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
with open(conf_file, 'a') as ambariConf:
ambariConf.write(key + "=" + value)
ambariConf.write("\n")
return 0
def setup_db(args):
#password access to ambari-server and mapred
configure_postgres_username_password(args)
dbname = args.postgredbname
file = args.init_script_file
username = args.postgres_username
password = args.postgres_password
command = SETUP_DB_CMD[:]
command[-1] = command[-1].format(file, username, password)
retcode, outdata, errdata = run_os_command(command)
if not retcode == 0:
print errdata
return retcode
def execute_db_script(args, file):
#password access to ambari-server and mapred
configure_postgres_username_password(args)
dbname = args.postgredbname
username = args.postgres_username
password = args.postgres_password
command = SETUP_DB_CMD[:]
command[-1] = command[-1].format(file, username, password)
retcode, outdata, errdata = run_os_command(command)
if not retcode == 0:
print errdata
return retcode
def check_db_consistency(args, file):
#password access to ambari-server and mapred
configure_postgres_username_password(args)
dbname = args.postgredbname
username = args.postgres_username
password = args.postgres_password
command = SETUP_DB_CMD[:]
command[-1] = command[-1].format(file, username, password)
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'):
return 0
return -1
def upgrade_stack(args, stack_id):
#password access to ambari-server and mapred
configure_postgres_username_password(args)
dbname = args.postgredbname
file = args.upgrade_stack_script_file
stack_name, stack_version = stack_id.split(STACK_NAME_VER_SEP)
command = UPGRADE_STACK_CMD[:]
command[-1] = command[-1].format(file, stack_name, stack_version)
retcode, outdata, errdata = run_os_command(command)
if not retcode == 0:
print errdata
return retcode
#
# Checks SELinux
#
def check_selinux():
try:
retcode, out, err = run_os_command(GET_SE_LINUX_ST_CMD)
se_status = re.search('(disabled|enabled)', out).group(0)
print "SELinux status is '" + se_status + "'"
if se_status == SE_STATUS_DISABLED:
return 0
else:
se_mode = ''
try:
se_mode = re.search('(enforcing|permissive)', out).group(0)
except AttributeError:
print_error_msg("Error determining SELinux mode. Exiting.")
sys.exit(0)
print "SELinux mode is '" + se_mode + "'"
if se_mode == SE_MODE_ENFORCING:
print "Temporarily disabling SELinux"
run_os_command(SE_SETENFORCE_CMD)
print_warning_msg(
"SELinux is set to 'permissive' mode and temporarily disabled."
" You should disable SELinux permanently.")
ok = get_YN_input("OK to continue [y/n] (y)? ", True)
if ok == False:
sys.exit(0)
return 0
except OSError:
print_warning_msg("Could not run {0}: OK".format(GET_SE_LINUX_ST_CMD))
return 0
def get_ambari_jars():
try:
conf_dir = os.environ[AMBARI_SERVER_LIB]
return conf_dir
except KeyError:
default_jar_location = "/usr/lib/ambari-server"
print_info_msg(AMBARI_SERVER_LIB + " is not set, using default "
+ default_jar_location)
return default_jar_location
def get_conf_dir():
try:
conf_dir = os.environ[AMBARI_CONF_VAR]
return conf_dir
except KeyError:
default_conf_dir = "/etc/ambari-server/conf"
print_info_msg(AMBARI_CONF_VAR + " is not set, using default "
+ default_conf_dir)
return default_conf_dir
def search_file(filename, search_path, pathsep=os.pathsep):
""" Given a search path, find file with requested name """
for path in string.split(search_path, pathsep):
candidate = os.path.join(path, filename)
if os.path.exists(candidate): return os.path.abspath(candidate)
return None
#
# Checks iptables
#
def check_iptables():
# not used
# retcode, out, err = run_os_command(IP_TBLS_ST_CMD)
''' This check doesn't work on CentOS 6.2 if firewall AND
iptables service are running if out == IP_TBLS_ENABLED:
print 'iptables is enabled now'
print 'Stopping iptables service'
'''
retcode, out, err = run_os_command(IP_TBLS_STOP_CMD)
print 'iptables is disabled now'
if not retcode == 0 and err and len(err) > 0:
print err
if err.strip() == IP_TBLS_SRVC_NT_FND:
return 0
else:
return retcode, out
def dlprogress(base_name, count, blockSize, totalSize):
percent = int(count * blockSize * 100 / totalSize)
if (totalSize < blockSize):
sys.stdout.write("\r" + base_name + "... %d%%" % (100))
else:
sys.stdout.write("\r" + base_name + "... %d%% (%.1f MB of %.1f MB)" % (
percent, count * blockSize / 1024 / 1024.0, totalSize / 1024 / 1024.0))
if (percent == 100 or totalSize < blockSize):
sys.stdout.write("\n")
sys.stdout.flush()
def track_jdk(base_name, url, local_name):
u = urllib2.urlopen(url)
h = u.info()
totalSize = int(h["Content-Length"])
fp = open(local_name, "wb")
blockSize = 8192
count = 0
percent = 0
while True:
chunk = u.read(blockSize)
if not chunk:
break
fp.write(chunk)
count += 1
dlprogress(base_name, count, blockSize, totalSize)
fp.flush()
fp.close()
#
# Downloads the JDK
#
def download_jdk(args):
conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
if conf_file is None:
print 'File %s not found in search path $%s: %s' %\
(AMBARI_PROPERTIES_FILE, AMBARI_CONF_VAR, get_conf_dir())
return -1
print_info_msg('Loading properties from ' + conf_file)
if get_JAVA_HOME():
return 0
if args.java_home and os.path.exists(args.java_home):
print_warning_msg("JAVA_HOME " + args.java_home
+ " must be valid on ALL hosts")
write_property(JAVA_HOME_PROPERTY, args.java_home)
return 0
properties = None
try:
properties = Properties()
properties.load(open(conf_file))
except (Exception), e:
print 'Could not read "%s": %s' % (conf_file, e)
return -1
try:
jdk_url = properties['jdk.url']
resources_dir = properties['resources.dir']
except (KeyError), e:
print 'Property ' + str(e) + ' is not defined at ' + conf_file
return -1
dest_file = resources_dir + os.sep + JDK_LOCAL_FILENAME
if not os.path.exists(dest_file):
print 'Downloading JDK from ' + jdk_url + ' to ' + dest_file
try:
size_command = JDK_DOWNLOAD_SIZE_CMD.format(jdk_url);
#Get Header from url,to get file size then
retcode, out, err = run_os_command(size_command)
if out.find("Content-Length") == -1:
print "Request header doesn't contain Content-Length";
return -1
start_with = int(out.find("Content-Length") + len("Content-Length") + 2)
end_with = out.find("\r\n", start_with)
src_size = int(out[start_with:end_with])
print 'JDK distribution size is ' + str(src_size) + ' bytes'
file_exists = os.path.isfile(dest_file)
file_size = -1
if file_exists:
file_size = os.stat(dest_file).st_size
if file_exists and file_size == src_size:
print_info_msg("File already exists")
else:
track_jdk(JDK_LOCAL_FILENAME, jdk_url, dest_file)
print 'Successfully downloaded JDK distribution to ' + dest_file
except Exception, e:
print_error_msg('Failed to download JDK: ' + str(e))
return -1
downloaded_size = os.stat(dest_file).st_size
if downloaded_size != src_size or downloaded_size < JDK_MIN_FILESIZE:
print_error_msg('Size of downloaded JDK distribution file is '
+ str(downloaded_size) + ' bytes, it is probably \
damaged or incomplete')
return -1
else:
print "JDK already exists using " + dest_file
try:
out = install_jdk(dest_file)
jdk_version = re.search('Creating (jdk.*)/jre', out).group(1)
except Exception, e:
print "Installation of JDK was failed: %s\n" % e.message
file_exists = os.path.isfile(dest_file)
if file_exists:
ok = get_YN_input("JDK found at "+dest_file+". "
"Would you like to re-download the JDK [y/n] (y)? ", True)
if (ok == False):
print "Unable to install JDK. Please remove JDK file found at "+ dest_file +" and re-run Ambari Server setup"
return -1
else:
track_jdk(JDK_LOCAL_FILENAME, jdk_url, dest_file)
print 'Successfully re-downloaded JDK distribution to ' + dest_file
try:
out = install_jdk(dest_file)
jdk_version = re.search('Creating (jdk.*)/jre', out).group(1)
except Exception, e:
print "Installation of JDK was failed: %s\n" % e.message
print "Unable to install JDK. Please remove JDK, file found at "+ dest_file +" and re-run Ambari Server setup"
return -1
else:
print "Unable to install JDK. File "+ dest_file +"does not exist, please re-run Ambari Server setup"
return -1
print "Successfully installed JDK to {0}/{1}".\
format(JDK_INSTALL_DIR, jdk_version)
write_property(JAVA_HOME_PROPERTY, "{0}/{1}".
format(JDK_INSTALL_DIR, jdk_version))
return 0
class RetCodeException(Exception): pass
def install_jdk(dest_file):
ok = get_YN_input("To install the Oracle JDK you must accept the "
"license terms found at "
"http://www.oracle.com/technetwork/java/javase/"
"downloads/jdk-6u21-license-159167.txt. Not accepting will "
"cancel the Ambari Server setup.\nDo you accept the "
"Oracle Binary Code License Agreement [y/n] (y)? ", True)
if (ok == False):
return -1
print "Installing JDK to {0}".format(JDK_INSTALL_DIR)
retcode, out, err = run_os_command(CREATE_JDK_DIR_CMD)
savedPath = os.getcwd()
os.chdir(JDK_INSTALL_DIR)
retcode, out, err = run_os_command(MAKE_FILE_EXECUTABLE_CMD.format(dest_file))
retcode, out, err = run_os_command(dest_file + ' -noregister')
os.chdir(savedPath)
if (retcode != 0):
raise RetCodeException("Installation JDK returned code %s" % retcode)
return out
def get_postgre_status():
retcode, out, err = run_os_command(PG_ST_CMD)
try:
pg_status = re.search('(stopped|running)', out).group(0)
except AttributeError:
pg_status = None
return pg_status
def check_postgre_up():
pg_status = get_postgre_status()
if pg_status == PG_STATUS_RUNNING:
print_info_msg ("PostgreSQL is running")
return 0
else:
print "About to start PostgreSQL"
retcode, out, err = run_os_command(PG_START_CMD)
return retcode
#
# Configures the OS settings in ambari properties.
#
def configure_os_settings():
conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
if conf_file is None:
print_error_msg ('File %s not found in search path $%s: %s'
% (AMBARI_PROPERTIES_FILE, AMBARI_CONF_VAR, get_conf_dir()))
return -1
print_info_msg ('Loading properties from ' + conf_file)
properties = None
try:
properties = Properties()
properties.load(open(conf_file))
except (Exception), e:
print_error_msg ('Could not read "%s": %s' % (conf_file, e))
return -1
try:
conf_os_type = properties[OS_TYPE_PROPERTY]
if conf_os_type != '':
print_info_msg ("os_type already setting in properties file")
return 0
except (KeyError), e:
print_error_msg ("os_type is not set in properties file")
os_system = platform.system()
if os_system != 'Linux':
print_error_msg ("Non-Linux systems are not supported")
return -1
os_info = platform.linux_distribution(
None, None, None, ['SuSE', 'redhat' ], 0
)
os_name = os_info[0].lower()
if os_name == 'suse':
os_name = 'sles'
os_version = os_info[1].split('.', 1)[0]
master_os_type = os_name + os_version
with open(conf_file, "a") as ambariConf:
ambariConf.write(OS_TYPE_PROPERTY + "=" + master_os_type)
ambariConf.write("\n")
ambariConf.closed
return 0
def get_JAVA_HOME():
conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
properties = Properties()
try:
properties.load(open(conf_file))
java_home = properties[JAVA_HOME_PROPERTY]
if (not 0 == len(java_home)) and (os.path.exists(java_home)):
return java_home
except (Exception), e:
print 'Could not read "%s": %s' % (conf_file, e)
return None
#
# Finds the available JDKs.
#
def find_jdk():
if get_JAVA_HOME():
return get_JAVA_HOME()
print "Looking for available JDKs at " + JDK_INSTALL_DIR
jdks = glob.glob(JDK_INSTALL_DIR + os.sep + "jdk*")
jdks.sort()
print "Found: " + str(jdks)
count = len(jdks)
if count == 0:
return
jdkPath = jdks[count - 1]
print "Selected JDK {0}".format(jdkPath)
return jdkPath
#
# Setup the Ambari Server.
#
def setup(args):
print 'Checking SELinux...'
retcode = check_selinux()
if not retcode == 0:
print_error_msg ('Failed to disable SELinux. Exiting.')
sys.exit(retcode)
print 'Checking iptables...'
retcode, out = check_iptables()
if not retcode == 0 and out == IP_TBLS_ENABLED:
print_error_msg ('Failed to stop iptables. Exiting.')
sys.exit(retcode)
print 'Checking PostgreSQL...'
retcode = check_postgre_up()
if not retcode == 0:
print_error_msg ('Unable to start PostgreSQL server. Exiting')
sys.exit(retcode)
print 'Configuring database...'
retcode = setup_db(args)
if not retcode == 0:
print_error_msg ('Running database init script was failed. Exiting.')
sys.exit(retcode)
print 'Configuring PostgreSQL...'
retcode = configure_postgres()
if not retcode == 0:
print_error_msg ('Unable to configure PostgreSQL server. Exiting')
sys.exit(retcode)
print 'Checking JDK...'
retcode = download_jdk(args)
if not retcode == 0:
print_error_msg ('Downloading or installing JDK failed. Exiting.')
sys.exit(retcode)
print 'Completing setup...'
retcode = configure_os_settings()
if not retcode == 0:
print_error_msg ('Configure of OS settings in '
'ambari.properties failed. Exiting.')
sys.exit(retcode)
print "Ambari Server 'setup' finished successfully"
#
# Resets the Ambari Server.
#
def reset(args):
okToRun = False
choice = raw_input("**** WARNING **** You are about to reset and clear the "
"Ambari Server database. This will remove all cluster "
"host and configuration information from the database. "
"You will be required to re-configure the Ambari server "
"and re-run the cluster wizard. \n"
"Are you SURE you want to perform the reset "
"[yes/no]? ").lower()
if choice in set(['yes']):
okToRun = True
if not okToRun:
print "Ambari Server 'reset' cancelled"
return -1
okToRun = False
choice = raw_input("Confirm server reset [yes/no]? ").lower()
if choice in set(['yes']):
okToRun = True
if not okToRun:
print "Ambari Server 'reset' cancelled"
return -1
print "Reseting the Server database..."
configure_postgres_username_password(args)
dbname = args.postgredbname
filename = args.drop_script_file
username = args.postgres_username
password = args.postgres_password
command = SETUP_DB_CMD[:]
command[-1] = command[-1].format(filename, username, password)
retcode, outdata, errdata = run_os_command(command)
if not retcode == 0:
print errdata
return retcode
print_info_msg ("About to run database setup")
setup_db(args)
print "Ambari Server 'reset' complete"
#
# Starts the Ambari Server.
#
def start(args):
if os.path.exists(PID_DIR + os.sep + PID_NAME):
f = open(PID_DIR + os.sep + PID_NAME, "r")
pid = int(f.readline())
f.close()
try:
os.kill(pid, 0)
print("Server is already running.")
return
except OSError, e:
print_info_msg("Server is not running, continue.")
conf_dir = get_conf_dir()
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 " + JDK_INSTALL_DIR)
return -1
retcode = check_postgre_up()
if not retcode == 0:
print_error_msg("Unable to start PostgreSQL server. Exiting")
sys.exit(retcode)
print 'Checking iptables...'
retcode, out = check_iptables()
if not retcode == 0 and out == IP_TBLS_ENABLED:
print_error_msg ("Failed to stop iptables. Exiting")
sys.exit(retcode)
command = SERVER_START_CMD.format(jdk_path, conf_dir, get_ambari_jars())
print "Running server: " + command
server_process = subprocess.Popen(["/bin/sh", "-c", command])
f = open(PID_DIR + os.sep + PID_NAME, "w")
f.write(str(server_process.pid))
f.close()
#
# Stops the Ambari Server.
#
def stop(args):
if os.path.exists(PID_DIR + os.sep + PID_NAME):
f = open(PID_DIR + os.sep + PID_NAME, "r")
pid = int(f.readline())
try:
os.killpg(os.getpgid(pid), signal.SIGKILL)
except OSError, e:
print_info_msg( "Unable to stop Ambari Server - " + str(e) )
return
f.close()
os.remove(f.name)
print "Ambari Server stopped"
else:
print "Ambari Server not running"
#
# Upgrades the Ambari Server.
#
def upgrade(args):
print 'Checking PostgreSQL...'
retcode = check_postgre_up()
if not retcode == 0:
printErrorMsg('PostgreSQL server not running. Exiting')
sys.exit(retcode)
file = args.upgrade_script_file
print 'Upgrading database...'
retcode = execute_db_script(args, file)
if not retcode == 0:
printErrorMsg('Database upgrade script has failed. Exiting.')
sys.exit(retcode)
print 'Checking database integrity...'
check_file = file[:-3] + "Check" + file[-4:]
retcode = check_db_consistency(args, check_file)
if not retcode == 0:
print 'Found inconsistency. Trying to fix...'
fix_file = file[:-3] + "Fix" + file[-4:]
retcode = execute_db_script(args, fix_file)
if not retcode == 0:
printErrorMsg('Database cannot be fixed. Exiting.')
sys.exit(retcode)
else:
print 'Database is consistent.'
print "Ambari Server 'upgrade' finished successfully"
#
# Prints an "info" messsage.
#
def print_info_msg(msg):
if VERBOSE:
print("INFO: " + msg)
#
# Prints an "error" messsage.
#
def print_error_msg(msg):
print("ERROR: " + msg)
#
# Prints a "warning" messsage.
#
def print_warning_msg(msg):
print("WARNING: " + msg)
#
# Gets the y/n input.
#
# return True if 'y' or False if 'n'
#
def get_YN_input(prompt,default):
yes = set(['yes','ye', 'y'])
no = set(['no','n'])
return get_choice_string_input(prompt,default,yes,no)
def get_choice_string_input(prompt,default,firstChoice,secondChoice):
if SILENT:
print(prompt)
return default
choice = raw_input(prompt).lower()
if choice in firstChoice:
return True
elif choice in secondChoice:
return False
elif choice is "": # Just enter pressed
return default
else:
print "input not recognized, please try again: "
return get_choice_string_input(prompt,default,firstChoice,secondChoice)
def get_validated_string_input(prompt, default, pattern, description, is_pass):
input =""
while not input:
if SILENT:
print (prompt)
input = default
elif is_pass:
input = getpass.getpass(prompt)
else:
input = raw_input(prompt)
if not input.strip():
input = default
break #done here and picking up default
else:
if not re.search(pattern,input.strip()):
print description
input=""
return input
def configure_postgres_password():
# setup password
passwordDefault = PG_DEFAULT_PASSWORD
passwordPrompt = 'Password [' + passwordDefault + ']: '
passwordPattern = "^[a-zA-Z0-9_-]*$"
passwordDescr = "Invalid characters in password. Use only alphanumeric or " \
"_ or - characters"
password = get_validated_string_input(passwordPrompt, passwordDefault,
passwordPattern, passwordDescr, True)
if password != passwordDefault:
password1 = get_validated_string_input("Re-enter password: ",
passwordDefault, passwordPattern, passwordDescr, True)
if password != password1:
print "Passwords do not match"
password = configure_postgres_password()
return password
def get_pass_file_path(conf_file):
return os.path.join(os.path.dirname(conf_file),
JDBC_PASSWORD_FILENAME)
def configure_postgres_username_password(args):
conf_file = search_file(AMBARI_PROPERTIES_FILE, get_conf_dir())
properties = Properties()
try:
properties.load(open(conf_file))
except Exception, e:
print 'Could not read ambari config file "%s": %s' % (conf_file, e)
return -1
username = properties[JDBC_USER_NAME_PROPERTY]
passFilePath = properties[JDBC_PASSWORD_FILE_PROPERTY]
if username and passFilePath:
print_info_msg("Database username + password already configured - skipping")
args.postgres_username=username
args.postgres_password = open(passFilePath).read()
return 1
# setup username
usernameDefault = 'ambari-server'
usernamePrompt = 'Username [' + usernameDefault + ']: '
usernamePattern = "^[a-zA-Z_][a-zA-Z0-9_\-]*$"
usernameDescr = "Invalid characters in username. Start with _ or alpha " \
"followed by alphanumeric or _ or - characters"
username = usernameDefault
# setup password
password = PG_DEFAULT_PASSWORD
ok = get_YN_input("Enter advanced database configuration [y/n] (n)? ", False)
if ok:
username = get_validated_string_input(usernamePrompt, usernameDefault,
usernamePattern, usernameDescr, False)
print "Database username set to: " + username
password = configure_postgres_password()
passFilePath = get_pass_file_path(conf_file)
print_info_msg ("Database username set to: " + username)
print_info_msg ("Database password set to: " + password)
with open(passFilePath, 'w+') as passFile:
passFile.write(password)
pass
os.chmod(passFilePath, stat.S_IREAD | stat.S_IWRITE)
write_property(JDBC_USER_NAME_PROPERTY, username)
write_property(JDBC_PASSWORD_FILE_PROPERTY,passFilePath)
args.postgres_username=username
args.postgres_password=password
#
# Main.
#
def main():
parser = optparse.OptionParser(usage="usage: %prog [options] action [stack_id]",)
parser.add_option('-d', '--postgredbname', default='ambari',
help="Database name in postgresql")
parser.add_option('-f', '--init-script-file',
default='/var/lib/ambari-server/'
'resources/Ambari-DDL-Postgres-CREATE.sql',
help="File with setup script")
parser.add_option('-r', '--drop-script-file', default="/var/lib/"
"ambari-server/resources/"
"Ambari-DDL-Postgres-DROP.sql",
help="File with drop script")
parser.add_option('-u', '--upgrade-script-file', default="/var/lib/"
"ambari-server/resources/upgrade/ddl/"
"Ambari-DDL-Postgres-UPGRADE-1.2.2.sql",
help="File with upgrade script")
parser.add_option('-t', '--upgrade-stack-script-file', default="/var/lib/"
"ambari-server/resources/upgrade/dml/"
"Ambari-DML-Postgres-UPGRADE_STACK.sql",
help="File with stack upgrade script")
parser.add_option('-j', '--java-home', default=None,
help="Use specified java_home. Must be valid on all hosts")
parser.add_option("-v", "--verbose",
action="store_true", dest="verbose", default=False,
help="Print verbose status messages")
parser.add_option("-s", "--silent",
action="store_true", dest="silent", default=False,
help="Silently accepts default prompt values")
(options, args) = parser.parse_args()
# set verbose
global VERBOSE
VERBOSE = options.verbose
# set silent
global SILENT
SILENT = options.silent
if len(args) == 0:
print parser.print_help()
parser.error("No action entered")
action = args[0]
if action == UPGRADE_STACK_ACTION:
args_number_required = 2
else:
args_number_required = 1
if len(args) < args_number_required:
print parser.print_help()
parser.error("Invalid number of arguments. Entered: " + str(len(args)) + ", required: " + str(args_number_required))
if action == SETUP_ACTION:
setup(options)
elif action == START_ACTION:
start(options)
elif action == STOP_ACTION:
stop(options)
elif action == RESET_ACTION:
reset(options)
elif action == UPGRADE_ACTION:
upgrade(options)
elif action == UPGRADE_STACK_ACTION:
stack_id = args[1]
upgrade_stack(options, stack_id)
else:
parser.error("Invalid action")
# A Python replacement for java.util.Properties
# Based on http://code.activestate.com/recipes
# /496795-a-python-replacement-for-javautilproperties/
class Properties(object):
def __init__(self, props=None):
self._props = {}
self._origprops = {}
self._keymap = {}
self.othercharre = re.compile(r'(?<!\\)(\s*\=)|(?<!\\)(\s*\:)')
self.othercharre2 = re.compile(r'(\s*\=)|(\s*\:)')
self.bspacere = re.compile(r'\\(?!\s$)')
def __parse(self, lines):
lineno = 0
i = iter(lines)
for line in i:
lineno += 1
line = line.strip()
if not line: continue
if line[0] == '#': continue
escaped = False
sepidx = -1
flag = 0
m = self.othercharre.search(line)
if m:
first, last = m.span()
start, end = 0, first
flag = 1
wspacere = re.compile(r'(?<![\\\=\:])(\s)')
else:
if self.othercharre2.search(line):
wspacere = re.compile(r'(?<![\\])(\s)')
start, end = 0, len(line)
m2 = wspacere.search(line, start, end)
if m2:
first, last = m2.span()
sepidx = first
elif m:
first, last = m.span()
sepidx = last - 1
while line[-1] == '\\':
nextline = i.next()
nextline = nextline.strip()
lineno += 1
line = line[:-1] + nextline
if sepidx != -1:
key, value = line[:sepidx], line[sepidx + 1:]
else:
key, value = line, ''
self.process_pair(key, value)
def process_pair(self, key, value):
oldkey = key
oldvalue = value
keyparts = self.bspacere.split(key)
strippable = False
lastpart = keyparts[-1]
if lastpart.find('\\ ') != -1:
keyparts[-1] = lastpart.replace('\\', '')
elif lastpart and lastpart[-1] == ' ':
strippable = True
key = ''.join(keyparts)
if strippable:
key = key.strip()
oldkey = oldkey.strip()
oldvalue = self.unescape(oldvalue)
value = self.unescape(value)
self._props[key] = value.strip()
if self._keymap.has_key(key):
oldkey = self._keymap.get(key)
self._origprops[oldkey] = oldvalue.strip()
else:
self._origprops[oldkey] = oldvalue.strip()
self._keymap[key] = oldkey
def unescape(self, value):
newvalue = value.replace('\:', ':')
newvalue = newvalue.replace('\=', '=')
return newvalue
def load(self, stream):
if type(stream) is not file:
raise TypeError, 'Argument should be a file object!'
if stream.mode != 'r':
raise ValueError, 'Stream should be opened in read-only mode!'
try:
lines = stream.readlines()
self.__parse(lines)
except IOError, e:
raise
def get_property(self, key):
return self._props.get(key, '')
def propertyNames(self):
return self._props.keys()
def getPropertyDict(self):
return self._props
def __getitem__(self, name):
return self.get_property(name)
def __getattr__(self, name):
try:
return self.__dict__[name]
except KeyError:
if hasattr(self._props, name):
return getattr(self._props, name)
if __name__ == "__main__":
main()