#!/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 logging
import logging.handlers
import signal
from optparse import OptionParser
import sys
import traceback
import os
import time
import platform
import ConfigParser
import ProcessHelper
import errno
import posixpath
from Controller import Controller
from AgentConfig import AgentConfig
from NetUtil import NetUtil
from Registry import Registry
import Constants

logger = logging.getLogger()
IS_WINDOWS = platform.system() == "Windows"
formatstr = "%(levelname)s %(asctime)s %(filename)s:%(lineno)d - %(message)s"
agentPid = os.getpid()
controller = None
configFileRelPath = "infra/conf/agent.ini"
logFileName = "slider-agent.log"

SERVER_STATUS_URL="https://{0}:{1}{2}"


def signal_handler(signum, frame):
  #we want the handler to run only for the agent process and not
  #for the children (e.g. namenode, etc.)
  if os.getpid() != agentPid:
    os._exit(0)
  logger.info('signal received, exiting.')
  global controller
  if controller is not None and hasattr(controller, 'actionQueue') and controller.actionQueue.yarn_docker_mode == False:
    docker_mode = controller.actionQueue.docker_mode
    if docker_mode:
      tmpdir = controller.actionQueue.dockerManager.stop_container()

  if controller is not None and hasattr(controller, 'stopCommand'):
    controller.stopCommand = _increment_task_id(controller.stopCommand)
    controller.appGracefulStopQueued = True
    controller.actionQueue.execute_command(controller.stopCommand)

  ProcessHelper.stopAgent()

def _increment_task_id(stored_command):
  taskId = int(stored_command['taskId'])
  taskId = taskId + 1
  stored_command['taskId'] = taskId
  stored_command['commandId'] = "{0}-1".format(taskId)
  return stored_command

def debug(sig, frame):
  """Interrupt running process, and provide a python prompt for
  interactive debugging."""
  d = {'_frame': frame}         # Allow access to frame object.
  d.update(frame.f_globals)  # Unless shadowed by global
  d.update(frame.f_locals)

  message = "Signal received : entering python shell.\nTraceback:\n"
  message += ''.join(traceback.format_stack(frame))
  logger.info(message)


def setup_logging(verbose, logfile):
  formatter = logging.Formatter(formatstr)
  rotateLog = logging.handlers.RotatingFileHandler(logfile, "a", 10000000, 25)
  rotateLog.setFormatter(formatter)
  logger.addHandler(rotateLog)

  if verbose:
    logging.basicConfig(format=formatstr, level=logging.DEBUG, filename=logfile)
    logger.setLevel(logging.DEBUG)
    logger.info("loglevel=logging.DEBUG")
  else:
    logging.basicConfig(format=formatstr, level=logging.INFO, filename=logfile)
    logger.setLevel(logging.INFO)
    logger.info("loglevel=logging.INFO")


def update_log_level(config, logfile):
  # Setting loglevel based on config file
  try:
    loglevel = config.get('agent', 'log_level')
    if loglevel is not None:
      if loglevel == 'DEBUG':
        logging.basicConfig(format=formatstr, level=logging.DEBUG, filename=logfile)
        logger.setLevel(logging.DEBUG)
        logger.info("Newloglevel=logging.DEBUG")
      else:
        logging.basicConfig(format=formatstr, level=logging.INFO, filename=logfile)
        logger.setLevel(logging.INFO)
        logger.debug("Newloglevel=logging.INFO")
  except Exception, err:
    logger.info("Default loglevel=DEBUG")


def bind_signal_handlers():
  signal.signal(signal.SIGINT, signal_handler)
  signal.signal(signal.SIGTERM, signal_handler)
  if platform.system() != "Windows":
    signal.signal(signal.SIGUSR1, debug)


def update_config_from_file(agentConfig):
  try:
    configFile = posixpath.join(agentConfig.getWorkRootPath(), configFileRelPath)
    if os.path.exists(configFile):
      logger.info("Config file: " + configFile)
      agentConfig.setConfig(configFile)
    else:
      logger.warn("No config found, using default")

  except Exception, err:
    logger.warn(err)


def perform_prestart_checks(config):
  if os.path.isfile(ProcessHelper.pidfile):
    print("%s already exists, deleting" % ProcessHelper.pidfile)
    os.remove(ProcessHelper.pidfile)
  # check if the key folders exist
  elif not os.path.isdir(config.getResolvedPath(AgentConfig.APP_PACKAGE_DIR)):
    msg = "Package dir %s does not exists, can't continue" \
          % config.getResolvedPath(AgentConfig.APP_PACKAGE_DIR)
    logger.error(msg)
    print(msg)
    sys.exit(1)

def ensure_folder_layout(config):
  ensure_path_exists(config.getResolvedPath(AgentConfig.APP_INSTALL_DIR))
  ensure_path_exists(config.getResolvedPath(AgentConfig.APP_LOG_DIR))
  ensure_path_exists(config.getResolvedPath(AgentConfig.APP_RUN_DIR))
  ensure_path_exists(config.getResolvedPath(AgentConfig.APP_TASK_DIR))
  ensure_path_exists(config.getResolvedPath(AgentConfig.LOG_DIR))
  ensure_path_exists(config.getResolvedPath(AgentConfig.RUN_DIR))

def ensure_path_exists(path):
  try:
    os.makedirs(os.path.realpath(path))
  except OSError as exception:
    if exception.errno != errno.EEXIST:
      raise
    pass
  pass

def write_pid():
  # agent only dumps self pid to file
  pid = str(os.getpid())
  file(ProcessHelper.pidfile, 'w').write(pid)


