mirror of
https://github.com/dw-0/kiauh.git
synced 2025-12-23 15:53:36 +05:00
refactor(KIAUH): full refactor of client and client-config installation
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
@@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 #
|
|
||||||
# ======================================================================= #
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from core.backup_manager import BACKUP_ROOT_DIR
|
|
||||||
|
|
||||||
MODULE_PATH = Path(__file__).resolve().parent
|
|
||||||
FLUIDD_DIR = Path.home().joinpath("fluidd")
|
|
||||||
FLUIDD_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("fluidd-backups")
|
|
||||||
FLUIDD_CONFIG_DIR = Path.home().joinpath("fluidd-config")
|
|
||||||
FLUIDD_NGINX_CFG = Path("/etc/nginx/sites-enabled/fluidd")
|
|
||||||
FLUIDD_URL = "https://github.com/fluidd-core/fluidd/releases/latest/download/fluidd.zip"
|
|
||||||
FLUIDD_UNSTABLE_URL = (
|
|
||||||
"https://github.com/fluidd-core/fluidd/releases/download/%TAG%/fluidd.zip"
|
|
||||||
)
|
|
||||||
FLUIDD_CONFIG_REPO_URL = "https://github.com/fluidd-core/fluidd-config.git"
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
[update_manager fluidd-config]
|
|
||||||
type: git_repo
|
|
||||||
primary_branch: master
|
|
||||||
path: ~/fluidd-config
|
|
||||||
origin: https://github.com/fluidd-core/fluidd-config.git
|
|
||||||
managed_services: klipper
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
[update_manager fluidd]
|
|
||||||
type: web
|
|
||||||
channel: stable
|
|
||||||
repo: fluidd-core/fluidd
|
|
||||||
path: ~/fluidd
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 typing import List
|
|
||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
|
||||||
from components.fluidd import FLUIDD_DIR, FLUIDD_CONFIG_DIR
|
|
||||||
from components.moonraker.moonraker import Moonraker
|
|
||||||
from core.config_manager.config_manager import ConfigManager
|
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
|
||||||
from utils import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED
|
|
||||||
from utils.filesystem_utils import remove_file
|
|
||||||
from utils.logger import Logger
|
|
||||||
|
|
||||||
|
|
||||||
def run_fluidd_removal(
|
|
||||||
remove_fluidd: bool,
|
|
||||||
remove_fl_config: bool,
|
|
||||||
remove_mr_updater_section: bool,
|
|
||||||
remove_flc_printer_cfg_include: bool,
|
|
||||||
) -> None:
|
|
||||||
if remove_fluidd:
|
|
||||||
remove_fluidd_dir()
|
|
||||||
remove_nginx_config()
|
|
||||||
remove_nginx_logs()
|
|
||||||
if remove_mr_updater_section:
|
|
||||||
remove_updater_section("update_manager fluidd")
|
|
||||||
if remove_fl_config:
|
|
||||||
remove_fluidd_cfg_dir()
|
|
||||||
remove_fluidd_cfg_symlink()
|
|
||||||
if remove_mr_updater_section:
|
|
||||||
remove_updater_section("update_manager fluidd-config")
|
|
||||||
if remove_flc_printer_cfg_include:
|
|
||||||
remove_printer_cfg_include()
|
|
||||||
|
|
||||||
|
|
||||||
def remove_fluidd_dir() -> None:
|
|
||||||
Logger.print_status("Removing Fluidd ...")
|
|
||||||
if not FLUIDD_DIR.exists():
|
|
||||||
Logger.print_info(f"'{FLUIDD_DIR}' does not exist. Skipping ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
shutil.rmtree(FLUIDD_DIR)
|
|
||||||
except OSError as e:
|
|
||||||
Logger.print_error(f"Unable to delete '{FLUIDD_DIR}':\n{e}")
|
|
||||||
|
|
||||||
|
|
||||||
def remove_nginx_config() -> None:
|
|
||||||
Logger.print_status("Removing Fluidd NGINX config ...")
|
|
||||||
try:
|
|
||||||
remove_file(NGINX_SITES_AVAILABLE.joinpath("fluidd"), True)
|
|
||||||
remove_file(NGINX_SITES_ENABLED.joinpath("fluidd"), True)
|
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
log = f"Unable to remove Fluidd NGINX config:\n{e.stderr.decode()}"
|
|
||||||
Logger.print_error(log)
|
|
||||||
|
|
||||||
|
|
||||||
def remove_nginx_logs() -> None:
|
|
||||||
Logger.print_status("Removing Fluidd NGINX logs ...")
|
|
||||||
try:
|
|
||||||
remove_file(Path("/var/log/nginx/fluidd-access.log"), True)
|
|
||||||
remove_file(Path("/var/log/nginx/fluidd-error.log"), True)
|
|
||||||
|
|
||||||
im = InstanceManager(Klipper)
|
|
||||||
instances: List[Klipper] = im.instances
|
|
||||||
if not instances:
|
|
||||||
return
|
|
||||||
|
|
||||||
for instance in instances:
|
|
||||||
remove_file(instance.log_dir.joinpath("fluidd-access.log"))
|
|
||||||
remove_file(instance.log_dir.joinpath("fluidd-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)
|
|
||||||
instances: List[Moonraker] = im.instances
|
|
||||||
if not instances:
|
|
||||||
Logger.print_info("Moonraker not installed. Skipped ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
for instance in instances:
|
|
||||||
Logger.print_status(f"Remove section '{name}' in '{instance.cfg_file}' ...")
|
|
||||||
|
|
||||||
if not instance.cfg_file.is_file():
|
|
||||||
Logger.print_info(f"'{instance.cfg_file}' does not exist. Skipped ...")
|
|
||||||
continue
|
|
||||||
|
|
||||||
cm = ConfigManager(instance.cfg_file)
|
|
||||||
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_fluidd_cfg_dir() -> None:
|
|
||||||
Logger.print_status("Removing fluidd-config ...")
|
|
||||||
if not FLUIDD_CONFIG_DIR.exists():
|
|
||||||
Logger.print_info(f"'{FLUIDD_CONFIG_DIR}' does not exist. Skipping ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
shutil.rmtree(FLUIDD_CONFIG_DIR)
|
|
||||||
except OSError as e:
|
|
||||||
Logger.print_error(f"Unable to delete '{FLUIDD_CONFIG_DIR}':\n{e}")
|
|
||||||
|
|
||||||
|
|
||||||
def remove_fluidd_cfg_symlink() -> None:
|
|
||||||
Logger.print_status("Removing fluidd.cfg symlinks ...")
|
|
||||||
im = InstanceManager(Klipper)
|
|
||||||
instances: List[Klipper] = im.instances
|
|
||||||
for instance in instances:
|
|
||||||
Logger.print_status(f"Removing symlink from '{instance.cfg_file}' ...")
|
|
||||||
try:
|
|
||||||
remove_file(instance.cfg_dir.joinpath("fluidd.cfg"))
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
Logger.print_error("Failed to remove symlink!")
|
|
||||||
|
|
||||||
|
|
||||||
def remove_printer_cfg_include() -> None:
|
|
||||||
Logger.print_status("Remove fluidd-config include from printer.cfg ...")
|
|
||||||
im = InstanceManager(Klipper)
|
|
||||||
instances: List[Klipper] = im.instances
|
|
||||||
if not instances:
|
|
||||||
Logger.print_info("Klipper not installed. Skipping ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
for instance in instances:
|
|
||||||
log = f"Removing include from '{instance.cfg_file}' ..."
|
|
||||||
Logger.print_status(log)
|
|
||||||
|
|
||||||
if not instance.cfg_file.is_file():
|
|
||||||
continue
|
|
||||||
|
|
||||||
cm = ConfigManager(instance.cfg_file)
|
|
||||||
if not cm.config.has_section("include fluidd.cfg"):
|
|
||||||
Logger.print_info("Section not present. Skipped ...")
|
|
||||||
continue
|
|
||||||
|
|
||||||
cm.config.remove_section("include fluidd.cfg")
|
|
||||||
cm.write_config()
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 typing import List
|
|
||||||
|
|
||||||
from components.fluidd import (
|
|
||||||
FLUIDD_URL,
|
|
||||||
FLUIDD_CONFIG_REPO_URL,
|
|
||||||
FLUIDD_CONFIG_DIR,
|
|
||||||
FLUIDD_DIR,
|
|
||||||
MODULE_PATH,
|
|
||||||
)
|
|
||||||
from components.fluidd.fluidd_dialogs import (
|
|
||||||
print_fluidd_already_installed_dialog,
|
|
||||||
print_install_fluidd_config_dialog,
|
|
||||||
print_fluidd_port_select_dialog,
|
|
||||||
print_moonraker_not_found_dialog,
|
|
||||||
)
|
|
||||||
from components.fluidd.fluidd_utils import symlink_webui_nginx_log
|
|
||||||
from kiauh import KIAUH_CFG
|
|
||||||
from components.klipper.klipper import Klipper
|
|
||||||
from components.moonraker.moonraker import Moonraker
|
|
||||||
from core.config_manager.config_manager import ConfigManager
|
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
|
||||||
from core.repo_manager.repo_manager import RepoManager
|
|
||||||
from utils import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED
|
|
||||||
from utils.common import check_install_dependencies
|
|
||||||
from utils.filesystem_utils import (
|
|
||||||
unzip,
|
|
||||||
copy_upstream_nginx_cfg,
|
|
||||||
copy_common_vars_nginx_cfg,
|
|
||||||
create_nginx_cfg,
|
|
||||||
create_symlink,
|
|
||||||
remove_file,
|
|
||||||
read_ports_from_nginx_configs,
|
|
||||||
get_next_free_port, is_valid_port,
|
|
||||||
)
|
|
||||||
from utils.input_utils import get_confirm, get_number_input
|
|
||||||
from utils.logger import Logger
|
|
||||||
from utils.system_utils import (
|
|
||||||
download_file,
|
|
||||||
set_nginx_permissions,
|
|
||||||
get_ipv4_addr,
|
|
||||||
control_systemd_service,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def install_fluidd() -> None:
|
|
||||||
mr_im = InstanceManager(Moonraker)
|
|
||||||
mr_instances: List[Moonraker] = mr_im.instances
|
|
||||||
|
|
||||||
if not mr_instances:
|
|
||||||
print_moonraker_not_found_dialog()
|
|
||||||
if not get_confirm("Continue Fluidd installation?", allow_go_back=True):
|
|
||||||
return
|
|
||||||
|
|
||||||
if Path.home().joinpath("fluidd").exists():
|
|
||||||
print_fluidd_already_installed_dialog()
|
|
||||||
do_reinstall = get_confirm("Re-install Fluidd?", allow_go_back=True)
|
|
||||||
if not do_reinstall:
|
|
||||||
return
|
|
||||||
|
|
||||||
kl_im = InstanceManager(Klipper)
|
|
||||||
kl_instances = kl_im.instances
|
|
||||||
install_fl_config = False
|
|
||||||
if kl_instances:
|
|
||||||
print_install_fluidd_config_dialog()
|
|
||||||
question = "Download the recommended macros?"
|
|
||||||
install_fl_config = get_confirm(question, allow_go_back=False)
|
|
||||||
|
|
||||||
cm = ConfigManager(cfg_file=KIAUH_CFG)
|
|
||||||
fluidd_port = cm.get_value("fluidd", "port")
|
|
||||||
ports_in_use = read_ports_from_nginx_configs()
|
|
||||||
|
|
||||||
# check if configured port is a valid number and not in use already
|
|
||||||
valid_port = is_valid_port(fluidd_port, ports_in_use)
|
|
||||||
while not valid_port:
|
|
||||||
next_port = get_next_free_port(ports_in_use)
|
|
||||||
print_fluidd_port_select_dialog(next_port, ports_in_use)
|
|
||||||
fluidd_port = str(get_number_input(
|
|
||||||
"Configure Fluidd for port",
|
|
||||||
min_count=int(next_port),
|
|
||||||
default=next_port,
|
|
||||||
))
|
|
||||||
valid_port = is_valid_port(fluidd_port, ports_in_use)
|
|
||||||
|
|
||||||
check_install_dependencies(["nginx"])
|
|
||||||
|
|
||||||
try:
|
|
||||||
download_fluidd()
|
|
||||||
if mr_instances:
|
|
||||||
patch_moonraker_conf(
|
|
||||||
mr_instances,
|
|
||||||
"Fluidd",
|
|
||||||
"update_manager fluidd",
|
|
||||||
"fluidd-updater.conf",
|
|
||||||
)
|
|
||||||
mr_im.restart_all_instance()
|
|
||||||
if install_fl_config and kl_instances:
|
|
||||||
download_fluidd_cfg()
|
|
||||||
create_fluidd_cfg_symlink(kl_instances)
|
|
||||||
patch_moonraker_conf(
|
|
||||||
mr_instances,
|
|
||||||
"fluidd-config",
|
|
||||||
"update_manager fluidd-config",
|
|
||||||
"fluidd-config-updater.conf",
|
|
||||||
)
|
|
||||||
patch_printer_config(kl_instances)
|
|
||||||
kl_im.restart_all_instance()
|
|
||||||
|
|
||||||
copy_upstream_nginx_cfg()
|
|
||||||
copy_common_vars_nginx_cfg()
|
|
||||||
create_fluidd_nginx_cfg(fluidd_port)
|
|
||||||
if kl_instances:
|
|
||||||
symlink_webui_nginx_log(kl_instances)
|
|
||||||
control_systemd_service("nginx", "restart")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
Logger.print_error(f"Fluidd installation failed!\n{e}")
|
|
||||||
return
|
|
||||||
|
|
||||||
log = f"Open Fluidd now on: http://{get_ipv4_addr()}:{fluidd_port}"
|
|
||||||
Logger.print_ok("Fluidd installation complete!", start="\n")
|
|
||||||
Logger.print_ok(log, prefix=False, end="\n\n")
|
|
||||||
|
|
||||||
|
|
||||||
def download_fluidd() -> None:
|
|
||||||
try:
|
|
||||||
Logger.print_status("Downloading Fluidd ...")
|
|
||||||
target = Path.home().joinpath("fluidd.zip")
|
|
||||||
download_file(FLUIDD_URL, target, True)
|
|
||||||
Logger.print_ok("Download complete!")
|
|
||||||
|
|
||||||
Logger.print_status("Extracting fluidd.zip ...")
|
|
||||||
unzip(Path.home().joinpath("fluidd.zip"), FLUIDD_DIR)
|
|
||||||
target.unlink(missing_ok=True)
|
|
||||||
Logger.print_ok("OK!")
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
Logger.print_error("Downloading Fluidd failed!")
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def update_fluidd() -> None:
|
|
||||||
Logger.print_status("Updating Fluidd ...")
|
|
||||||
download_fluidd()
|
|
||||||
|
|
||||||
|
|
||||||
def download_fluidd_cfg() -> None:
|
|
||||||
try:
|
|
||||||
Logger.print_status("Downloading fluidd-config ...")
|
|
||||||
rm = RepoManager(FLUIDD_CONFIG_REPO_URL, target_dir=FLUIDD_CONFIG_DIR)
|
|
||||||
rm.clone_repo()
|
|
||||||
except Exception:
|
|
||||||
Logger.print_error("Downloading fluidd-config failed!")
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def create_fluidd_cfg_symlink(klipper_instances: List[Klipper]) -> None:
|
|
||||||
Logger.print_status("Create symlink of fluidd.cfg ...")
|
|
||||||
source = Path(FLUIDD_CONFIG_DIR, "fluidd.cfg")
|
|
||||||
for instance in klipper_instances:
|
|
||||||
target = instance.cfg_dir
|
|
||||||
Logger.print_status(f"Linking {source} to {target}")
|
|
||||||
try:
|
|
||||||
create_symlink(source, target)
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
Logger.print_error("Creating symlink failed!")
|
|
||||||
|
|
||||||
|
|
||||||
def create_fluidd_nginx_cfg(port: int) -> None:
|
|
||||||
root_dir = FLUIDD_DIR
|
|
||||||
source = NGINX_SITES_AVAILABLE.joinpath("fluidd")
|
|
||||||
target = NGINX_SITES_ENABLED.joinpath("fluidd")
|
|
||||||
try:
|
|
||||||
Logger.print_status("Creating NGINX config for Fluidd ...")
|
|
||||||
remove_file(Path("/etc/nginx/sites-enabled/default"), True)
|
|
||||||
create_nginx_cfg("fluidd", port, root_dir)
|
|
||||||
create_symlink(source, target, True)
|
|
||||||
set_nginx_permissions()
|
|
||||||
Logger.print_ok("NGINX config for Fluidd successfully created.")
|
|
||||||
except Exception:
|
|
||||||
Logger.print_error("Creating NGINX config for Fluidd failed!")
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: could be fully extracted, its webui agnostic, and used for mainsail and fluidd
|
|
||||||
def patch_moonraker_conf(
|
|
||||||
moonraker_instances: List[Moonraker],
|
|
||||||
name: str,
|
|
||||||
section_name: str,
|
|
||||||
template_file: str,
|
|
||||||
) -> None:
|
|
||||||
for instance in moonraker_instances:
|
|
||||||
cfg_file = instance.cfg_file
|
|
||||||
Logger.print_status(f"Add {name} update section to '{cfg_file}' ...")
|
|
||||||
|
|
||||||
if not Path(cfg_file).exists():
|
|
||||||
Logger.print_warn(f"'{cfg_file}' not found!")
|
|
||||||
return
|
|
||||||
|
|
||||||
cm = ConfigManager(cfg_file)
|
|
||||||
if cm.config.has_section(section_name):
|
|
||||||
Logger.print_info("Section already exist. Skipped ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
template = MODULE_PATH.joinpath("assets", template_file)
|
|
||||||
with open(template, "r") as t:
|
|
||||||
template_content = "\n"
|
|
||||||
template_content += t.read()
|
|
||||||
|
|
||||||
with open(cfg_file, "a") as f:
|
|
||||||
f.write(template_content)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: could be made fully webui agnostic and extracted, and used for mainsail and fluidd
|
|
||||||
def patch_printer_config(klipper_instances: List[Klipper]) -> None:
|
|
||||||
for instance in klipper_instances:
|
|
||||||
cfg_file = instance.cfg_file
|
|
||||||
Logger.print_status(f"Including fluidd-config in '{cfg_file}' ...")
|
|
||||||
|
|
||||||
if not Path(cfg_file).exists():
|
|
||||||
Logger.print_warn(f"'{cfg_file}' not found!")
|
|
||||||
return
|
|
||||||
|
|
||||||
cm = ConfigManager(cfg_file)
|
|
||||||
if cm.config.has_section("include fluidd.cfg"):
|
|
||||||
Logger.print_info("Section already exist. Skipped ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
with open(cfg_file, "a") as f:
|
|
||||||
f.write("\n[include fluidd.cfg]")
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 json
|
|
||||||
import urllib.request
|
|
||||||
from json import JSONDecodeError
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from components.fluidd import FLUIDD_DIR, FLUIDD_BACKUP_DIR
|
|
||||||
from components.klipper.klipper import Klipper
|
|
||||||
from core.backup_manager.backup_manager import BackupManager
|
|
||||||
from utils import NGINX_SITES_AVAILABLE, NGINX_CONFD
|
|
||||||
from utils.common import get_install_status_webui
|
|
||||||
from utils.logger import Logger
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: could be extracted and made generic
|
|
||||||
def get_fluidd_status() -> str:
|
|
||||||
return get_install_status_webui(
|
|
||||||
FLUIDD_DIR,
|
|
||||||
NGINX_SITES_AVAILABLE.joinpath("fluidd"),
|
|
||||||
NGINX_CONFD.joinpath("upstreams.conf"),
|
|
||||||
NGINX_CONFD.joinpath("common_vars.conf"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: could be extracted and made generic
|
|
||||||
def symlink_webui_nginx_log(klipper_instances: List[Klipper]) -> None:
|
|
||||||
Logger.print_status("Link NGINX logs into log directory ...")
|
|
||||||
access_log = Path("/var/log/nginx/fluidd-access.log")
|
|
||||||
error_log = Path("/var/log/nginx/fluidd-error.log")
|
|
||||||
|
|
||||||
for instance in klipper_instances:
|
|
||||||
desti_access = instance.log_dir.joinpath("fluidd-access.log")
|
|
||||||
if not desti_access.exists():
|
|
||||||
desti_access.symlink_to(access_log)
|
|
||||||
|
|
||||||
desti_error = instance.log_dir.joinpath("fluidd-error.log")
|
|
||||||
if not desti_error.exists():
|
|
||||||
desti_error.symlink_to(error_log)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: could be extracted and made generic
|
|
||||||
def get_fluidd_local_version() -> str:
|
|
||||||
relinfo_file = FLUIDD_DIR.joinpath("release_info.json")
|
|
||||||
if not relinfo_file.is_file():
|
|
||||||
return "-"
|
|
||||||
|
|
||||||
with open(relinfo_file, "r") as f:
|
|
||||||
return json.load(f)["version"]
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: could be extracted and made generic
|
|
||||||
def get_fluidd_remote_version() -> str:
|
|
||||||
url = "https://api.github.com/repos/fluidd-core/fluidd/tags"
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(url) as response:
|
|
||||||
data = json.loads(response.read())
|
|
||||||
return data[0]["name"]
|
|
||||||
except (JSONDecodeError, TypeError):
|
|
||||||
return "ERROR"
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: could be extracted and made generic
|
|
||||||
def backup_fluidd_data() -> None:
|
|
||||||
with open(FLUIDD_DIR.joinpath(".version"), "r") as v:
|
|
||||||
version = v.readlines()[0]
|
|
||||||
bm = BackupManager()
|
|
||||||
bm.backup_directory(f"fluidd-{version}", FLUIDD_DIR, FLUIDD_BACKUP_DIR)
|
|
||||||
bm.backup_file(NGINX_SITES_AVAILABLE.joinpath("fluidd"), FLUIDD_BACKUP_DIR)
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 components.fluidd import fluidd_remove
|
|
||||||
from core.menus import BACK_HELP_FOOTER
|
|
||||||
from core.menus.base_menu import BaseMenu
|
|
||||||
from utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
|
||||||
class FluiddRemoveMenu(BaseMenu):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__(
|
|
||||||
header=False,
|
|
||||||
options={
|
|
||||||
"0": self.toggle_all,
|
|
||||||
"1": self.toggle_remove_fluidd,
|
|
||||||
"2": self.toggle_remove_fl_config,
|
|
||||||
"3": self.toggle_remove_updater_section,
|
|
||||||
"4": self.toggle_remove_printer_cfg_include,
|
|
||||||
"5": self.run_removal_process,
|
|
||||||
},
|
|
||||||
footer_type=BACK_HELP_FOOTER,
|
|
||||||
)
|
|
||||||
self.remove_fluidd = False
|
|
||||||
self.remove_fl_config = False
|
|
||||||
self.remove_updater_section = False
|
|
||||||
self.remove_printer_cfg_include = False
|
|
||||||
|
|
||||||
def print_menu(self) -> None:
|
|
||||||
header = " [ Remove Fluidd ] "
|
|
||||||
color = COLOR_RED
|
|
||||||
count = 62 - len(color) - len(RESET_FORMAT)
|
|
||||||
checked = f"[{COLOR_CYAN}x{RESET_FORMAT}]"
|
|
||||||
unchecked = "[ ]"
|
|
||||||
o1 = checked if self.remove_fluidd else unchecked
|
|
||||||
o2 = checked if self.remove_fl_config else unchecked
|
|
||||||
o3 = checked if self.remove_updater_section else unchecked
|
|
||||||
o4 = 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) Select everything |
|
|
||||||
|-------------------------------------------------------|
|
|
||||||
| 1) {o1} Remove Fluidd |
|
|
||||||
| 2) {o2} Remove fluidd-config |
|
|
||||||
| |
|
|
||||||
| printer.cfg & moonraker.conf |
|
|
||||||
| 3) {o3} Remove Moonraker update section |
|
|
||||||
| 4) {o4} Remove printer.cfg include |
|
|
||||||
|-------------------------------------------------------|
|
|
||||||
| 5) Continue |
|
|
||||||
"""
|
|
||||||
)[1:]
|
|
||||||
print(menu, end="")
|
|
||||||
|
|
||||||
def toggle_all(self, **kwargs) -> None:
|
|
||||||
self.remove_fluidd = True
|
|
||||||
self.remove_fl_config = True
|
|
||||||
self.remove_updater_section = True
|
|
||||||
self.remove_printer_cfg_include = True
|
|
||||||
|
|
||||||
def toggle_remove_fluidd(self, **kwargs) -> None:
|
|
||||||
self.remove_fluidd = not self.remove_fluidd
|
|
||||||
|
|
||||||
def toggle_remove_fl_config(self, **kwargs) -> None:
|
|
||||||
self.remove_fl_config = not self.remove_fl_config
|
|
||||||
|
|
||||||
def toggle_remove_updater_section(self, **kwargs) -> None:
|
|
||||||
self.remove_updater_section = not self.remove_updater_section
|
|
||||||
|
|
||||||
def toggle_remove_printer_cfg_include(self, **kwargs) -> None:
|
|
||||||
self.remove_printer_cfg_include = not self.remove_printer_cfg_include
|
|
||||||
|
|
||||||
def run_removal_process(self, **kwargs) -> None:
|
|
||||||
if (
|
|
||||||
not self.remove_fluidd
|
|
||||||
and not self.remove_fl_config
|
|
||||||
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
|
|
||||||
|
|
||||||
fluidd_remove.run_fluidd_removal(
|
|
||||||
remove_fluidd=self.remove_fluidd,
|
|
||||||
remove_fl_config=self.remove_fl_config,
|
|
||||||
remove_mr_updater_section=self.remove_updater_section,
|
|
||||||
remove_flc_printer_cfg_include=self.remove_printer_cfg_include,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.remove_fluidd = False
|
|
||||||
self.remove_fl_config = False
|
|
||||||
self.remove_updater_section = False
|
|
||||||
self.remove_printer_cfg_include = False
|
|
||||||
@@ -28,7 +28,7 @@ class KlipperRemoveMenu(BaseMenu):
|
|||||||
"2": self.toggle_remove_klipper_dir,
|
"2": self.toggle_remove_klipper_dir,
|
||||||
"3": self.toggle_remove_klipper_env,
|
"3": self.toggle_remove_klipper_env,
|
||||||
"4": self.toggle_delete_klipper_logs,
|
"4": self.toggle_delete_klipper_logs,
|
||||||
"5": self.run_removal_process,
|
"c": self.run_removal_process,
|
||||||
},
|
},
|
||||||
footer_type=BACK_HELP_FOOTER,
|
footer_type=BACK_HELP_FOOTER,
|
||||||
)
|
)
|
||||||
@@ -62,7 +62,7 @@ class KlipperRemoveMenu(BaseMenu):
|
|||||||
| 3) {o3} Remove Python Environment |
|
| 3) {o3} Remove Python Environment |
|
||||||
| 4) {o4} Delete all Log-Files |
|
| 4) {o4} Delete all Log-Files |
|
||||||
|-------------------------------------------------------|
|
|-------------------------------------------------------|
|
||||||
| 5) Continue |
|
| C) Continue |
|
||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
print(menu, end="")
|
print(menu, end="")
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 #
|
|
||||||
# ======================================================================= #
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from core.backup_manager import BACKUP_ROOT_DIR
|
|
||||||
|
|
||||||
MODULE_PATH = Path(__file__).resolve().parent
|
|
||||||
MAINSAIL_DIR = Path.home().joinpath("mainsail")
|
|
||||||
MAINSAIL_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("mainsail-backups")
|
|
||||||
MAINSAIL_CONFIG_DIR = Path.home().joinpath("mainsail-config")
|
|
||||||
MAINSAIL_CONFIG_JSON = MAINSAIL_DIR.joinpath("config.json")
|
|
||||||
MAINSAIL_URL = (
|
|
||||||
"https://github.com/mainsail-crew/mainsail/releases/latest/download/mainsail.zip"
|
|
||||||
)
|
|
||||||
MAINSAIL_UNSTABLE_URL = (
|
|
||||||
"https://github.com/mainsail-crew/mainsail/releases/download/%TAG%/mainsail.zip"
|
|
||||||
)
|
|
||||||
MAINSAIL_CONFIG_REPO_URL = "https://github.com/mainsail-crew/mainsail-config.git"
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
[update_manager mainsail-config]
|
|
||||||
type: git_repo
|
|
||||||
primary_branch: master
|
|
||||||
path: ~/mainsail-config
|
|
||||||
origin: https://github.com/mainsail-crew/mainsail-config.git
|
|
||||||
managed_services: klipper
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
[update_manager mainsail]
|
|
||||||
type: web
|
|
||||||
channel: stable
|
|
||||||
repo: mainsail-crew/mainsail
|
|
||||||
path: ~/mainsail
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 core.menus.base_menu import print_back_footer
|
|
||||||
from utils.constants import RESET_FORMAT, COLOR_YELLOW, COLOR_CYAN
|
|
||||||
|
|
||||||
|
|
||||||
def print_moonraker_not_found_dialog():
|
|
||||||
line1 = f"{COLOR_YELLOW}WARNING:{RESET_FORMAT}"
|
|
||||||
line2 = f"{COLOR_YELLOW}No local Moonraker installation was found!{RESET_FORMAT}"
|
|
||||||
dialog = textwrap.dedent(
|
|
||||||
f"""
|
|
||||||
/=======================================================\\
|
|
||||||
| {line1:<63}|
|
|
||||||
| {line2:<63}|
|
|
||||||
|-------------------------------------------------------|
|
|
||||||
| It is possible to install Mainsail without a local |
|
|
||||||
| Moonraker installation. If you continue, you need to |
|
|
||||||
| make sure, that Moonraker is installed on another |
|
|
||||||
| machine in your network. Otherwise Mainsail will NOT |
|
|
||||||
| work correctly. |
|
|
||||||
"""
|
|
||||||
)[1:]
|
|
||||||
|
|
||||||
print(dialog, end="")
|
|
||||||
print_back_footer()
|
|
||||||
|
|
||||||
|
|
||||||
def print_mainsail_already_installed_dialog():
|
|
||||||
line1 = f"{COLOR_YELLOW}WARNING:{RESET_FORMAT}"
|
|
||||||
line2 = f"{COLOR_YELLOW}Mainsail seems to be already installed!{RESET_FORMAT}"
|
|
||||||
dialog = textwrap.dedent(
|
|
||||||
f"""
|
|
||||||
/=======================================================\\
|
|
||||||
| {line1:<63}|
|
|
||||||
| {line2:<63}|
|
|
||||||
|-------------------------------------------------------|
|
|
||||||
| If you continue, your current Mainsail installation |
|
|
||||||
| will be overwritten. You will not loose any printer |
|
|
||||||
| configurations and the Moonraker database will remain |
|
|
||||||
| untouched. |
|
|
||||||
"""
|
|
||||||
)[1:]
|
|
||||||
|
|
||||||
print(dialog, end="")
|
|
||||||
print_back_footer()
|
|
||||||
|
|
||||||
|
|
||||||
def print_install_mainsail_config_dialog():
|
|
||||||
dialog = textwrap.dedent(
|
|
||||||
f"""
|
|
||||||
/=======================================================\\
|
|
||||||
| It is recommended to use special macros in order to |
|
|
||||||
| have Mainsail fully functional and working. |
|
|
||||||
| |
|
|
||||||
| The recommended macros for Mainsail can be seen here: |
|
|
||||||
| https://github.com/mainsail-crew/mainsail-config |
|
|
||||||
| |
|
|
||||||
| If you already use these macros skip this step. |
|
|
||||||
| Otherwise you should consider to answer with 'Y' to |
|
|
||||||
| download the recommended macros. |
|
|
||||||
\\=======================================================/
|
|
||||||
"""
|
|
||||||
)[1:]
|
|
||||||
|
|
||||||
print(dialog, end="")
|
|
||||||
|
|
||||||
|
|
||||||
def print_mainsail_port_select_dialog(port: str):
|
|
||||||
port = f"{COLOR_CYAN}{port}{RESET_FORMAT}"
|
|
||||||
dialog = textwrap.dedent(
|
|
||||||
f"""
|
|
||||||
/=======================================================\\
|
|
||||||
| Please select the port, Mainsail should be served on. |
|
|
||||||
| If you are unsure what to select, hit Enter to apply |
|
|
||||||
| the suggested value of: {port:38} |
|
|
||||||
| |
|
|
||||||
| In case you need Mainsail to be served on a specific |
|
|
||||||
| port, you can set it now. Make sure the port is not |
|
|
||||||
| used by any other application on your system! |
|
|
||||||
\\=======================================================/
|
|
||||||
"""
|
|
||||||
)[1:]
|
|
||||||
|
|
||||||
print(dialog, end="")
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 typing import List
|
|
||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
|
||||||
from components.mainsail import MAINSAIL_DIR, MAINSAIL_CONFIG_DIR
|
|
||||||
from components.mainsail.mainsail_utils import backup_config_json
|
|
||||||
from components.moonraker.moonraker import Moonraker
|
|
||||||
from core.config_manager.config_manager import ConfigManager
|
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
|
||||||
from utils import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED
|
|
||||||
from utils.filesystem_utils import remove_file
|
|
||||||
from 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_mainsail_cfg_dir()
|
|
||||||
remove_mainsail_cfg_symlink()
|
|
||||||
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 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(NGINX_SITES_AVAILABLE.joinpath("mainsail"), True)
|
|
||||||
remove_file(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)
|
|
||||||
instances: List[Klipper] = im.instances
|
|
||||||
if not instances:
|
|
||||||
return
|
|
||||||
|
|
||||||
for instance in instances:
|
|
||||||
remove_file(instance.log_dir.joinpath("mainsail-access.log"))
|
|
||||||
remove_file(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)
|
|
||||||
instances: List[Moonraker] = im.instances
|
|
||||||
if not instances:
|
|
||||||
Logger.print_info("Moonraker not installed. Skipped ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
for instance in instances:
|
|
||||||
Logger.print_status(f"Remove section '{name}' in '{instance.cfg_file}' ...")
|
|
||||||
|
|
||||||
if not instance.cfg_file.is_file():
|
|
||||||
Logger.print_info(f"'{instance.cfg_file}' does not exist. Skipped ...")
|
|
||||||
continue
|
|
||||||
|
|
||||||
cm = ConfigManager(instance.cfg_file)
|
|
||||||
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_mainsail_cfg_dir() -> None:
|
|
||||||
Logger.print_status("Removing mainsail-config ...")
|
|
||||||
if not 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_mainsail_cfg_symlink() -> None:
|
|
||||||
Logger.print_status("Removing mainsail.cfg symlinks ...")
|
|
||||||
im = InstanceManager(Klipper)
|
|
||||||
instances: List[Klipper] = im.instances
|
|
||||||
for instance in instances:
|
|
||||||
Logger.print_status(f"Removing symlink from '{instance.cfg_file}' ...")
|
|
||||||
try:
|
|
||||||
remove_file(instance.cfg_dir.joinpath("mainsail.cfg"))
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
Logger.print_error("Failed to remove symlink!")
|
|
||||||
|
|
||||||
|
|
||||||
def remove_printer_cfg_include() -> None:
|
|
||||||
Logger.print_status("Remove mainsail-config include from printer.cfg ...")
|
|
||||||
im = InstanceManager(Klipper)
|
|
||||||
instances: List[Klipper] = im.instances
|
|
||||||
if not instances:
|
|
||||||
Logger.print_info("Klipper not installed. Skipping ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
for instance in instances:
|
|
||||||
log = f"Removing include from '{instance.cfg_file}' ..."
|
|
||||||
Logger.print_status(log)
|
|
||||||
|
|
||||||
if not instance.cfg_file.is_file():
|
|
||||||
continue
|
|
||||||
|
|
||||||
cm = ConfigManager(instance.cfg_file)
|
|
||||||
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()
|
|
||||||
@@ -1,256 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 typing import List
|
|
||||||
|
|
||||||
from kiauh import KIAUH_CFG
|
|
||||||
from components.klipper.klipper import Klipper
|
|
||||||
from components.mainsail import (
|
|
||||||
MAINSAIL_URL,
|
|
||||||
MAINSAIL_DIR,
|
|
||||||
MAINSAIL_CONFIG_DIR,
|
|
||||||
MAINSAIL_CONFIG_REPO_URL,
|
|
||||||
MODULE_PATH,
|
|
||||||
)
|
|
||||||
from components.mainsail.mainsail_dialogs import (
|
|
||||||
print_moonraker_not_found_dialog,
|
|
||||||
print_mainsail_already_installed_dialog,
|
|
||||||
print_install_mainsail_config_dialog,
|
|
||||||
print_mainsail_port_select_dialog,
|
|
||||||
)
|
|
||||||
from components.mainsail.mainsail_utils import (
|
|
||||||
restore_config_json,
|
|
||||||
enable_mainsail_remotemode,
|
|
||||||
backup_config_json,
|
|
||||||
symlink_webui_nginx_log,
|
|
||||||
)
|
|
||||||
from components.moonraker.moonraker import Moonraker
|
|
||||||
from core.config_manager.config_manager import ConfigManager
|
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
|
||||||
from core.repo_manager.repo_manager import RepoManager
|
|
||||||
from utils import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED
|
|
||||||
from utils.common import check_install_dependencies
|
|
||||||
from utils.filesystem_utils import (
|
|
||||||
unzip,
|
|
||||||
copy_upstream_nginx_cfg,
|
|
||||||
copy_common_vars_nginx_cfg,
|
|
||||||
create_nginx_cfg,
|
|
||||||
create_symlink,
|
|
||||||
remove_file,
|
|
||||||
)
|
|
||||||
from utils.input_utils import get_confirm, get_number_input
|
|
||||||
from utils.logger import Logger
|
|
||||||
from utils.system_utils import (
|
|
||||||
download_file,
|
|
||||||
set_nginx_permissions,
|
|
||||||
get_ipv4_addr,
|
|
||||||
control_systemd_service,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def install_mainsail() -> None:
|
|
||||||
mr_im = InstanceManager(Moonraker)
|
|
||||||
mr_instances: List[Moonraker] = mr_im.instances
|
|
||||||
|
|
||||||
enable_remotemode = False
|
|
||||||
if not mr_instances:
|
|
||||||
print_moonraker_not_found_dialog()
|
|
||||||
if not get_confirm("Continue Mainsail installation?", allow_go_back=True):
|
|
||||||
return
|
|
||||||
|
|
||||||
# if moonraker is not installed or multiple instances
|
|
||||||
# are installed we enable mainsails remote mode
|
|
||||||
if not mr_instances or len(mr_instances) > 1:
|
|
||||||
enable_remotemode = True
|
|
||||||
|
|
||||||
do_reinstall = False
|
|
||||||
if Path.home().joinpath("mainsail").exists():
|
|
||||||
print_mainsail_already_installed_dialog()
|
|
||||||
do_reinstall = get_confirm("Re-install Mainsail?", allow_go_back=True)
|
|
||||||
if do_reinstall:
|
|
||||||
backup_config_json(is_temp=True)
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
kl_im = InstanceManager(Klipper)
|
|
||||||
kl_instances = kl_im.instances
|
|
||||||
install_ms_config = False
|
|
||||||
if kl_instances:
|
|
||||||
print_install_mainsail_config_dialog()
|
|
||||||
question = "Download the recommended macros?"
|
|
||||||
install_ms_config = get_confirm(question, allow_go_back=False)
|
|
||||||
|
|
||||||
# if a default port is configured in the kiauh.cfg, we use that for the port
|
|
||||||
# otherwise we default to port 80, but show the user a dialog to confirm/change that port
|
|
||||||
cm = ConfigManager(cfg_file=KIAUH_CFG)
|
|
||||||
default_port = cm.get_value("mainsail", "default_port")
|
|
||||||
is_valid_port = default_port and default_port.isdigit()
|
|
||||||
mainsail_port = default_port if is_valid_port else "80"
|
|
||||||
if not is_valid_port:
|
|
||||||
print_mainsail_port_select_dialog(mainsail_port)
|
|
||||||
mainsail_port = get_number_input(
|
|
||||||
"Configure Mainsail for port",
|
|
||||||
min_count=mainsail_port,
|
|
||||||
default=mainsail_port,
|
|
||||||
)
|
|
||||||
|
|
||||||
check_install_dependencies(["nginx"])
|
|
||||||
|
|
||||||
try:
|
|
||||||
download_mainsail()
|
|
||||||
if do_reinstall:
|
|
||||||
restore_config_json()
|
|
||||||
if enable_remotemode:
|
|
||||||
enable_mainsail_remotemode()
|
|
||||||
if mr_instances:
|
|
||||||
patch_moonraker_conf(
|
|
||||||
mr_instances,
|
|
||||||
"Mainsail",
|
|
||||||
"update_manager mainsail",
|
|
||||||
"mainsail-updater.conf",
|
|
||||||
)
|
|
||||||
mr_im.restart_all_instance()
|
|
||||||
if install_ms_config and kl_instances:
|
|
||||||
download_mainsail_cfg()
|
|
||||||
create_mainsail_cfg_symlink(kl_instances)
|
|
||||||
patch_moonraker_conf(
|
|
||||||
mr_instances,
|
|
||||||
"mainsail-config",
|
|
||||||
"update_manager mainsail-config",
|
|
||||||
"mainsail-config-updater.conf",
|
|
||||||
)
|
|
||||||
patch_printer_config(kl_instances)
|
|
||||||
kl_im.restart_all_instance()
|
|
||||||
|
|
||||||
copy_upstream_nginx_cfg()
|
|
||||||
copy_common_vars_nginx_cfg()
|
|
||||||
create_mainsail_nginx_cfg(mainsail_port)
|
|
||||||
if kl_instances:
|
|
||||||
symlink_webui_nginx_log(kl_instances)
|
|
||||||
control_systemd_service("nginx", "restart")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
Logger.print_error(f"Mainsail installation failed!\n{e}")
|
|
||||||
return
|
|
||||||
|
|
||||||
log = f"Open Mainsail now on: http://{get_ipv4_addr()}:{mainsail_port}"
|
|
||||||
Logger.print_ok("Mainsail installation complete!", start="\n")
|
|
||||||
Logger.print_ok(log, prefix=False, end="\n\n")
|
|
||||||
|
|
||||||
|
|
||||||
def download_mainsail() -> None:
|
|
||||||
try:
|
|
||||||
Logger.print_status("Downloading Mainsail ...")
|
|
||||||
target = Path.home().joinpath("mainsail.zip")
|
|
||||||
download_file(MAINSAIL_URL, target, True)
|
|
||||||
Logger.print_ok("Download complete!")
|
|
||||||
|
|
||||||
Logger.print_status("Extracting mainsail.zip ...")
|
|
||||||
unzip(Path.home().joinpath("mainsail.zip"), MAINSAIL_DIR)
|
|
||||||
target.unlink(missing_ok=True)
|
|
||||||
Logger.print_ok("OK!")
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
Logger.print_error("Downloading Mainsail failed!")
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def update_mainsail() -> None:
|
|
||||||
Logger.print_status("Updating Mainsail ...")
|
|
||||||
backup_config_json(is_temp=True)
|
|
||||||
download_mainsail()
|
|
||||||
restore_config_json()
|
|
||||||
|
|
||||||
|
|
||||||
def download_mainsail_cfg() -> None:
|
|
||||||
try:
|
|
||||||
Logger.print_status("Downloading mainsail-config ...")
|
|
||||||
rm = RepoManager(MAINSAIL_CONFIG_REPO_URL, target_dir=MAINSAIL_CONFIG_DIR)
|
|
||||||
rm.clone_repo()
|
|
||||||
except Exception:
|
|
||||||
Logger.print_error("Downloading mainsail-config failed!")
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def create_mainsail_cfg_symlink(klipper_instances: List[Klipper]) -> None:
|
|
||||||
Logger.print_status("Create symlink of mainsail.cfg ...")
|
|
||||||
source = Path(MAINSAIL_CONFIG_DIR, "mainsail.cfg")
|
|
||||||
for instance in klipper_instances:
|
|
||||||
target = instance.cfg_dir
|
|
||||||
Logger.print_status(f"Linking {source} to {target}")
|
|
||||||
try:
|
|
||||||
create_symlink(source, target)
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
Logger.print_error("Creating symlink failed!")
|
|
||||||
|
|
||||||
|
|
||||||
def create_mainsail_nginx_cfg(port: int) -> None:
|
|
||||||
root_dir = MAINSAIL_DIR
|
|
||||||
source = NGINX_SITES_AVAILABLE.joinpath("mainsail")
|
|
||||||
target = NGINX_SITES_ENABLED.joinpath("mainsail")
|
|
||||||
try:
|
|
||||||
Logger.print_status("Creating NGINX config for Mainsail ...")
|
|
||||||
remove_file(Path("/etc/nginx/sites-enabled/default"), True)
|
|
||||||
create_nginx_cfg("mainsail", port, root_dir)
|
|
||||||
create_symlink(source, target, True)
|
|
||||||
set_nginx_permissions()
|
|
||||||
Logger.print_ok("NGINX config for Mainsail successfully created.")
|
|
||||||
except Exception:
|
|
||||||
Logger.print_error("Creating NGINX config for Mainsail failed!")
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def patch_moonraker_conf(
|
|
||||||
moonraker_instances: List[Moonraker],
|
|
||||||
name: str,
|
|
||||||
section_name: str,
|
|
||||||
template_file: str,
|
|
||||||
) -> None:
|
|
||||||
for instance in moonraker_instances:
|
|
||||||
cfg_file = instance.cfg_file
|
|
||||||
Logger.print_status(f"Add {name} update section to '{cfg_file}' ...")
|
|
||||||
|
|
||||||
if not Path(cfg_file).exists():
|
|
||||||
Logger.print_warn(f"'{cfg_file}' not found!")
|
|
||||||
return
|
|
||||||
|
|
||||||
cm = ConfigManager(cfg_file)
|
|
||||||
if cm.config.has_section(section_name):
|
|
||||||
Logger.print_info("Section already exist. Skipped ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
template = MODULE_PATH.joinpath("assets", template_file)
|
|
||||||
with open(template, "r") as t:
|
|
||||||
template_content = "\n"
|
|
||||||
template_content += t.read()
|
|
||||||
|
|
||||||
with open(cfg_file, "a") as f:
|
|
||||||
f.write(template_content)
|
|
||||||
|
|
||||||
|
|
||||||
def patch_printer_config(klipper_instances: List[Klipper]) -> None:
|
|
||||||
for instance in klipper_instances:
|
|
||||||
cfg_file = instance.cfg_file
|
|
||||||
Logger.print_status(f"Including mainsail-config in '{cfg_file}' ...")
|
|
||||||
|
|
||||||
if not Path(cfg_file).exists():
|
|
||||||
Logger.print_warn(f"'{cfg_file}' not found!")
|
|
||||||
return
|
|
||||||
|
|
||||||
cm = ConfigManager(cfg_file)
|
|
||||||
if cm.config.has_section("include mainsail.cfg"):
|
|
||||||
Logger.print_info("Section already exist. Skipped ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
with open(cfg_file, "a") as f:
|
|
||||||
f.write("\n[include mainsail.cfg]")
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 json
|
|
||||||
import shutil
|
|
||||||
from json import JSONDecodeError
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
|
||||||
from components.mainsail import (
|
|
||||||
MAINSAIL_CONFIG_JSON,
|
|
||||||
MAINSAIL_DIR,
|
|
||||||
MAINSAIL_BACKUP_DIR,
|
|
||||||
)
|
|
||||||
from core.backup_manager.backup_manager import BackupManager
|
|
||||||
from utils import NGINX_SITES_AVAILABLE, NGINX_CONFD
|
|
||||||
from utils.common import get_install_status_webui
|
|
||||||
from utils.logger import Logger
|
|
||||||
|
|
||||||
|
|
||||||
def get_mainsail_status() -> str:
|
|
||||||
return get_install_status_webui(
|
|
||||||
MAINSAIL_DIR,
|
|
||||||
NGINX_SITES_AVAILABLE.joinpath("mainsail"),
|
|
||||||
NGINX_CONFD.joinpath("upstreams.conf"),
|
|
||||||
NGINX_CONFD.joinpath("common_vars.conf"),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def backup_config_json(is_temp=False) -> None:
|
|
||||||
Logger.print_status(f"Backup '{MAINSAIL_CONFIG_JSON}' ...")
|
|
||||||
bm = BackupManager()
|
|
||||||
if is_temp:
|
|
||||||
fn = Path.home().joinpath("config.json.kiauh.bak")
|
|
||||||
bm.backup_file(MAINSAIL_CONFIG_JSON, custom_filename=fn)
|
|
||||||
else:
|
|
||||||
bm.backup_file(MAINSAIL_CONFIG_JSON)
|
|
||||||
|
|
||||||
|
|
||||||
def restore_config_json() -> None:
|
|
||||||
try:
|
|
||||||
Logger.print_status(f"Restore '{MAINSAIL_CONFIG_JSON}' ...")
|
|
||||||
source = Path.home().joinpath("config.json.kiauh.bak")
|
|
||||||
shutil.copy(source, MAINSAIL_CONFIG_JSON)
|
|
||||||
except OSError:
|
|
||||||
Logger.print_info("Unable to restore config.json. Skipped ...")
|
|
||||||
|
|
||||||
|
|
||||||
def enable_mainsail_remotemode() -> None:
|
|
||||||
Logger.print_status("Enable Mainsails remote mode ...")
|
|
||||||
with open(MAINSAIL_CONFIG_JSON, "r") as f:
|
|
||||||
config_data = json.load(f)
|
|
||||||
|
|
||||||
if config_data["instancesDB"] == "browser":
|
|
||||||
Logger.print_info("Remote mode already configured. Skipped ...")
|
|
||||||
return
|
|
||||||
|
|
||||||
Logger.print_status("Setting instance storage location to 'browser' ...")
|
|
||||||
config_data["instancesDB"] = "browser"
|
|
||||||
|
|
||||||
with open(MAINSAIL_CONFIG_JSON, "w") as f:
|
|
||||||
json.dump(config_data, f, indent=4)
|
|
||||||
Logger.print_ok("Mainsails remote mode enabled!")
|
|
||||||
|
|
||||||
|
|
||||||
def symlink_webui_nginx_log(klipper_instances: List[Klipper]) -> None:
|
|
||||||
Logger.print_status("Link NGINX logs into log directory ...")
|
|
||||||
access_log = Path("/var/log/nginx/mainsail-access.log")
|
|
||||||
error_log = Path("/var/log/nginx/mainsail-error.log")
|
|
||||||
|
|
||||||
for instance in klipper_instances:
|
|
||||||
desti_access = instance.log_dir.joinpath("mainsail-access.log")
|
|
||||||
if not desti_access.exists():
|
|
||||||
desti_access.symlink_to(access_log)
|
|
||||||
|
|
||||||
desti_error = instance.log_dir.joinpath("mainsail-error.log")
|
|
||||||
if not desti_error.exists():
|
|
||||||
desti_error.symlink_to(error_log)
|
|
||||||
|
|
||||||
|
|
||||||
def get_mainsail_local_version() -> str:
|
|
||||||
relinfo_file = MAINSAIL_DIR.joinpath("release_info.json")
|
|
||||||
if not relinfo_file.is_file():
|
|
||||||
return "-"
|
|
||||||
|
|
||||||
with open(relinfo_file, "r") as f:
|
|
||||||
return json.load(f)["version"]
|
|
||||||
|
|
||||||
|
|
||||||
def get_mainsail_remote_version() -> str:
|
|
||||||
url = "https://api.github.com/repos/mainsail-crew/mainsail/tags"
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(url) as response:
|
|
||||||
data = json.loads(response.read())
|
|
||||||
return data[0]["name"]
|
|
||||||
except (JSONDecodeError, TypeError):
|
|
||||||
return "ERROR"
|
|
||||||
|
|
||||||
|
|
||||||
def backup_mainsail_data() -> None:
|
|
||||||
with open(MAINSAIL_DIR.joinpath(".version"), "r") as v:
|
|
||||||
version = v.readlines()[0]
|
|
||||||
bm = BackupManager()
|
|
||||||
bm.backup_directory(f"mainsail-{version}", MAINSAIL_DIR, MAINSAIL_BACKUP_DIR)
|
|
||||||
bm.backup_file(MAINSAIL_CONFIG_JSON, MAINSAIL_BACKUP_DIR)
|
|
||||||
bm.backup_file(NGINX_SITES_AVAILABLE.joinpath("mainsail"), MAINSAIL_BACKUP_DIR)
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# ======================================================================= #
|
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
|
||||||
# #
|
|
||||||
# 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 components.mainsail import mainsail_remove
|
|
||||||
from core.menus import BACK_HELP_FOOTER
|
|
||||||
from core.menus.base_menu import BaseMenu
|
|
||||||
from utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
|
||||||
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) Select everything |
|
|
||||||
|-------------------------------------------------------|
|
|
||||||
| 1) {o1} Remove Mainsail |
|
|
||||||
| 2) {o2} Remove mainsail-config |
|
|
||||||
| 3) {o3} Backup config.json |
|
|
||||||
| |
|
|
||||||
| printer.cfg & moonraker.conf |
|
|
||||||
| 4) {o4} Remove Moonraker update section |
|
|
||||||
| 5) {o5} Remove printer.cfg include |
|
|
||||||
|-------------------------------------------------------|
|
|
||||||
| 6) Continue |
|
|
||||||
"""
|
|
||||||
)[1:]
|
|
||||||
print(menu, end="")
|
|
||||||
|
|
||||||
def toggle_all(self, **kwargs) -> 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, **kwargs) -> None:
|
|
||||||
self.remove_mainsail = not self.remove_mainsail
|
|
||||||
|
|
||||||
def toggle_remove_ms_config(self, **kwargs) -> None:
|
|
||||||
self.remove_ms_config = not self.remove_ms_config
|
|
||||||
|
|
||||||
def toggle_backup_config_json(self, **kwargs) -> None:
|
|
||||||
self.backup_config_json = not self.backup_config_json
|
|
||||||
|
|
||||||
def toggle_remove_updater_section(self, **kwargs) -> None:
|
|
||||||
self.remove_updater_section = not self.remove_updater_section
|
|
||||||
|
|
||||||
def toggle_remove_printer_cfg_include(self, **kwargs) -> None:
|
|
||||||
self.remove_printer_cfg_include = not self.remove_printer_cfg_include
|
|
||||||
|
|
||||||
def run_removal_process(self, **kwargs) -> 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
|
|
||||||
@@ -29,7 +29,7 @@ class MoonrakerRemoveMenu(BaseMenu):
|
|||||||
"3": self.toggle_remove_moonraker_env,
|
"3": self.toggle_remove_moonraker_env,
|
||||||
"4": self.toggle_remove_moonraker_polkit,
|
"4": self.toggle_remove_moonraker_polkit,
|
||||||
"5": self.toggle_delete_moonraker_logs,
|
"5": self.toggle_delete_moonraker_logs,
|
||||||
"6": self.run_removal_process,
|
"c": self.run_removal_process,
|
||||||
},
|
},
|
||||||
footer_type=BACK_HELP_FOOTER,
|
footer_type=BACK_HELP_FOOTER,
|
||||||
)
|
)
|
||||||
@@ -66,7 +66,7 @@ class MoonrakerRemoveMenu(BaseMenu):
|
|||||||
| 4) {o4} Remove Policy Kit Rules |
|
| 4) {o4} Remove Policy Kit Rules |
|
||||||
| 5) {o5} Delete all Log-Files |
|
| 5) {o5} Delete all Log-Files |
|
||||||
|-------------------------------------------------------|
|
|-------------------------------------------------------|
|
||||||
| 6) Continue |
|
| C) Continue |
|
||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
print(menu, end="")
|
print(menu, end="")
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ import sys
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from components.webui_client import MAINSAIL_DIR
|
||||||
|
from components.webui_client.client_utils import enable_mainsail_remotemode
|
||||||
from kiauh import KIAUH_CFG
|
from kiauh import KIAUH_CFG
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.klipper.klipper_dialogs import print_instance_overview
|
from components.klipper.klipper_dialogs import print_instance_overview
|
||||||
from components.mainsail import MAINSAIL_DIR
|
|
||||||
from components.mainsail.mainsail_utils import enable_mainsail_remotemode
|
|
||||||
from components.moonraker import (
|
from components.moonraker import (
|
||||||
EXIT_MOONRAKER_SETUP,
|
EXIT_MOONRAKER_SETUP,
|
||||||
DEFAULT_MOONRAKER_REPO_URL,
|
DEFAULT_MOONRAKER_REPO_URL,
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
import shutil
|
import shutil
|
||||||
from typing import Dict, Literal, List, Union
|
from typing import Dict, Literal, List, Union
|
||||||
|
|
||||||
from components.mainsail import MAINSAIL_DIR
|
|
||||||
from components.mainsail.mainsail_utils import enable_mainsail_remotemode
|
|
||||||
from components.moonraker import (
|
from components.moonraker import (
|
||||||
DEFAULT_MOONRAKER_PORT,
|
DEFAULT_MOONRAKER_PORT,
|
||||||
MODULE_PATH,
|
MODULE_PATH,
|
||||||
@@ -23,6 +21,8 @@ from components.moonraker import (
|
|||||||
MOONRAKER_DB_BACKUP_DIR,
|
MOONRAKER_DB_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
from components.webui_client import MAINSAIL_DIR
|
||||||
|
from components.webui_client.client_utils import enable_mainsail_remotemode
|
||||||
from core.backup_manager.backup_manager import BackupManager
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.config_manager.config_manager import ConfigManager
|
from core.config_manager.config_manager import ConfigManager
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
|
|||||||
77
kiauh/components/webui_client/__init__.py
Normal file
77
kiauh/components/webui_client/__init__.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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 #
|
||||||
|
# ======================================================================= #
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Literal, TypedDict, Set
|
||||||
|
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
|
|
||||||
|
MODULE_PATH = Path(__file__).resolve().parent
|
||||||
|
|
||||||
|
###########
|
||||||
|
# MAINSAIL
|
||||||
|
###########
|
||||||
|
MAINSAIL_DIR = Path.home().joinpath("mainsail")
|
||||||
|
MAINSAIL_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("mainsail-backups")
|
||||||
|
MAINSAIL_CONFIG_DIR = Path.home().joinpath("mainsail-config")
|
||||||
|
MAINSAIL_CONFIG_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("mainsail-config-backups")
|
||||||
|
MAINSAIL_CONFIG_REPO_URL = "https://github.com/mainsail-crew/mainsail-config.git"
|
||||||
|
MAINSAIL_CONFIG_JSON = MAINSAIL_DIR.joinpath("config.json")
|
||||||
|
MAINSAIL_URL = (
|
||||||
|
"https://github.com/mainsail-crew/mainsail/releases/latest/download/mainsail.zip"
|
||||||
|
)
|
||||||
|
MAINSAIL_PRE_RLS_URL = (
|
||||||
|
"https://github.com/mainsail-crew/mainsail/releases/download/%TAG%/mainsail.zip"
|
||||||
|
)
|
||||||
|
MAINSAIL_TAGS_URL = "https://api.github.com/repos/mainsail-crew/mainsail/tags"
|
||||||
|
|
||||||
|
#########
|
||||||
|
# FLUIDD
|
||||||
|
#########
|
||||||
|
FLUIDD_DIR = Path.home().joinpath("fluidd")
|
||||||
|
FLUIDD_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("fluidd-backups")
|
||||||
|
FLUIDD_CONFIG_DIR = Path.home().joinpath("fluidd-config")
|
||||||
|
FLUIDD_CONFIG_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("fluidd-config-backups")
|
||||||
|
FLUIDD_CONFIG_REPO_URL = "https://github.com/fluidd-core/fluidd-config.git"
|
||||||
|
FLUIDD_URL = "https://github.com/fluidd-core/fluidd/releases/latest/download/fluidd.zip"
|
||||||
|
FLUIDD_PRE_RLS_URL = (
|
||||||
|
"https://github.com/fluidd-core/fluidd/releases/download/%TAG%/fluidd.zip"
|
||||||
|
)
|
||||||
|
FLUIDD_TAGS_URL = "https://api.github.com/repos/fluidd-core/fluidd/tags"
|
||||||
|
|
||||||
|
ClientName = Literal["mainsail", "fluidd"]
|
||||||
|
ClientConfigName = Literal["mainsail-config", "fluidd-config"]
|
||||||
|
|
||||||
|
|
||||||
|
class ClientData(TypedDict):
|
||||||
|
name: ClientName
|
||||||
|
display_name: str
|
||||||
|
dir: Path
|
||||||
|
backup_dir: Path
|
||||||
|
url: str
|
||||||
|
pre_release_url: str
|
||||||
|
tags_url: str
|
||||||
|
remote_mode: bool # required only for Mainsail
|
||||||
|
mr_conf_repo: str
|
||||||
|
mr_conf_path: str
|
||||||
|
client_config: "ClientConfigData"
|
||||||
|
|
||||||
|
|
||||||
|
class ClientConfigData(TypedDict):
|
||||||
|
name: ClientConfigName
|
||||||
|
display_name: str
|
||||||
|
cfg_filename: str
|
||||||
|
dir: Path
|
||||||
|
backup_dir: Path
|
||||||
|
url: str
|
||||||
|
printer_cfg_section: str
|
||||||
|
mr_conf_path: str
|
||||||
|
mr_conf_origin: str
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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 typing import List
|
||||||
|
|
||||||
|
from components.klipper.klipper import Klipper
|
||||||
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
from components.webui_client import ClientConfigData
|
||||||
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
|
from utils.filesystem_utils import remove_file, remove_config_section
|
||||||
|
from utils.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
|
def run_client_config_removal(
|
||||||
|
client_config: ClientConfigData,
|
||||||
|
remove_moonraker_conf_section: bool,
|
||||||
|
remove_printer_cfg_include: bool,
|
||||||
|
kl_instances: List[Klipper],
|
||||||
|
mr_instances: List[Moonraker],
|
||||||
|
) -> None:
|
||||||
|
remove_client_config_dir(client_config)
|
||||||
|
remove_client_config_symlink(client_config)
|
||||||
|
if remove_moonraker_conf_section:
|
||||||
|
remove_config_section(
|
||||||
|
f"update_manager {client_config.get('name')}", mr_instances
|
||||||
|
)
|
||||||
|
if remove_printer_cfg_include:
|
||||||
|
remove_config_section(client_config.get("printer_cfg_section"), kl_instances)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_client_config_dir(client_config: ClientConfigData) -> None:
|
||||||
|
Logger.print_status(f"Removing {client_config.get('name')} ...")
|
||||||
|
client_config_dir = client_config.get("dir")
|
||||||
|
if not client_config_dir.exists():
|
||||||
|
Logger.print_info(f"'{client_config_dir}' does not exist. Skipping ...")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
shutil.rmtree(client_config_dir)
|
||||||
|
except OSError as e:
|
||||||
|
Logger.print_error(f"Unable to delete '{client_config_dir}':\n{e}")
|
||||||
|
|
||||||
|
|
||||||
|
def remove_client_config_symlink(client_config: ClientConfigData) -> None:
|
||||||
|
Logger.print_status(f"Removing {client_config.get('cfg_filename')} symlinks ...")
|
||||||
|
im = InstanceManager(Klipper)
|
||||||
|
instances: List[Klipper] = im.instances
|
||||||
|
for instance in instances:
|
||||||
|
Logger.print_status(f"Removing symlink from '{instance.cfg_file}' ...")
|
||||||
|
try:
|
||||||
|
remove_file(instance.cfg_dir.joinpath(client_config.get("cfg_filename")))
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
Logger.print_error("Failed to remove symlink!")
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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 typing import List, get_args
|
||||||
|
|
||||||
|
from kiauh import KIAUH_CFG
|
||||||
|
from components.klipper.klipper import Klipper
|
||||||
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
from components.webui_client import ClientConfigData, ClientName, ClientData
|
||||||
|
from components.webui_client.client_dialogs import print_client_already_installed_dialog
|
||||||
|
from components.webui_client.client_utils import (
|
||||||
|
load_client_data,
|
||||||
|
backup_client_config_data,
|
||||||
|
)
|
||||||
|
from core.config_manager.config_manager import ConfigManager
|
||||||
|
|
||||||
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
|
from core.repo_manager.repo_manager import RepoManager
|
||||||
|
from utils.filesystem_utils import (
|
||||||
|
create_symlink,
|
||||||
|
add_config_section,
|
||||||
|
)
|
||||||
|
from utils.input_utils import get_confirm
|
||||||
|
from utils.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
|
def install_client_config(client_name: ClientName) -> None:
|
||||||
|
client: ClientData = load_client_data(client_name)
|
||||||
|
client_config: ClientConfigData = client.get("client_config")
|
||||||
|
d_name = client_config.get("display_name")
|
||||||
|
|
||||||
|
if check_existing_client_config_install(client_name):
|
||||||
|
Logger.print_info("Another Client-Config is already installed! Skipped ...")
|
||||||
|
return
|
||||||
|
|
||||||
|
if client_config.get("dir").exists():
|
||||||
|
print_client_already_installed_dialog(d_name)
|
||||||
|
if get_confirm(f"Re-install {d_name}?", allow_go_back=True):
|
||||||
|
shutil.rmtree(client_config.get("dir"))
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
mr_im = InstanceManager(Moonraker)
|
||||||
|
mr_instances: List[Moonraker] = mr_im.instances
|
||||||
|
kl_im = InstanceManager(Klipper)
|
||||||
|
kl_instances = kl_im.instances
|
||||||
|
|
||||||
|
try:
|
||||||
|
download_client_config(client_config)
|
||||||
|
create_client_config_symlink(client_config, kl_instances)
|
||||||
|
add_config_section(
|
||||||
|
section=f"update_manager {client_config.get('name')}",
|
||||||
|
instances=mr_instances,
|
||||||
|
options=[
|
||||||
|
("type", "git_repo"),
|
||||||
|
("primary_branch", "master"),
|
||||||
|
("path", client_config.get("mr_conf_path")),
|
||||||
|
("origin", client_config.get("mr_conf_origin")),
|
||||||
|
("managed_services", "klipper"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
add_config_section(client_config.get("printer_cfg_section"), kl_instances)
|
||||||
|
kl_im.restart_all_instance()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
Logger.print_error(f"{d_name} installation failed!\n{e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
Logger.print_ok(f"{d_name} installation complete!", start="\n")
|
||||||
|
|
||||||
|
|
||||||
|
def check_existing_client_config_install(client_name: ClientName) -> bool:
|
||||||
|
# check if any other client-configs are present
|
||||||
|
# as they can conflict each other, or are at least
|
||||||
|
# redundant to have, so we skip the installation
|
||||||
|
client_list = list(get_args(ClientName))
|
||||||
|
client_list.remove(client_name)
|
||||||
|
for c in client_list:
|
||||||
|
c_data: ClientData = load_client_data(c)
|
||||||
|
c_config_data: ClientConfigData = c_data.get("client_config")
|
||||||
|
if c_config_data.get("dir").exists():
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def download_client_config(client_config: ClientConfigData) -> None:
|
||||||
|
try:
|
||||||
|
Logger.print_status(f"Downloading {client_config.get('display_name')} ...")
|
||||||
|
rm = RepoManager(
|
||||||
|
client_config.get("url"), target_dir=str(client_config.get("dir"))
|
||||||
|
)
|
||||||
|
rm.clone_repo()
|
||||||
|
except Exception:
|
||||||
|
Logger.print_error(f"Downloading {client_config.get('display_name')} failed!")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def update_client_config(client: ClientData) -> None:
|
||||||
|
client_config: ClientConfigData = client.get("client_config")
|
||||||
|
|
||||||
|
Logger.print_status(f"Updating {client_config.get('display_name')} ...")
|
||||||
|
|
||||||
|
cm = ConfigManager(cfg_file=KIAUH_CFG)
|
||||||
|
if cm.get_value("kiauh", "backup_before_update"):
|
||||||
|
backup_client_config_data(client)
|
||||||
|
|
||||||
|
repo_manager = RepoManager(
|
||||||
|
repo=client_config.get("url"),
|
||||||
|
branch="master",
|
||||||
|
target_dir=str(client_config.get("dir")),
|
||||||
|
)
|
||||||
|
repo_manager.pull_repo()
|
||||||
|
|
||||||
|
Logger.print_ok(f"Successfully updated {client_config.get('display_name')}.")
|
||||||
|
Logger.print_warn("Remember to restart Klipper to reload the configurations!")
|
||||||
|
|
||||||
|
|
||||||
|
def create_client_config_symlink(
|
||||||
|
client_config: ClientConfigData, klipper_instances: List[Klipper] = None
|
||||||
|
) -> None:
|
||||||
|
if klipper_instances is None:
|
||||||
|
kl_im = InstanceManager(Klipper)
|
||||||
|
klipper_instances = kl_im.instances
|
||||||
|
|
||||||
|
Logger.print_status(f"Create symlink for {client_config.get('cfg_filename')} ...")
|
||||||
|
source = Path(client_config.get("dir"), client_config.get("cfg_filename"))
|
||||||
|
for instance in klipper_instances:
|
||||||
|
target = instance.cfg_dir
|
||||||
|
Logger.print_status(f"Linking {source} to {target}")
|
||||||
|
try:
|
||||||
|
create_symlink(source, target)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
Logger.print_error("Creating symlink failed!")
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
import textwrap
|
import textwrap
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from components.webui_client import ClientData
|
||||||
from core.menus.base_menu import print_back_footer
|
from core.menus.base_menu import print_back_footer
|
||||||
from utils.constants import RESET_FORMAT, COLOR_YELLOW, COLOR_CYAN
|
from utils.constants import RESET_FORMAT, COLOR_YELLOW, COLOR_CYAN
|
||||||
|
|
||||||
@@ -25,10 +26,10 @@ def print_moonraker_not_found_dialog():
|
|||||||
| {line1:<63}|
|
| {line1:<63}|
|
||||||
| {line2:<63}|
|
| {line2:<63}|
|
||||||
|-------------------------------------------------------|
|
|-------------------------------------------------------|
|
||||||
| It is possible to install Fluidd without a local |
|
| It is possible to install Mainsail without a local |
|
||||||
| Moonraker installation. If you continue, you need to |
|
| Moonraker installation. If you continue, you need to |
|
||||||
| make sure, that Moonraker is installed on another |
|
| make sure, that Moonraker is installed on another |
|
||||||
| machine in your network. Otherwise Fluidd will NOT |
|
| machine in your network. Otherwise Mainsail will NOT |
|
||||||
| work correctly. |
|
| work correctly. |
|
||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
@@ -37,19 +38,18 @@ def print_moonraker_not_found_dialog():
|
|||||||
print_back_footer()
|
print_back_footer()
|
||||||
|
|
||||||
|
|
||||||
def print_fluidd_already_installed_dialog():
|
def print_client_already_installed_dialog(name: str):
|
||||||
line1 = f"{COLOR_YELLOW}WARNING:{RESET_FORMAT}"
|
line1 = f"{COLOR_YELLOW}WARNING:{RESET_FORMAT}"
|
||||||
line2 = f"{COLOR_YELLOW}Fluidd seems to be already installed!{RESET_FORMAT}"
|
line2 = f"{COLOR_YELLOW}{name} seems to be already installed!{RESET_FORMAT}"
|
||||||
|
line3 = f"If you continue, your current {name}"
|
||||||
dialog = textwrap.dedent(
|
dialog = textwrap.dedent(
|
||||||
f"""
|
f"""
|
||||||
/=======================================================\\
|
/=======================================================\\
|
||||||
| {line1:<63}|
|
| {line1:<63}|
|
||||||
| {line2:<63}|
|
| {line2:<63}|
|
||||||
|-------------------------------------------------------|
|
|-------------------------------------------------------|
|
||||||
| If you continue, your current Fluidd installation |
|
| {line3:<54}|
|
||||||
| will be overwritten. You will not loose any printer |
|
| installation will be overwritten. |
|
||||||
| configurations and the Moonraker database will remain |
|
|
||||||
| untouched. |
|
|
||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
|
|
||||||
@@ -57,38 +57,21 @@ def print_fluidd_already_installed_dialog():
|
|||||||
print_back_footer()
|
print_back_footer()
|
||||||
|
|
||||||
|
|
||||||
def print_install_fluidd_config_dialog():
|
def print_client_port_select_dialog(name: str, port: str, ports_in_use: List[str]):
|
||||||
dialog = textwrap.dedent(
|
|
||||||
f"""
|
|
||||||
/=======================================================\\
|
|
||||||
| It is recommended to use special macros in order to |
|
|
||||||
| have Fluidd fully functional and working. |
|
|
||||||
| |
|
|
||||||
| The recommended macros for Fluidd can be seen here: |
|
|
||||||
| https://github.com/fluidd-core/fluidd-config |
|
|
||||||
| |
|
|
||||||
| If you already use these macros skip this step. |
|
|
||||||
| Otherwise you should consider to answer with 'Y' to |
|
|
||||||
| download the recommended macros. |
|
|
||||||
\\=======================================================/
|
|
||||||
"""
|
|
||||||
)[1:]
|
|
||||||
|
|
||||||
print(dialog, end="")
|
|
||||||
|
|
||||||
|
|
||||||
def print_fluidd_port_select_dialog(port: str, ports_in_use: List[str]):
|
|
||||||
port = f"{COLOR_CYAN}{port}{RESET_FORMAT}"
|
port = f"{COLOR_CYAN}{port}{RESET_FORMAT}"
|
||||||
|
line1 = f"Please select the port, {name} should be served on."
|
||||||
|
line2 = f"In case you need {name} to be served on a specific"
|
||||||
dialog = textwrap.dedent(
|
dialog = textwrap.dedent(
|
||||||
f"""
|
f"""
|
||||||
/=======================================================\\
|
/=======================================================\\
|
||||||
| Please select the port, Fluidd should be served on. |
|
| {line1:<54}|
|
||||||
| If you are unsure what to select, hit Enter to apply |
|
| If you are unsure what to select, hit Enter to apply |
|
||||||
| the suggested value of: {port:38} |
|
| the suggested value of: {port:38} |
|
||||||
| |
|
| |
|
||||||
| In case you need Fluidd to be served on a specific |
|
| {line2:<54}|
|
||||||
| port, you can set it now. Make sure the port is not |
|
| port, you can set it now. Make sure the port is not |
|
||||||
| used by any other application on your system! |
|
| used by any other application on your system! |
|
||||||
|
\\=======================================================/
|
||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
|
|
||||||
@@ -102,3 +85,27 @@ def print_fluidd_port_select_dialog(port: str, ports_in_use: List[str]):
|
|||||||
dialog += "\\=======================================================/\n"
|
dialog += "\\=======================================================/\n"
|
||||||
|
|
||||||
print(dialog, end="")
|
print(dialog, end="")
|
||||||
|
|
||||||
|
|
||||||
|
def print_install_client_config_dialog(client: ClientData):
|
||||||
|
name = client.get("display_name")
|
||||||
|
url = client.get("client_config").get("url").replace(".git", "")
|
||||||
|
line1 = f"have {name} fully functional and working."
|
||||||
|
line2 = f"The recommended macros for {name} can be seen here:"
|
||||||
|
dialog = textwrap.dedent(
|
||||||
|
f"""
|
||||||
|
/=======================================================\\
|
||||||
|
| It is recommended to use special macros in order to |
|
||||||
|
| {line1:<54}|
|
||||||
|
| |
|
||||||
|
| {line2:<54}|
|
||||||
|
| {url:<54}|
|
||||||
|
| |
|
||||||
|
| If you already use these macros skip this step. |
|
||||||
|
| Otherwise you should consider to answer with 'Y' to |
|
||||||
|
| download the recommended macros. |
|
||||||
|
\\=======================================================/
|
||||||
|
"""
|
||||||
|
)[1:]
|
||||||
|
|
||||||
|
print(dialog, end="")
|
||||||
75
kiauh/components/webui_client/client_remove.py
Normal file
75
kiauh/components/webui_client/client_remove.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from components.klipper.klipper import Klipper
|
||||||
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
from components.webui_client import ClientData
|
||||||
|
from components.webui_client.client_config.client_config_remove import (
|
||||||
|
run_client_config_removal,
|
||||||
|
)
|
||||||
|
from components.webui_client.client_utils import backup_mainsail_config_json
|
||||||
|
|
||||||
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
|
from utils.filesystem_utils import (
|
||||||
|
remove_nginx_config,
|
||||||
|
remove_nginx_logs,
|
||||||
|
remove_config_section,
|
||||||
|
)
|
||||||
|
from utils.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
|
def run_client_removal(
|
||||||
|
client: ClientData,
|
||||||
|
rm_client: bool,
|
||||||
|
rm_client_config: bool,
|
||||||
|
backup_ms_config_json: bool,
|
||||||
|
rm_moonraker_conf_section: bool,
|
||||||
|
rm_printer_cfg_section: bool,
|
||||||
|
) -> None:
|
||||||
|
mr_im = InstanceManager(Moonraker)
|
||||||
|
mr_instances: List[Moonraker] = mr_im.instances
|
||||||
|
kl_im = InstanceManager(Klipper)
|
||||||
|
kl_instances: List[Klipper] = kl_im.instances
|
||||||
|
if backup_ms_config_json and client.get("name") == "mainsail":
|
||||||
|
backup_mainsail_config_json()
|
||||||
|
if rm_client:
|
||||||
|
client_name = client.get("name")
|
||||||
|
remove_client_dir(client)
|
||||||
|
remove_nginx_config(client_name)
|
||||||
|
remove_nginx_logs(client_name)
|
||||||
|
if rm_moonraker_conf_section:
|
||||||
|
section = f"update_manager {client_name}"
|
||||||
|
remove_config_section(section, mr_instances)
|
||||||
|
if rm_client_config:
|
||||||
|
run_client_config_removal(
|
||||||
|
client.get("client_config"),
|
||||||
|
rm_moonraker_conf_section,
|
||||||
|
rm_printer_cfg_section,
|
||||||
|
kl_instances,
|
||||||
|
mr_instances,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_client_dir(client: ClientData) -> None:
|
||||||
|
Logger.print_status(f"Removing {client.get('display_name')} ...")
|
||||||
|
client_dir = client.get("dir")
|
||||||
|
if not client.get("dir").exists():
|
||||||
|
Logger.print_info(f"'{client_dir}' does not exist. Skipping ...")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
shutil.rmtree(client_dir)
|
||||||
|
except OSError as e:
|
||||||
|
Logger.print_error(f"Unable to delete '{client_dir}':\n{e}")
|
||||||
207
kiauh/components/webui_client/client_setup.py
Normal file
207
kiauh/components/webui_client/client_setup.py
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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 #
|
||||||
|
# ======================================================================= #
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from components.klipper.klipper import Klipper
|
||||||
|
from components.webui_client import (
|
||||||
|
ClientName,
|
||||||
|
ClientData,
|
||||||
|
)
|
||||||
|
|
||||||
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
from components.webui_client.client_config.client_config_setup import (
|
||||||
|
install_client_config,
|
||||||
|
check_existing_client_config_install,
|
||||||
|
)
|
||||||
|
from components.webui_client.client_dialogs import (
|
||||||
|
print_moonraker_not_found_dialog,
|
||||||
|
print_client_port_select_dialog,
|
||||||
|
print_install_client_config_dialog,
|
||||||
|
)
|
||||||
|
from components.webui_client.client_utils import (
|
||||||
|
backup_mainsail_config_json,
|
||||||
|
restore_mainsail_config_json,
|
||||||
|
enable_mainsail_remotemode,
|
||||||
|
symlink_webui_nginx_log,
|
||||||
|
load_client_data,
|
||||||
|
)
|
||||||
|
from core.config_manager.config_manager import ConfigManager
|
||||||
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
|
from kiauh import KIAUH_CFG
|
||||||
|
from utils import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED
|
||||||
|
from utils.common import check_install_dependencies
|
||||||
|
from utils.filesystem_utils import (
|
||||||
|
unzip,
|
||||||
|
copy_upstream_nginx_cfg,
|
||||||
|
copy_common_vars_nginx_cfg,
|
||||||
|
create_nginx_cfg,
|
||||||
|
create_symlink,
|
||||||
|
remove_file,
|
||||||
|
add_config_section,
|
||||||
|
read_ports_from_nginx_configs,
|
||||||
|
is_valid_port,
|
||||||
|
get_next_free_port,
|
||||||
|
)
|
||||||
|
from utils.input_utils import get_confirm, get_number_input
|
||||||
|
from utils.logger import Logger
|
||||||
|
from utils.system_utils import (
|
||||||
|
download_file,
|
||||||
|
set_nginx_permissions,
|
||||||
|
get_ipv4_addr,
|
||||||
|
control_systemd_service,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def install_client(client_name: ClientName) -> None:
|
||||||
|
client: ClientData = load_client_data(client_name)
|
||||||
|
d_name = client.get("display_name")
|
||||||
|
|
||||||
|
if client is None:
|
||||||
|
Logger.print_error("Missing parameter client_name!")
|
||||||
|
return
|
||||||
|
|
||||||
|
if client.get("dir").exists():
|
||||||
|
Logger.print_info(
|
||||||
|
f"{client.get('display_name')} seems to be already installed! Skipped ..."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
mr_im = InstanceManager(Moonraker)
|
||||||
|
mr_instances: List[Moonraker] = mr_im.instances
|
||||||
|
|
||||||
|
enable_remotemode = False
|
||||||
|
if not mr_instances:
|
||||||
|
print_moonraker_not_found_dialog()
|
||||||
|
if not get_confirm(
|
||||||
|
f"Continue {d_name} installation?",
|
||||||
|
allow_go_back=True,
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
# if moonraker is not installed or multiple instances
|
||||||
|
# are installed we enable mainsails remote mode
|
||||||
|
if client.get("remote_mode") and not mr_instances or len(mr_instances) > 1:
|
||||||
|
enable_remotemode = True
|
||||||
|
|
||||||
|
kl_im = InstanceManager(Klipper)
|
||||||
|
kl_instances = kl_im.instances
|
||||||
|
install_client_cfg = False
|
||||||
|
client_config = client.get("client_config")
|
||||||
|
if (
|
||||||
|
kl_instances
|
||||||
|
and not client_config.get("dir").exists()
|
||||||
|
and not check_existing_client_config_install(client.get("name"))
|
||||||
|
):
|
||||||
|
print_install_client_config_dialog(client)
|
||||||
|
question = f"Download the recommended {client_config.get('display_name')}?"
|
||||||
|
install_client_cfg = get_confirm(question, allow_go_back=False)
|
||||||
|
|
||||||
|
cm = ConfigManager(cfg_file=KIAUH_CFG)
|
||||||
|
client_port = cm.get_value(client.get("name"), "port")
|
||||||
|
ports_in_use = read_ports_from_nginx_configs()
|
||||||
|
|
||||||
|
# check if configured port is a valid number and not in use already
|
||||||
|
valid_port = is_valid_port(client_port, ports_in_use)
|
||||||
|
while not valid_port:
|
||||||
|
next_port = get_next_free_port(ports_in_use)
|
||||||
|
print_client_port_select_dialog(d_name, next_port, ports_in_use)
|
||||||
|
client_port = str(
|
||||||
|
get_number_input(
|
||||||
|
f"Configure {d_name} for port",
|
||||||
|
min_count=int(next_port),
|
||||||
|
default=next_port,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
valid_port = is_valid_port(client_port, ports_in_use)
|
||||||
|
|
||||||
|
check_install_dependencies(["nginx"])
|
||||||
|
|
||||||
|
try:
|
||||||
|
download_client(client)
|
||||||
|
if enable_remotemode and client.get("name") == "mainsail":
|
||||||
|
enable_mainsail_remotemode()
|
||||||
|
if mr_instances:
|
||||||
|
add_config_section(
|
||||||
|
section=f"update_manager {client.get('name')}",
|
||||||
|
instances=mr_instances,
|
||||||
|
options=[
|
||||||
|
("type", "web"),
|
||||||
|
("channel", "stable"),
|
||||||
|
("repo", client.get("mr_conf_repo")),
|
||||||
|
("path", client.get("mr_conf_path")),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
mr_im.restart_all_instance()
|
||||||
|
if install_client_cfg and kl_instances:
|
||||||
|
install_client_config(client.get("name"))
|
||||||
|
|
||||||
|
copy_upstream_nginx_cfg()
|
||||||
|
copy_common_vars_nginx_cfg()
|
||||||
|
create_client_nginx_cfg(client, client_port)
|
||||||
|
if kl_instances:
|
||||||
|
symlink_webui_nginx_log(kl_instances)
|
||||||
|
control_systemd_service("nginx", "restart")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
Logger.print_error(f"{d_name} installation failed!\n{e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
log = f"Open {d_name} now on: http://{get_ipv4_addr()}:{client_port}"
|
||||||
|
Logger.print_ok(f"{d_name} installation complete!", start="\n")
|
||||||
|
Logger.print_ok(log, prefix=False, end="\n\n")
|
||||||
|
|
||||||
|
|
||||||
|
def download_client(client: ClientData) -> None:
|
||||||
|
zipfile = f"{client.get('name').lower()}.zip"
|
||||||
|
target = Path().home().joinpath(zipfile)
|
||||||
|
try:
|
||||||
|
Logger.print_status(f"Downloading {zipfile} ...")
|
||||||
|
download_file(client.get("url"), target, True)
|
||||||
|
Logger.print_ok("Download complete!")
|
||||||
|
|
||||||
|
Logger.print_status(f"Extracting {zipfile} ...")
|
||||||
|
unzip(target, client.get("dir"))
|
||||||
|
target.unlink(missing_ok=True)
|
||||||
|
Logger.print_ok("OK!")
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
Logger.print_error(f"Downloading {zipfile} failed!")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def update_client(client: ClientData) -> None:
|
||||||
|
Logger.print_status(f"Updating {client.get('display_name')} ...")
|
||||||
|
if client.get("name") == "mainsail":
|
||||||
|
backup_mainsail_config_json(is_temp=True)
|
||||||
|
|
||||||
|
download_client(client)
|
||||||
|
|
||||||
|
if client.get("name") == "mainsail":
|
||||||
|
restore_mainsail_config_json()
|
||||||
|
|
||||||
|
|
||||||
|
def create_client_nginx_cfg(client: ClientData, port: int) -> None:
|
||||||
|
d_name = client.get("display_name")
|
||||||
|
root_dir = client.get("dir")
|
||||||
|
source = NGINX_SITES_AVAILABLE.joinpath(client.get("name"))
|
||||||
|
target = NGINX_SITES_ENABLED.joinpath(client.get("name"))
|
||||||
|
try:
|
||||||
|
Logger.print_status(f"Creating NGINX config for {d_name} ...")
|
||||||
|
remove_file(Path("/etc/nginx/sites-enabled/default"), True)
|
||||||
|
create_nginx_cfg(client.get("name"), port, root_dir)
|
||||||
|
create_symlink(source, target, True)
|
||||||
|
set_nginx_permissions()
|
||||||
|
Logger.print_ok(f"NGINX config for {d_name} successfully created.")
|
||||||
|
except Exception:
|
||||||
|
Logger.print_error(f"Creating NGINX config for {d_name} failed!")
|
||||||
|
raise
|
||||||
237
kiauh/components/webui_client/client_utils.py
Normal file
237
kiauh/components/webui_client/client_utils.py
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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 json
|
||||||
|
import shutil
|
||||||
|
from json import JSONDecodeError
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Optional, Dict, Literal, Union
|
||||||
|
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
from components.klipper.klipper import Klipper
|
||||||
|
from components.webui_client import (
|
||||||
|
MAINSAIL_CONFIG_JSON,
|
||||||
|
MAINSAIL_DIR,
|
||||||
|
MAINSAIL_BACKUP_DIR,
|
||||||
|
FLUIDD_PRE_RLS_URL,
|
||||||
|
FLUIDD_BACKUP_DIR,
|
||||||
|
FLUIDD_URL,
|
||||||
|
FLUIDD_DIR,
|
||||||
|
ClientData,
|
||||||
|
FLUIDD_CONFIG_REPO_URL,
|
||||||
|
FLUIDD_CONFIG_DIR,
|
||||||
|
ClientConfigData,
|
||||||
|
MAINSAIL_PRE_RLS_URL,
|
||||||
|
MAINSAIL_URL,
|
||||||
|
MAINSAIL_CONFIG_REPO_URL,
|
||||||
|
MAINSAIL_CONFIG_DIR,
|
||||||
|
ClientName,
|
||||||
|
MAINSAIL_TAGS_URL,
|
||||||
|
FLUIDD_TAGS_URL,
|
||||||
|
FLUIDD_CONFIG_BACKUP_DIR,
|
||||||
|
MAINSAIL_CONFIG_BACKUP_DIR,
|
||||||
|
)
|
||||||
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
|
from core.repo_manager.repo_manager import RepoManager
|
||||||
|
from utils import NGINX_SITES_AVAILABLE, NGINX_CONFD
|
||||||
|
from utils.common import get_install_status_webui, get_install_status_common
|
||||||
|
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_YELLOW
|
||||||
|
from utils.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
|
def load_client_data(client_name: ClientName) -> Optional[ClientData]:
|
||||||
|
client_data = None
|
||||||
|
|
||||||
|
if client_name == "mainsail":
|
||||||
|
client_config_data = ClientConfigData(
|
||||||
|
name="mainsail-config",
|
||||||
|
display_name="Mainsail-Config",
|
||||||
|
cfg_filename="mainsail.cfg",
|
||||||
|
dir=MAINSAIL_CONFIG_DIR,
|
||||||
|
backup_dir=MAINSAIL_CONFIG_BACKUP_DIR,
|
||||||
|
url=MAINSAIL_CONFIG_REPO_URL,
|
||||||
|
printer_cfg_section="include mainsail.cfg",
|
||||||
|
mr_conf_path="~/mainsail-config",
|
||||||
|
mr_conf_origin=MAINSAIL_CONFIG_REPO_URL,
|
||||||
|
)
|
||||||
|
client_data = ClientData(
|
||||||
|
name=client_name,
|
||||||
|
display_name=client_name.capitalize(),
|
||||||
|
dir=MAINSAIL_DIR,
|
||||||
|
backup_dir=MAINSAIL_BACKUP_DIR,
|
||||||
|
url=MAINSAIL_URL,
|
||||||
|
pre_release_url=MAINSAIL_PRE_RLS_URL,
|
||||||
|
tags_url=MAINSAIL_TAGS_URL,
|
||||||
|
remote_mode=True,
|
||||||
|
mr_conf_repo="mainsail-crew/mainsail",
|
||||||
|
mr_conf_path="~/mainsail",
|
||||||
|
client_config=client_config_data,
|
||||||
|
)
|
||||||
|
elif client_name == "fluidd":
|
||||||
|
client_config_data = ClientConfigData(
|
||||||
|
name="fluidd-config",
|
||||||
|
display_name="Fluidd-Config",
|
||||||
|
cfg_filename="fluidd.cfg",
|
||||||
|
dir=FLUIDD_CONFIG_DIR,
|
||||||
|
backup_dir=FLUIDD_CONFIG_BACKUP_DIR,
|
||||||
|
url=FLUIDD_CONFIG_REPO_URL,
|
||||||
|
printer_cfg_section="include fluidd.cfg",
|
||||||
|
mr_conf_path="~/fluidd-config",
|
||||||
|
mr_conf_origin=FLUIDD_CONFIG_REPO_URL,
|
||||||
|
)
|
||||||
|
client_data = ClientData(
|
||||||
|
name=client_name,
|
||||||
|
display_name=client_name.capitalize(),
|
||||||
|
dir=FLUIDD_DIR,
|
||||||
|
backup_dir=FLUIDD_BACKUP_DIR,
|
||||||
|
url=FLUIDD_URL,
|
||||||
|
pre_release_url=FLUIDD_PRE_RLS_URL,
|
||||||
|
tags_url=FLUIDD_TAGS_URL,
|
||||||
|
remote_mode=False,
|
||||||
|
mr_conf_repo="fluidd-core/fluidd",
|
||||||
|
mr_conf_path="~/fluidd",
|
||||||
|
client_config=client_config_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
return client_data
|
||||||
|
|
||||||
|
|
||||||
|
def get_client_status(client: ClientData) -> str:
|
||||||
|
return get_install_status_webui(
|
||||||
|
client.get("dir"),
|
||||||
|
NGINX_SITES_AVAILABLE.joinpath(client.get("name")),
|
||||||
|
NGINX_CONFD.joinpath("upstreams.conf"),
|
||||||
|
NGINX_CONFD.joinpath("common_vars.conf"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_client_config_status(client: ClientData) -> Dict[
|
||||||
|
Literal["repo", "local", "remote"],
|
||||||
|
Union[str, int],
|
||||||
|
]:
|
||||||
|
client_config = client.get("client_config")
|
||||||
|
client_config = client_config.get("dir")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"repo": RepoManager.get_repo_name(client_config),
|
||||||
|
"local": RepoManager.get_local_commit(client_config),
|
||||||
|
"remote": RepoManager.get_remote_commit(client_config),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_client_config(clients: List[ClientData]) -> str:
|
||||||
|
installed = []
|
||||||
|
for client in clients:
|
||||||
|
client_config = client.get("client_config")
|
||||||
|
if client_config.get("dir").exists():
|
||||||
|
installed.append(client)
|
||||||
|
|
||||||
|
if len(installed) > 1:
|
||||||
|
return f"{COLOR_YELLOW}Conflict!{RESET_FORMAT}"
|
||||||
|
elif len(installed) == 1:
|
||||||
|
cfg = installed[0].get("client_config")
|
||||||
|
return f"{COLOR_CYAN}{cfg.get('display_name')}{RESET_FORMAT}"
|
||||||
|
|
||||||
|
return f"{COLOR_CYAN}-{RESET_FORMAT}"
|
||||||
|
|
||||||
|
|
||||||
|
def backup_mainsail_config_json(is_temp=False) -> None:
|
||||||
|
Logger.print_status(f"Backup '{MAINSAIL_CONFIG_JSON}' ...")
|
||||||
|
bm = BackupManager()
|
||||||
|
if is_temp:
|
||||||
|
fn = Path.home().joinpath("config.json.kiauh.bak")
|
||||||
|
bm.backup_file(MAINSAIL_CONFIG_JSON, custom_filename=fn)
|
||||||
|
else:
|
||||||
|
bm.backup_file(MAINSAIL_CONFIG_JSON)
|
||||||
|
|
||||||
|
|
||||||
|
def restore_mainsail_config_json() -> None:
|
||||||
|
try:
|
||||||
|
Logger.print_status(f"Restore '{MAINSAIL_CONFIG_JSON}' ...")
|
||||||
|
source = Path.home().joinpath("config.json.kiauh.bak")
|
||||||
|
shutil.copy(source, MAINSAIL_CONFIG_JSON)
|
||||||
|
except OSError:
|
||||||
|
Logger.print_info("Unable to restore config.json. Skipped ...")
|
||||||
|
|
||||||
|
|
||||||
|
def enable_mainsail_remotemode() -> None:
|
||||||
|
Logger.print_status("Enable Mainsails remote mode ...")
|
||||||
|
with open(MAINSAIL_CONFIG_JSON, "r") as f:
|
||||||
|
config_data = json.load(f)
|
||||||
|
|
||||||
|
if config_data["instancesDB"] == "browser":
|
||||||
|
Logger.print_info("Remote mode already configured. Skipped ...")
|
||||||
|
return
|
||||||
|
|
||||||
|
Logger.print_status("Setting instance storage location to 'browser' ...")
|
||||||
|
config_data["instancesDB"] = "browser"
|
||||||
|
|
||||||
|
with open(MAINSAIL_CONFIG_JSON, "w") as f:
|
||||||
|
json.dump(config_data, f, indent=4)
|
||||||
|
Logger.print_ok("Mainsails remote mode enabled!")
|
||||||
|
|
||||||
|
|
||||||
|
def symlink_webui_nginx_log(klipper_instances: List[Klipper]) -> None:
|
||||||
|
Logger.print_status("Link NGINX logs into log directory ...")
|
||||||
|
access_log = Path("/var/log/nginx/mainsail-access.log")
|
||||||
|
error_log = Path("/var/log/nginx/mainsail-error.log")
|
||||||
|
|
||||||
|
for instance in klipper_instances:
|
||||||
|
desti_access = instance.log_dir.joinpath("mainsail-access.log")
|
||||||
|
if not desti_access.exists():
|
||||||
|
desti_access.symlink_to(access_log)
|
||||||
|
|
||||||
|
desti_error = instance.log_dir.joinpath("mainsail-error.log")
|
||||||
|
if not desti_error.exists():
|
||||||
|
desti_error.symlink_to(error_log)
|
||||||
|
|
||||||
|
|
||||||
|
def get_local_client_version(client: ClientData) -> str:
|
||||||
|
relinfo_file = client.get("dir").joinpath("release_info.json")
|
||||||
|
if not relinfo_file.is_file():
|
||||||
|
return "-"
|
||||||
|
|
||||||
|
with open(relinfo_file, "r") as f:
|
||||||
|
return json.load(f)["version"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_remote_client_version(client: ClientData) -> str:
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(client.get("tags_url")) as response:
|
||||||
|
data = json.loads(response.read())
|
||||||
|
return data[0]["name"]
|
||||||
|
except (JSONDecodeError, TypeError):
|
||||||
|
return "ERROR"
|
||||||
|
|
||||||
|
|
||||||
|
def backup_client_data(client: ClientData) -> None:
|
||||||
|
name = client.get("name")
|
||||||
|
src = client.get("dir")
|
||||||
|
dest = client.get("backup_dir")
|
||||||
|
|
||||||
|
with open(src.joinpath(".version"), "r") as v:
|
||||||
|
version = v.readlines()[0]
|
||||||
|
|
||||||
|
bm = BackupManager()
|
||||||
|
bm.backup_directory(f"{name}-{version}", src, dest)
|
||||||
|
if name == "mainsail":
|
||||||
|
bm.backup_file(MAINSAIL_CONFIG_JSON, dest)
|
||||||
|
bm.backup_file(NGINX_SITES_AVAILABLE.joinpath(name), dest)
|
||||||
|
|
||||||
|
|
||||||
|
def backup_client_config_data(client: ClientData) -> None:
|
||||||
|
client_config = client.get("client_config")
|
||||||
|
name = client_config.get("name")
|
||||||
|
source = client_config.get("dir")
|
||||||
|
target = client_config.get("backup_dir")
|
||||||
|
bm = BackupManager()
|
||||||
|
bm.backup_directory(name, source, target)
|
||||||
149
kiauh/components/webui_client/menus/client_remove_menu.py
Normal file
149
kiauh/components/webui_client/menus/client_remove_menu.py
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||||
|
# #
|
||||||
|
# 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 typing import Callable, Dict
|
||||||
|
|
||||||
|
from components.webui_client import client_remove, ClientData
|
||||||
|
from core.menus import BACK_HELP_FOOTER
|
||||||
|
from core.menus.base_menu import BaseMenu
|
||||||
|
from utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
|
class ClientRemoveMenu(BaseMenu):
|
||||||
|
def __init__(self, client: ClientData):
|
||||||
|
self.client = client
|
||||||
|
self.rm_client = False
|
||||||
|
self.rm_client_config = False
|
||||||
|
self.backup_mainsail_config_json = False
|
||||||
|
self.rm_moonraker_conf_section = False
|
||||||
|
self.rm_printer_cfg_section = False
|
||||||
|
|
||||||
|
super().__init__(
|
||||||
|
header=False,
|
||||||
|
options=self.get_options(),
|
||||||
|
footer_type=BACK_HELP_FOOTER,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_options(self) -> Dict[str, Callable]:
|
||||||
|
options = {
|
||||||
|
"0": self.toggle_all,
|
||||||
|
"1": self.toggle_rm_client,
|
||||||
|
"2": self.toggle_rm_client_config,
|
||||||
|
"3": self.toggle_rm_printer_cfg_section,
|
||||||
|
"4": self.toggle_rm_moonraker_conf_section,
|
||||||
|
"c": self.run_removal_process,
|
||||||
|
}
|
||||||
|
if self.client.get("name") == "mainsail":
|
||||||
|
options["5"] = self.toggle_backup_mainsail_config_json
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
|
def print_menu(self) -> None:
|
||||||
|
client_name = self.client.get("display_name")
|
||||||
|
client_config = self.client.get("client_config")
|
||||||
|
client_config_name = client_config.get("display_name")
|
||||||
|
|
||||||
|
header = f" [ Remove {client_name} ] "
|
||||||
|
color = COLOR_RED
|
||||||
|
count = 62 - len(color) - len(RESET_FORMAT)
|
||||||
|
checked = f"[{COLOR_CYAN}x{RESET_FORMAT}]"
|
||||||
|
unchecked = "[ ]"
|
||||||
|
o1 = checked if self.rm_client else unchecked
|
||||||
|
o2 = checked if self.rm_client_config else unchecked
|
||||||
|
o3 = checked if self.rm_printer_cfg_section else unchecked
|
||||||
|
o4 = checked if self.rm_moonraker_conf_section 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) Select everything |
|
||||||
|
|-------------------------------------------------------|
|
||||||
|
| 1) {o1} Remove {client_name:16} |
|
||||||
|
| 2) {o2} Remove {client_config_name:24} |
|
||||||
|
| |
|
||||||
|
| printer.cfg & moonraker.conf |
|
||||||
|
| 3) {o3} Remove printer.cfg include |
|
||||||
|
| 4) {o4} Remove Moonraker update section |
|
||||||
|
"""
|
||||||
|
)[1:]
|
||||||
|
|
||||||
|
if self.client.get("name") == "mainsail":
|
||||||
|
o5 = checked if self.backup_mainsail_config_json else unchecked
|
||||||
|
menu += textwrap.dedent(
|
||||||
|
f"""
|
||||||
|
| |
|
||||||
|
| Mainsail config.json |
|
||||||
|
| 5) {o5} Backup config.json |
|
||||||
|
"""
|
||||||
|
)[1:]
|
||||||
|
|
||||||
|
menu += textwrap.dedent(
|
||||||
|
"""
|
||||||
|
|-------------------------------------------------------|
|
||||||
|
| C) Continue |
|
||||||
|
"""
|
||||||
|
)[1:]
|
||||||
|
print(menu, end="")
|
||||||
|
|
||||||
|
def toggle_all(self, **kwargs) -> None:
|
||||||
|
self.rm_client = True
|
||||||
|
self.rm_client_config = True
|
||||||
|
self.backup_mainsail_config_json = True
|
||||||
|
self.rm_moonraker_conf_section = True
|
||||||
|
self.rm_printer_cfg_section = True
|
||||||
|
|
||||||
|
def toggle_rm_client(self, **kwargs) -> None:
|
||||||
|
self.rm_client = not self.rm_client
|
||||||
|
|
||||||
|
def toggle_rm_client_config(self, **kwargs) -> None:
|
||||||
|
self.rm_client_config = not self.rm_client_config
|
||||||
|
|
||||||
|
def toggle_backup_mainsail_config_json(self, **kwargs) -> None:
|
||||||
|
self.backup_mainsail_config_json = not self.backup_mainsail_config_json
|
||||||
|
|
||||||
|
def toggle_rm_moonraker_conf_section(self, **kwargs) -> None:
|
||||||
|
self.rm_moonraker_conf_section = not self.rm_moonraker_conf_section
|
||||||
|
|
||||||
|
def toggle_rm_printer_cfg_section(self, **kwargs) -> None:
|
||||||
|
self.rm_printer_cfg_section = not self.rm_printer_cfg_section
|
||||||
|
|
||||||
|
def run_removal_process(self, **kwargs) -> None:
|
||||||
|
if (
|
||||||
|
not self.rm_client
|
||||||
|
and not self.rm_client_config
|
||||||
|
and not self.backup_mainsail_config_json
|
||||||
|
and not self.rm_moonraker_conf_section
|
||||||
|
and not self.rm_printer_cfg_section
|
||||||
|
):
|
||||||
|
error = f"{COLOR_RED}Nothing selected ...{RESET_FORMAT}"
|
||||||
|
print(error)
|
||||||
|
return
|
||||||
|
|
||||||
|
client_remove.run_client_removal(
|
||||||
|
client=self.client,
|
||||||
|
rm_client=self.rm_client,
|
||||||
|
rm_client_config=self.rm_client_config,
|
||||||
|
backup_ms_config_json=self.backup_mainsail_config_json,
|
||||||
|
rm_moonraker_conf_section=self.rm_moonraker_conf_section,
|
||||||
|
rm_printer_cfg_section=self.rm_printer_cfg_section,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.rm_client = False
|
||||||
|
self.rm_client_config = False
|
||||||
|
self.backup_mainsail_config_json = False
|
||||||
|
self.rm_moonraker_conf_section = False
|
||||||
|
self.rm_printer_cfg_section = False
|
||||||
@@ -12,11 +12,15 @@
|
|||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from components.klipper.klipper_utils import backup_klipper_dir
|
from components.klipper.klipper_utils import backup_klipper_dir
|
||||||
from components.mainsail.mainsail_utils import backup_mainsail_data
|
|
||||||
from components.moonraker.moonraker_utils import (
|
from components.moonraker.moonraker_utils import (
|
||||||
backup_moonraker_dir,
|
backup_moonraker_dir,
|
||||||
backup_moonraker_db_dir,
|
backup_moonraker_db_dir,
|
||||||
)
|
)
|
||||||
|
from components.webui_client.client_utils import (
|
||||||
|
backup_client_data,
|
||||||
|
load_client_data,
|
||||||
|
backup_client_config_data,
|
||||||
|
)
|
||||||
from core.menus import BACK_FOOTER
|
from core.menus import BACK_FOOTER
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
from utils.common import backup_printer_config_dir
|
from utils.common import backup_printer_config_dir
|
||||||
@@ -35,6 +39,10 @@ class BackupMenu(BaseMenu):
|
|||||||
"3": self.backup_printer_config,
|
"3": self.backup_printer_config,
|
||||||
"4": self.backup_moonraker_db,
|
"4": self.backup_moonraker_db,
|
||||||
"5": self.backup_mainsail,
|
"5": self.backup_mainsail,
|
||||||
|
"6": self.backup_fluidd,
|
||||||
|
"7": self.backup_mainsail_config,
|
||||||
|
"8": self.backup_fluidd_config,
|
||||||
|
"9": self.backup_klipperscreen,
|
||||||
},
|
},
|
||||||
footer_type=BACK_FOOTER,
|
footer_type=BACK_FOOTER,
|
||||||
)
|
)
|
||||||
@@ -51,15 +59,15 @@ class BackupMenu(BaseMenu):
|
|||||||
|-------------------------------------------------------|
|
|-------------------------------------------------------|
|
||||||
| {line1:^62} |
|
| {line1:^62} |
|
||||||
|-------------------------------------------------------|
|
|-------------------------------------------------------|
|
||||||
| Klipper & Moonraker API: | Touchscreen GUI: |
|
| Klipper & Moonraker API: | Client-Config: |
|
||||||
| 1) [Klipper] | 7) [KlipperScreen] |
|
| 1) [Klipper] | 7) [Mainsail-Config] |
|
||||||
| 2) [Moonraker] | |
|
| 2) [Moonraker] | 8) [Fluidd-Config] |
|
||||||
| 3) [Config Folder] | Other: |
|
| 3) [Config Folder] | |
|
||||||
| 4) [Moonraker Database] | 9) [Telegram Bot] |
|
| 4) [Moonraker Database] | Touchscreen GUI: |
|
||||||
| | |
|
| | 9) [KlipperScreen] |
|
||||||
| Klipper Webinterface: | |
|
| Webinterface: | |
|
||||||
| 5) [Mainsail] | |
|
| 5) [Mainsail] | |
|
||||||
| 6) [Fluidd] | |
|
| 6) [Fluidd] | |
|
||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
print(menu, end="")
|
print(menu, end="")
|
||||||
@@ -77,13 +85,16 @@ class BackupMenu(BaseMenu):
|
|||||||
backup_moonraker_db_dir()
|
backup_moonraker_db_dir()
|
||||||
|
|
||||||
def backup_mainsail(self, **kwargs):
|
def backup_mainsail(self, **kwargs):
|
||||||
backup_mainsail_data()
|
backup_client_data(load_client_data("mainsail"))
|
||||||
|
|
||||||
def backup_fluidd(self, **kwargs):
|
def backup_fluidd(self, **kwargs):
|
||||||
pass
|
backup_client_data(load_client_data("fluidd"))
|
||||||
|
|
||||||
|
def backup_mainsail_config(self, **kwargs):
|
||||||
|
backup_client_config_data(load_client_data("mainsail"))
|
||||||
|
|
||||||
|
def backup_fluidd_config(self, **kwargs):
|
||||||
|
backup_client_config_data(load_client_data("fluidd"))
|
||||||
|
|
||||||
def backup_klipperscreen(self, **kwargs):
|
def backup_klipperscreen(self, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def backup_telegram_bot(self, **kwargs):
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@
|
|||||||
|
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from components.fluidd import fluidd_setup
|
|
||||||
from components.klipper import klipper_setup
|
from components.klipper import klipper_setup
|
||||||
from components.mainsail import mainsail_setup
|
|
||||||
from components.moonraker import moonraker_setup
|
from components.moonraker import moonraker_setup
|
||||||
|
from components.webui_client import client_setup
|
||||||
|
from components.webui_client.client_config import client_config_setup
|
||||||
from core.menus import BACK_FOOTER
|
from core.menus import BACK_FOOTER
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
from utils.constants import COLOR_GREEN, RESET_FORMAT
|
from utils.constants import COLOR_GREEN, RESET_FORMAT
|
||||||
@@ -31,13 +31,11 @@ class InstallMenu(BaseMenu):
|
|||||||
"2": self.install_moonraker,
|
"2": self.install_moonraker,
|
||||||
"3": self.install_mainsail,
|
"3": self.install_mainsail,
|
||||||
"4": self.install_fluidd,
|
"4": self.install_fluidd,
|
||||||
"5": self.install_klipperscreen,
|
"5": self.install_mainsail_config,
|
||||||
"6": self.install_pretty_gcode,
|
"6": self.install_fluidd_config,
|
||||||
"7": self.install_telegram_bot,
|
"7": None,
|
||||||
"8": self.install_obico,
|
"8": None,
|
||||||
"9": self.install_octoeverywhere,
|
"9": None,
|
||||||
"10": self.install_mobileraker,
|
|
||||||
"11": self.install_crowsnest,
|
|
||||||
},
|
},
|
||||||
footer_type=BACK_FOOTER,
|
footer_type=BACK_FOOTER,
|
||||||
)
|
)
|
||||||
@@ -51,16 +49,18 @@ class InstallMenu(BaseMenu):
|
|||||||
/=======================================================\\
|
/=======================================================\\
|
||||||
| {color}{header:~^{count}}{RESET_FORMAT} |
|
| {color}{header:~^{count}}{RESET_FORMAT} |
|
||||||
|-------------------------------------------------------|
|
|-------------------------------------------------------|
|
||||||
| Firmware & API: | Other: |
|
| Firmware & API: | Touchscreen GUI: |
|
||||||
| 1) [Klipper] | 6) [PrettyGCode] |
|
| 1) [Klipper] | 7) [KlipperScreen] |
|
||||||
| 2) [Moonraker] | 7) [Telegram Bot] |
|
| 2) [Moonraker] | |
|
||||||
| | 8) $(obico_install_title) |
|
| | Android / iOS: |
|
||||||
| Klipper Webinterface: | 9) [OctoEverywhere] |
|
| Webinterface: | 8) [Mobileraker] |
|
||||||
| 3) [Mainsail] | 10) [Mobileraker] |
|
| 3) [Mainsail] | |
|
||||||
| 4) [Fluidd] | |
|
| 4) [Fluidd] | Webcam Streamer: |
|
||||||
| | Webcam Streamer: |
|
| | 9) [Crowsnest] |
|
||||||
| Touchscreen GUI: | 11) [Crowsnest] |
|
| Client-Config: | |
|
||||||
| 5) [KlipperScreen] | |
|
| 5) [Mainsail-Config] | |
|
||||||
|
| 6) [Fluidd-Config] | |
|
||||||
|
| | |
|
||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
print(menu, end="")
|
print(menu, end="")
|
||||||
@@ -72,28 +72,13 @@ class InstallMenu(BaseMenu):
|
|||||||
moonraker_setup.install_moonraker()
|
moonraker_setup.install_moonraker()
|
||||||
|
|
||||||
def install_mainsail(self, **kwargs):
|
def install_mainsail(self, **kwargs):
|
||||||
mainsail_setup.install_mainsail()
|
client_setup.install_client(client_name="mainsail")
|
||||||
|
|
||||||
|
def install_mainsail_config(self, **kwargs):
|
||||||
|
client_config_setup.install_client_config(client_name="mainsail")
|
||||||
|
|
||||||
def install_fluidd(self, **kwargs):
|
def install_fluidd(self, **kwargs):
|
||||||
fluidd_setup.install_fluidd()
|
client_setup.install_client(client_name="fluidd")
|
||||||
|
|
||||||
def install_klipperscreen(self, **kwargs):
|
def install_fluidd_config(self, **kwargs):
|
||||||
print("install_klipperscreen")
|
client_config_setup.install_client_config(client_name="fluidd")
|
||||||
|
|
||||||
def install_pretty_gcode(self, **kwargs):
|
|
||||||
print("install_pretty_gcode")
|
|
||||||
|
|
||||||
def install_telegram_bot(self, **kwargs):
|
|
||||||
print("install_telegram_bot")
|
|
||||||
|
|
||||||
def install_obico(self, **kwargs):
|
|
||||||
print("install_obico")
|
|
||||||
|
|
||||||
def install_octoeverywhere(self, **kwargs):
|
|
||||||
print("install_octoeverywhere")
|
|
||||||
|
|
||||||
def install_mobileraker(self, **kwargs):
|
|
||||||
print("install_mobileraker")
|
|
||||||
|
|
||||||
def install_crowsnest(self, **kwargs):
|
|
||||||
print("install_crowsnest")
|
|
||||||
|
|||||||
@@ -11,11 +11,14 @@
|
|||||||
|
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from components.fluidd.fluidd_utils import get_fluidd_status
|
|
||||||
from components.klipper.klipper_utils import get_klipper_status
|
from components.klipper.klipper_utils import get_klipper_status
|
||||||
from components.log_uploads.menus.log_upload_menu import LogUploadMenu
|
from components.log_uploads.menus.log_upload_menu import LogUploadMenu
|
||||||
from components.mainsail.mainsail_utils import get_mainsail_status
|
|
||||||
from components.moonraker.moonraker_utils import get_moonraker_status
|
from components.moonraker.moonraker_utils import get_moonraker_status
|
||||||
|
from components.webui_client.client_utils import (
|
||||||
|
get_client_status,
|
||||||
|
load_client_data,
|
||||||
|
get_current_client_config,
|
||||||
|
)
|
||||||
from core.menus import QUIT_FOOTER
|
from core.menus import QUIT_FOOTER
|
||||||
from core.menus.advanced_menu import AdvancedMenu
|
from core.menus.advanced_menu import AdvancedMenu
|
||||||
from core.menus.backup_menu import BackupMenu
|
from core.menus.backup_menu import BackupMenu
|
||||||
@@ -61,13 +64,11 @@ class MainMenu(BaseMenu):
|
|||||||
self.ks_status = ""
|
self.ks_status = ""
|
||||||
self.mb_status = ""
|
self.mb_status = ""
|
||||||
self.cn_status = ""
|
self.cn_status = ""
|
||||||
self.tg_status = ""
|
self.cc_status = ""
|
||||||
self.ob_status = ""
|
|
||||||
self.oe_status = ""
|
|
||||||
self.init_status()
|
self.init_status()
|
||||||
|
|
||||||
def init_status(self) -> None:
|
def init_status(self) -> None:
|
||||||
status_vars = ["kl", "mr", "ms", "fl", "ks", "mb", "cn", "tg", "ob", "oe"]
|
status_vars = ["kl", "mr", "ms", "fl", "ks", "mb", "cn"]
|
||||||
for var in status_vars:
|
for var in status_vars:
|
||||||
setattr(self, f"{var}_status", f"{COLOR_RED}Not installed!{RESET_FORMAT}")
|
setattr(self, f"{var}_status", f"{COLOR_RED}Not installed!{RESET_FORMAT}")
|
||||||
|
|
||||||
@@ -87,9 +88,15 @@ class MainMenu(BaseMenu):
|
|||||||
self.mr_status = self.format_status_by_code(mr_code, mr_status, mr_instances)
|
self.mr_status = self.format_status_by_code(mr_code, mr_status, mr_instances)
|
||||||
self.mr_repo = f"{COLOR_CYAN}{moonraker_status.get('repo')}{RESET_FORMAT}"
|
self.mr_repo = f"{COLOR_CYAN}{moonraker_status.get('repo')}{RESET_FORMAT}"
|
||||||
# mainsail
|
# mainsail
|
||||||
self.ms_status = get_mainsail_status()
|
mainsail_client_data = load_client_data("mainsail")
|
||||||
|
self.ms_status = get_client_status(mainsail_client_data)
|
||||||
# fluidd
|
# fluidd
|
||||||
self.fl_status = get_fluidd_status()
|
fluidd_client_data = load_client_data("fluidd")
|
||||||
|
self.fl_status = get_client_status(fluidd_client_data)
|
||||||
|
# client-config
|
||||||
|
self.cc_status = get_current_client_config(
|
||||||
|
[mainsail_client_data, fluidd_client_data]
|
||||||
|
)
|
||||||
|
|
||||||
def format_status_by_code(self, code: int, status: str, count: str) -> str:
|
def format_status_by_code(self, code: int, status: str, count: str) -> str:
|
||||||
if code == 1:
|
if code == 1:
|
||||||
@@ -120,13 +127,11 @@ class MainMenu(BaseMenu):
|
|||||||
| 4) [Advanced] |------------------------------------|
|
| 4) [Advanced] |------------------------------------|
|
||||||
| 5) [Backup] | Mainsail: {self.ms_status:<26} |
|
| 5) [Backup] | Mainsail: {self.ms_status:<26} |
|
||||||
| | Fluidd: {self.fl_status:<26} |
|
| | Fluidd: {self.fl_status:<26} |
|
||||||
| E) [Extensions] | KlipperScreen: {self.ks_status:<26} |
|
| S) [Settings] | Client-Config: {self.cc_status:<26} |
|
||||||
| | Mobileraker: {self.mb_status:<26} |
|
|
||||||
| | |
|
| | |
|
||||||
|
| Community: | KlipperScreen: {self.ks_status:<26} |
|
||||||
|
| E) [Extensions] | Mobileraker: {self.mb_status:<26} |
|
||||||
| | Crowsnest: {self.cn_status:<26} |
|
| | Crowsnest: {self.cn_status:<26} |
|
||||||
| | Telegram Bot: {self.tg_status:<26} |
|
|
||||||
| | Obico: {self.ob_status:<26} |
|
|
||||||
| S) [Settings] | OctoEverywhere: {self.oe_status:<26} |
|
|
||||||
|-------------------------------------------------------|
|
|-------------------------------------------------------|
|
||||||
| {COLOR_CYAN}{footer1:^16}{RESET_FORMAT} | {footer2:^43} |
|
| {COLOR_CYAN}{footer1:^16}{RESET_FORMAT} | {footer2:^43} |
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -11,10 +11,10 @@
|
|||||||
|
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from components.fluidd.menus.fluidd_remove_menu import FluiddRemoveMenu
|
|
||||||
from components.klipper.menus.klipper_remove_menu import KlipperRemoveMenu
|
from components.klipper.menus.klipper_remove_menu import KlipperRemoveMenu
|
||||||
from components.mainsail.menus.mainsail_remove_menu import MainsailRemoveMenu
|
|
||||||
from components.moonraker.menus.moonraker_remove_menu import MoonrakerRemoveMenu
|
from components.moonraker.menus.moonraker_remove_menu import MoonrakerRemoveMenu
|
||||||
|
from components.webui_client.client_utils import load_client_data
|
||||||
|
from components.webui_client.menus.client_remove_menu import ClientRemoveMenu
|
||||||
from core.menus import BACK_FOOTER
|
from core.menus import BACK_FOOTER
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
from utils.constants import COLOR_RED, RESET_FORMAT
|
from utils.constants import COLOR_RED, RESET_FORMAT
|
||||||
@@ -29,8 +29,8 @@ class RemoveMenu(BaseMenu):
|
|||||||
options={
|
options={
|
||||||
"1": KlipperRemoveMenu,
|
"1": KlipperRemoveMenu,
|
||||||
"2": MoonrakerRemoveMenu,
|
"2": MoonrakerRemoveMenu,
|
||||||
"3": MainsailRemoveMenu,
|
"3": ClientRemoveMenu(client=load_client_data("mainsail")),
|
||||||
"4": FluiddRemoveMenu,
|
"4": ClientRemoveMenu(client=load_client_data("fluidd")),
|
||||||
"5": None,
|
"5": None,
|
||||||
"6": None,
|
"6": None,
|
||||||
"7": None,
|
"7": None,
|
||||||
|
|||||||
@@ -11,22 +11,22 @@
|
|||||||
|
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from components.fluidd.fluidd_setup import update_fluidd
|
|
||||||
from components.fluidd.fluidd_utils import (
|
|
||||||
get_fluidd_local_version,
|
|
||||||
get_fluidd_remote_version,
|
|
||||||
)
|
|
||||||
from components.klipper.klipper_setup import update_klipper
|
from components.klipper.klipper_setup import update_klipper
|
||||||
from components.klipper.klipper_utils import (
|
from components.klipper.klipper_utils import (
|
||||||
get_klipper_status,
|
get_klipper_status,
|
||||||
)
|
)
|
||||||
from components.mainsail.mainsail_setup import update_mainsail
|
|
||||||
from components.mainsail.mainsail_utils import (
|
|
||||||
get_mainsail_local_version,
|
|
||||||
get_mainsail_remote_version,
|
|
||||||
)
|
|
||||||
from components.moonraker.moonraker_setup import update_moonraker
|
from components.moonraker.moonraker_setup import update_moonraker
|
||||||
from components.moonraker.moonraker_utils import get_moonraker_status
|
from components.moonraker.moonraker_utils import get_moonraker_status
|
||||||
|
from components.webui_client.client_config.client_config_setup import (
|
||||||
|
update_client_config,
|
||||||
|
)
|
||||||
|
from components.webui_client.client_setup import update_client
|
||||||
|
from components.webui_client.client_utils import (
|
||||||
|
get_local_client_version,
|
||||||
|
get_remote_client_version,
|
||||||
|
load_client_data,
|
||||||
|
get_client_config_status,
|
||||||
|
)
|
||||||
from core.menus import BACK_FOOTER
|
from core.menus import BACK_FOOTER
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
from utils.constants import (
|
from utils.constants import (
|
||||||
@@ -50,14 +50,12 @@ class UpdateMenu(BaseMenu):
|
|||||||
"2": self.update_moonraker,
|
"2": self.update_moonraker,
|
||||||
"3": self.update_mainsail,
|
"3": self.update_mainsail,
|
||||||
"4": self.update_fluidd,
|
"4": self.update_fluidd,
|
||||||
"5": self.update_klipperscreen,
|
"5": self.update_mainsail_config,
|
||||||
"6": self.update_pgc_for_klipper,
|
"6": self.update_fluidd_config,
|
||||||
"7": self.update_telegram_bot,
|
"7": self.update_klipperscreen,
|
||||||
"8": self.update_moonraker_obico,
|
"8": self.update_mobileraker,
|
||||||
"9": self.update_octoeverywhere,
|
"9": self.update_crowsnest,
|
||||||
"10": self.update_mobileraker,
|
"10": self.upgrade_system_packages,
|
||||||
"11": self.update_crowsnest,
|
|
||||||
"12": self.upgrade_system_packages,
|
|
||||||
},
|
},
|
||||||
footer_type=BACK_FOOTER,
|
footer_type=BACK_FOOTER,
|
||||||
)
|
)
|
||||||
@@ -69,6 +67,10 @@ class UpdateMenu(BaseMenu):
|
|||||||
self.ms_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
|
self.ms_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||||
self.fl_local = f"{COLOR_WHITE}{RESET_FORMAT}"
|
self.fl_local = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||||
self.fl_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
|
self.fl_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||||
|
self.mc_local = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||||
|
self.mc_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||||
|
self.fc_local = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||||
|
self.fc_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||||
|
|
||||||
def print_menu(self):
|
def print_menu(self):
|
||||||
self.fetch_update_status()
|
self.fetch_update_status()
|
||||||
@@ -87,22 +89,20 @@ class UpdateMenu(BaseMenu):
|
|||||||
| 1) Klipper | {self.kl_local:<22} | {self.kl_remote:<22} |
|
| 1) Klipper | {self.kl_local:<22} | {self.kl_remote:<22} |
|
||||||
| 2) Moonraker | {self.mr_local:<22} | {self.mr_remote:<22} |
|
| 2) Moonraker | {self.mr_local:<22} | {self.mr_remote:<22} |
|
||||||
| | | |
|
| | | |
|
||||||
| Klipper Webinterface: |---------------|---------------|
|
| Webinterface: |---------------|---------------|
|
||||||
| 3) Mainsail | {self.ms_local:<22} | {self.ms_remote:<22} |
|
| 3) Mainsail | {self.ms_local:<22} | {self.ms_remote:<22} |
|
||||||
| 4) Fluidd | {self.fl_local:<22} | {self.fl_remote:<22} |
|
| 4) Fluidd | {self.fl_local:<22} | {self.fl_remote:<22} |
|
||||||
| | | |
|
| | | |
|
||||||
| Touchscreen GUI: |---------------|---------------|
|
| Client-Config: |---------------|---------------|
|
||||||
| 5) KlipperScreen | | |
|
| 5) Mainsail-Config | {self.mc_local:<22} | {self.mc_remote:<22} |
|
||||||
|
| 6) Fluidd-Config | {self.fc_local:<22} | {self.fc_remote:<22} |
|
||||||
| | | |
|
| | | |
|
||||||
| Other: |---------------|---------------|
|
| Other: |---------------|---------------|
|
||||||
| 6) PrettyGCode | | |
|
| 7) KlipperScreen | | |
|
||||||
| 7) Telegram Bot | | |
|
| 8) Mobileraker | | |
|
||||||
| 8) Obico for Klipper | | |
|
| 9) Crowsnest | | |
|
||||||
| 9) OctoEverywhere | | |
|
|
||||||
| 10) Mobileraker | | |
|
|
||||||
| 11) Crowsnest | | |
|
|
||||||
| |-------------------------------|
|
| |-------------------------------|
|
||||||
| 12) System | |
|
| 10) System | |
|
||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
print(menu, end="")
|
print(menu, end="")
|
||||||
@@ -117,34 +117,24 @@ class UpdateMenu(BaseMenu):
|
|||||||
update_moonraker()
|
update_moonraker()
|
||||||
|
|
||||||
def update_mainsail(self, **kwargs):
|
def update_mainsail(self, **kwargs):
|
||||||
update_mainsail()
|
update_client(load_client_data("mainsail"))
|
||||||
|
|
||||||
|
def update_mainsail_config(self, **kwargs):
|
||||||
|
update_client_config(load_client_data("mainsail"))
|
||||||
|
|
||||||
def update_fluidd(self, **kwargs):
|
def update_fluidd(self, **kwargs):
|
||||||
update_fluidd()
|
update_client(load_client_data("fluidd"))
|
||||||
|
|
||||||
def update_klipperscreen(self, **kwargs):
|
def update_fluidd_config(self, **kwargs):
|
||||||
print("update_klipperscreen")
|
update_client_config(load_client_data("fluidd"))
|
||||||
|
|
||||||
def update_pgc_for_klipper(self, **kwargs):
|
def update_klipperscreen(self, **kwargs): ...
|
||||||
print("update_pgc_for_klipper")
|
|
||||||
|
|
||||||
def update_telegram_bot(self, **kwargs):
|
def update_mobileraker(self, **kwargs): ...
|
||||||
print("update_telegram_bot")
|
|
||||||
|
|
||||||
def update_moonraker_obico(self, **kwargs):
|
def update_crowsnest(self, **kwargs): ...
|
||||||
print("update_moonraker_obico")
|
|
||||||
|
|
||||||
def update_octoeverywhere(self, **kwargs):
|
def upgrade_system_packages(self, **kwargs): ...
|
||||||
print("update_octoeverywhere")
|
|
||||||
|
|
||||||
def update_mobileraker(self, **kwargs):
|
|
||||||
print("update_mobileraker")
|
|
||||||
|
|
||||||
def update_crowsnest(self, **kwargs):
|
|
||||||
print("update_crowsnest")
|
|
||||||
|
|
||||||
def upgrade_system_packages(self, **kwargs):
|
|
||||||
print("upgrade_system_packages")
|
|
||||||
|
|
||||||
def fetch_update_status(self):
|
def fetch_update_status(self):
|
||||||
# klipper
|
# klipper
|
||||||
@@ -166,18 +156,38 @@ class UpdateMenu(BaseMenu):
|
|||||||
self.mr_local = f"{COLOR_YELLOW}{self.mr_local}{RESET_FORMAT}"
|
self.mr_local = f"{COLOR_YELLOW}{self.mr_local}{RESET_FORMAT}"
|
||||||
self.mr_remote = f"{COLOR_GREEN}{self.mr_remote}{RESET_FORMAT}"
|
self.mr_remote = f"{COLOR_GREEN}{self.mr_remote}{RESET_FORMAT}"
|
||||||
# mainsail
|
# mainsail
|
||||||
self.ms_local = get_mainsail_local_version()
|
mainsail_client_data = load_client_data("mainsail")
|
||||||
self.ms_remote = get_mainsail_remote_version()
|
self.ms_local = get_local_client_version(mainsail_client_data)
|
||||||
|
self.ms_remote = get_remote_client_version(mainsail_client_data)
|
||||||
if self.ms_local == self.ms_remote:
|
if self.ms_local == self.ms_remote:
|
||||||
self.ms_local = f"{COLOR_GREEN}{self.ms_local}{RESET_FORMAT}"
|
self.ms_local = f"{COLOR_GREEN}{self.ms_local}{RESET_FORMAT}"
|
||||||
else:
|
else:
|
||||||
self.ms_local = f"{COLOR_YELLOW}{self.ms_local}{RESET_FORMAT}"
|
self.ms_local = f"{COLOR_YELLOW}{self.ms_local}{RESET_FORMAT}"
|
||||||
self.ms_remote = f"{COLOR_GREEN if self.ms_remote != 'ERROR' else COLOR_RED}{self.ms_remote}{RESET_FORMAT}"
|
self.ms_remote = f"{COLOR_GREEN if self.ms_remote != 'ERROR' else COLOR_RED}{self.ms_remote}{RESET_FORMAT}"
|
||||||
# fluidd
|
# fluidd
|
||||||
self.fl_local = get_fluidd_local_version()
|
fluidd_client_data = load_client_data("fluidd")
|
||||||
self.fl_remote = get_fluidd_remote_version()
|
self.fl_local = get_local_client_version(fluidd_client_data)
|
||||||
|
self.fl_remote = get_remote_client_version(fluidd_client_data)
|
||||||
if self.fl_local == self.fl_remote:
|
if self.fl_local == self.fl_remote:
|
||||||
self.fl_local = f"{COLOR_GREEN}{self.fl_local}{RESET_FORMAT}"
|
self.fl_local = f"{COLOR_GREEN}{self.fl_local}{RESET_FORMAT}"
|
||||||
else:
|
else:
|
||||||
self.fl_local = f"{COLOR_YELLOW}{self.fl_local}{RESET_FORMAT}"
|
self.fl_local = f"{COLOR_YELLOW}{self.fl_local}{RESET_FORMAT}"
|
||||||
self.fl_remote = f"{COLOR_GREEN if self.fl_remote != 'ERROR' else COLOR_RED}{self.fl_remote}{RESET_FORMAT}"
|
self.fl_remote = f"{COLOR_GREEN if self.fl_remote != 'ERROR' else COLOR_RED}{self.fl_remote}{RESET_FORMAT}"
|
||||||
|
# mainsail-config
|
||||||
|
mc_status = get_client_config_status(load_client_data("mainsail"))
|
||||||
|
self.mc_local = mc_status.get("local")
|
||||||
|
self.mc_remote = mc_status.get("remote")
|
||||||
|
if self.mc_local == self.mc_remote:
|
||||||
|
self.mc_local = f"{COLOR_GREEN}{self.mc_local}{RESET_FORMAT}"
|
||||||
|
else:
|
||||||
|
self.mc_local = f"{COLOR_YELLOW}{self.mc_local}{RESET_FORMAT}"
|
||||||
|
self.mc_remote = f"{COLOR_GREEN}{self.mc_remote}{RESET_FORMAT}"
|
||||||
|
# fluidd-config
|
||||||
|
fc_status = get_client_config_status(load_client_data("fluidd"))
|
||||||
|
self.fc_local = fc_status.get("local")
|
||||||
|
self.fc_remote = fc_status.get("remote")
|
||||||
|
if self.fc_local == self.mc_remote:
|
||||||
|
self.fc_local = f"{COLOR_GREEN}{self.fc_local}{RESET_FORMAT}"
|
||||||
|
else:
|
||||||
|
self.fc_local = f"{COLOR_YELLOW}{self.fc_local}{RESET_FORMAT}"
|
||||||
|
self.fc_remote = f"{COLOR_GREEN}{self.fc_remote}{RESET_FORMAT}"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# ======================================================================= #
|
# ======================================================================= #
|
||||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||||
# #
|
# #
|
||||||
@@ -7,14 +8,20 @@
|
|||||||
# #
|
# #
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license #
|
# This file may be distributed under the terms of the GNU GPLv3 license #
|
||||||
# ======================================================================= #
|
# ======================================================================= #
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from typing import List
|
from typing import List, Type, TypeVar, Union, Tuple
|
||||||
|
|
||||||
|
from components.klipper.klipper import Klipper
|
||||||
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
from core.config_manager.config_manager import ConfigManager
|
||||||
|
from core.instance_manager.base_instance import BaseInstance
|
||||||
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from utils import (
|
from utils import (
|
||||||
NGINX_SITES_AVAILABLE,
|
NGINX_SITES_AVAILABLE,
|
||||||
MODULE_PATH,
|
MODULE_PATH,
|
||||||
@@ -24,6 +31,10 @@ from utils import (
|
|||||||
from utils.logger import Logger
|
from utils.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
|
B = TypeVar('B', bound='BaseInstance')
|
||||||
|
ConfigOption = Tuple[str, str]
|
||||||
|
|
||||||
|
|
||||||
def check_file_exist(file_path: Path, sudo=False) -> bool:
|
def check_file_exist(file_path: Path, sudo=False) -> bool:
|
||||||
"""
|
"""
|
||||||
Helper function for checking the existence of a file |
|
Helper function for checking the existence of a file |
|
||||||
@@ -169,3 +180,102 @@ def get_next_free_port(ports_in_use: List[str]) -> str:
|
|||||||
used_ports = set(map(int, ports_in_use))
|
used_ports = set(map(int, ports_in_use))
|
||||||
|
|
||||||
return str(min(valid_ports - used_ports))
|
return str(min(valid_ports - used_ports))
|
||||||
|
|
||||||
|
|
||||||
|
def add_config_section(section: str, instances: List[B], options: List[ConfigOption] = None) -> None:
|
||||||
|
for instance in instances:
|
||||||
|
cfg_file = instance.cfg_file
|
||||||
|
Logger.print_status(f"Add section '[{section}]' to '{cfg_file}' ...")
|
||||||
|
|
||||||
|
if not Path(cfg_file).exists():
|
||||||
|
Logger.print_warn(f"'{cfg_file}' not found!")
|
||||||
|
continue
|
||||||
|
|
||||||
|
cm = ConfigManager(cfg_file)
|
||||||
|
if cm.config.has_section(section):
|
||||||
|
Logger.print_info("Section already exist. Skipped ...")
|
||||||
|
continue
|
||||||
|
|
||||||
|
cm.config.add_section(section)
|
||||||
|
|
||||||
|
if options is not None:
|
||||||
|
for option in options:
|
||||||
|
cm.config.set(section, option[0], option[1])
|
||||||
|
|
||||||
|
cm.write_config()
|
||||||
|
|
||||||
|
|
||||||
|
def remove_config_section(section: str, instances: List[B]) -> None:
|
||||||
|
for instance in instances:
|
||||||
|
cfg_file = instance.cfg_file
|
||||||
|
Logger.print_status(f"Remove section '[{section}]' from '{cfg_file}' ...")
|
||||||
|
|
||||||
|
if not Path(cfg_file).exists():
|
||||||
|
Logger.print_warn(f"'{cfg_file}' not found!")
|
||||||
|
continue
|
||||||
|
|
||||||
|
cm = ConfigManager(cfg_file)
|
||||||
|
if not cm.config.has_section(section):
|
||||||
|
Logger.print_info("Section does not exist. Skipped ...")
|
||||||
|
continue
|
||||||
|
|
||||||
|
cm.config.remove_section(section)
|
||||||
|
cm.write_config()
|
||||||
|
|
||||||
|
|
||||||
|
def patch_moonraker_conf(
|
||||||
|
moonraker_instances: List[Moonraker],
|
||||||
|
name: str,
|
||||||
|
section_name: str,
|
||||||
|
template_file: str,
|
||||||
|
) -> None:
|
||||||
|
for instance in moonraker_instances:
|
||||||
|
cfg_file = instance.cfg_file
|
||||||
|
Logger.print_status(f"Add {name} update section to '{cfg_file}' ...")
|
||||||
|
|
||||||
|
if not Path(cfg_file).exists():
|
||||||
|
Logger.print_warn(f"'{cfg_file}' not found!")
|
||||||
|
return
|
||||||
|
|
||||||
|
cm = ConfigManager(cfg_file)
|
||||||
|
if cm.config.has_section(section_name):
|
||||||
|
Logger.print_info("Section already exist. Skipped ...")
|
||||||
|
return
|
||||||
|
|
||||||
|
template = MODULE_PATH.joinpath("assets", template_file)
|
||||||
|
with open(template, "r") as t:
|
||||||
|
template_content = "\n"
|
||||||
|
template_content += t.read()
|
||||||
|
|
||||||
|
with open(cfg_file, "a") as f:
|
||||||
|
f.write(template_content)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_nginx_config(name: str) -> None:
|
||||||
|
Logger.print_status(f"Removing NGINX config for {name.capitalize()} ...")
|
||||||
|
try:
|
||||||
|
remove_file(NGINX_SITES_AVAILABLE.joinpath(name), True)
|
||||||
|
remove_file(NGINX_SITES_ENABLED.joinpath(name), True)
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
log = f"Unable to remove NGINX config '{name}':\n{e.stderr.decode()}"
|
||||||
|
Logger.print_error(log)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_nginx_logs(name: str) -> None:
|
||||||
|
Logger.print_status(f"Removing NGINX logs for {name.capitalize()} ...")
|
||||||
|
try:
|
||||||
|
remove_file(Path(f"/var/log/nginx/{name}-access.log"), True)
|
||||||
|
remove_file(Path(f"/var/log/nginx/{name}-error.log"), True)
|
||||||
|
|
||||||
|
im = InstanceManager(Klipper)
|
||||||
|
instances: List[Klipper] = im.instances
|
||||||
|
if not instances:
|
||||||
|
return
|
||||||
|
|
||||||
|
for instance in instances:
|
||||||
|
remove_file(instance.log_dir.joinpath(f"{name}-access.log"))
|
||||||
|
remove_file(instance.log_dir.joinpath(f"{name}-error.log"))
|
||||||
|
|
||||||
|
except (OSError, subprocess.CalledProcessError) as e:
|
||||||
|
Logger.print_error(f"Unable to remove NGINX logs:\n{e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user