mirror of
https://github.com/dw-0/kiauh.git
synced 2025-12-16 20:14:32 +05:00
feat: implement port reconfiguration for webclients (#586)
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
@@ -34,7 +34,7 @@ from utils.input_utils import get_confirm
|
|||||||
from utils.instance_utils import get_instances
|
from utils.instance_utils import get_instances
|
||||||
|
|
||||||
|
|
||||||
def install_client_config(client_data: BaseWebClient) -> None:
|
def install_client_config(client_data: BaseWebClient, cfg_backup=True) -> None:
|
||||||
client_config: BaseWebClientConfig = client_data.client_config
|
client_config: BaseWebClientConfig = client_data.client_config
|
||||||
display_name = client_config.display_name
|
display_name = client_config.display_name
|
||||||
|
|
||||||
@@ -56,7 +56,8 @@ def install_client_config(client_data: BaseWebClient) -> None:
|
|||||||
download_client_config(client_config)
|
download_client_config(client_config)
|
||||||
create_client_config_symlink(client_config, kl_instances)
|
create_client_config_symlink(client_config, kl_instances)
|
||||||
|
|
||||||
backup_printer_config_dir()
|
if cfg_backup:
|
||||||
|
backup_printer_config_dir()
|
||||||
|
|
||||||
add_config_section(
|
add_config_section(
|
||||||
section=f"update_manager {client_config.name}",
|
section=f"update_manager {client_config.name}",
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ def print_client_port_select_dialog(
|
|||||||
dialog_content.extend(
|
dialog_content.extend(
|
||||||
[
|
[
|
||||||
"\n\n",
|
"\n\n",
|
||||||
"The following ports were found to be in use already:",
|
"The following ports were found to be already in use:",
|
||||||
*[f"● {port}" for port in ports_in_use],
|
*[f"● {p}" for p in ports_in_use if p != port],
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -36,8 +36,9 @@ from components.webui_client.client_utils import (
|
|||||||
symlink_webui_nginx_log,
|
symlink_webui_nginx_log,
|
||||||
)
|
)
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from core.logger import Logger
|
from core.logger import DialogCustomColor, DialogType, Logger
|
||||||
from utils.common import check_install_dependencies
|
from core.settings.kiauh_settings import KiauhSettings
|
||||||
|
from utils.common import backup_printer_config_dir, check_install_dependencies
|
||||||
from utils.config_utils import add_config_section
|
from utils.config_utils import add_config_section
|
||||||
from utils.fs_utils import unzip
|
from utils.fs_utils import unzip
|
||||||
from utils.input_utils import get_confirm
|
from utils.input_utils import get_confirm
|
||||||
@@ -49,16 +50,11 @@ from utils.sys_utils import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def install_client(client: BaseWebClient) -> None:
|
def install_client(
|
||||||
if client is None:
|
client: BaseWebClient,
|
||||||
raise ValueError("Missing parameter client_data!")
|
settings: KiauhSettings,
|
||||||
|
reinstall: bool = False,
|
||||||
if client.client_dir.exists():
|
) -> None:
|
||||||
Logger.print_info(
|
|
||||||
f"{client.display_name} seems to be already installed! Skipped ..."
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
mr_instances: List[Moonraker] = get_instances(Moonraker)
|
mr_instances: List[Moonraker] = get_instances(Moonraker)
|
||||||
|
|
||||||
enable_remotemode = False
|
enable_remotemode = False
|
||||||
@@ -88,7 +84,10 @@ def install_client(client: BaseWebClient) -> None:
|
|||||||
question = f"Download the recommended {client_config.display_name}?"
|
question = f"Download the recommended {client_config.display_name}?"
|
||||||
install_client_cfg = get_confirm(question, allow_go_back=False)
|
install_client_cfg = get_confirm(question, allow_go_back=False)
|
||||||
|
|
||||||
port: int = get_client_port_selection(client)
|
default_port: int = int(settings.get(client.name, "port"))
|
||||||
|
port: int = (
|
||||||
|
default_port if reinstall else get_client_port_selection(client, settings)
|
||||||
|
)
|
||||||
|
|
||||||
check_install_dependencies({"nginx"})
|
check_install_dependencies({"nginx"})
|
||||||
|
|
||||||
@@ -96,20 +95,22 @@ def install_client(client: BaseWebClient) -> None:
|
|||||||
download_client(client)
|
download_client(client)
|
||||||
if enable_remotemode and client.client == WebClientType.MAINSAIL:
|
if enable_remotemode and client.client == WebClientType.MAINSAIL:
|
||||||
enable_mainsail_remotemode()
|
enable_mainsail_remotemode()
|
||||||
if mr_instances:
|
|
||||||
add_config_section(
|
backup_printer_config_dir()
|
||||||
section=f"update_manager {client.name}",
|
add_config_section(
|
||||||
instances=mr_instances,
|
section=f"update_manager {client.name}",
|
||||||
options=[
|
instances=mr_instances,
|
||||||
("type", "web"),
|
options=[
|
||||||
("channel", "stable"),
|
("type", "web"),
|
||||||
("repo", str(client.repo_path)),
|
("channel", "stable"),
|
||||||
("path", str(client.client_dir)),
|
("repo", str(client.repo_path)),
|
||||||
],
|
("path", str(client.client_dir)),
|
||||||
)
|
],
|
||||||
InstanceManager.restart_all(mr_instances)
|
)
|
||||||
|
InstanceManager.restart_all(mr_instances)
|
||||||
|
|
||||||
if install_client_cfg and kl_instances:
|
if install_client_cfg and kl_instances:
|
||||||
install_client_config(client)
|
install_client_config(client, False)
|
||||||
|
|
||||||
copy_upstream_nginx_cfg()
|
copy_upstream_nginx_cfg()
|
||||||
copy_common_vars_nginx_cfg()
|
copy_common_vars_nginx_cfg()
|
||||||
@@ -127,12 +128,24 @@ def install_client(client: BaseWebClient) -> None:
|
|||||||
cmd_sysctl_service("nginx", "restart")
|
cmd_sysctl_service("nginx", "restart")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Logger.print_error(f"{client.display_name} installation failed!\n{e}")
|
Logger.print_error(e)
|
||||||
|
Logger.print_dialog(
|
||||||
|
DialogType.ERROR,
|
||||||
|
center_content=True,
|
||||||
|
content=[f"{client.display_name} installation failed!"],
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
log = f"Open {client.display_name} now on: http://{get_ipv4_addr()}:{port}"
|
# noinspection HttpUrlsUsage
|
||||||
Logger.print_ok(f"{client.display_name} installation complete!", start="\n")
|
Logger.print_dialog(
|
||||||
Logger.print_ok(log, prefix=False, end="\n\n")
|
DialogType.CUSTOM,
|
||||||
|
custom_title=f"{client.display_name} installation complete!",
|
||||||
|
custom_color=DialogCustomColor.GREEN,
|
||||||
|
center_content=True,
|
||||||
|
content=[
|
||||||
|
f"Open {client.display_name} now on: http://{get_ipv4_addr()}:{port}",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def download_client(client: BaseWebClient) -> None:
|
def download_client(client: BaseWebClient) -> None:
|
||||||
|
|||||||
@@ -370,19 +370,26 @@ def read_ports_from_nginx_configs() -> List[int]:
|
|||||||
return sorted(ports_to_ints_list, key=lambda x: int(x))
|
return sorted(ports_to_ints_list, key=lambda x: int(x))
|
||||||
|
|
||||||
|
|
||||||
def get_client_port_selection(client: BaseWebClient) -> int:
|
def get_client_port_selection(
|
||||||
settings = KiauhSettings()
|
client: BaseWebClient,
|
||||||
|
settings: KiauhSettings,
|
||||||
|
reconfigure=False,
|
||||||
|
) -> int:
|
||||||
default_port: int = int(settings.get(client.name, "port"))
|
default_port: int = int(settings.get(client.name, "port"))
|
||||||
|
|
||||||
ports_in_use: List[int] = read_ports_from_nginx_configs()
|
ports_in_use: List[int] = read_ports_from_nginx_configs()
|
||||||
next_free_port: int = get_next_free_port(ports_in_use)
|
next_free_port: int = get_next_free_port(ports_in_use)
|
||||||
|
|
||||||
port: int = next_free_port if default_port in ports_in_use else default_port
|
port: int = (
|
||||||
|
next_free_port
|
||||||
|
if not reconfigure and default_port in ports_in_use
|
||||||
|
else default_port
|
||||||
|
)
|
||||||
|
|
||||||
print_client_port_select_dialog(client.display_name, port, ports_in_use)
|
print_client_port_select_dialog(client.display_name, port, ports_in_use)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
question = f"Configure {client.display_name} for port"
|
_type = "Reconfigure" if reconfigure else "Configure"
|
||||||
|
question = f"{_type} {client.display_name} for port"
|
||||||
port_input = get_number_input(question, min_count=80, default=port)
|
port_input = get_number_input(question, min_count=80, default=port)
|
||||||
|
|
||||||
if port_input not in ports_in_use:
|
if port_input not in ports_in_use:
|
||||||
@@ -400,3 +407,23 @@ def get_next_free_port(ports_in_use: List[int]) -> int:
|
|||||||
used_ports = set(map(int, ports_in_use))
|
used_ports = set(map(int, ports_in_use))
|
||||||
|
|
||||||
return min(valid_ports - used_ports)
|
return min(valid_ports - used_ports)
|
||||||
|
|
||||||
|
|
||||||
|
def set_listen_port(client: BaseWebClient, curr_port: int, new_port: int) -> None:
|
||||||
|
"""
|
||||||
|
Set the port the client should listen on in the NGINX config
|
||||||
|
:param curr_port: The current port the client listens on
|
||||||
|
:param new_port: The new port to set
|
||||||
|
:param client: The client to set the port for
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
config = NGINX_SITES_AVAILABLE.joinpath(client.name)
|
||||||
|
with open(config, "r") as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if "listen" in line:
|
||||||
|
lines[i] = line.replace(str(curr_port), str(new_port))
|
||||||
|
|
||||||
|
with open(config, "w") as f:
|
||||||
|
f.writelines(lines)
|
||||||
|
|||||||
104
kiauh/components/webui_client/menus/client_install_menu.py
Normal file
104
kiauh/components/webui_client/menus/client_install_menu.py
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# ======================================================================= #
|
||||||
|
# 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 __future__ import annotations
|
||||||
|
|
||||||
|
import textwrap
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from components.webui_client.base_data import BaseWebClient
|
||||||
|
from components.webui_client.client_setup import install_client
|
||||||
|
from components.webui_client.client_utils import (
|
||||||
|
get_client_port_selection,
|
||||||
|
set_listen_port,
|
||||||
|
)
|
||||||
|
from core.constants import COLOR_CYAN, COLOR_GREEN, RESET_FORMAT
|
||||||
|
from core.logger import DialogCustomColor, DialogType, Logger
|
||||||
|
from core.menus import Option
|
||||||
|
from core.menus.base_menu import BaseMenu
|
||||||
|
from core.settings.kiauh_settings import KiauhSettings, WebUiSettings
|
||||||
|
from utils.sys_utils import cmd_sysctl_service, get_ipv4_addr
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyUnusedLocal
|
||||||
|
class ClientInstallMenu(BaseMenu):
|
||||||
|
def __init__(
|
||||||
|
self, client: BaseWebClient, previous_menu: Type[BaseMenu] | None = None
|
||||||
|
):
|
||||||
|
super().__init__()
|
||||||
|
self.previous_menu: Type[BaseMenu] | None = previous_menu
|
||||||
|
self.client: BaseWebClient = client
|
||||||
|
self.settings = KiauhSettings()
|
||||||
|
self.client_settings: WebUiSettings = self.settings[client.name]
|
||||||
|
|
||||||
|
def set_previous_menu(self, previous_menu: Type[BaseMenu] | None) -> None:
|
||||||
|
from core.menus.install_menu import InstallMenu
|
||||||
|
|
||||||
|
self.previous_menu = previous_menu if previous_menu is not None else InstallMenu
|
||||||
|
|
||||||
|
def set_options(self) -> None:
|
||||||
|
self.options = {
|
||||||
|
"1": Option(method=self.reinstall_client),
|
||||||
|
"2": Option(method=self.change_listen_port),
|
||||||
|
}
|
||||||
|
|
||||||
|
def print_menu(self) -> None:
|
||||||
|
client_name = self.client.display_name
|
||||||
|
|
||||||
|
header = f" [ Installation Menu > {client_name} ] "
|
||||||
|
color = COLOR_GREEN
|
||||||
|
count = 62 - len(color) - len(RESET_FORMAT)
|
||||||
|
port = f"(Current: {COLOR_CYAN}{int(self.client_settings.port)}{RESET_FORMAT})"
|
||||||
|
menu = textwrap.dedent(
|
||||||
|
f"""
|
||||||
|
╔═══════════════════════════════════════════════════════╗
|
||||||
|
║ {color}{header:~^{count}}{RESET_FORMAT} ║
|
||||||
|
╟───────────────────────────────────────────────────────╢
|
||||||
|
║ 1) Reinstall {client_name:16} ║
|
||||||
|
║ 2) Reconfigure Listen Port {port:<34} ║
|
||||||
|
╟───────────────────────────────────────────────────────╢
|
||||||
|
"""
|
||||||
|
)[1:]
|
||||||
|
print(menu, end="")
|
||||||
|
|
||||||
|
def reinstall_client(self, **kwargs) -> None:
|
||||||
|
install_client(self.client, settings=self.settings, reinstall=True)
|
||||||
|
|
||||||
|
def change_listen_port(self, **kwargs) -> None:
|
||||||
|
curr_port = int(self.client_settings.port)
|
||||||
|
new_port = get_client_port_selection(
|
||||||
|
self.client,
|
||||||
|
self.settings,
|
||||||
|
reconfigure=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd_sysctl_service("nginx", "stop")
|
||||||
|
set_listen_port(self.client, curr_port, new_port)
|
||||||
|
|
||||||
|
Logger.print_status("Saving new port configuration ...")
|
||||||
|
self.client_settings.port = new_port
|
||||||
|
self.settings.save()
|
||||||
|
Logger.print_ok("Port configuration saved!")
|
||||||
|
|
||||||
|
cmd_sysctl_service("nginx", "start")
|
||||||
|
|
||||||
|
# noinspection HttpUrlsUsage
|
||||||
|
Logger.print_dialog(
|
||||||
|
DialogType.CUSTOM,
|
||||||
|
custom_title="Port reconfiguration complete!",
|
||||||
|
custom_color=DialogCustomColor.GREEN,
|
||||||
|
center_content=True,
|
||||||
|
content=[
|
||||||
|
f"Open {self.client.display_name} now on: "
|
||||||
|
f"http://{get_ipv4_addr()}:{new_port}",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def _go_back(self, **kwargs) -> None:
|
||||||
|
if self.previous_menu is not None:
|
||||||
|
self.previous_menu().run()
|
||||||
@@ -15,13 +15,17 @@ from components.crowsnest.crowsnest import install_crowsnest
|
|||||||
from components.klipper import klipper_setup
|
from components.klipper import klipper_setup
|
||||||
from components.klipperscreen.klipperscreen import install_klipperscreen
|
from components.klipperscreen.klipperscreen import install_klipperscreen
|
||||||
from components.moonraker import moonraker_setup
|
from components.moonraker import moonraker_setup
|
||||||
from components.webui_client import client_setup
|
from components.webui_client.client_config.client_config_setup import (
|
||||||
from components.webui_client.client_config import client_config_setup
|
install_client_config,
|
||||||
|
)
|
||||||
|
from components.webui_client.client_setup import install_client
|
||||||
from components.webui_client.fluidd_data import FluiddData
|
from components.webui_client.fluidd_data import FluiddData
|
||||||
from components.webui_client.mainsail_data import MainsailData
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
|
from components.webui_client.menus.client_install_menu import ClientInstallMenu
|
||||||
from core.constants import COLOR_GREEN, RESET_FORMAT
|
from core.constants import COLOR_GREEN, RESET_FORMAT
|
||||||
from core.menus import Option
|
from core.menus import Option
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
|
from core.settings.kiauh_settings import KiauhSettings
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
@@ -80,16 +84,24 @@ class InstallMenu(BaseMenu):
|
|||||||
moonraker_setup.install_moonraker()
|
moonraker_setup.install_moonraker()
|
||||||
|
|
||||||
def install_mainsail(self, **kwargs) -> None:
|
def install_mainsail(self, **kwargs) -> None:
|
||||||
client_setup.install_client(MainsailData())
|
client: MainsailData = MainsailData()
|
||||||
|
if client.client_dir.exists():
|
||||||
|
ClientInstallMenu(client, self.__class__).run()
|
||||||
|
else:
|
||||||
|
install_client(client, settings=KiauhSettings())
|
||||||
|
|
||||||
def install_mainsail_config(self, **kwargs) -> None:
|
def install_mainsail_config(self, **kwargs) -> None:
|
||||||
client_config_setup.install_client_config(MainsailData())
|
install_client_config(MainsailData())
|
||||||
|
|
||||||
def install_fluidd(self, **kwargs) -> None:
|
def install_fluidd(self, **kwargs) -> None:
|
||||||
client_setup.install_client(FluiddData())
|
client: FluiddData = FluiddData()
|
||||||
|
if client.client_dir.exists():
|
||||||
|
ClientInstallMenu(client, self.__class__).run()
|
||||||
|
else:
|
||||||
|
install_client(client, settings=KiauhSettings())
|
||||||
|
|
||||||
def install_fluidd_config(self, **kwargs) -> None:
|
def install_fluidd_config(self, **kwargs) -> None:
|
||||||
client_config_setup.install_client_config(FluiddData())
|
install_client_config(FluiddData())
|
||||||
|
|
||||||
def install_klipperscreen(self, **kwargs) -> None:
|
def install_klipperscreen(self, **kwargs) -> None:
|
||||||
install_klipperscreen()
|
install_klipperscreen()
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ def add_config_section(
|
|||||||
instances: List[InstanceType],
|
instances: List[InstanceType],
|
||||||
options: List[ConfigOption] | None = None,
|
options: List[ConfigOption] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
if not instances:
|
||||||
|
return
|
||||||
|
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
cfg_file = instance.cfg_file
|
cfg_file = instance.cfg_file
|
||||||
Logger.print_status(f"Add section '[{section}]' to '{cfg_file}' ...")
|
Logger.print_status(f"Add section '[{section}]' to '{cfg_file}' ...")
|
||||||
|
|||||||
Reference in New Issue
Block a user