From 4915896099d123c8f7a6d5d2e4d584630177677c Mon Sep 17 00:00:00 2001 From: dw-0 Date: Thu, 21 Dec 2023 22:53:41 +0100 Subject: [PATCH] feat(Mainsail): remove Mainsail Signed-off-by: Dominik Willner --- kiauh/core/menus/remove_menu.py | 6 +- kiauh/modules/mainsail/mainsail_remove.py | 150 ++++++++++++++++++ kiauh/modules/mainsail/mainsail_utils.py | 2 + kiauh/modules/mainsail/menus/__init__.py | 0 .../mainsail/menus/mainsail_remove_menu.py | 121 ++++++++++++++ kiauh/utils/filesystem_utils.py | 26 +++ 6 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 kiauh/modules/mainsail/mainsail_remove.py create mode 100644 kiauh/modules/mainsail/menus/__init__.py create mode 100644 kiauh/modules/mainsail/menus/mainsail_remove_menu.py create mode 100644 kiauh/utils/filesystem_utils.py diff --git a/kiauh/core/menus/remove_menu.py b/kiauh/core/menus/remove_menu.py index 1271557..4082c8f 100644 --- a/kiauh/core/menus/remove_menu.py +++ b/kiauh/core/menus/remove_menu.py @@ -14,6 +14,8 @@ import textwrap from kiauh.core.menus import BACK_FOOTER from kiauh.core.menus.base_menu import BaseMenu from kiauh.modules.klipper import klipper_setup +from kiauh.modules.mainsail import mainsail_setup +from kiauh.modules.mainsail.menus.mainsail_remove_menu import MainsailRemoveMenu from kiauh.modules.moonraker import moonraker_setup from kiauh.utils.constants import COLOR_RED, RESET_FORMAT @@ -26,7 +28,7 @@ class RemoveMenu(BaseMenu): options={ 1: self.remove_klipper, 2: self.remove_moonraker, - 3: self.remove_mainsail, + 3: MainsailRemoveMenu, 4: self.remove_mainsail_config, 5: self.remove_fluidd, 6: self.remove_fluidd_config, @@ -77,7 +79,7 @@ class RemoveMenu(BaseMenu): moonraker_setup.run_moonraker_setup(install=False) def remove_mainsail(self): - print("remove_mainsail") + mainsail_setup.run_mainsail_removal() def remove_mainsail_config(self): print("remove_mainsail_config") diff --git a/kiauh/modules/mainsail/mainsail_remove.py b/kiauh/modules/mainsail/mainsail_remove.py new file mode 100644 index 0000000..525ad3f --- /dev/null +++ b/kiauh/modules/mainsail/mainsail_remove.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 + +# ======================================================================= # +# Copyright (C) 2020 - 2023 Dominik Willner # +# # +# This file is part of KIAUH - Klipper Installation And Update Helper # +# https://github.com/dw-0/kiauh # +# # +# This file may be distributed under the terms of the GNU GPLv3 license # +# ======================================================================= # + + +import shutil +import subprocess +from pathlib import Path + +from kiauh.core.config_manager.config_manager import ConfigManager +from kiauh.core.instance_manager.instance_manager import InstanceManager +from kiauh.modules.klipper.klipper import Klipper +from kiauh.modules.mainsail import MAINSAIL_DIR, MAINSAIL_CONFIG_DIR +from kiauh.modules.mainsail.mainsail_utils import backup_config_json +from kiauh.modules.moonraker.moonraker import Moonraker +from kiauh.utils import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED +from kiauh.utils.filesystem_utils import remove_file +from kiauh.utils.logger import Logger + + +def run_mainsail_removal( + remove_mainsail: bool, + remove_ms_config: bool, + backup_ms_config_json: bool, + remove_mr_updater_section: bool, + remove_msc_printer_cfg_include: bool, +) -> None: + if backup_ms_config_json: + backup_config_json() + if remove_mainsail: + remove_mainsail_dir() + remove_nginx_config() + remove_nginx_logs() + if remove_mr_updater_section: + remove_updater_section("update_manager mainsail") + if remove_ms_config: + remove_ms_config_dir() + if remove_mr_updater_section: + remove_updater_section("update_manager mainsail-config") + if remove_msc_printer_cfg_include: + remove_printer_cfg_include() + + +def remove_mainsail_dir() -> None: + Logger.print_status("Removing Mainsail ...") + if not Path(MAINSAIL_DIR).exists(): + Logger.print_info(f"'{MAINSAIL_DIR}' does not exist. Skipping ...") + return + + try: + shutil.rmtree(MAINSAIL_DIR) + except OSError as e: + Logger.print_error(f"Unable to delete '{MAINSAIL_DIR}':\n{e}") + + +def remove_nginx_config() -> None: + Logger.print_status("Removing Mainsails NGINX config ...") + try: + remove_file(Path(NGINX_SITES_AVAILABLE).joinpath("mainsail"), True) + remove_file(Path(NGINX_SITES_ENABLED).joinpath("mainsail"), True) + + except subprocess.CalledProcessError as e: + log = f"Unable to remove Mainsail NGINX config:\n{e.stderr.decode()}" + Logger.print_error(log) + + +def remove_nginx_logs() -> None: + Logger.print_status("Removing Mainsails NGINX logs ...") + try: + remove_file(Path("/var/log/nginx/mainsail-access.log"), True) + remove_file(Path("/var/log/nginx/mainsail-error.log"), True) + + im = InstanceManager(Klipper) + if not im.instances: + return + + for instance in im.instances: + remove_file(Path(instance.log_dir).joinpath("mainsail-access.log")) + remove_file(Path(instance.log_dir).joinpath("mainsail-error.log")) + + except (OSError, subprocess.CalledProcessError) as e: + Logger.print_error(f"Unable to NGINX logs:\n{e}") + + +def remove_updater_section(name: str) -> None: + Logger.print_status("Remove updater section from moonraker.conf ...") + im = InstanceManager(Moonraker) + if not im.instances: + Logger.print_info("Moonraker not installed. Skipping ...") + return + + for instance in im.instances: + log = f"Remove section '{name}' in '{instance.cfg_file}' ..." + Logger.print_status(log) + + if not Path(instance.cfg_file).exists(): + Logger.print_info("Section not present. Skipping ...") + continue + + cm = ConfigManager(instance.cfg_file) + cm.read_config() + if not cm.config.has_section(name): + Logger.print_info("Section not present. Skipped ...") + continue + + cm.config.remove_section(name) + cm.write_config() + + +def remove_ms_config_dir() -> None: + Logger.print_status("Removing mainsail-config ...") + if not Path(MAINSAIL_CONFIG_DIR).exists(): + Logger.print_info(f"'{MAINSAIL_CONFIG_DIR}' does not exist. Skipping ...") + return + + try: + shutil.rmtree(MAINSAIL_CONFIG_DIR) + except OSError as e: + Logger.print_error(f"Unable to delete '{MAINSAIL_CONFIG_DIR}':\n{e}") + + +def remove_printer_cfg_include() -> None: + Logger.print_status("Remove mainsail-config include from printer.cfg ...") + im = InstanceManager(Klipper) + if not im.instances: + Logger.print_info("Klipper not installed. Skipping ...") + return + + for instance in im.instances: + log = f"Removing include from '{instance.cfg_file}' ..." + Logger.print_status(log) + + if not Path(instance.cfg_file).exists(): + continue + + cm = ConfigManager(instance.cfg_file) + cm.read_config() + if not cm.config.has_section("include mainsail.cfg"): + Logger.print_info("Section not present. Skipped ...") + continue + + cm.config.remove_section("include mainsail.cfg") + cm.write_config() diff --git a/kiauh/modules/mainsail/mainsail_utils.py b/kiauh/modules/mainsail/mainsail_utils.py index 92f7a61..4cfc9d5 100644 --- a/kiauh/modules/mainsail/mainsail_utils.py +++ b/kiauh/modules/mainsail/mainsail_utils.py @@ -20,6 +20,8 @@ from kiauh.modules.mainsail import MAINSAIL_CONFIG_JSON from kiauh.utils.logger import Logger +# TODO: give this method an optional target dir to backup to +# alteratively use the BackupManager for handling this task (probably best) def backup_config_json() -> None: try: Logger.print_status(f"Backup '{MAINSAIL_CONFIG_JSON}' ...") diff --git a/kiauh/modules/mainsail/menus/__init__.py b/kiauh/modules/mainsail/menus/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/kiauh/modules/mainsail/menus/mainsail_remove_menu.py b/kiauh/modules/mainsail/menus/mainsail_remove_menu.py new file mode 100644 index 0000000..fd56a60 --- /dev/null +++ b/kiauh/modules/mainsail/menus/mainsail_remove_menu.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 + +# ======================================================================= # +# Copyright (C) 2020 - 2023 Dominik Willner # +# # +# This file is part of KIAUH - Klipper Installation And Update Helper # +# https://github.com/dw-0/kiauh # +# # +# This file may be distributed under the terms of the GNU GPLv3 license # +# ======================================================================= # + +import textwrap + +from kiauh.core.menus import BACK_HELP_FOOTER +from kiauh.core.menus.base_menu import BaseMenu +from kiauh.modules.mainsail import mainsail_remove +from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN + + +class MainsailRemoveMenu(BaseMenu): + def __init__(self): + super().__init__( + header=False, + options={ + 0: self.toggle_all, + 1: self.toggle_remove_mainsail, + 2: self.toggle_remove_ms_config, + 3: self.toggle_backup_config_json, + 4: self.toggle_remove_updater_section, + 5: self.toggle_remove_printer_cfg_include, + 6: self.run_removal_process, + }, + footer_type=BACK_HELP_FOOTER, + ) + self.remove_mainsail = False + self.remove_ms_config = False + self.backup_config_json = False + self.remove_updater_section = False + self.remove_printer_cfg_include = False + + def print_menu(self) -> None: + header = " [ Remove Mainsail ] " + color = COLOR_RED + count = 62 - len(color) - len(RESET_FORMAT) + checked = f"[{COLOR_CYAN}x{RESET_FORMAT}]" + unchecked = "[ ]" + o1 = checked if self.remove_mainsail else unchecked + o2 = checked if self.remove_ms_config else unchecked + o3 = checked if self.backup_config_json else unchecked + o4 = checked if self.remove_updater_section else unchecked + o5 = checked if self.remove_printer_cfg_include else unchecked + menu = textwrap.dedent( + f""" + /=======================================================\\ + | {color}{header:~^{count}}{RESET_FORMAT} | + |-------------------------------------------------------| + | Enter a number and hit enter to select / deselect | + | the specific option for removal. | + |-------------------------------------------------------| + | 0) Everything | + |-------------------------------------------------------| + | 1) {o1} Remove Mainsail Web UI | + | 2) {o2} Remove mainsail-config | + | 3) {o3} Backup Mainsail config.json | + | | + | printer.cfg & moonraker.conf | + | 4) {o4} Remove Moonraker updater section | + | 5) {o5} Remove printer.cfg include | + |-------------------------------------------------------| + | 6) Start removal | + """ + )[1:] + print(menu, end="") + + def toggle_all(self) -> None: + self.remove_mainsail = True + self.remove_ms_config = True + self.backup_config_json = True + self.remove_updater_section = True + self.remove_printer_cfg_include = True + + def toggle_remove_mainsail(self) -> None: + self.remove_mainsail = not self.remove_mainsail + + def toggle_remove_ms_config(self) -> None: + self.remove_ms_config = not self.remove_ms_config + + def toggle_backup_config_json(self) -> None: + self.backup_config_json = not self.backup_config_json + + def toggle_remove_updater_section(self) -> None: + self.remove_updater_section = not self.remove_updater_section + + def toggle_remove_printer_cfg_include(self) -> None: + self.remove_printer_cfg_include = not self.remove_printer_cfg_include + + def run_removal_process(self) -> None: + if ( + not self.remove_mainsail + and not self.remove_ms_config + and not self.backup_config_json + and not self.remove_updater_section + and not self.remove_printer_cfg_include + ): + error = f"{COLOR_RED}Nothing selected! Select options to remove first.{RESET_FORMAT}" + print(error) + return + + mainsail_remove.run_mainsail_removal( + remove_mainsail=self.remove_mainsail, + remove_ms_config=self.remove_ms_config, + backup_ms_config_json=self.backup_config_json, + remove_mr_updater_section=self.remove_updater_section, + remove_msc_printer_cfg_include=self.remove_printer_cfg_include, + ) + + self.remove_mainsail = False + self.remove_ms_config = False + self.backup_config_json = False + self.remove_updater_section = False + self.remove_printer_cfg_include = False diff --git a/kiauh/utils/filesystem_utils.py b/kiauh/utils/filesystem_utils.py new file mode 100644 index 0000000..b89e939 --- /dev/null +++ b/kiauh/utils/filesystem_utils.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 + +# ======================================================================= # +# Copyright (C) 2020 - 2023 Dominik Willner # +# # +# This file is part of KIAUH - Klipper Installation And Update Helper # +# https://github.com/dw-0/kiauh # +# # +# This file may be distributed under the terms of the GNU GPLv3 license # +# ======================================================================= # + +import subprocess +from pathlib import Path + + +from kiauh.utils.logger import Logger + + +def remove_file(file_path: Path, sudo=False) -> None: + try: + command = f"{'sudo ' if sudo else ''}rm -f {file_path}" + subprocess.run(command, stderr=subprocess.PIPE, check=True, shell=True) + except subprocess.CalledProcessError as e: + log = f"Cannot remove file {file_path}: {e.stderr.decode()}" + Logger.print_error(log) + raise