blob: ad9ef0d878b6d5cea4cf71b2386dfc1378156e47 [file] [log] [blame]
#!/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.
# Script to check if hcat_server is reachable.
# Checks if databases can be enumerated, and databases can be created/dropped.
import sys, os, random, string, logging, logging.handlers
from optparse import OptionParser
from decimal import *
def generate_random_id( length=8, charset=(string.ascii_lowercase + string.digits) ):
return ''.join(random.choice(charset) for i in range(length))
# PING-DB related "constants".
HCAT_CHECK_DATABASE_NAME = 'hcat_ping_' + generate_random_id()
HCAT_CHECK_DATABASE_LOCATION = '/tmp/hcat_ping/' + HCAT_CHECK_DATABASE_NAME
ATTEMPT_CLEANUP=False
logger = logging.getLogger()
logLevels = [ logging.ERROR, logging.INFO, logging.DEBUG ]
THE_CHECK_COMMAND = ""
def check_unique_database_name():
global HCAT_CHECK_DATABASE_NAME
global HCAT_CHECK_DATABASE_LOCATION
# If directory already exists, pick a new database-name/location.
while run_command_quietly("hadoop dfs -ls " + HCAT_CHECK_DATABASE_LOCATION) == 0:
HCAT_CHECK_DATABASENAME = 'hcat_ping_' + generate_random_id()
HCAT_CHECK_DATABASE_LOCATION = '/tmp/hcat_ping/' + HCAT_CHECK_DATABASE_NAME
def run_command_quietly(command):
global logger
os.putenv("HADOOP_HOME_WARN_SUPPRESS", "true")
return_code = os.system(command + " >/dev/null 2>&1")
logger.debug("Running command: " + command + " ... returned " + str(return_code))
return return_code
def run_hcat_command(command):
return run_command_quietly(THE_CHECK_COMMAND + " -e \"" + command + "\" ")
def init_ping_command():
global THE_CHECK_COMMAND
if is_command_in_path("hcat"):
THE_CHECK_COMMAND = "hcat"
elif is_command_in_path("hive"):
THE_CHECK_COMMAND = "hive"
else:
logger.error("Could not find hcat or hive in $PATH. Can't connect to \
HCatalog Server.")
sys.exit(2)
def is_command_in_path(command):
return run_command_quietly("which " + command) == 0
def list_databases():
global logger
return_code = run_hcat_command("SHOW DATABASES")
if return_code != 0:
logger.debug("Could not list-databases.")
return False
return True
def create_database():
check_unique_database_name()
global ATTEMPT_CLEANUP
global logger
ATTEMPT_CLEANUP = True # State is changing. Must attempt cleanup.
create_db = "CREATE DATABASE " + HCAT_CHECK_DATABASE_NAME + " LOCATION '"+ HCAT_CHECK_DATABASE_LOCATION + "'"
list_db_dir = "hadoop dfs -ls " + HCAT_CHECK_DATABASE_LOCATION
if run_hcat_command(create_db) !=0 or run_command_quietly(list_db_dir) != 0:
logger.debug("Creating database failed.")
return False
return True
def drop_database(suppressError):
global logger
drop_db = "DROP DATABASE " + HCAT_CHECK_DATABASE_NAME
list_db_dir = "hadoop dfs -ls " + HCAT_CHECK_DATABASE_LOCATION
if run_hcat_command(drop_db) != 0 or run_command_quietly(list_db_dir) == 0:
if not suppressError:
logger.debug("Dropping database failed.")
return False
return True
def cleanup():
drop_database(True)
run_command_quietly( "hadoop dfs -rmr -skipTrash " + HCAT_CHECK_DATABASE_LOCATION )
def parse_options():
global logger
global logLevels
streamHandler = logging.StreamHandler()
logger.addHandler(streamHandler)
parser = OptionParser()
parser.add_option("-v", "--verbose", dest="verbosity_level",
help="Controls verbosity of output to LEVEL (0-2)", metavar="LEVEL", default="1")
parser.add_option("-f", "--file", dest="filename",
help="Write output to FILE", metavar="FILE")
(options, args) = parser.parse_args()
level = int(Decimal(options.verbosity_level))
if not level in range(0,3):
print "Invalid verbosity level. Should be in range [0, 2]."
sys.exit(3)
if options.filename:
logger.removeHandler(streamHandler)
handler = logging.handlers.RotatingFileHandler(options.filename,
maxBytes=1024*1024,
backupCount=3)
logger.addHandler(handler)
else:
handler = streamHandler
formatter = logging.Formatter("%(asctime)s %(filename)s:%(lineno)d %(levelname)s - %(message)s")
handler.setFormatter( formatter )
logger.setLevel( logLevels[level] )
def main(*args):
global logger
try:
try:
parse_options()
init_ping_command()
# Not making assumptions on availability of ternary.
if list_databases() and create_database() and drop_database(False):
logger.info("HCatalog Server is running fine.")
return 0 # OK!
else:
logger.critical("HCatalog Server could not be contacted.")
return 2 # Critical!
except SystemExit, sysExit:
return sysExit
except Exception, e:
logger.exception("Could not determine if HCatalog Server is running.")
return 3 # Unknown Error.
finally: # Nested try. Pre-2.5 Python won't allow try-except-finally.
if ATTEMPT_CLEANUP:
cleanup()
if __name__ == '__main__':
sys.exit( main(*sys.argv) )