Skip to content
Snippets Groups Projects
Commit 1e3a7beb authored by Thibault VINCENT's avatar Thibault VINCENT
Browse files

console logging + daemonize option

parent 71e26b4b
No related branches found
No related tags found
No related merge requests found
......@@ -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 = {
......@@ -35,8 +30,6 @@ DEFAULT_CONFIGURATION = {
'force_xen' : 'no',
}
MAX_AUTH_TIMEOUT = 10
def run_node(options):
'''
'''
......@@ -53,45 +46,48 @@ def run_node(options):
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)
if options['stdout']:
handler = logging.StreamHandler()
else:
facility = logging.handlers.SysLogHandler.LOG_DAEMON
handler = logging.handlers.SysLogHandler(address='/dev/log',
facility=facility)
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
......@@ -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()
......@@ -164,7 +162,38 @@ if __name__ == '__main__':
else:
options[opt] = default
while True:
run_node(options)
logging.warning('Critical error, restarting node !')
sleep(2)
\ No newline at end of file
# 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.critical('Critical error, restarting node !')
sleep(2)
......@@ -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
......
......@@ -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
......@@ -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
......@@ -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
}
#
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment