diff --git a/bootstrapvz/base/manifest.py b/bootstrapvz/base/manifest.py index 2854068..27e7686 100644 --- a/bootstrapvz/base/manifest.py +++ b/bootstrapvz/base/manifest.py @@ -136,3 +136,10 @@ class Manifest(object): return {'__class__': 'bootstrapvz.base.manifest.Manifest', 'path': self.path, 'data': self.data} + + def __setstate__(self, state): + self.path = state['path'] + self.load(state['data']) + self.initialize() + self.validate() + self.parse() diff --git a/bootstrapvz/common/exceptions.py b/bootstrapvz/common/exceptions.py index a349c07..dee0d53 100644 --- a/bootstrapvz/common/exceptions.py +++ b/bootstrapvz/common/exceptions.py @@ -2,6 +2,7 @@ class ManifestError(Exception): def __init__(self, message, manifest_path, data_path=None): + super(ManifestError, self).__init__(message) self.message = message self.manifest_path = manifest_path self.data_path = data_path @@ -16,6 +17,7 @@ class ManifestError(Exception): class TaskListError(Exception): def __init__(self, message): + super(TaskListError, self).__init__(message) self.message = message def __str__(self): diff --git a/bootstrapvz/remote/__init__.py b/bootstrapvz/remote/__init__.py index 3c61646..a7ec9da 100644 --- a/bootstrapvz/remote/__init__.py +++ b/bootstrapvz/remote/__init__.py @@ -1,22 +1,31 @@ """Remote module containing methods to bootstrap remotely """ +import bootstrapvz.common.exceptions def register_deserialization_handlers(): from Pyro4.util import SerializerBase SerializerBase.register_dict_to_class('bootstrapvz.base.manifest.Manifest', deserialize_manifest) SerializerBase.register_dict_to_class('bootstrapvz.base.bootstrapinfo.BootstrapInformation', deserialize_bootstrapinfo) + SerializerBase.register_dict_to_class('bootstrapvz.common.exceptions.ManifestError', deserialize_exception) + SerializerBase.register_dict_to_class('bootstrapvz.common.exceptions.TaskListError', deserialize_exception) + SerializerBase.register_dict_to_class('bootstrapvz.common.exceptions.TaskError', deserialize_exception) def unregister_deserialization_handlers(): from Pyro4.util import SerializerBase SerializerBase.unregister_dict_to_class('bootstrapvz.base.manifest.Manifest') SerializerBase.unregister_dict_to_class('bootstrapvz.base.bootstrapinfo.BootstrapInformation') + SerializerBase.unregister_dict_to_class('bootstrapvz.common.exceptions.ManifestError') + SerializerBase.unregister_dict_to_class('bootstrapvz.common.exceptions.TaskListError') + SerializerBase.unregister_dict_to_class('bootstrapvz.common.exceptions.TaskError') def deserialize_manifest(classname, state): from bootstrapvz.base.manifest import Manifest - return Manifest(path=state['path'], data=state['data']) + manifest = Manifest.__new__(Manifest) + manifest.__setstate__(state) + return manifest def deserialize_bootstrapinfo(classname, state): @@ -24,3 +33,13 @@ def deserialize_bootstrapinfo(classname, state): bootstrap_info = BootstrapInformation.__new__(BootstrapInformation) bootstrap_info.__setstate__(state) return bootstrap_info + +deserialize_map = {'bootstrapvz.common.exceptions.ManifestError': bootstrapvz.common.exceptions.ManifestError, + 'bootstrapvz.common.exceptions.TaskListError': bootstrapvz.common.exceptions.TaskListError, + 'bootstrapvz.common.exceptions.TaskError': bootstrapvz.common.exceptions.TaskError, + } + + +def deserialize_exception(classname, data): + from Pyro4.util import SerializerBase + return SerializerBase.make_exception(deserialize_map[classname], data) diff --git a/bootstrapvz/remote/callback.py b/bootstrapvz/remote/callback.py index 25b197b..f6f1f6e 100644 --- a/bootstrapvz/remote/callback.py +++ b/bootstrapvz/remote/callback.py @@ -1,20 +1,19 @@ +import Pyro4 import logging + +Pyro4.config.REQUIRE_EXPOSE = True log = logging.getLogger(__name__) class CallbackServer(object): def __init__(self, listen_port, remote_port): - self.listen_port = listen_port - self.remote_port = remote_port - - def start(self, log_server): - import Pyro4 - self.daemon = Pyro4.Daemon(host='localhost', port=self.listen_port, - nathost='localhost', natport=self.remote_port, + self.daemon = Pyro4.Daemon(host='localhost', port=listen_port, + nathost='localhost', natport=remote_port, unixsocket=None) - self.daemon.register(log_server) + self.daemon.register(self) + def start(self): def serve(): self.daemon.requestLoop() from threading import Thread @@ -27,3 +26,13 @@ class CallbackServer(object): self.daemon.shutdown() if hasattr(self, 'thread'): self.thread.join() + + @Pyro4.expose + def handle_log(self, pickled_record): + import pickle + record = pickle.loads(pickled_record) + log = logging.getLogger() + record.extra = getattr(record, 'extra', {}) + record.extra['source'] = 'remote' + log.handle(record) + diff --git a/bootstrapvz/remote/log.py b/bootstrapvz/remote/log.py index 793ffea..fc7d66d 100644 --- a/bootstrapvz/remote/log.py +++ b/bootstrapvz/remote/log.py @@ -15,18 +15,9 @@ class LogForwarder(logging.Handler): if record.exc_info is not None: import traceback exc_type, exc_value, exc_traceback = record.exc_info - record.exc_info = traceback.print_exception(exc_type, exc_value, exc_traceback) + record.extra = getattr(record, 'extra', {}) + record.extra['traceback'] = traceback.format_exception(exc_type, exc_value, exc_traceback) + record.exc_info = None # TODO: Use serpent instead import pickle - self.server.handle(pickle.dumps(record)) - - -class LogServer(object): - - def handle(self, pickled_record): - import pickle - record = pickle.loads(pickled_record) - log = logging.getLogger() - record.extra = getattr(record, 'extra', {}) - record.extra['source'] = 'remote' - log.handle(record) + self.server.handle_log(pickle.dumps(record)) diff --git a/bootstrapvz/remote/main.py b/bootstrapvz/remote/main.py index 0289b15..b038dd3 100644 --- a/bootstrapvz/remote/main.py +++ b/bootstrapvz/remote/main.py @@ -82,13 +82,11 @@ def run(manifest, build_server, debug=False, dry_run=False): from callback import CallbackServer callback_server = CallbackServer(listen_port=build_server.local_callback_port, remote_port=build_server.remote_callback_port) - from log import LogServer - log_server = LogServer() try: # Start the callback server (in a background thread) - callback_server.start(log_server) + callback_server.start() # Tell the RPC daemon about the callback server - connection.set_log_server(log_server) + connection.set_callback_server(callback_server) # Everything has been set up, begin the bootstrapping process bootstrap_info = connection.run(manifest, diff --git a/bootstrapvz/remote/server.py b/bootstrapvz/remote/server.py index 2d43f44..fdd11c6 100644 --- a/bootstrapvz/remote/server.py +++ b/bootstrapvz/remote/server.py @@ -56,9 +56,10 @@ class Server(object): return run(*args, **kwargs) @Pyro4.expose - def set_log_server(self, server): - self.log_forwarder.set_server(server) - log.debug('Successfully set the log forwarding server') + def set_callback_server(self, server): + self.callback_server = server + self.log_forwarder.set_server(self.callback_server) + log.debug('Forwarding logs to the callback server now') @Pyro4.expose def ping(self):