update_manager: make application package updates generic

This ignores an attempt to update packages if system updates are disabled and opens the possibility for supporting updates for other linux distributions.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2021-07-07 18:07:36 -04:00
parent 74630f933a
commit b6cd19d6ef
2 changed files with 48 additions and 17 deletions

View File

@ -194,18 +194,13 @@ class AppDeploy(BaseDeploy):
return prev_hash != cur_hash
async def _install_packages(self, package_list: List[str]) -> None:
pkgs = " ".join(package_list)
apt_cmd = self.cmd_helper.get_system_update_command()
self.notify_status("Installing system dependencies...")
# Install packages with apt-get
try:
await self.cmd_helper.run_cmd(
f"{apt_cmd} update", timeout=300., notify=True)
await self.cmd_helper.run_cmd(
f"{apt_cmd} install --yes {pkgs}", timeout=3600.,
notify=True)
await self.cmd_helper.install_packages(
package_list, timeout=3600., notify=True)
except Exception:
self.log_exc("Error updating packages via apt-get")
self.log_exc("Error updating packages")
return
async def _update_virtualenv(self,

View File

@ -53,7 +53,6 @@ SUPPLEMENTAL_CFG_PATH = os.path.join(
os.path.dirname(__file__), "update_manager.conf")
KLIPPER_DEFAULT_PATH = os.path.expanduser("~/klipper")
KLIPPER_DEFAULT_EXEC = os.path.expanduser("~/klippy-env/bin/python")
APT_CMD = "sudo DEBIAN_FRONTEND=noninteractive apt-get"
# Check To see if Updates are necessary each hour
UPDATE_REFRESH_INTERVAL_MS = 3600000
@ -452,6 +451,7 @@ class CommandHelper:
shell_cmd: SCMDComp = self.server.lookup_component('shell_command')
self.scmd_error = shell_cmd.error
self.build_shell_command = shell_cmd.build_shell_command
self.pkg_updater: Optional[PackageDeploy] = None
AsyncHTTPClient.configure(None, defaults=dict(user_agent="Moonraker"))
self.http_client = AsyncHTTPClient()
@ -495,6 +495,9 @@ class CommandHelper:
def is_update_busy(self) -> bool:
return self.cur_update_app is not None
def set_package_updater(self, updater: PackageDeploy) -> None:
self.pkg_updater = updater
def get_rate_limit_stats(self) -> Dict[str, Any]:
return {
'github_rate_limit': self.gh_rate_limit,
@ -704,8 +707,13 @@ class CommandHelper:
self.server.send_event(
"update_manager:update_response", notification)
def get_system_update_command(self) -> str:
return APT_CMD
async def install_packages(self,
package_list: List[str],
**kwargs
) -> None:
if self.pkg_updater is None:
return
await self.pkg_updater.install_packages(package_list, **kwargs)
def close(self) -> None:
self.http_client.close()
@ -771,13 +779,17 @@ class StreamingDownload:
self.busy_evt.set()
class PackageDeploy(BaseDeploy):
APT_CMD = "sudo DEBIAN_FRONTEND=noninteractive apt-get"
def __init__(self,
config: ConfigHelper,
cmd_helper: CommandHelper
) -> None:
super().__init__(config, cmd_helper)
cmd_helper.set_package_updater(self)
self.available_packages: List[str] = []
self.refresh_evt: Optional[asyncio.Event] = None
# Initialze to current time so an update is not performed on init
self.last_apt_update_time: float = time.time()
self.mutex: asyncio.Lock = asyncio.Lock()
async def refresh(self, fetch_packages: bool = True) -> None:
@ -788,9 +800,7 @@ class PackageDeploy(BaseDeploy):
async with self.mutex:
self.refresh_evt = asyncio.Event()
try:
if fetch_packages:
await self.cmd_helper.run_cmd(
f"{APT_CMD} update", timeout=300., retries=3)
await self._update_apt(force=fetch_packages)
res = await self.cmd_helper.run_cmd_with_response(
"apt list --upgradable", timeout=60.)
pkg_list = [p.strip() for p in res.split("\n") if p.strip()]
@ -809,18 +819,44 @@ class PackageDeploy(BaseDeploy):
async def update(self) -> None:
async with self.mutex:
if not self.available_packages:
return
self.cmd_helper.notify_update_response("Updating packages...")
try:
await self._update_apt(force=True, notify=True)
await self.cmd_helper.run_cmd(
f"{APT_CMD} update", timeout=300., notify=True)
await self.cmd_helper.run_cmd(
f"{APT_CMD} upgrade --yes", timeout=3600., notify=True)
f"{self.APT_CMD} upgrade --yes", timeout=3600.,
notify=True)
except Exception:
raise self.server.error("Error updating system packages")
self.available_packages = []
self.cmd_helper.notify_update_response(
"Package update finished...", is_complete=True)
async def _update_apt(self,
force: bool = False,
notify: bool = False
) -> None:
curtime = time.time()
if force or curtime > self.last_apt_update_time + 3600.:
# Don't update if a request was done within the last hour
await self.cmd_helper.run_cmd(
f"{self.APT_CMD} update", timeout=300., notify=notify)
self.last_apt_update_time = time.time()
async def install_packages(self,
package_list: List[str],
**kwargs
) -> None:
timeout: float = kwargs.get('timeout', 300.)
retries: int = kwargs.get('retries', 3)
notify: bool = kwargs.get('notify', False)
pkgs = " ".join(package_list)
await self._update_apt(notify=notify)
await self.cmd_helper.run_cmd(
f"{self.APT_CMD} install --yes {pkgs}", timeout=timeout,
retries=retries, notify=notify)
def get_update_status(self) -> Dict[str, Any]:
return {
'package_count': len(self.available_packages),