| #!/usr/bin/env python |
| |
| # |
| # 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 getpass |
| |
| import os |
| import platform |
| import subprocess |
| from threading import Thread |
| import sys |
| import time |
| import errno |
| |
| LIB = "lib" |
| CONF = "conf" |
| LOG="logs" |
| WEBAPP="server" + os.sep + "webapp" |
| DATA="data" |
| ENV_KEYS = ["JAVA_HOME", "METADATA_OPTS", "METADATA_LOG_DIR", "METADATA_PID_DIR", "METADATA_CONF", "METADATACPPATH", "METADATA_DATA_DIR", "METADATA_HOME_DIR", "METADATA_EXPANDED_WEBAPP_DIR"] |
| METADATA_CONF = "METADATA_CONF" |
| METADATA_LOG = "METADATA_LOG_DIR" |
| METADATA_PID = "METADATA_PID_DIR" |
| METADATA_WEBAPP = "METADATA_EXPANDED_WEBAPP_DIR" |
| METADATA_OPTS = "METADATA_OPTS" |
| METADATA_DATA = "METADATA_DATA_DIR" |
| METADATA_HOME = "METADATA_HOME_DIR" |
| IS_WINDOWS = platform.system() == "Windows" |
| ON_POSIX = 'posix' in sys.builtin_module_names |
| DEBUG = False |
| |
| def scriptDir(): |
| """ |
| get the script path |
| """ |
| return os.path.dirname(os.path.realpath(__file__)) |
| |
| def metadataDir(): |
| home = os.path.dirname(scriptDir()) |
| return os.environ.get(METADATA_HOME, home) |
| |
| def libDir(dir) : |
| return os.path.join(dir, LIB) |
| |
| def confDir(dir): |
| localconf = os.path.join(dir, CONF) |
| return os.environ.get(METADATA_CONF, localconf) |
| |
| def logDir(dir): |
| localLog = os.path.join(dir, LOG) |
| return os.environ.get(METADATA_LOG, localLog) |
| |
| def pidFile(dir): |
| localPid = os.path.join(dir, LOG) |
| return os.path.join(os.environ.get(METADATA_PID, localPid), 'atlas.pid') |
| |
| def dataDir(dir): |
| data = os.path.join(dir, DATA) |
| return os.environ.get(METADATA_DATA, data) |
| |
| def webAppDir(dir): |
| webapp = os.path.join(dir, WEBAPP) |
| return os.environ.get(METADATA_WEBAPP, webapp) |
| |
| def expandWebApp(dir): |
| webappDir = webAppDir(dir) |
| webAppMetadataDir = os.path.join(webappDir, "atlas") |
| d = os.sep |
| if not os.path.exists(os.path.join(webAppMetadataDir, "WEB-INF")): |
| try: |
| os.makedirs(webAppMetadataDir) |
| except OSError, e: |
| if e.errno != errno.EEXIST: |
| raise e |
| pass |
| os.chdir(webAppMetadataDir) |
| jar(os.path.join(metadataDir(), "server", "webapp", "atlas.war")) |
| |
| def dirMustExist(dirname): |
| if not os.path.exists(dirname): |
| os.mkdir(dirname) |
| return dirname |
| |
| def executeEnvSh(confDir): |
| envscript = '%s/atlas-env.sh' % confDir |
| if not IS_WINDOWS and os.path.exists(envscript): |
| envCmd = 'source %s && env' % envscript |
| command = ['bash', '-c', envCmd] |
| |
| proc = subprocess.Popen(command, stdout = subprocess.PIPE) |
| |
| for line in proc.stdout: |
| (key, _, value) = line.strip().partition("=") |
| if key in ENV_KEYS: |
| os.environ[key] = value |
| |
| proc.communicate() |
| |
| def java(classname, args, classpath, jvm_opts_list, logdir=None): |
| java_home = os.environ.get("JAVA_HOME", None) |
| if java_home: |
| prg = os.path.join(java_home, "bin", "java") |
| else: |
| prg = which("java") |
| |
| commandline = [prg] |
| commandline.extend(jvm_opts_list) |
| commandline.append("-classpath") |
| commandline.append(classpath) |
| commandline.append(classname) |
| commandline.extend(args) |
| return runProcess(commandline, logdir) |
| |
| def jar(path): |
| java_home = os.environ.get("JAVA_HOME", None) |
| if java_home: |
| prg = os.path.join(java_home, "bin", "jar") |
| else: |
| prg = which("jar") |
| |
| commandline = [prg] |
| commandline.append("-xf") |
| commandline.append(path) |
| process = runProcess(commandline) |
| process.wait() |
| |
| def is_exe(fpath): |
| return os.path.isfile(fpath) and os.access(fpath, os.X_OK) |
| |
| def which(program): |
| |
| fpath, fname = os.path.split(program) |
| if fpath: |
| if is_exe(program): |
| return program |
| else: |
| for path in os.environ["PATH"].split(os.pathsep): |
| path = path.strip('"') |
| exe_file = os.path.join(path, program) |
| if is_exe(exe_file): |
| return exe_file |
| |
| return None |
| |
| def runProcess(commandline, logdir=None): |
| """ |
| Run a process |
| :param commandline: command line |
| :return:the return code |
| """ |
| global finished |
| debug ("Executing : %s" % commandline) |
| timestr = time.strftime("metadata.%Y%m%d-%H%M%S") |
| stdoutFile = None |
| stderrFile = None |
| if logdir: |
| stdoutFile = open(os.path.join(logdir, timestr + ".out"), "w") |
| stderrFile = open(os.path.join(logdir,timestr + ".err"), "w") |
| return subprocess.Popen(commandline, stdout=stdoutFile, stderr=stderrFile) |
| |
| def print_output(name, src, toStdErr): |
| """ |
| Relay the output stream to stdout line by line |
| :param name: |
| :param src: source stream |
| :param toStdErr: flag set if stderr is to be the dest |
| :return: |
| """ |
| |
| global needPassword |
| debug ("starting printer for %s" % name ) |
| line = "" |
| while not finished: |
| (line, done) = read(src, line) |
| if done: |
| out(toStdErr, line + "\n") |
| flush(toStdErr) |
| if line.find("Enter password for") >= 0: |
| needPassword = True |
| line = "" |
| out(toStdErr, line) |
| # closedown: read remainder of stream |
| c = src.read(1) |
| while c!="" : |
| c = c.decode('utf-8') |
| out(toStdErr, c) |
| if c == "\n": |
| flush(toStdErr) |
| c = src.read(1) |
| flush(toStdErr) |
| src.close() |
| |
| def read_input(name, exe): |
| """ |
| Read input from stdin and send to process |
| :param name: |
| :param process: process to send input to |
| :return: |
| """ |
| global needPassword |
| debug ("starting reader for %s" % name ) |
| while not finished: |
| if needPassword: |
| needPassword = False |
| if sys.stdin.isatty(): |
| cred = getpass.getpass() |
| else: |
| cred = sys.stdin.readline().rstrip() |
| exe.stdin.write(cred + "\n") |
| |
| def debug(text): |
| if DEBUG: print '[DEBUG] ' + text |
| |
| |
| def error(text): |
| print '[ERROR] ' + text |
| sys.stdout.flush() |
| |
| def info(text): |
| print text |
| sys.stdout.flush() |
| |
| |
| def out(toStdErr, text) : |
| """ |
| Write to one of the system output channels. |
| This action does not add newlines. If you want that: write them yourself |
| :param toStdErr: flag set if stderr is to be the dest |
| :param text: text to write. |
| :return: |
| """ |
| if toStdErr: |
| sys.stderr.write(text) |
| else: |
| sys.stdout.write(text) |
| |
| def flush(toStdErr) : |
| """ |
| Flush the output stream |
| :param toStdErr: flag set if stderr is to be the dest |
| :return: |
| """ |
| if toStdErr: |
| sys.stderr.flush() |
| else: |
| sys.stdout.flush() |
| |
| def read(pipe, line): |
| """ |
| read a char, append to the listing if there is a char that is not \n |
| :param pipe: pipe to read from |
| :param line: line being built up |
| :return: (the potentially updated line, flag indicating newline reached) |
| """ |
| |
| c = pipe.read(1) |
| if c != "": |
| o = c.decode('utf-8') |
| if o != '\n': |
| line += o |
| return line, False |
| else: |
| return line, True |
| else: |
| return line, False |
| |
| def writePid(metadata_pid_file, process): |
| f = open(metadata_pid_file, 'w') |
| f.write(str(process.pid)) |
| f.close() |
| |
| |