def stop_agent():
# stop existing Slider agent
  pid = -1
  try:
    f = open(ProcessHelper.pidfile, 'r')
    pid = f.read()
    pid = int(pid)
    f.close()
    os.kill(pid, signal.SIGTERM)
    time.sleep(5)
    if os.path.exists(ProcessHelper.pidfile):
      raise Exception("PID file still exists.")
  except Exception, err:
    if pid == -1:
      print ("Agent process is not running")
    else:
      if not IS_WINDOWS:
        os.kill(pid, signal.SIGKILL)
    os._exit(1)


def main():
  parser = OptionParser()
  parser.add_option("-v", "--verbose", dest="verbose", help="verbose log output", default=False)
  parser.add_option("-l", "--label", dest="label", help="label of the agent", default=None)
  parser.add_option("--zk-quorum", dest=Constants.ZK_QUORUM, help="Zookeeper Quorum", default=None)
  parser.add_option("--zk-reg-path", dest=Constants.ZK_REG_PATH, help="Zookeeper Registry Path", default=None)
  parser.add_option("--debug", dest="debug", help="Agent debug hint", default="")
  (options, args) = parser.parse_args()

  if not Constants.AGENT_WORK_ROOT in os.environ and not 'PWD' in os.environ:
    parser.error("AGENT_WORK_ROOT environment variable or PWD must be set.")
  if Constants.AGENT_WORK_ROOT in os.environ:
    options.root_folder = os.environ[Constants.AGENT_WORK_ROOT]
  else:
    # some launch environments do not end up setting all environment variables
    options.root_folder = os.environ['PWD']

  if not 'AGENT_LOG_ROOT' in os.environ:
    parser.error("AGENT_LOG_ROOT environment variable must be set.")
  options.log_folder = os.environ['AGENT_LOG_ROOT']
  all_log_folders = [x.strip() for x in options.log_folder.split(',')]
  if len(all_log_folders) > 1:
    options.log_folder = all_log_folders[0]

  # If there are multiple log folder, separate by comma, pick one

  if not options.label:
    parser.error("label is required.");

  if not IS_WINDOWS:
    bind_signal_handlers()

  # Check for configuration file.
  agentConfig = AgentConfig(options.root_folder, options.log_folder, options.label)
  update_config_from_file(agentConfig)

  # update configurations if needed
  if options.zk_quorum:
      agentConfig.set(AgentConfig.SERVER_SECTION, Constants.ZK_QUORUM, options.zk_quorum)

  if options.zk_reg_path:
      agentConfig.set(AgentConfig.SERVER_SECTION, Constants.ZK_REG_PATH, options.zk_reg_path)

  if options.debug:
    agentConfig.set(AgentConfig.AGENT_SECTION, AgentConfig.APP_DBG_CMD, options.debug)

  logFile = posixpath.join(agentConfig.getResolvedPath(AgentConfig.LOG_DIR), logFileName)
  setup_logging(options.verbose, logFile)
  update_log_level(agentConfig, logFile)

  secDir = posixpath.join(agentConfig.getResolvedPath(AgentConfig.RUN_DIR), "security")
  logger.info("Security/Keys directory: " + secDir)
  agentConfig.set(AgentConfig.SECURITY_SECTION, "keysdir", secDir)

  perform_prestart_checks(agentConfig)
  ensure_folder_layout(agentConfig)
  # create security dir if necessary
  ensure_path_exists(secDir)

  write_pid()

  logger.info("Using AGENT_WORK_ROOT = " + options.root_folder)
  logger.info("Using AGENT_LOG_ROOT = " + options.log_folder)

  if len(all_log_folders) > 1:
    logger.info("Selected log folder from available: " + ",".join(all_log_folders))

  # Extract the AM hostname and secured port from ZK registry
  zk_lookup_tries = 0
  while zk_lookup_tries < Constants.MAX_AM_CONNECT_RETRIES:
    registry = Registry(options.zk_quorum, options.zk_reg_path)
    amHost, amUnsecuredPort, amSecuredPort = registry.readAMHostPort()

    tryConnect = True
    if not amHost or not amSecuredPort or not amUnsecuredPort:
      logger.info("Unable to extract AM host details from ZK, retrying ...")
      tryConnect = False
      time.sleep(NetUtil.CONNECT_SERVER_RETRY_INTERVAL_SEC)

    if tryConnect:
      if amHost:
        agentConfig.set(AgentConfig.SERVER_SECTION, "hostname", amHost)

      if amSecuredPort:
        agentConfig.set(AgentConfig.SERVER_SECTION, "secured_port", amSecuredPort)

      if amUnsecuredPort:
        agentConfig.set(AgentConfig.SERVER_SECTION, "port", amUnsecuredPort)

      server_url = SERVER_STATUS_URL.format(
        agentConfig.get(AgentConfig.SERVER_SECTION, 'hostname'),
        agentConfig.get(AgentConfig.SERVER_SECTION, 'port'),
        agentConfig.get(AgentConfig.SERVER_SECTION, 'check_path'))
      print("Connecting to the server at " + server_url + "...")
      logger.info('Connecting to the server at: ' + server_url)

      # Wait until server is reachable and continue to query ZK
      netutil = NetUtil()
      retries = netutil.try_to_connect(server_url, 3, logger)
      if retries < 3:
        break;
      pass
    pass
    zk_lookup_tries += 1
  pass

  # Launch Controller communication
  global controller
  controller = Controller(agentConfig)
  controller.start()
  
  try:
    while controller.is_alive():
      controller.join(timeout=1.0)
  except (KeyboardInterrupt, SystemExit):
    logger.info("... agent interrupted")
    pass


if __name__ == "__main__":
  main()
