#!/usr/bin/env python

# Dependcies:
#   sudo yum install python-simplejson

import logging, signal

from time   import sleep
from sys    import exit, path
from os     import devnull

path.insert(0, '/usr/lib/emi/emir-serp')
path.insert(0, '/usr/lib64/emi/emir-serp')

from daemon import Daemon
from EMIR import EMIRConfiguration, EMIRClient

def createloggerhandler(log_file):
  logger_handler = logging.FileHandler(log_file)
  logger_formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
  logger_handler.setFormatter(logger_formatter)
  return logger_handler

def reopenloggerhandler(signum, frame):
  global logger_handler, log_file
  logger = logging.getLogger('emir-serp')
  logger.removeHandler(logger_handler)
  logger_handler = createloggerhandler(log_file)
  logger.addHandler(logger_handler)
  
class EmirSerp(Daemon):
  def __init__(self, pid_file, config_file):

    # Initialize EMIR related components
    try: 
      self.config = EMIRConfiguration(config_file) 
    except Exception, inst: 
      print inst 
      exit(1) 
    self.client = EMIRClient(self.config)


    # Initialize self.logger
    self.logger = logging.getLogger('emir-serp')
    self.logger.setLevel(self.config.loglevel)

    # Check wether there is any service entry to be registered
    if not self.config.getServiceEntries():
      self.logger.info("No service entries has been defined")
      exit(0)

    # Check whether the EMIR is URL is valid and the service is available
    try:
      self.logger.debug("EMIR service on url '%s://%s:%s' is running since %s" % (self.config.protocol, self.config.host, self.config.port, self.client.ping()))
    except:
      self.logger.error("Connection failed to %s://%s:%s" % (self.config.protocol, self.config.host, self.config.port))
      exit(1)

    # Call parent's constructor to daemonize the process
    super(EmirSerp,self).__init__(pid_file, devnull, devnull, devnull, '/tmp')

  def run(self):
    # Try to send registration message. If do not manage to fall back
    # to update. For example because of already existing registration
    # entries.
    # initial registration:
    # 1: do "register"
    # 2: if "register" fails, try "update"
    try:
      self.logger.debug('Registering service entries')
      self.client.register()
    except Exception, ex:
      try:
        self.logger.debug('Falling back to initial service entry update')
        self.client.update()
      except Exception, ex:
        self.logger.error("Registration failed: %s" % ex)
        #exit(1)

    # After the successful initial registration wait the selected time
    # (where the configured period is given in hours so have to be
    # multiplied by 60*60) then try to send an update message.
    sleep(self.config.period * 60 * 60)
    # periodic registration
    # 1: do "update"
    # 2: if "update" fails, try "register" (maybe the EMIR lost the data)
    while self.daemon_alive:
      try:
        self.logger.debug('Periodical registration update')
        self.client.update()
      except Exception, ex:
        try:
          self.logger.debug('Falling back to register service entry instead of update. Data may lost on server side.')
          self.client.register()
        except Exception, ex:
          self.logger.error("Update failed: %s" % ex)
          #exit(1)
      sleep(self.config.period * 60 * 60)

    # Delete registered entries
    try:
      self.logger.debug('Deleting reqistered entries')
      self.client.delete()
    except Exception, ex:
      self.logger.error('Error during deletion: %s' % ex)
      #exit(1)
    # Call parents stop() function to stop the daemon itself

    self.stop()

if __name__ == "__main__":
  from optparse import OptionParser
  parser = OptionParser()
  # Location of the configuration file.
  parser.add_option("-c", "--config-file", dest="config_file", default='/etc/emi/emir-serp/emir-serp.ini',
                    help="""the path of the config file
                    [default: %default]""")
  # Location of the pid file.
  parser.add_option("-p", "--pid-file", dest="pid_file", default='/var/run/emi/emir-serp/emir-serp.pid',
                    help="""the path of the PID file
                    [default: %default]""")
  # Location of the log file.
  parser.add_option("-l", "--log-file", dest="log_file", default='/var/log/emi/emir-serp/emir-serp.log',
                    help="""the path of the log file
                    [default: %default]""")
  # The daemon is started in foreground mode ( = 1) or in the
  # background ( = 0 )
  parser.add_option("-f", "--foreground", action="store_true", dest="foreground", default=False,
                    help="run in foreground [default: %default]")
  (options, args) = parser.parse_args()

  # Initialize 'emir-serp' logger object
  global logger_handler, log_file

  log_file = options.log_file
  logger_handler = createloggerhandler(log_file)
  logging.getLogger('emir-serp').addHandler(logger_handler)

  signal.signal(signal.SIGHUP, reopenloggerhandler)

  # Creating and starting the daemon class and process
  myDaemon = EmirSerp(options.pid_file, options.config_file)

  if options.foreground:
    myDaemon.run()
  else:
    myDaemon.start()

  exit(0)

