mirror of
https://github.com/dw-0/kiauh.git
synced 2025-12-23 15:53:36 +05:00
Compare commits
26 Commits
55435ff935
...
eabdca0e3d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eabdca0e3d | ||
|
|
1620efe56c | ||
|
|
b6c6edb622 | ||
|
|
099d47df2f | ||
|
|
ba1cdb3739 | ||
|
|
8e7d4db988 | ||
|
|
8f960495ba | ||
|
|
095823bf28 | ||
|
|
397038e43e | ||
|
|
061e222664 | ||
|
|
3f5ff50d69 | ||
|
|
5ebe941125 | ||
|
|
f5eb9486cc | ||
|
|
7a9e752f9c | ||
|
|
30bc56b198 | ||
|
|
b2567995de | ||
|
|
6fcd7a3f08 | ||
|
|
25dfbb83df | ||
|
|
899b204dc7 | ||
|
|
5cf4b018fc | ||
|
|
ae9d1b98da | ||
|
|
16d3388ff2 | ||
|
|
b88d0085ba | ||
|
|
0b6613e464 | ||
|
|
d99cda544a | ||
|
|
a50dce20de |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
custom: https://paypal.me/dwillner0
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
.idea
|
||||
.vscode
|
||||
.idea
|
||||
.pytest_cache
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
### 📋 Prerequisites
|
||||
KIAUH is a script that assists you in installing Klipper on a Linux operating system that has
|
||||
already been flashed to your Raspberry Pi's (or other SBC's) SD card. As a result, you must ensure
|
||||
that you have a functional Linux system on hand. `Raspberry Pi OS Lite (32bit)` is a recommended Linux image
|
||||
that you have a functional Linux system on hand. `Raspberry Pi OS Lite (either 32bit or 64bit)` is a recommended Linux image
|
||||
if you are using a Raspberry Pi. The [official Raspberry Pi Imager](https://www.raspberrypi.com/software/)
|
||||
is the simplest way to flash an image like this to an SD card.
|
||||
|
||||
@@ -39,7 +39,7 @@ select `Choose OS -> Raspberry Pi OS (other)`: \
|
||||
<img src="https://raw.githubusercontent.com/dw-0/kiauh/master/resources/screenshots/rpi_imager1.png" alt="KIAUH logo" height="350">
|
||||
</p>
|
||||
|
||||
* Then select `Raspberry Pi OS Lite (32bit)`:
|
||||
* Then select `Raspberry Pi OS Lite (32bit)` (or 64bit if you want to use that instead):
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/dw-0/kiauh/master/resources/screenshots/rpi_imager2.png" alt="KIAUH logo" height="350">
|
||||
</p>
|
||||
@@ -125,7 +125,7 @@ prompt and confirm by hitting ENTER.
|
||||
<tr>
|
||||
<th><img src="https://raw.githubusercontent.com/fluidd-core/fluidd/master/docs/assets/images/logo.svg" alt="Fluidd Logo" height="64"></th>
|
||||
<th><img src="https://avatars.githubusercontent.com/u/31575189?v=4" alt="jordanruthe avatar" height="64"></th>
|
||||
<th><img src="https://camo.githubusercontent.com/627be7fc67195b626b298af9b9677d7c58e698c67305e54324cffbe06130d4a4/68747470733a2f2f6f63746f7072696e742e6f72672f6173736574732f696d672f6c6f676f2e706e67" alt="OctoPrint Logo" height="64"></th>
|
||||
<th><img src="https://raw.githubusercontent.com/OctoPrint/OctoPrint/master/docs/images/octoprint-logo.png" alt="OctoPrint Logo" height="64"></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>by <a href="https://github.com/fluidd-core">fluidd-core</a></th>
|
||||
|
||||
2
kiauh.sh
2
kiauh.sh
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -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,
|
||||
"3": self.toggle_remove_klipper_env,
|
||||
"4": self.toggle_delete_klipper_logs,
|
||||
"5": self.run_removal_process,
|
||||
"c": self.run_removal_process,
|
||||
},
|
||||
footer_type=BACK_HELP_FOOTER,
|
||||
)
|
||||
@@ -62,7 +62,7 @@ class KlipperRemoveMenu(BaseMenu):
|
||||
| 3) {o3} Remove Python Environment |
|
||||
| 4) {o4} Delete all Log-Files |
|
||||
|-------------------------------------------------------|
|
||||
| 5) Continue |
|
||||
| C) Continue |
|
||||
"""
|
||||
)[1:]
|
||||
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,
|
||||
"4": self.toggle_remove_moonraker_polkit,
|
||||
"5": self.toggle_delete_moonraker_logs,
|
||||
"6": self.run_removal_process,
|
||||
"c": self.run_removal_process,
|
||||
},
|
||||
footer_type=BACK_HELP_FOOTER,
|
||||
)
|
||||
@@ -66,7 +66,7 @@ class MoonrakerRemoveMenu(BaseMenu):
|
||||
| 4) {o4} Remove Policy Kit Rules |
|
||||
| 5) {o5} Delete all Log-Files |
|
||||
|-------------------------------------------------------|
|
||||
| 6) Continue |
|
||||
| C) Continue |
|
||||
"""
|
||||
)[1:]
|
||||
print(menu, end="")
|
||||
|
||||
@@ -14,11 +14,11 @@ import sys
|
||||
from pathlib import Path
|
||||
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 components.klipper.klipper import Klipper
|
||||
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 (
|
||||
EXIT_MOONRAKER_SETUP,
|
||||
DEFAULT_MOONRAKER_REPO_URL,
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
import shutil
|
||||
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 (
|
||||
DEFAULT_MOONRAKER_PORT,
|
||||
MODULE_PATH,
|
||||
@@ -23,6 +21,8 @@ from components.moonraker import (
|
||||
MOONRAKER_DB_BACKUP_DIR,
|
||||
)
|
||||
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.config_manager.config_manager import ConfigManager
|
||||
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
|
||||
from typing import List
|
||||
|
||||
from components.webui_client import ClientData
|
||||
from core.menus.base_menu import print_back_footer
|
||||
from utils.constants import RESET_FORMAT, COLOR_YELLOW, COLOR_CYAN
|
||||
|
||||
@@ -25,10 +26,10 @@ def print_moonraker_not_found_dialog():
|
||||
| {line1:<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 |
|
||||
| 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. |
|
||||
"""
|
||||
)[1:]
|
||||
@@ -37,19 +38,18 @@ def print_moonraker_not_found_dialog():
|
||||
print_back_footer()
|
||||
|
||||
|
||||
def print_fluidd_already_installed_dialog():
|
||||
def print_client_already_installed_dialog(name: str):
|
||||
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(
|
||||
f"""
|
||||
/=======================================================\\
|
||||
| {line1:<63}|
|
||||
| {line2:<63}|
|
||||
|-------------------------------------------------------|
|
||||
| If you continue, your current Fluidd installation |
|
||||
| will be overwritten. You will not loose any printer |
|
||||
| configurations and the Moonraker database will remain |
|
||||
| untouched. |
|
||||
| {line3:<54}|
|
||||
| installation will be overwritten. |
|
||||
"""
|
||||
)[1:]
|
||||
|
||||
@@ -57,38 +57,21 @@ def print_fluidd_already_installed_dialog():
|
||||
print_back_footer()
|
||||
|
||||
|
||||
def print_install_fluidd_config_dialog():
|
||||
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]):
|
||||
def print_client_port_select_dialog(name: str, port: str, ports_in_use: List[str]):
|
||||
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(
|
||||
f"""
|
||||
/=======================================================\\
|
||||
| Please select the port, Fluidd should be served on. |
|
||||
| {line1:<54}|
|
||||
| If you are unsure what to select, hit Enter to apply |
|
||||
| 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 |
|
||||
| used by any other application on your system! |
|
||||
\\=======================================================/
|
||||
"""
|
||||
)[1:]
|
||||
|
||||
@@ -102,3 +85,27 @@ def print_fluidd_port_select_dialog(port: str, ports_in_use: List[str]):
|
||||
dialog += "\\=======================================================/\n"
|
||||
|
||||
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
|
||||
|
||||
from components.klipper.klipper_utils import backup_klipper_dir
|
||||
from components.mainsail.mainsail_utils import backup_mainsail_data
|
||||
from components.moonraker.moonraker_utils import (
|
||||
backup_moonraker_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.base_menu import BaseMenu
|
||||
from utils.common import backup_printer_config_dir
|
||||
@@ -35,6 +39,10 @@ class BackupMenu(BaseMenu):
|
||||
"3": self.backup_printer_config,
|
||||
"4": self.backup_moonraker_db,
|
||||
"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,
|
||||
)
|
||||
@@ -51,13 +59,13 @@ class BackupMenu(BaseMenu):
|
||||
|-------------------------------------------------------|
|
||||
| {line1:^62} |
|
||||
|-------------------------------------------------------|
|
||||
| Klipper & Moonraker API: | Touchscreen GUI: |
|
||||
| 1) [Klipper] | 7) [KlipperScreen] |
|
||||
| 2) [Moonraker] | |
|
||||
| 3) [Config Folder] | Other: |
|
||||
| 4) [Moonraker Database] | 9) [Telegram Bot] |
|
||||
| | |
|
||||
| Klipper Webinterface: | |
|
||||
| Klipper & Moonraker API: | Client-Config: |
|
||||
| 1) [Klipper] | 7) [Mainsail-Config] |
|
||||
| 2) [Moonraker] | 8) [Fluidd-Config] |
|
||||
| 3) [Config Folder] | |
|
||||
| 4) [Moonraker Database] | Touchscreen GUI: |
|
||||
| | 9) [KlipperScreen] |
|
||||
| Webinterface: | |
|
||||
| 5) [Mainsail] | |
|
||||
| 6) [Fluidd] | |
|
||||
"""
|
||||
@@ -77,13 +85,16 @@ class BackupMenu(BaseMenu):
|
||||
backup_moonraker_db_dir()
|
||||
|
||||
def backup_mainsail(self, **kwargs):
|
||||
backup_mainsail_data()
|
||||
backup_client_data(load_client_data("mainsail"))
|
||||
|
||||
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):
|
||||
pass
|
||||
|
||||
def backup_telegram_bot(self, **kwargs):
|
||||
pass
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
|
||||
import textwrap
|
||||
|
||||
from components.fluidd import fluidd_setup
|
||||
from components.klipper import klipper_setup
|
||||
from components.mainsail import mainsail_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.base_menu import BaseMenu
|
||||
from utils.constants import COLOR_GREEN, RESET_FORMAT
|
||||
@@ -31,13 +31,11 @@ class InstallMenu(BaseMenu):
|
||||
"2": self.install_moonraker,
|
||||
"3": self.install_mainsail,
|
||||
"4": self.install_fluidd,
|
||||
"5": self.install_klipperscreen,
|
||||
"6": self.install_pretty_gcode,
|
||||
"7": self.install_telegram_bot,
|
||||
"8": self.install_obico,
|
||||
"9": self.install_octoeverywhere,
|
||||
"10": self.install_mobileraker,
|
||||
"11": self.install_crowsnest,
|
||||
"5": self.install_mainsail_config,
|
||||
"6": self.install_fluidd_config,
|
||||
"7": None,
|
||||
"8": None,
|
||||
"9": None,
|
||||
},
|
||||
footer_type=BACK_FOOTER,
|
||||
)
|
||||
@@ -51,16 +49,18 @@ class InstallMenu(BaseMenu):
|
||||
/=======================================================\\
|
||||
| {color}{header:~^{count}}{RESET_FORMAT} |
|
||||
|-------------------------------------------------------|
|
||||
| Firmware & API: | Other: |
|
||||
| 1) [Klipper] | 6) [PrettyGCode] |
|
||||
| 2) [Moonraker] | 7) [Telegram Bot] |
|
||||
| | 8) $(obico_install_title) |
|
||||
| Klipper Webinterface: | 9) [OctoEverywhere] |
|
||||
| 3) [Mainsail] | 10) [Mobileraker] |
|
||||
| 4) [Fluidd] | |
|
||||
| | Webcam Streamer: |
|
||||
| Touchscreen GUI: | 11) [Crowsnest] |
|
||||
| 5) [KlipperScreen] | |
|
||||
| Firmware & API: | Touchscreen GUI: |
|
||||
| 1) [Klipper] | 7) [KlipperScreen] |
|
||||
| 2) [Moonraker] | |
|
||||
| | Android / iOS: |
|
||||
| Webinterface: | 8) [Mobileraker] |
|
||||
| 3) [Mainsail] | |
|
||||
| 4) [Fluidd] | Webcam Streamer: |
|
||||
| | 9) [Crowsnest] |
|
||||
| Client-Config: | |
|
||||
| 5) [Mainsail-Config] | |
|
||||
| 6) [Fluidd-Config] | |
|
||||
| | |
|
||||
"""
|
||||
)[1:]
|
||||
print(menu, end="")
|
||||
@@ -72,28 +72,13 @@ class InstallMenu(BaseMenu):
|
||||
moonraker_setup.install_moonraker()
|
||||
|
||||
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):
|
||||
fluidd_setup.install_fluidd()
|
||||
client_setup.install_client(client_name="fluidd")
|
||||
|
||||
def install_klipperscreen(self, **kwargs):
|
||||
print("install_klipperscreen")
|
||||
|
||||
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")
|
||||
def install_fluidd_config(self, **kwargs):
|
||||
client_config_setup.install_client_config(client_name="fluidd")
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
|
||||
import textwrap
|
||||
|
||||
from components.fluidd.fluidd_utils import get_fluidd_status
|
||||
from components.klipper.klipper_utils import get_klipper_status
|
||||
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.webui_client.client_utils import (
|
||||
get_client_status,
|
||||
load_client_data,
|
||||
get_current_client_config,
|
||||
)
|
||||
from core.menus import QUIT_FOOTER
|
||||
from core.menus.advanced_menu import AdvancedMenu
|
||||
from core.menus.backup_menu import BackupMenu
|
||||
@@ -61,13 +64,11 @@ class MainMenu(BaseMenu):
|
||||
self.ks_status = ""
|
||||
self.mb_status = ""
|
||||
self.cn_status = ""
|
||||
self.tg_status = ""
|
||||
self.ob_status = ""
|
||||
self.oe_status = ""
|
||||
self.cc_status = ""
|
||||
self.init_status()
|
||||
|
||||
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:
|
||||
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_repo = f"{COLOR_CYAN}{moonraker_status.get('repo')}{RESET_FORMAT}"
|
||||
# mainsail
|
||||
self.ms_status = get_mainsail_status()
|
||||
mainsail_client_data = load_client_data("mainsail")
|
||||
self.ms_status = get_client_status(mainsail_client_data)
|
||||
# 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:
|
||||
if code == 1:
|
||||
@@ -120,13 +127,11 @@ class MainMenu(BaseMenu):
|
||||
| 4) [Advanced] |------------------------------------|
|
||||
| 5) [Backup] | Mainsail: {self.ms_status:<26} |
|
||||
| | Fluidd: {self.fl_status:<26} |
|
||||
| E) [Extensions] | KlipperScreen: {self.ks_status:<26} |
|
||||
| | Mobileraker: {self.mb_status:<26} |
|
||||
| S) [Settings] | Client-Config: {self.cc_status:<26} |
|
||||
| | |
|
||||
| Community: | KlipperScreen: {self.ks_status:<26} |
|
||||
| E) [Extensions] | Mobileraker: {self.mb_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} |
|
||||
"""
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
|
||||
import textwrap
|
||||
|
||||
from components.fluidd.menus.fluidd_remove_menu import FluiddRemoveMenu
|
||||
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.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.base_menu import BaseMenu
|
||||
from utils.constants import COLOR_RED, RESET_FORMAT
|
||||
@@ -29,8 +29,8 @@ class RemoveMenu(BaseMenu):
|
||||
options={
|
||||
"1": KlipperRemoveMenu,
|
||||
"2": MoonrakerRemoveMenu,
|
||||
"3": MainsailRemoveMenu,
|
||||
"4": FluiddRemoveMenu,
|
||||
"3": ClientRemoveMenu(client=load_client_data("mainsail")),
|
||||
"4": ClientRemoveMenu(client=load_client_data("fluidd")),
|
||||
"5": None,
|
||||
"6": None,
|
||||
"7": None,
|
||||
|
||||
@@ -11,22 +11,22 @@
|
||||
|
||||
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_utils import (
|
||||
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_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.base_menu import BaseMenu
|
||||
from utils.constants import (
|
||||
@@ -50,14 +50,12 @@ class UpdateMenu(BaseMenu):
|
||||
"2": self.update_moonraker,
|
||||
"3": self.update_mainsail,
|
||||
"4": self.update_fluidd,
|
||||
"5": self.update_klipperscreen,
|
||||
"6": self.update_pgc_for_klipper,
|
||||
"7": self.update_telegram_bot,
|
||||
"8": self.update_moonraker_obico,
|
||||
"9": self.update_octoeverywhere,
|
||||
"10": self.update_mobileraker,
|
||||
"11": self.update_crowsnest,
|
||||
"12": self.upgrade_system_packages,
|
||||
"5": self.update_mainsail_config,
|
||||
"6": self.update_fluidd_config,
|
||||
"7": self.update_klipperscreen,
|
||||
"8": self.update_mobileraker,
|
||||
"9": self.update_crowsnest,
|
||||
"10": self.upgrade_system_packages,
|
||||
},
|
||||
footer_type=BACK_FOOTER,
|
||||
)
|
||||
@@ -69,6 +67,10 @@ class UpdateMenu(BaseMenu):
|
||||
self.ms_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||
self.fl_local = 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):
|
||||
self.fetch_update_status()
|
||||
@@ -87,22 +89,20 @@ class UpdateMenu(BaseMenu):
|
||||
| 1) Klipper | {self.kl_local:<22} | {self.kl_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} |
|
||||
| 4) Fluidd | {self.fl_local:<22} | {self.fl_remote:<22} |
|
||||
| | | |
|
||||
| Touchscreen GUI: |---------------|---------------|
|
||||
| 5) KlipperScreen | | |
|
||||
| Client-Config: |---------------|---------------|
|
||||
| 5) Mainsail-Config | {self.mc_local:<22} | {self.mc_remote:<22} |
|
||||
| 6) Fluidd-Config | {self.fc_local:<22} | {self.fc_remote:<22} |
|
||||
| | | |
|
||||
| Other: |---------------|---------------|
|
||||
| 6) PrettyGCode | | |
|
||||
| 7) Telegram Bot | | |
|
||||
| 8) Obico for Klipper | | |
|
||||
| 9) OctoEverywhere | | |
|
||||
| 10) Mobileraker | | |
|
||||
| 11) Crowsnest | | |
|
||||
| 7) KlipperScreen | | |
|
||||
| 8) Mobileraker | | |
|
||||
| 9) Crowsnest | | |
|
||||
| |-------------------------------|
|
||||
| 12) System | |
|
||||
| 10) System | |
|
||||
"""
|
||||
)[1:]
|
||||
print(menu, end="")
|
||||
@@ -117,34 +117,24 @@ class UpdateMenu(BaseMenu):
|
||||
update_moonraker()
|
||||
|
||||
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):
|
||||
update_fluidd()
|
||||
update_client(load_client_data("fluidd"))
|
||||
|
||||
def update_klipperscreen(self, **kwargs):
|
||||
print("update_klipperscreen")
|
||||
def update_fluidd_config(self, **kwargs):
|
||||
update_client_config(load_client_data("fluidd"))
|
||||
|
||||
def update_pgc_for_klipper(self, **kwargs):
|
||||
print("update_pgc_for_klipper")
|
||||
def update_klipperscreen(self, **kwargs): ...
|
||||
|
||||
def update_telegram_bot(self, **kwargs):
|
||||
print("update_telegram_bot")
|
||||
def update_mobileraker(self, **kwargs): ...
|
||||
|
||||
def update_moonraker_obico(self, **kwargs):
|
||||
print("update_moonraker_obico")
|
||||
def update_crowsnest(self, **kwargs): ...
|
||||
|
||||
def update_octoeverywhere(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 upgrade_system_packages(self, **kwargs): ...
|
||||
|
||||
def fetch_update_status(self):
|
||||
# klipper
|
||||
@@ -166,18 +156,38 @@ class UpdateMenu(BaseMenu):
|
||||
self.mr_local = f"{COLOR_YELLOW}{self.mr_local}{RESET_FORMAT}"
|
||||
self.mr_remote = f"{COLOR_GREEN}{self.mr_remote}{RESET_FORMAT}"
|
||||
# mainsail
|
||||
self.ms_local = get_mainsail_local_version()
|
||||
self.ms_remote = get_mainsail_remote_version()
|
||||
mainsail_client_data = load_client_data("mainsail")
|
||||
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:
|
||||
self.ms_local = f"{COLOR_GREEN}{self.ms_local}{RESET_FORMAT}"
|
||||
else:
|
||||
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}"
|
||||
# fluidd
|
||||
self.fl_local = get_fluidd_local_version()
|
||||
self.fl_remote = get_fluidd_remote_version()
|
||||
fluidd_client_data = load_client_data("fluidd")
|
||||
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:
|
||||
self.fl_local = f"{COLOR_GREEN}{self.fl_local}{RESET_FORMAT}"
|
||||
else:
|
||||
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}"
|
||||
# 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
|
||||
|
||||
# ======================================================================= #
|
||||
# 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 #
|
||||
# ======================================================================= #
|
||||
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
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 (
|
||||
NGINX_SITES_AVAILABLE,
|
||||
MODULE_PATH,
|
||||
@@ -24,6 +31,10 @@ from utils import (
|
||||
from utils.logger import Logger
|
||||
|
||||
|
||||
B = TypeVar('B', bound='BaseInstance')
|
||||
ConfigOption = Tuple[str, str]
|
||||
|
||||
|
||||
def check_file_exist(file_path: Path, sudo=False) -> bool:
|
||||
"""
|
||||
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))
|
||||
|
||||
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}")
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
[mcu]
|
||||
serial: /dev/serial/by-id/<your-mcu-id>
|
||||
|
||||
[virtual_sdcard]
|
||||
path: %GCODES_DIR%
|
||||
on_error_gcode: CANCEL_PRINT
|
||||
|
||||
[printer]
|
||||
kinematics: none
|
||||
max_velocity: 1000
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -33,23 +33,25 @@ function backup_before_update() {
|
||||
|
||||
function backup_config_dir() {
|
||||
check_for_backup_dir
|
||||
local current_date instance_names config_pathes
|
||||
local current_date config_pathes
|
||||
|
||||
config_pathes=$(get_config_folders)
|
||||
readarray -t -d" " instance_names < <(get_multi_instance_names)
|
||||
|
||||
if [[ -n "${config_pathes}" ]]; then
|
||||
current_date=$(get_date)
|
||||
status_msg "Timestamp: ${current_date}"
|
||||
|
||||
local i=0 folder
|
||||
local i=0 folder folder_name target_dir
|
||||
for folder in ${config_pathes}; do
|
||||
local folder_name="${instance_names[${i}]}"
|
||||
status_msg "Create backup of ${folder} ..."
|
||||
mkdir -p "${BACKUP_DIR}/configs/${current_date}/${folder_name}"
|
||||
cp -r "${folder}" "${_}"
|
||||
ok_msg "Backup created in:\n${BACKUP_DIR}/configs/${current_date}/${folder_name}"
|
||||
|
||||
folder_name=$(echo "${folder}" | rev | cut -d"/" -f2 | rev)
|
||||
target_dir="${BACKUP_DIR}/configs/${current_date}/${folder_name}"
|
||||
mkdir -p "${target_dir}"
|
||||
cp -r "${folder}" "${target_dir}"
|
||||
i=$(( i + 1 ))
|
||||
|
||||
ok_msg "Backup created in:\n${target_dir}"
|
||||
done
|
||||
else
|
||||
ok_msg "No config directory found! Skipping backup ..."
|
||||
@@ -61,20 +63,22 @@ function backup_moonraker_database() {
|
||||
local current_date db_pathes
|
||||
|
||||
db_pathes=$(get_instance_folder_path "database")
|
||||
readarray -t -d" " instance_names < <(get_multi_instance_names)
|
||||
|
||||
if [[ -n ${db_pathes} ]]; then
|
||||
current_date=$(get_date)
|
||||
status_msg "Timestamp: ${current_date}"
|
||||
|
||||
local i=0 database
|
||||
local i=0 database folder_name target_dir
|
||||
for database in ${db_pathes}; do
|
||||
local folder_name="${instance_names[${i}]}"
|
||||
status_msg "Create backup of ${database} ..."
|
||||
mkdir -p "${BACKUP_DIR}/moonraker_databases/${current_date}/${folder_name}"
|
||||
cp -r "${database}" "${_}"
|
||||
ok_msg "Backup created in:\n${BACKUP_DIR}/moonraker_databases/${current_date}/${folder_name}"
|
||||
|
||||
folder_name=$(echo "${database}" | rev | cut -d"/" -f2 | rev)
|
||||
target_dir="${BACKUP_DIR}/moonraker_databases/${current_date}/${folder_name}"
|
||||
mkdir -p "${target_dir}"
|
||||
cp -r "${database}" "${target_dir}"
|
||||
i=$(( i + 1 ))
|
||||
|
||||
ok_msg "Backup created in:\n${target_dir}"
|
||||
done
|
||||
else
|
||||
print_error "No Moonraker database found! Skipping backup ..."
|
||||
@@ -191,3 +195,19 @@ function backup_telegram_bot() {
|
||||
print_error "Can't back up MoonrakerTelegramBot directory!\n Not found!"
|
||||
fi
|
||||
}
|
||||
|
||||
function backup_octoeverywhere() {
|
||||
local current_date
|
||||
|
||||
if [[ -d ${OCTOEVERYWHERE_DIR} ]] ; then
|
||||
status_msg "Creating OctoEverywhere backup ..."
|
||||
check_for_backup_dir
|
||||
current_date=$(get_date)
|
||||
status_msg "Timestamp: ${current_date}"
|
||||
mkdir -p "${BACKUP_DIR}/OctoEverywhere-backups/${current_date}"
|
||||
cp -r "${OCTOEVERYWHERE_DIR}" "${_}" && cp -r "${OCTOEVERYWHERE_ENV}" "${_}"
|
||||
print_confirm "OctoEverywhere backup complete!"
|
||||
else
|
||||
print_error "Can't back up OctoEverywhere directory!\n Not found!"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -52,16 +52,57 @@ function init_flash_process() {
|
||||
esac
|
||||
done
|
||||
|
||||
### step 2: select how the mcu is connected to the host
|
||||
### step 2: select how the mcu is flashed (flash/serialflash)
|
||||
select_flash_command
|
||||
|
||||
### step 3: select how the mcu is connected to the host
|
||||
select_mcu_connection
|
||||
|
||||
### step 3: select which detected mcu should be flashed
|
||||
### step 4: select which detected mcu should be flashed
|
||||
select_mcu_id "${method}"
|
||||
}
|
||||
|
||||
#================================================#
|
||||
#=================== STEP 2 =====================#
|
||||
#================================================#
|
||||
function select_flash_command() {
|
||||
unset flash_command
|
||||
|
||||
top_border
|
||||
echo -e "| How to flash MCU? |"
|
||||
echo -e "| 1) make flash (default) |"
|
||||
echo -e "| 2) make serialflash (stm32flash) |"
|
||||
blank_line
|
||||
back_help_footer
|
||||
|
||||
local choice
|
||||
while true; do
|
||||
read -p "${cyan}###### Flashing command:${white} " -i "1" -e choice
|
||||
case "${choice}" in
|
||||
1)
|
||||
select_msg "Selected 'make flash' command"
|
||||
flash_command="flash"
|
||||
break;;
|
||||
2)
|
||||
select_msg "Selected 'make serialflash' command"
|
||||
flash_command="serialflash"
|
||||
break;;
|
||||
B|b)
|
||||
advanced_menu
|
||||
break;;
|
||||
H|h)
|
||||
clear && print_header
|
||||
show_mcu_flash_command_help
|
||||
break;;
|
||||
*)
|
||||
error_msg "Invalid command!";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
#================================================#
|
||||
#=================== STEP 3 =====================#
|
||||
#================================================#
|
||||
function select_mcu_connection() {
|
||||
top_border
|
||||
echo -e "| ${yellow}Make sure that the controller board is connected now!${white} |"
|
||||
@@ -112,7 +153,6 @@ function print_detected_mcu_to_screen() {
|
||||
fi
|
||||
|
||||
for mcu in "${mcu_list[@]}"; do
|
||||
mcu=$(echo "${mcu}" | rev | cut -d"/" -f1 | rev)
|
||||
echo -e " ● MCU #${i}: ${cyan}${mcu}${white}"
|
||||
i=$(( i + 1 ))
|
||||
done
|
||||
@@ -120,7 +160,7 @@ function print_detected_mcu_to_screen() {
|
||||
}
|
||||
|
||||
#================================================#
|
||||
#=================== STEP 3 =====================#
|
||||
#=================== STEP 4 =====================#
|
||||
#================================================#
|
||||
function select_mcu_id() {
|
||||
local i=0 sel_index=0 method=${1}
|
||||
@@ -195,7 +235,7 @@ function start_flash_mcu() {
|
||||
local device=${1}
|
||||
do_action_service "stop" "klipper"
|
||||
|
||||
if make flash FLASH_DEVICE="${device}"; then
|
||||
if make ${flash_command} FLASH_DEVICE="${device}"; then
|
||||
ok_msg "Flashing successfull!"
|
||||
else
|
||||
warn_msg "Flashing failed!"
|
||||
@@ -387,6 +427,36 @@ function show_flash_method_help() {
|
||||
done
|
||||
}
|
||||
|
||||
function show_mcu_flash_command_help() {
|
||||
top_border
|
||||
echo -e "| ~~~~~~~~ < ? > Help: Flash MCU < ? > ~~~~~~~~ |"
|
||||
hr
|
||||
echo -e "| ${cyan}make flash:${white} |"
|
||||
echo -e "| The default command to flash controller board, it |"
|
||||
echo -e "| will detect selected microcontroller and use suitable |"
|
||||
echo -e "| tool for flashing it. |"
|
||||
blank_line
|
||||
echo -e "| ${cyan}make serialflash:${white} |"
|
||||
echo -e "| Special command to flash STM32 microcontrollers in |"
|
||||
echo -e "| DFU mode but connected via serial. stm32flash command |"
|
||||
echo -e "| will be used internally. |"
|
||||
blank_line
|
||||
back_footer
|
||||
|
||||
local choice
|
||||
while true; do
|
||||
read -p "${cyan}###### Please select:${white} " choice
|
||||
case "${choice}" in
|
||||
B|b)
|
||||
clear && print_header
|
||||
select_flash_command
|
||||
break;;
|
||||
*)
|
||||
error_msg "Invalid command!";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
function show_mcu_connection_help() {
|
||||
top_border
|
||||
echo -e "| ~~~~~~~~ < ? > Help: Flash MCU < ? > ~~~~~~~~ |"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -244,6 +244,7 @@ function run_klipper_setup() {
|
||||
|
||||
### finalizing the setup with writing instance names to the kiauh.ini
|
||||
set_multi_instance_names
|
||||
mask_disrupting_services
|
||||
|
||||
print_confirm "${confirm}" && return
|
||||
}
|
||||
@@ -333,6 +334,7 @@ function create_klipper_service() {
|
||||
|
||||
local printer_data
|
||||
local cfg_dir
|
||||
local gcodes_dir
|
||||
local cfg
|
||||
local log
|
||||
local klippy_serial
|
||||
@@ -345,6 +347,7 @@ function create_klipper_service() {
|
||||
|
||||
printer_data="${HOME}/${instance_name}_data"
|
||||
cfg_dir="${printer_data}/config"
|
||||
gcodes_dir="${printer_data}/gcodes"
|
||||
cfg="${cfg_dir}/printer.cfg"
|
||||
log="${printer_data}/logs/klippy.log"
|
||||
klippy_serial="${printer_data}/comms/klippy.serial"
|
||||
@@ -375,18 +378,20 @@ function create_klipper_service() {
|
||||
fi
|
||||
|
||||
if [[ ! -f ${cfg} ]]; then
|
||||
write_example_printer_cfg "${cfg}"
|
||||
write_example_printer_cfg "${cfg}" "${gcodes_dir}"
|
||||
fi
|
||||
}
|
||||
|
||||
function write_example_printer_cfg() {
|
||||
local cfg=${1}
|
||||
local gcodes_dir=${2}
|
||||
local cfg_template
|
||||
|
||||
cfg_template="${KIAUH_SRCDIR}/resources/example.printer.cfg"
|
||||
|
||||
status_msg "Creating minimal example printer.cfg ..."
|
||||
if cp "${cfg_template}" "${cfg}"; then
|
||||
sed -i "s|%GCODES_DIR%|${gcodes_dir}|" "${cfg}"
|
||||
ok_msg "Minimal example printer.cfg created!"
|
||||
else
|
||||
error_msg "Couldn't create minimal example printer.cfg!"
|
||||
@@ -625,3 +630,34 @@ function get_klipper_python_ver() {
|
||||
version=$("${KLIPPY_ENV}"/bin/python --version 2>&1 | cut -d" " -f2 | cut -d"." -f1)
|
||||
echo "${version}"
|
||||
}
|
||||
|
||||
function mask_disrupting_services() {
|
||||
local brltty="false"
|
||||
local brltty_udev="false"
|
||||
local modem_manager="false"
|
||||
|
||||
[[ $(dpkg -s brltty 2>/dev/null | grep "Status") = *\ installed ]] && brltty="true"
|
||||
[[ $(dpkg -s brltty-udev 2>/dev/null | grep "Status") = *\ installed ]] && brltty_udev="true"
|
||||
[[ $(dpkg -s ModemManager 2>/dev/null | grep "Status") = *\ installed ]] && modem_manager="true"
|
||||
|
||||
status_msg "Installed brltty package detected, masking brltty service ..."
|
||||
if [[ ${brltty} == "true" ]]; then
|
||||
sudo systemctl stop brltty
|
||||
sudo systemctl mask brltty
|
||||
fi
|
||||
ok_msg "brltty service masked!"
|
||||
|
||||
status_msg "Installed brltty-udev package detected, masking brltty-udev service ..."
|
||||
if [[ ${brltty_udev} == "true" ]]; then
|
||||
sudo systemctl stop brltty-udev
|
||||
sudo systemctl mask brltty-udev
|
||||
fi
|
||||
ok_msg "brltty-udev service masked!"
|
||||
|
||||
status_msg "Installed ModemManager package detected, masking ModemManager service ..."
|
||||
if [[ ${modem_manager} == "true" ]]; then
|
||||
sudo systemctl stop ModemManager
|
||||
sudo systemctl mask ModemManager
|
||||
fi
|
||||
ok_msg "ModemManager service masked!"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -119,6 +119,8 @@ function update_klipperscreen() {
|
||||
old_md5=$(md5sum "${KLIPPERSCREEN_DIR}/scripts/KlipperScreen-requirements.txt" | cut -d " " -f1)
|
||||
|
||||
do_action_service "stop" "KlipperScreen"
|
||||
backup_before_update "klipperscreen"
|
||||
|
||||
cd "${KLIPPERSCREEN_DIR}"
|
||||
git pull origin master -q && ok_msg "Fetch successfull!"
|
||||
git checkout -f master && ok_msg "Checkout successfull"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -61,8 +61,8 @@ function mobileraker_setup() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
status_msg "Installing Mobileraker's companion ..."
|
||||
if "${MOBILERAKER_DIR}"/scripts/install-mobileraker-companion.sh; then
|
||||
status_msg "Starting installer of Mobileraker's companion ..."
|
||||
if "${MOBILERAKER_DIR}"/scripts/install.sh; then
|
||||
ok_msg "Mobileraker's companion successfully installed!"
|
||||
else
|
||||
print_error "Mobileraker's companion installation failed!"
|
||||
@@ -233,7 +233,7 @@ primary_branch:main
|
||||
managed_services: mobileraker
|
||||
env: ${HOME}/mobileraker-env/bin/python
|
||||
requirements: scripts/mobileraker-requirements.txt
|
||||
install_script: scripts/install-mobileraker-companion.sh
|
||||
install_script: scripts/install.sh
|
||||
MOONRAKER_CONF
|
||||
|
||||
fi
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -63,7 +63,7 @@ function obico_server_url_prompt() {
|
||||
}
|
||||
|
||||
function moonraker_obico_setup_dialog() {
|
||||
status_msg "Initializing Moonraker-obico installation ..."
|
||||
status_msg "Initializing Obico installation ..."
|
||||
|
||||
local moonraker_count
|
||||
local moonraker_names
|
||||
@@ -73,7 +73,7 @@ function moonraker_obico_setup_dialog() {
|
||||
if (( moonraker_count == 0 )); then
|
||||
### return early if moonraker is not installed
|
||||
local error="Moonraker not installed! Please install Moonraker first!"
|
||||
log_error "Moonraker-obico setup started without Moonraker being installed. Aborting setup."
|
||||
log_error "Obico setup started without Moonraker being installed. Aborting setup."
|
||||
print_error "${error}" && return
|
||||
elif (( moonraker_count > 1 )); then
|
||||
# moonraker_names is valid only in case of multi-instance
|
||||
@@ -90,10 +90,10 @@ function moonraker_obico_setup_dialog() {
|
||||
if (( allowed_moonraker_obico_count == 0 && moonraker_count > 0 )) && [[ $(get_moonraker_obico_status) != "Not linked!" ]]; then
|
||||
local yn
|
||||
while true; do
|
||||
echo "${yellow}Obico for Klipper is already installed.${white}"
|
||||
echo "${yellow}Obico is already installed.${white}"
|
||||
echo "It is safe to run the install again to repair any issues."
|
||||
echo ""
|
||||
local question="Do you want to reinstall Obico for Klipper?"
|
||||
local question="Do you want to reinstall Obico?"
|
||||
read -p "${cyan}###### ${question} (Y/n):${white} " yn
|
||||
case "${yn}" in
|
||||
Y|y|Yes|yes|"")
|
||||
@@ -101,7 +101,7 @@ function moonraker_obico_setup_dialog() {
|
||||
break;;
|
||||
N|n|No|no)
|
||||
select_msg "No"
|
||||
abort_msg "Exiting Obico for Klipper installation...\n"
|
||||
abort_msg "Exiting Obico installation...\n"
|
||||
return;;
|
||||
*)
|
||||
error_msg "Invalid Input!";;
|
||||
@@ -126,31 +126,30 @@ function moonraker_obico_setup_dialog() {
|
||||
done
|
||||
blank_line
|
||||
if (( existing_moonraker_obico_count > 0 )); then
|
||||
printf "|${green}%-55s${white}|\n" " ${existing_moonraker_obico_count} Moonraker-obico instances already installed!"
|
||||
printf "|${green}%-55s${white}|\n" " ${existing_moonraker_obico_count} Obico instances already installed!"
|
||||
for svc in ${moonraker_obico_services}; do
|
||||
printf "|${cyan}%-57s${white}|\n" " ● moonraker-obco-$(get_instance_name "${svc}")"
|
||||
done
|
||||
fi
|
||||
blank_line
|
||||
echo -e "| The setup will apply the same names to |"
|
||||
echo -e "| Moonraker-obico! |"
|
||||
echo -e "| The setup will apply the same names to Obico! |"
|
||||
blank_line
|
||||
echo -e "| Please select the number of Moonraker-obico instances |"
|
||||
echo -e "| to install. Usually one Moonraker-obico instance per |"
|
||||
echo -e "| Please select the number of Obico instances |"
|
||||
echo -e "| to install. Usually one Obico instance per |"
|
||||
echo -e "| Moonraker instance is required, but you may not |"
|
||||
echo -e "| install more Moonraker-obico instances than available |"
|
||||
echo -e "| install more Obico instances than available |"
|
||||
echo -e "| Moonraker instances. |"
|
||||
bottom_border
|
||||
|
||||
### ask for amount of instances
|
||||
local re="^[1-9][0-9]*$"
|
||||
while [[ ! ${new_moonraker_obico_count} =~ ${re} || ${new_moonraker_obico_count} -gt ${allowed_moonraker_obico_count} ]]; do
|
||||
read -p "${cyan}###### Number of new Moonraker-obico instances to set up:${white} " -i "${allowed_moonraker_obico_count}" -e new_moonraker_obico_count
|
||||
read -p "${cyan}###### Number of new Obico instances to set up:${white} " -i "${allowed_moonraker_obico_count}" -e new_moonraker_obico_count
|
||||
### break if input is valid
|
||||
[[ ${new_moonraker_obico_count} =~ ${re} && ${new_moonraker_obico_count} -le ${allowed_moonraker_obico_count} ]] && break
|
||||
### conditional error messages
|
||||
[[ ! ${new_moonraker_obico_count} =~ ${re} ]] && error_msg "Input not a number"
|
||||
(( new_moonraker_obico_count > allowed_moonraker_obico_count )) && error_msg "Number of Moonraker-obico instances larger than installed Moonraker instances"
|
||||
(( new_moonraker_obico_count > allowed_moonraker_obico_count )) && error_msg "Number of Obico instances larger than installed Moonraker instances"
|
||||
done && select_msg "${new_moonraker_obico_count}"
|
||||
else
|
||||
log_error "Internal error. moonraker_count of '${moonraker_count}' not equal or grather than one!"
|
||||
@@ -160,8 +159,8 @@ function moonraker_obico_setup_dialog() {
|
||||
### Step 2: Confirm instance amount
|
||||
local yn
|
||||
while true; do
|
||||
(( new_moonraker_obico_count == 1 )) && local question="Install Moonraker-obico?"
|
||||
(( new_moonraker_obico_count > 1 )) && local question="Install ${new_moonraker_obico_count} Moonraker-obico instances?"
|
||||
(( new_moonraker_obico_count == 1 )) && local question="Install Obico?"
|
||||
(( new_moonraker_obico_count > 1 )) && local question="Install ${new_moonraker_obico_count} Obico instances?"
|
||||
read -p "${cyan}###### ${question} (Y/n):${white} " yn
|
||||
case "${yn}" in
|
||||
Y|y|Yes|yes|"")
|
||||
@@ -169,7 +168,7 @@ function moonraker_obico_setup_dialog() {
|
||||
break;;
|
||||
N|n|No|no)
|
||||
select_msg "No"
|
||||
abort_msg "Exiting Moonraker-obico setup ...\n"
|
||||
abort_msg "Exiting Obico setup ...\n"
|
||||
return;;
|
||||
*)
|
||||
error_msg "Invalid Input!";;
|
||||
@@ -191,8 +190,8 @@ function moonraker_obico_setup_dialog() {
|
||||
fi
|
||||
done
|
||||
|
||||
(( new_moonraker_obico_count > 1 )) && status_msg "Installing ${new_moonraker_obico_count} Moonraker-obico instances ..."
|
||||
(( new_moonraker_obico_count == 1 )) && status_msg "Installing Moonraker-obico ..."
|
||||
(( new_moonraker_obico_count > 1 )) && status_msg "Installing ${new_moonraker_obico_count} Obico instances ..."
|
||||
(( new_moonraker_obico_count == 1 )) && status_msg "Installing Obico ..."
|
||||
|
||||
### Step 5: Clone the moonraker-obico repo
|
||||
clone_moonraker_obico "${MOONRAKER_OBICO_REPO}"
|
||||
@@ -244,17 +243,16 @@ function moonraker_obico_setup_dialog() {
|
||||
if (( ${#not_linked_instances[@]} > 0 )); then
|
||||
top_border
|
||||
if (( moonraker_count == 1 )); then
|
||||
printf "|${green}%-55s${white}|\n" " Moonraker-obico not linked to the server!"
|
||||
printf "|${green}%-55s${white}|\n" " Obico not linked to the server!"
|
||||
else
|
||||
printf "|${green}%-55s${white}|\n" " ${#not_linked_instances[@]} Moonraker-obico instances not linked to the server!"
|
||||
printf "|${green}%-55s${white}|\n" " ${#not_linked_instances[@]} Obico instances not linked to the server!"
|
||||
for i in "${not_linked_instances[@]}"; do
|
||||
printf "|${cyan}%-57s${white}|\n" " ● moonraker-obico-${moonraker_names[${i}]}"
|
||||
done
|
||||
fi
|
||||
blank_line
|
||||
echo -e "| To link to your Obico Server account, you need to |"
|
||||
echo -e "| obtain the 6-digit verification code in the Obico |"
|
||||
echo -e "| mobile or web app. For more information, visit: |"
|
||||
echo -e "| It will take only 10 seconds to link printer to Obico.|"
|
||||
echo -e "| For more information, visit: |"
|
||||
echo -e "| https://www.obico.io/docs/user-guides/klipper-setup/ |"
|
||||
blank_line
|
||||
echo -e "| If you don't want to link the printer now, you can |"
|
||||
@@ -272,7 +270,7 @@ function moonraker_obico_setup_dialog() {
|
||||
break;;
|
||||
N|n|No|no)
|
||||
select_msg "No"
|
||||
abort_msg "Exiting Moonraker-obico setup ...\n"
|
||||
abort_msg "Exiting Obico setup ...\n"
|
||||
return;;
|
||||
*)
|
||||
error_msg "Invalid Input!";;
|
||||
@@ -295,13 +293,13 @@ function moonraker_obico_setup_dialog() {
|
||||
function clone_moonraker_obico() {
|
||||
local repo=${1}
|
||||
|
||||
status_msg "Cloning Moonraker-obico from ${repo} ..."
|
||||
### force remove existing Moonraker-obico dir
|
||||
status_msg "Cloning Obico from ${repo} ..."
|
||||
### force remove existing Obico dir
|
||||
[[ -d "${MOONRAKER_OBICO_DIR}" ]] && rm -rf "${MOONRAKER_OBICO_DIR}"
|
||||
|
||||
cd "${HOME}" || exit 1
|
||||
if ! git clone "${repo}" "${MOONRAKER_OBICO_DIR}"; then
|
||||
print_error "Cloning Moonraker-obico from\n ${repo}\n failed!"
|
||||
print_error "Cloning Obico from\n ${repo}\n failed!"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
@@ -316,7 +314,7 @@ function moonraker_obico_install() {
|
||||
|
||||
function remove_moonraker_obico_systemd() {
|
||||
[[ -z $(moonraker_obico_systemd) ]] && return
|
||||
status_msg "Removing Moonraker-obico Systemd Services ..."
|
||||
status_msg "Removing Obico Systemd Services ..."
|
||||
|
||||
for service in $(moonraker_obico_systemd | cut -d"/" -f5); do
|
||||
status_msg "Removing ${service} ..."
|
||||
@@ -329,7 +327,7 @@ function remove_moonraker_obico_systemd() {
|
||||
### reloading units
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl reset-failed
|
||||
ok_msg "Moonraker-obico Services removed!"
|
||||
ok_msg "Obico Services removed!"
|
||||
}
|
||||
|
||||
function remove_moonraker_obico_logs() {
|
||||
@@ -361,7 +359,7 @@ function remove_legacy_moonraker_obico_logs() {
|
||||
function remove_moonraker_obico_dir() {
|
||||
[[ ! -d ${MOONRAKER_OBICO_DIR} ]] && return
|
||||
|
||||
status_msg "Removing Moonraker-obico directory ..."
|
||||
status_msg "Removing Obico directory ..."
|
||||
rm -rf "${MOONRAKER_OBICO_DIR}"
|
||||
ok_msg "Directory removed!"
|
||||
}
|
||||
@@ -380,7 +378,7 @@ function remove_moonraker_obico() {
|
||||
remove_moonraker_obico_dir
|
||||
remove_moonraker_obico_env
|
||||
|
||||
print_confirm "Moonraker-obico was successfully removed!"
|
||||
print_confirm "Obico was successfully removed!"
|
||||
return
|
||||
}
|
||||
|
||||
@@ -394,7 +392,7 @@ function update_moonraker_obico() {
|
||||
if [[ ! -d ${MOONRAKER_OBICO_DIR} ]]; then
|
||||
clone_moonraker_obico "${MOONRAKER_OBICO_REPO}"
|
||||
else
|
||||
status_msg "Updating Moonraker-obico ..."
|
||||
status_msg "Updating Obico ..."
|
||||
cd "${MOONRAKER_OBICO_DIR}" && git pull
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -77,10 +77,12 @@ function change_klipper_repo_menu() {
|
||||
error_msg "Invalid command!";;
|
||||
esac
|
||||
done
|
||||
break
|
||||
else
|
||||
status_msg "Set custom Klipper repository to:\n ● Repository: ${repos[${option}]}\n ● Branch: ${branches[${option}]}"
|
||||
set_custom_klipper_repo "${repos[${option}]}" "${branches[${option}]}"
|
||||
ok_msg "This repo will now be used for new Klipper installations!\n"
|
||||
break
|
||||
fi
|
||||
|
||||
elif [[ ${option} =~ ${back} ]]; then
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -25,7 +25,7 @@ function backup_ui() {
|
||||
echo -e "| | |"
|
||||
echo -e "| Klipper Webinterface: | Other: |"
|
||||
echo -e "| 5) [Mainsail] | 9) [Telegram Bot] |"
|
||||
echo -e "| 6) [Fluidd] | |"
|
||||
echo -e "| 6) [Fluidd] | 10) [OctoEverywhere] |"
|
||||
back_footer
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ function backup_menu() {
|
||||
do_action "backup_octoprint" "backup_ui";;
|
||||
9)
|
||||
do_action "backup_telegram_bot" "backup_ui";;
|
||||
10)
|
||||
do_action "backup_octoeverywhere" "backup_ui";;
|
||||
B|b)
|
||||
clear; main_menu; break;;
|
||||
*)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -35,7 +35,7 @@ function install_ui() {
|
||||
}
|
||||
|
||||
function install_menu() {
|
||||
clear -x && sudo -v && clear -x # (re)cache sudo credentials so password prompt doesn't bork ui
|
||||
clear -x && sudo true && clear -x # (re)cache sudo credentials so password prompt doesn't bork ui
|
||||
print_header
|
||||
install_ui
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -57,7 +57,7 @@ function print_status() {
|
||||
elif [[ ${status} == "Incomplete!" ]]; then
|
||||
status="${yellow}${status}${white}"
|
||||
elif [[ ${status} == "Not linked!" ]]; then
|
||||
### "Not linked!" is only required for Moonraker-obico
|
||||
### "Not linked!" is only required for Obico for Klipper
|
||||
status="${yellow}${status}${white}"
|
||||
else
|
||||
status="${green}${status}${white}"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
@@ -41,7 +41,7 @@ function update_ui() {
|
||||
}
|
||||
|
||||
function update_menu() {
|
||||
clear -x && sudo -v && clear -x # (re)cache sudo credentials so password prompt doesn't bork ui
|
||||
clear -x && sudo true && clear -x # (re)cache sudo credentials so password prompt doesn't bork ui
|
||||
do_action "" "update_ui"
|
||||
|
||||
local action
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#=======================================================================#
|
||||
# Copyright (C) 2020 - 2023 Dominik Willner <th33xitus@gmail.com> #
|
||||
# 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 #
|
||||
|
||||
Reference in New Issue
Block a user