update_manager: add support for extensions
While use of "unofficial" klippy extras an moonraker components is not officially supported, there is no harm in facilitating updates for these extensions in the update manager. This adds configuration which will restart either moonraker or klipper after an extension is updated. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
16737d086d
commit
c8042a5700
|
@ -9,6 +9,7 @@ import pathlib
|
|||
import shutil
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
from .base_deploy import BaseDeploy
|
||||
|
||||
# Annotation imports
|
||||
|
@ -79,8 +80,29 @@ class AppDeploy(BaseDeploy):
|
|||
self.venv_args = config.get('venv_args', None)
|
||||
|
||||
self.info_tags: List[str] = config.getlist("info_tags", [])
|
||||
self.is_service = config.getboolean("is_system_service", True)
|
||||
|
||||
self.managed_services: List[str] = []
|
||||
svc_default = []
|
||||
if config.getboolean("is_system_service", True):
|
||||
svc_default.append(self.name)
|
||||
svc_choices = [self.name, "klipper", "moonraker"]
|
||||
services: List[str] = config.getlist(
|
||||
"managed_services", svc_default, separator=None
|
||||
)
|
||||
for svc in services:
|
||||
if svc not in svc_choices:
|
||||
raw = " ".join(services)
|
||||
self.server.add_warning(
|
||||
f"[{config.get_name()}]: Option 'restart_action: {raw}' "
|
||||
f"contains an invalid value '{svc}'. All values must be "
|
||||
f"one of the following choices: {svc_choices}"
|
||||
)
|
||||
break
|
||||
for svc in svc_choices:
|
||||
if svc in services and svc not in self.managed_services:
|
||||
self.managed_services.append(svc)
|
||||
logging.debug(
|
||||
f"Extension {self.name} managed services: {self.managed_services}"
|
||||
)
|
||||
# We need to fetch all potential options for an Application. Not
|
||||
# all options apply to each subtype, however we can't limit the
|
||||
# options in children if we want to switch between channels and
|
||||
|
@ -167,25 +189,30 @@ class AppDeploy(BaseDeploy):
|
|||
raise NotImplementedError
|
||||
|
||||
async def restart_service(self):
|
||||
if not self.is_service:
|
||||
self.notify_status(
|
||||
"Application not configured as service, skipping restart")
|
||||
if not self.managed_services:
|
||||
return
|
||||
if self.name == "moonraker":
|
||||
# Launch restart async so the request can return
|
||||
# before the server restarts
|
||||
event_loop = self.server.get_event_loop()
|
||||
event_loop.delay_callback(.1, self._do_restart)
|
||||
else:
|
||||
await self._do_restart()
|
||||
is_full = self.cmd_helper.is_full_update()
|
||||
for svc in self.managed_services:
|
||||
if is_full and svc != self.name:
|
||||
self.notify_status(f"Service {svc} restart postponed...")
|
||||
self.cmd_helper.add_pending_restart(svc)
|
||||
continue
|
||||
self.cmd_helper.remove_pending_restart(svc)
|
||||
self.notify_status(f"Restarting service {svc}...")
|
||||
if svc == "moonraker":
|
||||
# Launch restart async so the request can return
|
||||
# before the server restarts
|
||||
event_loop = self.server.get_event_loop()
|
||||
event_loop.delay_callback(.1, self._do_restart, svc)
|
||||
else:
|
||||
await self._do_restart(svc)
|
||||
|
||||
async def _do_restart(self) -> None:
|
||||
self.notify_status("Restarting Service...")
|
||||
async def _do_restart(self, svc_name: str) -> None:
|
||||
machine: Machine = self.server.lookup_component("machine")
|
||||
try:
|
||||
await machine.do_service_action("restart", self.name)
|
||||
await machine.do_service_action("restart", svc_name)
|
||||
except Exception:
|
||||
if self.name == "moonraker":
|
||||
if svc_name == "moonraker":
|
||||
# We will always get an error when restarting moonraker
|
||||
# from within the child process, so ignore it
|
||||
return
|
||||
|
|
|
@ -27,6 +27,7 @@ from typing import (
|
|||
Any,
|
||||
Awaitable,
|
||||
Optional,
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
|
@ -324,10 +325,13 @@ class UpdateManager:
|
|||
kupdater = self.updaters.get('klipper')
|
||||
if isinstance(kupdater, AppDeploy):
|
||||
self.klippy_identified_evt = asyncio.Event()
|
||||
klippy_updated = True
|
||||
check_restart = True
|
||||
if not await self._check_need_reinstall(app_name):
|
||||
klippy_updated = await kupdater.update()
|
||||
if klippy_updated:
|
||||
check_restart = await kupdater.update()
|
||||
if self.cmd_helper.needs_service_restart(app_name):
|
||||
await kupdater.restart_service()
|
||||
check_restart = True
|
||||
if check_restart:
|
||||
self.cmd_helper.notify_update_response(
|
||||
"Waiting for Klippy to reconnect (this may take"
|
||||
" up to 2 minutes)...")
|
||||
|
@ -344,8 +348,11 @@ class UpdateManager:
|
|||
|
||||
# Update Moonraker
|
||||
app_name = 'moonraker'
|
||||
moon_updater = cast(AppDeploy, self.updaters["moonraker"])
|
||||
if not await self._check_need_reinstall(app_name):
|
||||
await self.updaters['moonraker'].update()
|
||||
await moon_updater.update()
|
||||
if self.cmd_helper.needs_service_restart(app_name):
|
||||
await moon_updater.restart_service()
|
||||
self.cmd_helper.set_full_complete(True)
|
||||
self.cmd_helper.notify_update_response(
|
||||
"Full Update Complete", is_complete=True)
|
||||
|
@ -490,6 +497,7 @@ class CommandHelper:
|
|||
self.cur_update_id: Optional[int] = None
|
||||
self.full_update: bool = False
|
||||
self.full_complete: bool = False
|
||||
self.pending_service_restarts: Set[str] = set()
|
||||
|
||||
def get_server(self) -> Server:
|
||||
return self.server
|
||||
|
@ -511,10 +519,18 @@ class CommandHelper:
|
|||
self.cur_update_id = uid
|
||||
self.full_update = app == "full"
|
||||
self.full_complete = not self.full_update
|
||||
self.pending_service_restarts.clear()
|
||||
|
||||
def is_full_update(self) -> bool:
|
||||
return self.full_update
|
||||
|
||||
def add_pending_restart(self, svc_name: str) -> None:
|
||||
self.pending_service_restarts.add(svc_name)
|
||||
|
||||
def remove_pending_restart(self, svc_name: str) -> None:
|
||||
if svc_name in self.pending_service_restarts:
|
||||
self.pending_service_restarts.remove(svc_name)
|
||||
|
||||
def set_full_complete(self, complete: bool = False):
|
||||
self.full_complete = complete
|
||||
|
||||
|
@ -522,6 +538,10 @@ class CommandHelper:
|
|||
self.cur_update_app = self.cur_update_id = None
|
||||
self.full_update = False
|
||||
self.full_complete = False
|
||||
self.pending_service_restarts.clear()
|
||||
|
||||
def needs_service_restart(self, svc_name: str) -> bool:
|
||||
return svc_name in self.pending_service_restarts
|
||||
|
||||
def is_app_updating(self, app_name: str) -> bool:
|
||||
return self.cur_update_app == app_name
|
||||
|
|
Loading…
Reference in New Issue