moonraker: don't crash the server if an optional plugin fails to import

The server can still operate and be used to fetch the logs if a plugin fails to load.  Add a 'failed_plugins' field to the /server/info response so clients can notify users that this plugin failed to load.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Arksine 2021-01-06 12:32:26 -05:00
parent f1a75117db
commit d1388080c4
1 changed files with 6 additions and 2 deletions

View File

@ -64,6 +64,7 @@ class Server:
self.init_attempts = 0 self.init_attempts = 0
self.klippy_state = "disconnected" self.klippy_state = "disconnected"
self.subscriptions = {} self.subscriptions = {}
self.failed_plugins = []
# Server/IOLoop # Server/IOLoop
self.server_running = False self.server_running = False
@ -132,11 +133,12 @@ class Server:
if not os.path.exists(mod_path): if not os.path.exists(mod_path):
msg = f"Plugin ({plugin_name}) does not exist" msg = f"Plugin ({plugin_name}) does not exist"
logging.info(msg) logging.info(msg)
self.failed_plugins.append(plugin_name)
if default == Sentinel: if default == Sentinel:
raise ServerError(msg) raise ServerError(msg)
return default return default
module = importlib.import_module("plugins." + plugin_name)
try: try:
module = importlib.import_module("plugins." + plugin_name)
func_name = "load_plugin" func_name = "load_plugin"
if hasattr(module, "load_plugin_multi"): if hasattr(module, "load_plugin_multi"):
func_name = "load_plugin_multi" func_name = "load_plugin_multi"
@ -147,6 +149,7 @@ class Server:
except Exception: except Exception:
msg = f"Unable to load plugin ({plugin_name})" msg = f"Unable to load plugin ({plugin_name})"
logging.exception(msg) logging.exception(msg)
self.failed_plugins.append(plugin_name)
if default == Sentinel: if default == Sentinel:
raise ServerError(msg) raise ServerError(msg)
return default return default
@ -464,7 +467,8 @@ class Server:
return { return {
'klippy_connected': self.klippy_connection.is_connected(), 'klippy_connected': self.klippy_connection.is_connected(),
'klippy_state': self.klippy_state, 'klippy_state': self.klippy_state,
'plugins': list(self.plugins.keys())} 'plugins': list(self.plugins.keys()),
'failed_plugins': self.failed_plugins}
class KlippyConnection: class KlippyConnection:
def __init__(self, on_recd, on_close): def __init__(self, on_recd, on_close):