Compare commits

..

1 Commits

Author SHA1 Message Date
dw-0
5c5e30295a Merge 655b781aef into b6c6edb622 2024-03-03 18:29:29 +01:00
13 changed files with 91 additions and 93 deletions

View File

@@ -11,10 +11,7 @@
from pathlib import Path
from components.webui_client.client_utils import (
get_existing_client_config,
get_existing_clients,
)
from components.webui_client.client_utils import get_existing_client_config
from kiauh import KIAUH_CFG
from components.klipper import (
EXIT_KLIPPER_SETUP,
@@ -99,8 +96,7 @@ def install_klipper() -> None:
kl_im.reload_daemon()
except Exception as e:
Logger.print_error(e)
except Exception:
Logger.print_error("Klipper installation failed!")
return
@@ -186,6 +182,6 @@ def create_klipper_instance(name: str, create_example_cfg: bool) -> None:
kl_im.enable_instance()
if create_example_cfg:
# if a client-config is installed, include it in the new example cfg
clients = get_existing_clients()
create_example_printer_cfg(new_instance, clients)
client_configs = get_existing_client_config()
create_example_printer_cfg(new_instance, client_configs)
kl_im.start_instance()

View File

@@ -34,16 +34,12 @@ from components.klipper.klipper_dialogs import (
from components.moonraker.moonraker import Moonraker
from components.moonraker.moonraker_utils import moonraker_to_multi_conversion
from components.webui_client import ClientData
from components.webui_client.client_config.client_config_setup import (
create_client_config_symlink,
)
from core.backup_manager.backup_manager import BackupManager
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 core.instance_manager.name_scheme import NameScheme
from core.repo_manager.repo_manager import RepoManager
from utils import PRINTER_CFG_BACKUP_DIR
from utils.common import get_install_status_common
from utils.constants import CURRENT_USER
from utils.input_utils import get_confirm, get_string_input, get_number_input
@@ -162,43 +158,23 @@ def klipper_to_multi_conversion(new_name: str) -> None:
Logger.print_status("Convert Klipper single to multi instance ...")
im = InstanceManager(Klipper)
im.current_instance = im.instances[0]
# temporarily store the data dir path
old_data_dir = im.instances[0].data_dir
old_data_dir_name = im.instances[0].data_dir_name
# backup the old data_dir
bm = BackupManager()
name = f"config-{old_data_dir_name}"
bm.backup_directory(
name,
source=im.current_instance.cfg_dir,
target=PRINTER_CFG_BACKUP_DIR,
)
# remove the old single instance
im.stop_instance()
im.disable_instance()
im.delete_instance()
# create a new klipper instance with the new name
new_instance = Klipper(suffix=new_name)
im.current_instance = new_instance
im.current_instance = Klipper(suffix=new_name)
new_data_dir: Path = im.current_instance.data_dir
if not new_instance.data_dir.is_dir():
# rename the old data dir and use it for the new instance
Logger.print_status(f"Rename '{old_data_dir}' to '{new_instance.data_dir}' ...")
old_data_dir.rename(new_instance.data_dir)
# rename the old data dir and use it for the new instance
Logger.print_status(f"Rename '{old_data_dir}' to '{new_data_dir}' ...")
if not new_data_dir.is_dir():
old_data_dir.rename(new_data_dir)
else:
Logger.print_info(f"Existing '{new_instance.data_dir}' found ...")
Logger.print_info(f"'{new_data_dir}' already exist. Skipped ...")
# patch the virtual_sdcard sections path value to match the new printer_data foldername
cm = ConfigManager(new_instance.cfg_file)
if cm.config.has_section("virtual_sdcard"):
cm.set_value("virtual_sdcard", "path", str(new_instance.gcodes_dir))
cm.write_config()
# finalize creating the new instance
im.create_instance()
im.enable_instance()
im.start_instance()
@@ -287,7 +263,7 @@ def get_highest_index(instance_list: List[Klipper]) -> int:
def create_example_printer_cfg(
instance: Klipper, clients: Optional[List[ClientData]] = None
instance: Klipper, client_configs: Optional[List[ClientData]] = None
) -> None:
Logger.print_status(f"Creating example printer.cfg in '{instance.cfg_dir}'")
if instance.cfg_file.is_file():
@@ -306,12 +282,10 @@ def create_example_printer_cfg(
cm.set_value("virtual_sdcard", "path", str(instance.gcodes_dir))
# include existing client configs in the example config
if clients is not None and len(clients) > 0:
for c in clients:
client_config = c.get("client_config")
section = client_config.get("printer_cfg_section")
if client_configs is not None and len(client_configs) > 0:
for c in client_configs:
section = c.get("client_config").get("printer_cfg_section")
cm.config.add_section(section=section)
create_client_config_symlink(client_config, [instance])
cm.write_config()

View File

@@ -49,7 +49,7 @@ def upload_logfile(logfile: LogFile) -> None:
try:
response = urllib.request.urlopen(req)
link = response.read().decode("utf-8")
Logger.print_ok("Upload successful! Access it via the following link:")
Logger.print_ok("Upload successfull! Access it via the following link:")
Logger.print_ok(f">>>> {link}", False)
except Exception as e:
Logger.print_error(f"Uploading logfile failed!")

View File

@@ -35,17 +35,12 @@ class Moonraker(BaseInstance):
self.backup_dir = self.data_dir.joinpath("backup")
self.certs_dir = self.data_dir.joinpath("certs")
self._db_dir = self.data_dir.joinpath("database")
self._comms_dir = self.data_dir.joinpath("comms")
self.log = self.log_dir.joinpath("moonraker.log")
@property
def db_dir(self) -> Path:
return self._db_dir
@property
def comms_dir(self) -> Path:
return self._comms_dir
def create(self, create_example_cfg: bool = False) -> None:
Logger.print_status("Creating new Moonraker Instance ...")
service_template_path = MODULE_PATH.joinpath("assets/moonraker.service")

View File

@@ -130,6 +130,12 @@ def check_moonraker_install_requirements() -> bool:
Logger.print_warn("Moonraker cannot be installed! Install Klipper first.")
return False
mr_instance_count = len(InstanceManager(Moonraker).instances)
if mr_instance_count >= kl_instance_count:
Logger.print_warn("Unable to install more Moonraker instances!")
Logger.print_warn("More Klipper instances required.")
return False
return True
@@ -187,6 +193,17 @@ def install_moonraker_polkit() -> None:
Logger.print_error(log)
def handle_existing_instances(instance_list: List[Klipper]) -> bool:
instance_count = len(instance_list)
if instance_count > 0:
print_instance_overview(instance_list)
if not get_confirm("Add new instances?", allow_go_back=True):
return False
return True
def update_moonraker() -> None:
if not get_confirm("Update Moonraker now?"):
return

View File

@@ -150,27 +150,13 @@ def moonraker_to_multi_conversion(new_name: str) -> None:
return
Logger.print_status("Convert Moonraker single to multi instance ...")
# remove the old single instance
im.current_instance = im.instances[0]
im.stop_instance()
im.disable_instance()
im.delete_instance()
# create a new moonraker instance with the new name
new_instance = Moonraker(suffix=new_name)
im.current_instance = new_instance
# patch the server sections klippy_uds_address value to match the new printer_data foldername
cm = ConfigManager(new_instance.cfg_file)
if cm.config.has_section("server"):
cm.set_value(
"server",
"klippy_uds_address",
str(new_instance.comms_dir.joinpath("klippy.sock")),
)
cm.write_config()
# create a new klipper instance with the new name
im.current_instance = Moonraker(suffix=new_name)
# create, enable and start the new moonraker instance
im.create_instance()
im.enable_instance()

View File

@@ -24,13 +24,19 @@ 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)
remove_config_section(f"update_manager {client_config.get('name')}", mr_instances)
remove_config_section(client_config.get("printer_cfg_section"), kl_instances)
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:
@@ -50,9 +56,9 @@ def remove_client_config_symlink(client_config: ClientConfigData) -> None:
im = InstanceManager(Klipper)
instances: List[Klipper] = im.instances
for instance in instances:
Logger.print_status(f"Removing symlink from '{instance.cfg_dir}' ...")
Logger.print_status(f"Removing symlink from '{instance.cfg_file}' ...")
symlink = instance.cfg_dir.joinpath(client_config.get("cfg_filename"))
if not symlink.is_symlink():
if not symlink.exists():
Logger.print_info(f"'{symlink}' does not exist. Skipping ...")
continue

View File

@@ -35,27 +35,28 @@ def run_client_removal(
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)
section = f"update_manager {client_name}"
remove_config_section(section, mr_instances)
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,
)

View File

@@ -25,6 +25,8 @@ class ClientRemoveMenu(BaseMenu):
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,
@@ -37,10 +39,12 @@ class ClientRemoveMenu(BaseMenu):
"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["3"] = self.toggle_backup_mainsail_config_json
options["5"] = self.toggle_backup_mainsail_config_json
return options
@@ -56,6 +60,8 @@ class ClientRemoveMenu(BaseMenu):
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"""
/=======================================================\\
@@ -68,14 +74,20 @@ class ClientRemoveMenu(BaseMenu):
|-------------------------------------------------------|
| 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":
o3 = checked if self.backup_mainsail_config_json else unchecked
o5 = checked if self.backup_mainsail_config_json else unchecked
menu += textwrap.dedent(
f"""
| 3) {o3} Backup config.json |
| |
| Mainsail config.json |
| 5) {o5} Backup config.json |
"""
)[1:]
@@ -91,6 +103,8 @@ class ClientRemoveMenu(BaseMenu):
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
@@ -101,11 +115,19 @@ class ClientRemoveMenu(BaseMenu):
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)
@@ -116,8 +138,12 @@ class ClientRemoveMenu(BaseMenu):
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

View File

@@ -56,7 +56,7 @@ class BackupManager:
try:
Path(target).mkdir(exist_ok=True)
shutil.copyfile(file, target.joinpath(filename))
Logger.print_ok("Backup successful!")
Logger.print_ok("Backup successfull!")
except OSError as e:
Logger.print_error(f"Unable to backup '{file}':\n{e}")
else:
@@ -77,7 +77,7 @@ class BackupManager:
target.joinpath(f"{name.lower()}-{date}-{time}"),
ignore=self.ignore_folders_func,
)
Logger.print_ok("Backup successful!")
Logger.print_ok("Backup successfull!")
except OSError as e:
Logger.print_error(f"Unable to backup directory '{source}':\n{e}")
return

View File

@@ -140,7 +140,7 @@ class RepoManager:
command = ["git", "clone", self.repo, self.target_dir]
subprocess.run(command, check=True)
Logger.print_ok("Clone successful!")
Logger.print_ok("Clone successfull!")
except subprocess.CalledProcessError as e:
log = f"Error cloning repository {self.repo}: {e.stderr.decode()}"
Logger.print_error(log)
@@ -151,7 +151,7 @@ class RepoManager:
command = ["git", "checkout", f"{self.branch}"]
subprocess.run(command, cwd=self.target_dir, check=True)
Logger.print_ok("Checkout successful!")
Logger.print_ok("Checkout successfull!")
except subprocess.CalledProcessError as e:
log = f"Error checking out branch {self.branch}: {e.stderr.decode()}"
Logger.print_error(log)

View File

@@ -68,7 +68,7 @@ class GcodeShellCmdExtension(BaseExtension):
im.start_all_instance()
Logger.print_ok("Installing G-Code Shell Command extension successful!")
Logger.print_ok("Installing G-Code Shell Command extension successfull!")
def remove_extension(self, **kwargs) -> None:
extension_installed = check_file_exist(EXTENSION_TARGET_PATH)

View File

@@ -71,7 +71,7 @@ def create_python_venv(target: Path) -> None:
if not target.exists():
try:
venv.create(target, with_pip=True)
Logger.print_ok("Setup of virtualenv successful!")
Logger.print_ok("Setup of virtualenv successfull!")
except OSError as e:
Logger.print_error(f"Error setting up virtualenv:\n{e}")
raise
@@ -111,7 +111,7 @@ def update_python_pip(target: Path) -> None:
Logger.print_error("Updating pip failed!")
return
Logger.print_ok("Updating pip successful!")
Logger.print_ok("Updating pip successfull!")
except FileNotFoundError as e:
Logger.print_error(e)
raise
@@ -127,20 +127,17 @@ def install_python_requirements(target: Path, requirements: Path) -> None:
:param requirements: Path to the requirements.txt file
:return: None
"""
Logger.print_status("Installing Python requirements ...")
try:
# always update pip before installing requirements
update_python_pip(target)
Logger.print_status("Installing Python requirements ...")
command = [target.joinpath("bin/pip"), "install", "-r", f"{requirements}"]
result = subprocess.run(command, stderr=subprocess.PIPE, text=True)
if result.returncode != 0 or result.stderr:
Logger.print_error(f"{result.stderr}", False)
Logger.print_error("Installing Python requirements failed!")
return
Logger.print_ok("Installing Python requirements successful!")
Logger.print_ok("Installing Python requirements successfull!")
except subprocess.CalledProcessError as e:
log = f"Error installing Python requirements:\n{e.output.decode()}"
Logger.print_error(log)
@@ -183,7 +180,7 @@ def update_system_package_lists(silent: bool, rls_info_change=False) -> None:
Logger.print_error("Updating system package list failed!")
return
Logger.print_ok("System package list update successful!")
Logger.print_ok("System package list updated successfully!")
except subprocess.CalledProcessError as e:
kill(f"Error updating system package list:\n{e.stderr.decode()}")