Loading bin/cc-node +68 −39 Original line number Diff line number Diff line Loading @@ -5,22 +5,17 @@ from optparse import OptionParser from sjrpc.core import RpcError from ccnode.ccnode import CCNode import ConfigParser import sys import sys, os, atexit import logging import logging.handlers import signal import threading from daemon import DaemonContext from time import sleep from math import exp try: import daemon DAEMONIZE = True except ImportError: DAEMONIZE = False from ccnode import __version__ MAX_AUTH_TIMEOUT = 10 DEFAULT_CONFIG_FILE = '/etc/cc-node.conf' DEFAULT_PID_FILE = '/var/run/cc-node.pid' DEFAULT_CONFIGURATION = { Loading @@ -35,8 +30,6 @@ DEFAULT_CONFIGURATION = { 'force_xen' : 'no', } MAX_AUTH_TIMEOUT = 10 def run_node(options): ''' ''' Loading @@ -53,45 +46,48 @@ def run_node(options): logger = logging.getLogger() logger.setLevel(level) if options['stdout']: handler = logging.StreamHandler() else: 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) handler.setFormatter(logging.Formatter('cc-node: %(levelname)s %(message)s') ) logger.handlers = [] logger.addHandler(handler) # setup SIGINT handler # setup SIGINT/SIGTERM handler def shutdown_handler(signum, frame): ''' Handler called when SIGINT emited Handler called when SIGINT/SIGTERM emited ''' logging.info('SIGINT received, node shutdown in progress') logging.error('Letal signal received, node shutdown in progress') try: ''' #FIXME REGRESSION if node: logging.debug('Closing server connection') node.manager.shutdown() ''' pass except: pass sys.exit(0) finally: os._exit(1) # register SIGINT and SIGTERM handler signal.signal(signal.SIGINT, shutdown_handler) signal.signal(signal.SIGTERM, shutdown_handler) # re-authentication thread def authentication(node): timeout = 1 while node: if node.get_manager().is_running(): logging.debug('Sending authentication request') result = node.authentify(options['login'], options['password']) if result: logging.info('Authentication suscessfull') logging.info('Sending authentication request') if node.authentify(options['login'], options['password']): logging.error('Authentication suscessfull') return else: logging.error('Authentication failure') timeout += 0.1 if timeout >= MAX_AUTH_TIMEOUT: timeout = MAX_AUTH_TIMEOUT Loading @@ -101,46 +97,48 @@ def run_node(options): none = None auth_thread = None try: logging.info('Initializing node client') logging.error('Initializing node client') try: node = CCNode(options['address'], int(options['port']), options['detect_hypervisor'] == 'yes', options['command_execution'] == 'yes', force_xen=(options['force_xen'] == 'yes')) except Exception as err: logging.critical('Client initialization failure: `%s`:`%s`' % (repr(err), err)) logging.error('Client initialization failure: `%s`:`%s`', repr(err), err) raise err # start main loop and auth thread logging.debug('Starting authentication thread') logging.info('Starting authentication thread') auth_thread = threading.Thread(target=authentication, args=(node,), name='Auth') auth_thread.daemon = True auth_thread.start() logging.debug('Starting node main loop') logging.info('Starting main loop') node.run() except Exception as err: logging.error('run_node: `%s` -> `%s`', repr(err), err) if auth_thread: del auth_thread auth_thread = None if node: node.manager.shutdown() del node node = None finally: return if __name__ == '__main__': usage = 'usage: %prog [OPTION...]' op = OptionParser(usage, version='%%prog %s' % __version__) op = OptionParser(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, op.add_option('-p', '--pidfile', default=DEFAULT_PID_FILE, help='pid file (default: %default)') op.add_option('-s', '--stdout', action='store_true', default=False, help='log on standard output instead of syslog') cliopts, args = op.parse_args() Loading @@ -164,7 +162,38 @@ if __name__ == '__main__': else: options[opt] = default # Merge command options and .conf file options for opt in ('daemonize', 'pidfile', 'stdout'): if getattr(cliopts, opt) is not None: options[opt] = getattr(cliopts, opt) # Create option set for the daemonization process daemon_opts = {} daemonize = options['daemonize'] if isinstance(daemonize, str): daemonize = daemonize in ('yes', 'true') daemon_opts['detach_process'] = daemonize if not daemonize: daemon_opts['stderr'] = sys.stderr daemon_opts['stdout'] = sys.stderr if options['pidfile']: #daemon_opts['pidfile'] = lockfile.FileLock(options['pidfile']) pidfile = open(cliopts.pidfile, 'w') daemon_opts['files_preserve'] = [pidfile] with DaemonContext(**daemon_opts): # write pid in pidfile if pidfile is not None: pidfile.write('%s' % os.getpid()) pidfile.flush() # register pidfile cleaning @atexit.register def clean_pidfile(): pidfile.seek(0) pidfile.truncate() pidfile.flush() # run node while True: run_node(options) logging.warning('Critical error, restarting node !') logging.critical('Critical error, restarting node !') sleep(2) debian/control +1 −1 Original line number Diff line number Diff line Loading @@ -8,7 +8,7 @@ Standards-Version: 3.9.1 Package: cc-node Architecture: all Depends: ${misc:Depends}, ${python:Depends}, python-sjrpc ( >= 8 ), python-psutil Depends: ${misc:Depends}, ${python:Depends}, python-sjrpc ( >= 9 ), python-psutil, python-daemon Recommends: python-libvirt XB-Python-Version: ${python:Versions} Description: CloudControl node Loading debian/init +6 −6 Original line number Diff line number Diff line Loading @@ -17,8 +17,8 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="CloudControl node" NAME=cc-node DAEMON=/usr/bin/cc-node DAEMON_ARGS="" PIDFILE=/var/run/$NAME.pid DAEMON_OPTS="-d -p $PIDFILE" # Defaults: USER=root Loading @@ -29,6 +29,7 @@ GROUP=root # Load various rcS variables . /lib/init/vars.sh # Override the VERBOSE variable so we always have feedback messages VERBOSE=yes Loading @@ -52,11 +53,10 @@ VERBOSE=yes # do_start() { start-stop-daemon --start --quiet --background --name $NAME \ --exec $(readlink -f $(which python)) --test > /dev/null || return 2 start-stop-daemon --start --quiet --background --make-pidfile \ --pidfile $PIDFILE --chuid $USER:$GROUP --exec $DAEMON \ -- $DAEMON_OPTS || return 1 start-stop-daemon --start --quiet --name $NAME --test \ --exec $(readlink -f $(which python)) > /dev/null || return 2 start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$GROUP \ --exec $DAEMON -- $DAEMON_OPTS || return 1 } # Loading Loading
bin/cc-node +68 −39 Original line number Diff line number Diff line Loading @@ -5,22 +5,17 @@ from optparse import OptionParser from sjrpc.core import RpcError from ccnode.ccnode import CCNode import ConfigParser import sys import sys, os, atexit import logging import logging.handlers import signal import threading from daemon import DaemonContext from time import sleep from math import exp try: import daemon DAEMONIZE = True except ImportError: DAEMONIZE = False from ccnode import __version__ MAX_AUTH_TIMEOUT = 10 DEFAULT_CONFIG_FILE = '/etc/cc-node.conf' DEFAULT_PID_FILE = '/var/run/cc-node.pid' DEFAULT_CONFIGURATION = { Loading @@ -35,8 +30,6 @@ DEFAULT_CONFIGURATION = { 'force_xen' : 'no', } MAX_AUTH_TIMEOUT = 10 def run_node(options): ''' ''' Loading @@ -53,45 +46,48 @@ def run_node(options): logger = logging.getLogger() logger.setLevel(level) if options['stdout']: handler = logging.StreamHandler() else: 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) handler.setFormatter(logging.Formatter('cc-node: %(levelname)s %(message)s') ) logger.handlers = [] logger.addHandler(handler) # setup SIGINT handler # setup SIGINT/SIGTERM handler def shutdown_handler(signum, frame): ''' Handler called when SIGINT emited Handler called when SIGINT/SIGTERM emited ''' logging.info('SIGINT received, node shutdown in progress') logging.error('Letal signal received, node shutdown in progress') try: ''' #FIXME REGRESSION if node: logging.debug('Closing server connection') node.manager.shutdown() ''' pass except: pass sys.exit(0) finally: os._exit(1) # register SIGINT and SIGTERM handler signal.signal(signal.SIGINT, shutdown_handler) signal.signal(signal.SIGTERM, shutdown_handler) # re-authentication thread def authentication(node): timeout = 1 while node: if node.get_manager().is_running(): logging.debug('Sending authentication request') result = node.authentify(options['login'], options['password']) if result: logging.info('Authentication suscessfull') logging.info('Sending authentication request') if node.authentify(options['login'], options['password']): logging.error('Authentication suscessfull') return else: logging.error('Authentication failure') timeout += 0.1 if timeout >= MAX_AUTH_TIMEOUT: timeout = MAX_AUTH_TIMEOUT Loading @@ -101,46 +97,48 @@ def run_node(options): none = None auth_thread = None try: logging.info('Initializing node client') logging.error('Initializing node client') try: node = CCNode(options['address'], int(options['port']), options['detect_hypervisor'] == 'yes', options['command_execution'] == 'yes', force_xen=(options['force_xen'] == 'yes')) except Exception as err: logging.critical('Client initialization failure: `%s`:`%s`' % (repr(err), err)) logging.error('Client initialization failure: `%s`:`%s`', repr(err), err) raise err # start main loop and auth thread logging.debug('Starting authentication thread') logging.info('Starting authentication thread') auth_thread = threading.Thread(target=authentication, args=(node,), name='Auth') auth_thread.daemon = True auth_thread.start() logging.debug('Starting node main loop') logging.info('Starting main loop') node.run() except Exception as err: logging.error('run_node: `%s` -> `%s`', repr(err), err) if auth_thread: del auth_thread auth_thread = None if node: node.manager.shutdown() del node node = None finally: return if __name__ == '__main__': usage = 'usage: %prog [OPTION...]' op = OptionParser(usage, version='%%prog %s' % __version__) op = OptionParser(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, op.add_option('-p', '--pidfile', default=DEFAULT_PID_FILE, help='pid file (default: %default)') op.add_option('-s', '--stdout', action='store_true', default=False, help='log on standard output instead of syslog') cliopts, args = op.parse_args() Loading @@ -164,7 +162,38 @@ if __name__ == '__main__': else: options[opt] = default # Merge command options and .conf file options for opt in ('daemonize', 'pidfile', 'stdout'): if getattr(cliopts, opt) is not None: options[opt] = getattr(cliopts, opt) # Create option set for the daemonization process daemon_opts = {} daemonize = options['daemonize'] if isinstance(daemonize, str): daemonize = daemonize in ('yes', 'true') daemon_opts['detach_process'] = daemonize if not daemonize: daemon_opts['stderr'] = sys.stderr daemon_opts['stdout'] = sys.stderr if options['pidfile']: #daemon_opts['pidfile'] = lockfile.FileLock(options['pidfile']) pidfile = open(cliopts.pidfile, 'w') daemon_opts['files_preserve'] = [pidfile] with DaemonContext(**daemon_opts): # write pid in pidfile if pidfile is not None: pidfile.write('%s' % os.getpid()) pidfile.flush() # register pidfile cleaning @atexit.register def clean_pidfile(): pidfile.seek(0) pidfile.truncate() pidfile.flush() # run node while True: run_node(options) logging.warning('Critical error, restarting node !') logging.critical('Critical error, restarting node !') sleep(2)
debian/control +1 −1 Original line number Diff line number Diff line Loading @@ -8,7 +8,7 @@ Standards-Version: 3.9.1 Package: cc-node Architecture: all Depends: ${misc:Depends}, ${python:Depends}, python-sjrpc ( >= 8 ), python-psutil Depends: ${misc:Depends}, ${python:Depends}, python-sjrpc ( >= 9 ), python-psutil, python-daemon Recommends: python-libvirt XB-Python-Version: ${python:Versions} Description: CloudControl node Loading
debian/init +6 −6 Original line number Diff line number Diff line Loading @@ -17,8 +17,8 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="CloudControl node" NAME=cc-node DAEMON=/usr/bin/cc-node DAEMON_ARGS="" PIDFILE=/var/run/$NAME.pid DAEMON_OPTS="-d -p $PIDFILE" # Defaults: USER=root Loading @@ -29,6 +29,7 @@ GROUP=root # Load various rcS variables . /lib/init/vars.sh # Override the VERBOSE variable so we always have feedback messages VERBOSE=yes Loading @@ -52,11 +53,10 @@ VERBOSE=yes # do_start() { start-stop-daemon --start --quiet --background --name $NAME \ --exec $(readlink -f $(which python)) --test > /dev/null || return 2 start-stop-daemon --start --quiet --background --make-pidfile \ --pidfile $PIDFILE --chuid $USER:$GROUP --exec $DAEMON \ -- $DAEMON_OPTS || return 1 start-stop-daemon --start --quiet --name $NAME --test \ --exec $(readlink -f $(which python)) > /dev/null || return 2 start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$GROUP \ --exec $DAEMON -- $DAEMON_OPTS || return 1 } # Loading