| #!/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 sys |
| import os |
| import signal |
| import subprocess |
| import re |
| import string |
| import glob |
| import platform |
| import xml.etree.ElementTree as ET |
| 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" |
| |
| #sudo check command |
| SUDO_CHECK_CMD = "rpm -qa | grep sudo" |
| |
| |
| # 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') |
| |
| 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=2 -XX:+UseConcMarkSweepGC " + 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" |
| |
| # database commands |
| SETUP_DB_CMD = "sudo -u postgres psql -f {0} -v username=\"{1}\" -v password=\'{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 = "sudo -u postgres 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" |
| |
| def configure_pg_hba_ambaridb_users(): |
| args = optparse.Values() |
| configurePostgresUsernamePassword(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 check_ambaridb_user_configured(): |
| if 'ambari-server' in open(PG_HBA_CONF_FILE).read(): |
| return True |
| else: |
| return False |
| |
| 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 == "None" or result == "-N": |
| printInfoMsg("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": |
| printInfoMsg("PostgreSQL is stopped. Restarting ...") |
| retcode, out, err = run_os_command(PG_START_CMD) |
| return retcode |
| return 0 |
| |
| def line_prepender(filename, lines): |
| for line in reversed(lines): |
| with open(filename,'r+') as f: |
| content = f.read() |
| f.seek(0,0) |
| f.write(line.rstrip('\r\n') + '\n' + content) |
| |
| def run_os_command(cmd): |
| printInfoMsg( 'about to run command: ' + cmd) |
| process = subprocess.Popen(cmd.split(' '), |
| 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 writeProperty(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 |
| pass |
| |
| def setup_db(args): |
| #password access to ambari-server and mapred |
| configurePostgresUsernamePassword(args) |
| dbname = args.postgredbname |
| file = args.init_script_file |
| username = args.postgres_username |
| password = args.postgres_password |
| command = SETUP_DB_CMD.format(file,username,password) |
| 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: |
| printErrorMsg ("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) |
| printWarningMsg ("SELinux is set to 'permissive' mode and temporarily disabled. You should disable SELinux permanently.") |
| ok = getYNInput("OK to continue [y/n] (y)? ",True) |
| if ok == False: |
| sys.exit (0) |
| return 0 |
| except OSError: |
| printWarningMsg("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" |
| printInfoMsg (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" |
| printInfoMsg (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(): |
| 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 |
| |
| |
| # 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.processPair(key, value) |
| |
| def processPair(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 getProperty(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.getProperty(name) |
| |
| def __getattr__(self, name): |
| try: |
| return self.__dict__[name] |
| except KeyError: |
| if hasattr(self._props,name): |
| return getattr(self._props, name) |
| |
| JDK_DOWNLOAD_CMD = "curl --create-dirs -o {0} {1}" |
| JDK_DOWNLOAD_SIZE_CMD = "curl -I {0}" |
| |
| 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 |
| printInfoMsg ('Loading properties from ' + conf_file) |
| |
| if get_JAVA_HOME(): |
| return 0 |
| |
| if args.java_home and os.path.exists(args.java_home): |
| printWarningMsg("JAVA_HOME " + args.java_home + " must be valid on ALL hosts") |
| writeProperty(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) ; |
| retcode, out, err = run_os_command(size_command)#Get Header from url,to get file size then |
| if out.find("Content-Length") == -1: |
| print "Request headr 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: |
| printInfoMsg ("File already exists") |
| else: |
| track_jdk(JDK_LOCAL_FILENAME, jdk_url, dest_file) |
| print 'Successfully downloaded JDK distribution to ' + dest_file |
| except Exception, e: |
| printErrorMsg ('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: |
| printErrorMsg ('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 |
| |
| ok = getYNInput("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) |
| jdk_version = re.search('Creating (jdk.*)/jre', out).group(1) |
| print "Successfully installed JDK to {0}/{1}".format(JDK_INSTALL_DIR, jdk_version) |
| writeProperty(JAVA_HOME_PROPERTY, "{0}/{1}".format(JDK_INSTALL_DIR, jdk_version)) |
| return 0 |
| |
| 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: |
| printInfoMsg ("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: |
| printErrorMsg ('File %s not found in search path $%s: %s' % (AMBARI_PROPERTIES_FILE, AMBARI_CONF_VAR, get_conf_dir())) |
| return -1 |
| printInfoMsg ('Loading properties from ' + conf_file) |
| properties = None |
| try: |
| properties = Properties() |
| properties.load(open(conf_file)) |
| except (Exception), e: |
| printErrorMsg ('Could not read "%s": %s' % (conf_file, e)) |
| return -1 |
| try: |
| conf_os_type = properties[OS_TYPE_PROPERTY] |
| if conf_os_type != '': |
| printInfoMsg ("os_type already setting in properties file") |
| return 0 |
| except (KeyError), e: |
| printErrorMsg ("os_type is not set in properties file") |
| |
| os_system = platform.system() |
| if os_system != 'Linux': |
| printErrorMsg ("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 findJDK(): |
| 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 |
| |
| def check_sudo(): |
| retcode, out, err = run_os_command(SUDO_CHECK_CMD) |
| if re.search('sudo', out) == None: |
| return 1 |
| return 0 |
| pass |
| |
| # |
| # Setup the Ambari Server. |
| # |
| def setup(args): |
| |
| retcode = check_sudo() |
| if not retcode == 0: |
| printErrorMsg('ERROR: sudo command not found on host. Please install sudo and re-run ambari-server setup. Exiting.') |
| sys.exit(retcode) |
| |
| print 'Checking SELinux...' |
| retcode = check_selinux() |
| if not retcode == 0: |
| printErrorMsg ('Failed to disable SELinux. Exiting.') |
| sys.exit(retcode) |
| |
| print 'Checking iptables...' |
| retcode, out = check_iptables() |
| if (not retcode == 0 and out == IP_TBLS_ENABLED): |
| printErrorMsg ('Failed to stop iptables. Exiting.') |
| sys.exit(retcode) |
| |
| print 'Checking PostgreSQL...' |
| retcode = check_postgre_up() |
| if not retcode == 0: |
| printErrorMsg ('Unable to start PostgreSQL server. Exiting') |
| sys.exit(retcode) |
| |
| print 'Configuring database...' |
| retcode = setup_db(args) |
| if not retcode == 0: |
| printErrorMsg ('Running database init script was failed. Exiting.') |
| sys.exit(retcode) |
| |
| print 'Configuring PostgreSQL...' |
| retcode = configure_postgres() |
| if not retcode == 0: |
| printErrorMsg ('Unable to configure PostgreSQL server. Exiting') |
| sys.exit(retcode) |
| |
| print 'Checking JDK...' |
| retcode = download_jdk(args) |
| if not retcode == 0: |
| printErrorMsg ('Downloading or installing JDK failed. Exiting.') |
| sys.exit(retcode) |
| |
| print 'Completing setup...' |
| retcode = configure_os_settings() |
| if not retcode == 0: |
| printErrorMsg ('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. \nAre you SURE you want to perform the reset [yes/no]? ").lower() |
| if (choice in set(['yes'])): |
| okToRun = True |
| |
| if (False == 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 (False == okToRun): |
| print "Ambari Server 'reset' cancelled" |
| return -1 |
| |
| print "Reseting the Server database..." |
| |
| configurePostgresUsernamePassword(args) |
| dbname = args.postgredbname |
| filename = args.drop_script_file |
| username = args.postgres_username |
| password = args.postgres_password |
| command = SETUP_DB_CMD.format(filename, username, password) |
| retcode, outdata, errdata = run_os_command(command) |
| if not retcode == 0: |
| print errdata |
| return retcode |
| |
| printInfoMsg ("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: |
| printInfoMsg("Server is not running, continue.") |
| |
| conf_dir = get_conf_dir() |
| jdk_path = findJDK() |
| if jdk_path is None: |
| printErrorMsg("No JDK found, please run \"setup\" command to install JDK automatically or "\ |
| "install any JDK manually to " + JDK_INSTALL_DIR) |
| return -1 |
| retcode = check_postgre_up() |
| if not retcode == 0: |
| printErrorMsg("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): |
| printErrorMsg ("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: |
| printInfoMsg( "Unable to stop Ambari Server - " + str(e) ) |
| return |
| f.close() |
| os.remove(f.name) |
| print "Ambari Server stopped" |
| else: |
| print "Ambari Server not running" |
| |
| # |
| # Prints an "info" messsage. |
| # |
| def printInfoMsg(msg): |
| if (VERBOSE): |
| print("INFO: " + msg) |
| |
| # |
| # Prints an "error" messsage. |
| # |
| def printErrorMsg(msg): |
| print("ERROR: " + msg) |
| |
| # |
| # Prints a "warning" messsage. |
| # |
| def printWarningMsg(msg): |
| print("WARNING: " + msg) |
| |
| # |
| # Gets the y/n input. |
| # |
| # return True if 'y' or False if 'n' |
| # |
| def getYNInput(prompt,default): |
| yes = set(['yes','ye', 'y']) |
| no = set(['no','n']) |
| return getChoiceStringInput(prompt,default,yes,no) |
| |
| # |
| # Gets the yes/no input. |
| # |
| # return True if 'yes' or False if 'no/n' |
| # |
| def getYesNoInput(prompt,default): |
| yes = set(['yes']) |
| no = set(['no','n','']) |
| return getChoiceStringInput(prompt,default,yes,no) |
| |
| def getChoiceStringInput(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 |
| return default |
| |
| def getValidatedStringInput(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 saveUsernamePassword(pathtofile, username, password): |
| tree = ET.parse(pathtofile) |
| root = tree.getroot() |
| for property in root.iter('{http://java.sun.com/xml/ns/persistence}property'): |
| if(property.get('name') == 'javax.persistence.jdbc.user'): |
| property.set('value', username) |
| print 'setting username to: ' + username |
| if(property.get('name') == 'javax.persistence.jdbc.password'): |
| print 'setting password to: ' + password |
| property.set('value', password) |
| #save copy of existing config |
| shutil.move(pathtofile, pathtofile+'.bak.ambari') |
| tree.write(pathtofile) |
| |
| def configurePostgresPassword(): |
| # 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 = getValidatedStringInput(passwordPrompt, passwordDefault, passwordPattern, passwordDescr, True) |
| if password != passwordDefault: |
| password1 = getValidatedStringInput("Re-enter password: ", passwordDefault, passwordPattern, passwordDescr, True) |
| if password != password1: |
| print "Passwords do not match" |
| password = configurePostgresPassword() |
| |
| return password |
| |
| def configurePostgresUsernamePassword(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 "%s": %s' % (conf_file, e) |
| return -1 |
| |
| username = properties[JDBC_USER_NAME_PROPERTY] |
| passFilePath = properties[JDBC_PASSWORD_FILE_PROPERTY] |
| |
| if username and passFilePath: |
| printInfoMsg("Database username + password already configured - skipping") |
| args.postgres_username=username |
| with open(passFilePath) as passFile: |
| args.postgres_password=passFile.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 = getYNInput("Enter advanced database configuration [y/n] (n)? ", False) |
| if ok == True: |
| username = getValidatedStringInput(usernamePrompt, usernameDefault, usernamePattern, usernameDescr, False) |
| print "Database username set to: " + username |
| password = configurePostgresPassword() |
| |
| |
| passFilePath = os.path.join(os.path.dirname(conf_file), JDBC_PASSWORD_FILENAME) |
| |
| printInfoMsg ("Database username set to: " + username) |
| printInfoMsg ("Database password set to: " + password) |
| |
| writeProperty(JDBC_USER_NAME_PROPERTY, username) |
| with open(passFilePath, 'w+') as passFile: |
| passFile.write(password) |
| pass |
| os.chmod(passFilePath, stat.S_IREAD | stat.S_IWRITE) |
| |
| writeProperty(JDBC_PASSWORD_FILE_PROPERTY,passFilePath) |
| args.postgres_username=username |
| args.postgres_password=password |
| |
| # |
| # Main. |
| # |
| def main(): |
| parser = optparse.OptionParser(usage="usage: %prog [options] action",) |
| 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('-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 not len(args) == 1: |
| print parser.print_help() |
| parser.error("Invalid number of arguments") |
| |
| action = args[0] |
| |
| if action == SETUP_ACTION: |
| setup(options) |
| elif action == START_ACTION: |
| start(options) |
| elif action == STOP_ACTION: |
| stop(options) |
| elif action == RESET_ACTION: |
| reset(options) |
| else: |
| parser.error("Invalid action") |
| |
| if __name__ == "__main__": |
| main() |