#!/usr/bin/env python #coding=utf8 from optparse import OptionParser from sjrpc.core import RpcError from ccnode.ccnode import CCNode import ConfigParser import sys import logging import logging.handlers import signal import threading from time import sleep from math import exp try: import daemon DAEMONIZE = True except ImportError: DAEMONIZE = False __VERSION__ = 3 DEFAULT_CONFIG_FILE = '/etc/cc-node.conf' DEFAULT_PID_FILE = '/var/run/cc-node.pid' DEFAULT_CONFIGURATION = { 'address': None, 'login': None, 'password': None, 'port': 1984, 'verbosity': 0, #'ssl_cert': '', } MAX_AUTH_TIMEOUT = 10 def run_node(options): # Setup logging facility: level = logging.ERROR verb = int(options['verbosity']) if verb: if verb == 1: level = logging.WARNING elif verb == 2: level = logging.INFO else: level = logging.DEBUG logger = logging.getLogger() logger.setLevel(level) facility = logging.handlers.SysLogHandler.LOG_DAEMON handler = logging.handlers.SysLogHandler(address='/dev/log', facility=facility) fmt = logging.Formatter('cc-node: %(levelname)s %(message)s') handler.setFormatter(fmt) logger.handlers = [] logger.addHandler(handler) logging.debug('Connecting to server') try: node = CCNode(options['address'], int(options['port'])) except Exception as err: logging.critical('Starting fail: %s' % err) return else: logging.info('Connected to server %s' % options['address']) def authentication(): timeout = 1 while node.manager.is_running(): result = node.authentify(options['login'], options['password']) if result: logging.info('Authentication suscessfull.') return else: timeout += 0.1 maxtimeout = MAX_AUTH_TIMEOUT if timeout == maxtimeout: timeout = maxtimeout sleep(exp(timeout)) def shutdown_handler(signum, frame): ''' Handler called when SIGINT emited ''' node.manager.shutdown() logging.info('Node properly exited by SIGINT') sys.exit(0) signal.signal(signal.SIGINT, shutdown_handler) threading.Thread(target=authentication).start() try: node.run() except Exception as err: node.manager.shutdown() logging.critical('Node failed: %s' % err) return if __name__ == '__main__': usage = 'usage: %prog [OPTION...]' op = OptionParser(usage, version='%%prog %s' % __VERSION__) op.add_option('-c', '--config', default=DEFAULT_CONFIG_FILE, help='configuration file (default: %default)') op.add_option('-d', '--daemonize', default=False, action='store_true', help='run as daemon and write pid file') op.add_option('-p', '--pid-file', default=DEFAULT_PID_FILE, help='pid file (default: %default)') cliopts, args = op.parse_args() # Reading the config file: config = ConfigParser.SafeConfigParser() config.read(cliopts.config) try: options = dict(config.items('node')) except ConfigParser.NoSectionError: sys.stderr.write("Configuration error: 'node' section must exist " "in '%s'\n" % cliopts.config) sys.exit(1) # Applying default config file options: for opt, default in DEFAULT_CONFIGURATION.iteritems(): if opt not in options or not options[opt]: if default is None: sys.stderr.write("Configuration error: you must specify '%s' " "option in '%s' !\n" % (opt, cliopts.config)) sys.exit(1) else: options[opt] = default while True: run_node(options) logging.warning('Critical error, restarting node') sleep(2)