diff --git a/moonraker/moonraker.py b/moonraker/moonraker.py index 469e17e..467c82d 100644 --- a/moonraker/moonraker.py +++ b/moonraker/moonraker.py @@ -13,7 +13,8 @@ import logging import json import confighelper import utils -from tornado import iostream +import asyncio +from tornado import iostream, gen from tornado.ioloop import IOLoop from tornado.util import TimeoutError from tornado.locks import Event @@ -69,6 +70,8 @@ class Server: self.register_endpoint( "/server/info", ['GET'], self._handle_info_request) + self.register_endpoint( + "/server/restart", ['POST'], self._handle_server_restart) # Setup remote methods accessable to Klippy. Note that all # registered remote methods should be of the notification type, @@ -155,6 +158,8 @@ class Server: # ***** Klippy Connection ***** async def _connect_klippy(self): + if not self.server_running: + return ret = await self.klippy_connection.connect(self.klippy_address) if not ret: self.ioloop.call_later(.25, self._connect_klippy) @@ -200,9 +205,12 @@ class Server: self.send_event("server:klippy_disconnect") if self.init_handle is not None: self.ioloop.remove_timeout(self.init_handle) - self.ioloop.call_later(.25, self._connect_klippy) + if self.server_running: + self.ioloop.call_later(.25, self._connect_klippy) async def _initialize(self): + if not self.server_running: + return await self._check_ready() await self._request_endpoints() # Subscribe to "webhooks" @@ -356,19 +364,21 @@ class Server: return result async def _stop_server(self): - # XXX - Currently this function is not used. - # Should I expose functionality to shutdown - # or restart the server, or simply remove this? - logging.info( - "Shutting Down Webserver") - for plugin in self.plugins: + self.server_running = False + for name, plugin in self.plugins.items(): if hasattr(plugin, "close"): - await plugin.close() + ret = plugin.close() + if asyncio.iscoroutine(ret): + await ret self.klippy_connection.close() - if self.server_running: - self.server_running = False - await self.moonraker_app.close() - self.ioloop.stop() + while self.klippy_state != "disconnected": + await gen.sleep(.1) + await self.moonraker_app.close() + self.ioloop.stop() + + async def _handle_server_restart(self, path, method, args): + self.ioloop.spawn_callback(self._stop_server) + return "ok" async def _handle_info_request(self, path, method, args): return { @@ -494,20 +504,29 @@ def main(): # Start IOLoop and Server io_loop = IOLoop.current() - try: - server = Server(cmd_line_args) - except Exception: - logging.exception("Moonraker Error") - ql.stop() - exit(1) - try: - server.start() - io_loop.start() - except Exception: - logging.exception("Server Running Error") + estatus = 0 + while True: + try: + server = Server(cmd_line_args) + except Exception: + logging.exception("Moonraker Error") + estatus = 1 + break + try: + server.start() + io_loop.start() + except Exception: + logging.exception("Server Running Error") + estatus = 1 + break + # Since we are running outside of the the server + # it is ok to use a blocking sleep here + time.sleep(.5) + logging.info("Attempting Server Restart...") io_loop.close(True) logging.info("Server Shutdown") ql.stop() + exit(estatus) if __name__ == '__main__':