mirror of
https://github.com/dw-0/kiauh.git
synced 2025-12-23 15:53:36 +05:00
feat(Mainsail): implement Mainsail installer
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
@@ -10,3 +10,7 @@ method: https
|
|||||||
repository_url: https://github.com/Arksine/moonraker
|
repository_url: https://github.com/Arksine/moonraker
|
||||||
branch: master
|
branch: master
|
||||||
method: https
|
method: https
|
||||||
|
|
||||||
|
[mainsail]
|
||||||
|
default_port: 80
|
||||||
|
unstable_releases: False
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import textwrap
|
|||||||
from kiauh.core.menus import BACK_FOOTER
|
from kiauh.core.menus import BACK_FOOTER
|
||||||
from kiauh.core.menus.base_menu import BaseMenu
|
from kiauh.core.menus.base_menu import BaseMenu
|
||||||
from kiauh.modules.klipper import klipper_setup
|
from kiauh.modules.klipper import klipper_setup
|
||||||
|
from kiauh.modules.mainsail import mainsail_setup
|
||||||
from kiauh.modules.moonraker import moonraker_setup
|
from kiauh.modules.moonraker import moonraker_setup
|
||||||
from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT
|
from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ class InstallMenu(BaseMenu):
|
|||||||
moonraker_setup.run_moonraker_setup(install=True)
|
moonraker_setup.run_moonraker_setup(install=True)
|
||||||
|
|
||||||
def install_mainsail(self):
|
def install_mainsail(self):
|
||||||
print("install_mainsail")
|
mainsail_setup.run_mainsail_setup(install=True)
|
||||||
|
|
||||||
def install_fluidd(self):
|
def install_fluidd(self):
|
||||||
print("install_fluidd")
|
print("install_fluidd")
|
||||||
|
|||||||
26
kiauh/modules/mainsail/__init__.py
Normal file
26
kiauh/modules/mainsail/__init__.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2023 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
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
MODULE_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
MAINSAIL_DIR = os.path.join(Path.home(), "mainsail")
|
||||||
|
MAINSAIL_CONFIG_DIR = os.path.join(Path.home(), "mainsail-config")
|
||||||
|
MAINSAIL_CONFIG_JSON = os.path.join(MAINSAIL_DIR, "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"
|
||||||
95
kiauh/modules/mainsail/mainsail_dialogs.py
Normal file
95
kiauh/modules/mainsail/mainsail_dialogs.py
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2023 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 kiauh.core.menus.base_menu import print_back_footer
|
||||||
|
from kiauh.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="")
|
||||||
272
kiauh/modules/mainsail/mainsail_setup.py
Normal file
272
kiauh/modules/mainsail/mainsail_setup.py
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# ======================================================================= #
|
||||||
|
# Copyright (C) 2020 - 2023 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 os.path
|
||||||
|
import shutil
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from kiauh import KIAUH_CFG
|
||||||
|
from kiauh.core.config_manager.config_manager import ConfigManager
|
||||||
|
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||||
|
from kiauh.core.repo_manager.repo_manager import RepoManager
|
||||||
|
from kiauh.modules.klipper.klipper import Klipper
|
||||||
|
from kiauh.modules.mainsail import (
|
||||||
|
MAINSAIL_URL,
|
||||||
|
MAINSAIL_DIR,
|
||||||
|
MAINSAIL_CONFIG_DIR,
|
||||||
|
MAINSAIL_CONFIG_REPO_URL,
|
||||||
|
MAINSAIL_CONFIG_JSON,
|
||||||
|
MODULE_PATH,
|
||||||
|
)
|
||||||
|
from kiauh.modules.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 kiauh.modules.moonraker.moonraker import Moonraker
|
||||||
|
from kiauh.utils.common import check_install_dependencies
|
||||||
|
from kiauh.utils.input_utils import get_confirm, get_number_input
|
||||||
|
from kiauh.utils.logger import Logger
|
||||||
|
from kiauh.utils.system_utils import (
|
||||||
|
download_file,
|
||||||
|
unzip,
|
||||||
|
create_upstream_nginx_cfg,
|
||||||
|
create_nginx_cfg,
|
||||||
|
delete_default_nginx_cfg,
|
||||||
|
enable_nginx_cfg,
|
||||||
|
set_nginx_permissions,
|
||||||
|
get_ipv4_addr,
|
||||||
|
control_systemd_service,
|
||||||
|
create_common_vars_nginx_cfg,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run_mainsail_setup(install: bool) -> None:
|
||||||
|
im_mr = InstanceManager(Moonraker)
|
||||||
|
is_moonraker_installed = len(im_mr.instances) > 0
|
||||||
|
|
||||||
|
enable_remotemode = False
|
||||||
|
if not is_moonraker_installed:
|
||||||
|
print_moonraker_not_found_dialog()
|
||||||
|
do_continue = get_confirm("Continue Mainsail installation?", allow_go_back=True)
|
||||||
|
if do_continue:
|
||||||
|
enable_remotemode = True
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
is_mainsail_installed = Path(f"{Path.home()}/mainsail").exists()
|
||||||
|
do_reinstall = False
|
||||||
|
if is_mainsail_installed:
|
||||||
|
print_mainsail_already_installed_dialog()
|
||||||
|
do_reinstall = get_confirm("Re-install Mainsail?", allow_go_back=True)
|
||||||
|
if do_reinstall:
|
||||||
|
backup_config_json()
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
im_kl = InstanceManager(Klipper)
|
||||||
|
is_klipper_installed = len(im_kl.instances) > 0
|
||||||
|
install_ms_config = False
|
||||||
|
if is_klipper_installed:
|
||||||
|
print_install_mainsail_config_dialog()
|
||||||
|
question = "Download the recommended macros?"
|
||||||
|
install_ms_config = get_confirm(question, allow_go_back=False)
|
||||||
|
|
||||||
|
cm = ConfigManager(cfg_file=KIAUH_CFG)
|
||||||
|
cm.read_config()
|
||||||
|
default_port = cm.get_value("mainsail", "default_port")
|
||||||
|
mainsail_port = default_port if default_port else 80
|
||||||
|
if not default_port:
|
||||||
|
print_mainsail_port_select_dialog(f"{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 is_moonraker_installed:
|
||||||
|
patch_moonraker_conf(
|
||||||
|
im_mr.instances,
|
||||||
|
"Mainsail",
|
||||||
|
"update_manager mainsail",
|
||||||
|
"mainsail-updater.conf",
|
||||||
|
)
|
||||||
|
im_mr.restart_all_instance()
|
||||||
|
if is_klipper_installed and install_ms_config:
|
||||||
|
download_mainsail_config()
|
||||||
|
patch_moonraker_conf(
|
||||||
|
im_mr.instances,
|
||||||
|
"mainsail-config",
|
||||||
|
"update_manager mainsail-config",
|
||||||
|
"mainsail-config-updater.conf",
|
||||||
|
)
|
||||||
|
patch_printer_config(im_kl.instances)
|
||||||
|
im_kl.restart_all_instance()
|
||||||
|
|
||||||
|
create_upstream_nginx_cfg()
|
||||||
|
create_common_vars_nginx_cfg()
|
||||||
|
create_mainsail_nginx_cfg(mainsail_port)
|
||||||
|
if is_klipper_installed:
|
||||||
|
symlink_webui_nginx_log(im_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 ...")
|
||||||
|
download_file(MAINSAIL_URL, f"{Path.home()}", "mainsail.zip")
|
||||||
|
Logger.print_ok("Download complete!")
|
||||||
|
|
||||||
|
Logger.print_status("Extracting mainsail.zip ...")
|
||||||
|
unzip(f"{Path.home()}/mainsail.zip", MAINSAIL_DIR)
|
||||||
|
Logger.print_ok("OK!")
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
Logger.print_error("Downloading Mainsail failed!")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def download_mainsail_config() -> 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_nginx_cfg(port: int) -> None:
|
||||||
|
try:
|
||||||
|
Logger.print_status("Creating NGINX config for Mainsail ...")
|
||||||
|
root_dir = MAINSAIL_DIR
|
||||||
|
delete_default_nginx_cfg()
|
||||||
|
create_nginx_cfg("mainsail", port, root_dir)
|
||||||
|
enable_nginx_cfg("mainsail")
|
||||||
|
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 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 = Path(instance.log_dir).joinpath("mainsail-access.log")
|
||||||
|
if not desti_access.exists():
|
||||||
|
desti_access.symlink_to(access_log)
|
||||||
|
|
||||||
|
desti_error = Path(instance.log_dir).joinpath("mainsail-error.log")
|
||||||
|
if not desti_error.exists():
|
||||||
|
desti_error.symlink_to(error_log)
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
cm.read_config()
|
||||||
|
if cm.config.has_section(section_name):
|
||||||
|
Logger.print_info("Section already exist. Skipped ...")
|
||||||
|
return
|
||||||
|
|
||||||
|
template = os.path.join(MODULE_PATH, "res", 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)
|
||||||
|
cm.read_config()
|
||||||
|
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]")
|
||||||
|
|
||||||
|
|
||||||
|
def backup_config_json() -> None:
|
||||||
|
try:
|
||||||
|
Logger.print_status(f"Backup '{MAINSAIL_CONFIG_JSON}' ...")
|
||||||
|
target = os.path.join(Path.home(), "config.json.kiauh.bak")
|
||||||
|
shutil.copy(MAINSAIL_CONFIG_JSON, target)
|
||||||
|
except OSError:
|
||||||
|
Logger.print_info(f"Unable to backup config.json. Skipped ...")
|
||||||
|
|
||||||
|
|
||||||
|
def restore_config_json() -> None:
|
||||||
|
try:
|
||||||
|
Logger.print_status(f"Restore '{MAINSAIL_CONFIG_JSON}' ...")
|
||||||
|
source = os.path.join(Path.home(), "config.json.kiauh.bak")
|
||||||
|
shutil.copy(source, MAINSAIL_CONFIG_JSON)
|
||||||
|
except OSError:
|
||||||
|
Logger.print_info(f"Unable to restore config.json. Skipped ...")
|
||||||
|
|
||||||
|
|
||||||
|
def enable_mainsail_remotemode() -> None:
|
||||||
|
with open(MAINSAIL_CONFIG_JSON, "r") as f:
|
||||||
|
config_data = json.load(f)
|
||||||
|
|
||||||
|
if config_data["instancesDB"] == "browser":
|
||||||
|
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)
|
||||||
6
kiauh/modules/mainsail/res/mainsail-config-updater.conf
Normal file
6
kiauh/modules/mainsail/res/mainsail-config-updater.conf
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[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
|
||||||
5
kiauh/modules/mainsail/res/mainsail-updater.conf
Normal file
5
kiauh/modules/mainsail/res/mainsail-updater.conf
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[update_manager mainsail]
|
||||||
|
type: web
|
||||||
|
channel: stable
|
||||||
|
repo: mainsail-crew/mainsail
|
||||||
|
path: ~/mainsail
|
||||||
Reference in New Issue
Block a user