Skip to content
Snippets Groups Projects
Commit 89ca6d91 authored by Anael Beutot's avatar Anael Beutot
Browse files

RPC deconnection error handling.

When the node is disconnected from the cc-server, it keeps it internal state
until the connection pass, then in case the same role is returned by the
cc-server, it just reregister its objects and tags, else it remove the previous
main plugin and recreate a new one corresponding to the adequate role.
parent 338462d9
No related branches found
No related tags found
No related merge requests found
...@@ -28,6 +28,9 @@ class RPCStartHandler(Thread): ...@@ -28,6 +28,9 @@ class RPCStartHandler(Thread):
This class inherits from :class:`Thread` but only the connection part is run This class inherits from :class:`Thread` but only the connection part is run
in a background thread. in a background thread.
Note:
As :class:`Thread`, it can be started only one time.
""" """
def __init__(self, loop): def __init__(self, loop):
""" """
...@@ -56,6 +59,7 @@ class RPCStartHandler(Thread): ...@@ -56,6 +59,7 @@ class RPCStartHandler(Thread):
port=self.loop.config.server_port, port=self.loop.config.server_port,
handler=self.loop.rpc_handler, handler=self.loop.rpc_handler,
loop=self.loop.evloop, loop=self.loop.evloop,
on_disconnect=self.loop.restart_rpc_connection,
) )
logger.debug('Connection created') logger.debug('Connection created')
except IOError: except IOError:
...@@ -121,27 +125,47 @@ class RPCStartHandler(Thread): ...@@ -121,27 +125,47 @@ class RPCStartHandler(Thread):
return return
# set handler according to which role was returned by the cc-server # set handler according to which role was returned by the cc-server
if response == u'host': if response == self.loop.role and response is not None:
# we don't need to reload the plugins
# but we need to register the objects and tags
self.loop.tag_db.rpc_register()
elif response == u'host':
# close previous plugins if needed
if self.loop.role is not None:
self.loop.close_plugins()
# re-register the tags of the main loop
self.loop.tag_db.register()
logger.debug('Role host affected') logger.debug('Role host affected')
from ccnode.host import Handler as HostHandler from ccnode.host import Handler as HostHandler
self.loop.role = HostHandler(loop=self.loop) self.loop.main_plugin = HostHandler(loop=self.loop)
self.loop.role = u'host'
self.loop.register_plugin(self.loop.main_plugin)
elif response == u'hv': elif response == u'hv':
# close previous plugins if needed
if self.loop.role is not None:
self.loop.close_plugins()
# re-register the tags of the main loop
self.loop.tag_db.register()
logger.debug('Role hypervisor affected') logger.debug('Role hypervisor affected')
# we don't import those modules at the top because some dependancies
# may not be installed
from ccnode.hypervisor import Handler as HypervisorHandler from ccnode.hypervisor import Handler as HypervisorHandler
self.loop.role = HypervisorHandler( self.loop.main_plugin = HypervisorHandler(
hypervisor_name=self.loop.config.server_user, hypervisor_name=self.loop.config.server_user,
loop=self.loop, loop=self.loop,
) )
self.loop.role = u'hv'
self.loop.register_plugin(self.loop.main_plugin)
else: else:
logger.error('Failed authentication, role returned: %s', response) logger.error('Failed authentication, role returned: %s', response)
self.loop.role = None self.loop.role = None
self.auth_id = None self.auth_id = None
return # we also close the previously opened plugins
self.loop.close_plugins()
return # we retry while it fails
if self.loop.role is not None: self.stop()
self.stop() logger.info('Successfully authenticated with role %s', response)
logger.info('Successfully authenticated with role %s', response)
self.loop.register_plugin(self.loop.role)
self.auth_id = None self.auth_id = None
...@@ -176,6 +200,7 @@ class MainLoop(object): ...@@ -176,6 +200,7 @@ class MainLoop(object):
# role # role
self.role = None self.role = None
self.main_plugin = None
# tag database # tag database
self.tag_db = TagDB(self, tags=DEFAULT_TAGS) self.tag_db = TagDB(self, tags=DEFAULT_TAGS)
...@@ -255,6 +280,19 @@ class MainLoop(object): ...@@ -255,6 +280,19 @@ class MainLoop(object):
plugin.stop() plugin.stop()
def restart_rpc_connection(self, *args):
if not self.rpc_connected:
return
logger.error('Lost connection to the cc-server, will attempt'
' reconnection')
# clear connection
self.rpc_con = None
# attempt to connect to the cc-server again
self.connect = RPCStartHandler(self)
self.connect.start()
def start(self): def start(self):
logger.info('Starting node') logger.info('Starting node')
for signal in self.signals.itervalues(): for signal in self.signals.itervalues():
...@@ -270,13 +308,17 @@ class MainLoop(object): ...@@ -270,13 +308,17 @@ class MainLoop(object):
self.connect.stop() self.connect.stop()
# close rpc # close rpc
if self.rpc_con is not None: if self.rpc_con is not None:
# disable callback to prevent trampoline calls
self.rpc_con._on_disconnect = None # FIXME doesn't work
self.rpc_con.shutdown() self.rpc_con.shutdown()
# close all plugins # close all plugins
for plugin in self.registered_plugins: for plugin in self.registered_plugins:
plugin.stop() plugin.stop()
self.registered_plugins = set() self.registered_plugins = set()
# FIXME check for closing of main tags that were not in plugin
self.role = None self.role = None
self.main_plugin = None
self.evloop.stop() self.evloop.stop()
def reload(self, watcher=None, revents=None): def reload(self, watcher=None, revents=None):
......
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