From c8ab6edfddb7fff0db01914806529cec07b77992 Mon Sep 17 00:00:00 2001 From: Mikhail Sandakov Date: Mon, 22 Jul 2024 15:40:43 +0300 Subject: [PATCH] Verify that the Plesk database is functioning before attempting to collaborate on any Plesk extensions --- pleskdistup/actions/extensions.py | 36 ++++++++++++++++++++----------- pleskdistup/actions/plesk.py | 12 +++++++++-- pleskdistup/common/src/plesk.py | 15 +++++++++++++ 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/pleskdistup/actions/extensions.py b/pleskdistup/actions/extensions.py index 222acf3..1aef74a 100644 --- a/pleskdistup/actions/extensions.py +++ b/pleskdistup/actions/extensions.py @@ -146,21 +146,28 @@ def __init__(self) -> None: self.ext_name = "tuxcare-els" def _is_required(self) -> bool: - # If database is not ready, we can't be sure about installed extensions - if (not plesk.is_plesk_database_ready()): + try: + return self.ext_name in dict(plesk.list_installed_extensions()) + except plesk.PleskDatabaseIsDown: + # If database is not ready we will not be able to uninstall the extension anyway + log.warn("Mark the Tuxcare ELS extension uninstallation as unnecessary because the Plesk database isn't running") return False - return self.ext_name in dict(plesk.list_installed_extensions()) - def _prepare_action(self) -> action.ActionResult: - plesk.uninstall_extension(self.ext_name) + try: + plesk.uninstall_extension(self.ext_name) + except plesk.PleskDatabaseIsDown: + log.warn("Removing TuxCare ELS extension called when Plesk database is already down") return action.ActionResult() def _post_action(self) -> action.ActionResult: return action.ActionResult() def _revert_action(self) -> action.ActionResult: - plesk.install_extension(self.ext_name) + try: + plesk.install_extension(self.ext_name) + except plesk.PleskDatabaseIsDown: + log.warn("Re-installing TuxCare ELS extension called when Plesk database is still down") return action.ActionResult() def estimate_prepare_time(self) -> int: @@ -233,13 +240,16 @@ def description(self, val: str) -> None: raise NotImplementedError def _do_check(self) -> bool: - extensions = dict(plesk.list_installed_extensions()) - log.debug(f"Detected installed Plesk extensions: {extensions}") + try: + extensions = dict(plesk.list_installed_extensions()) + log.debug(f"Detected installed Plesk extensions: {extensions}") - self.installed_violations = set(extension for extension in self.installed if extension not in extensions) - log.debug(f"Missing required extensions: {self.installed_violations}") + self.installed_violations = set(extension for extension in self.installed if extension not in extensions) + log.debug(f"Missing required extensions: {self.installed_violations}") - self.not_installed_violations = set(extension for extension in self.not_installed if extension in extensions) - log.debug(f"Installed conflicting extensions: {self.not_installed_violations}") + self.not_installed_violations = set(extension for extension in self.not_installed if extension in extensions) + log.debug(f"Installed conflicting extensions: {self.not_installed_violations}") - return not self.installed_violations and not self.not_installed_violations + return not self.installed_violations and not self.not_installed_violations + except plesk.PleskDatabaseIsDown: + return True diff --git a/pleskdistup/actions/plesk.py b/pleskdistup/actions/plesk.py index b32cd91..fed8d45 100644 --- a/pleskdistup/actions/plesk.py +++ b/pleskdistup/actions/plesk.py @@ -237,7 +237,12 @@ def name(self): return res def _prepare_action(self) -> action.ActionResult: - installed_extensions = set(ext[0] for ext in plesk.list_installed_extensions()) + try: + installed_extensions = set(ext[0] for ext in plesk.list_installed_extensions()) + except plesk.PleskDatabaseIsDown: + log.warn("Plesk database is down, can't retrieve installed extensions") + installed_extensions = set() + log.debug(f"Currently installed extensions: {installed_extensions}") if installed_extensions: res_ext = installed_extensions @@ -262,7 +267,10 @@ def estimate_prepare_time(self) -> int: if self.extensions_to_update is not None: extnum = len(self.extensions_to_update) else: - extnum = len(set(ext[0] for ext in plesk.list_installed_extensions())) + try: + extnum = len(set(ext[0] for ext in plesk.list_installed_extensions())) + except plesk.PleskDatabaseIsDown: + extnum = 0 return 20 * extnum def estimate_post_time(self) -> int: diff --git a/pleskdistup/common/src/plesk.py b/pleskdistup/common/src/plesk.py index c3e700d..e41c6ed 100644 --- a/pleskdistup/common/src/plesk.py +++ b/pleskdistup/common/src/plesk.py @@ -114,6 +114,9 @@ def remove_conversion_flag(status_flag_path: str) -> None: def list_installed_extensions() -> typing.List[typing.Tuple[str, str]]: + if not is_plesk_database_ready(): + raise PleskDatabaseIsDown("retrieving installed extensions") + ext_info = subprocess.check_output(["/usr/sbin/plesk", "bin", "extension", "--list"], universal_newlines=True).splitlines() res: typing.List[typing.Tuple[str, str]] = [] for line in ext_info: @@ -124,10 +127,16 @@ def list_installed_extensions() -> typing.List[typing.Tuple[str, str]]: def install_extension(name: str) -> None: + if not is_plesk_database_ready(): + raise PleskDatabaseIsDown(f"extension {name!r} installation") + util.logged_check_call(["/usr/sbin/plesk", "bin", "extension", "--install", name]) def uninstall_extension(name: str) -> None: + if not is_plesk_database_ready(): + raise PleskDatabaseIsDown(f"extension {name!r} uninstallation") + util.logged_check_call(["/usr/sbin/plesk", "bin", "extension", "--uninstall", name]) @@ -198,6 +207,12 @@ def list_installed_components() -> typing.Dict[str, PleskComponent]: return res +class PleskDatabaseIsDown(Exception): + def __init__(self, message: str = ""): + self.message = f"Plesk database is not ready at: {message}" + super().__init__(self.message) + + def is_plesk_database_ready() -> bool: if mariadb.is_mariadb_installed(): return systemd.is_service_active("mariadb")