refactor(crowsnest): fix crowsnest install status and update for v5 (#799)

fix: fix crowsnest install status and update for v5

Crowsnest v5 introduced multiple breaking changes resulting in a
'Incomplete' install status even after successful installation.
This adds support for the new v5 setup with backwards compatibility for
old versions.

Signed-off-by: Patrick Gehrsitz <github@mryel.de>
This commit is contained in:
Patrick Gehrsitz
2026-05-30 15:36:32 +02:00
committed by GitHub
parent b90a8f13b1
commit 9f97ae6c2a
2 changed files with 70 additions and 8 deletions
+2
View File
@@ -19,10 +19,12 @@ CROWSNEST_SERVICE_NAME = "crowsnest.service"
# directories # directories
CROWSNEST_DIR = Path.home().joinpath("crowsnest") CROWSNEST_DIR = Path.home().joinpath("crowsnest")
CROWSNEST_ENV_DIR = Path.home().joinpath("crowsnest-env")
# files # files
CROWSNEST_MULTI_CONFIG = CROWSNEST_DIR.joinpath("tools/.config") CROWSNEST_MULTI_CONFIG = CROWSNEST_DIR.joinpath("tools/.config")
CROWSNEST_INSTALL_SCRIPT = CROWSNEST_DIR.joinpath("tools/install.sh") CROWSNEST_INSTALL_SCRIPT = CROWSNEST_DIR.joinpath("tools/install.sh")
CROWSNEST_DEPS_JSON_FILE = CROWSNEST_DIR.joinpath("system-dependencies.json")
CROWSNEST_BIN_FILE = Path("/usr/local/bin/crowsnest") CROWSNEST_BIN_FILE = Path("/usr/local/bin/crowsnest")
CROWSNEST_LOGROTATE_FILE = Path("/etc/logrotate.d/crowsnest") CROWSNEST_LOGROTATE_FILE = Path("/etc/logrotate.d/crowsnest")
CROWSNEST_SERVICE_FILE = SYSTEMD.joinpath(CROWSNEST_SERVICE_NAME) CROWSNEST_SERVICE_FILE = SYSTEMD.joinpath(CROWSNEST_SERVICE_NAME)
+68 -8
View File
@@ -16,7 +16,9 @@ from typing import List
from components.crowsnest import ( from components.crowsnest import (
CROWSNEST_BIN_FILE, CROWSNEST_BIN_FILE,
CROWSNEST_DEPS_JSON_FILE,
CROWSNEST_DIR, CROWSNEST_DIR,
CROWSNEST_ENV_DIR,
CROWSNEST_INSTALL_SCRIPT, CROWSNEST_INSTALL_SCRIPT,
CROWSNEST_LOGROTATE_FILE, CROWSNEST_LOGROTATE_FILE,
CROWSNEST_MULTI_CONFIG, CROWSNEST_MULTI_CONFIG,
@@ -25,6 +27,8 @@ from components.crowsnest import (
CROWSNEST_SERVICE_NAME, CROWSNEST_SERVICE_NAME,
) )
from components.klipper.klipper import Klipper from components.klipper.klipper import Klipper
from components.moonraker.utils.sysdeps_parser import SysDepsParser
from components.moonraker.utils.utils import load_sysdeps_json
from core.logger import DialogType, Logger from core.logger import DialogType, Logger
from core.services.backup_service import BackupService from core.services.backup_service import BackupService
from core.settings.kiauh_settings import KiauhSettings from core.settings.kiauh_settings import KiauhSettings
@@ -34,6 +38,7 @@ from utils.common import (
get_install_status, get_install_status,
) )
from utils.git_utils import ( from utils.git_utils import (
get_current_branch,
git_clone_wrapper, git_clone_wrapper,
git_pull_wrapper, git_pull_wrapper,
) )
@@ -135,8 +140,7 @@ def update_crowsnest() -> None:
git_pull_wrapper(CROWSNEST_DIR) git_pull_wrapper(CROWSNEST_DIR)
deps = parse_packages_from_file(CROWSNEST_INSTALL_SCRIPT) install_crowsnest_packages()
check_install_dependencies({*deps})
cmd_sysctl_service(CROWSNEST_SERVICE_NAME, "restart") cmd_sysctl_service(CROWSNEST_SERVICE_NAME, "restart")
@@ -147,12 +151,68 @@ def update_crowsnest() -> None:
def get_crowsnest_status() -> ComponentStatus: def get_crowsnest_status() -> ComponentStatus:
files = [ """
CROWSNEST_BIN_FILE, Get the current install status of Crowsnest. Depending on the version the installed
CROWSNEST_LOGROTATE_FILE, files are different. If a version is not yet specified, it will search for a
CROWSNEST_SERVICE_FILE, non_existant file resulting in 'Incomplete' status.
] :return: Installation status
return get_install_status(CROWSNEST_DIR, files=files) """
files_dict = {
4: [
CROWSNEST_BIN_FILE,
CROWSNEST_LOGROTATE_FILE,
CROWSNEST_SERVICE_FILE,
],
5: [CROWSNEST_SERVICE_FILE],
}
version = get_crowsnest_version()
non_existant = CROWSNEST_DIR.joinpath("non_existant")
files = files_dict.get(version, [non_existant])
env_dir = None
if version >= 5:
env_dir = CROWSNEST_ENV_DIR
return get_install_status(CROWSNEST_DIR, files=files, env_dir=env_dir)
def get_crowsnest_version() -> int:
"""
Get the current major version. Starting with v5 the default branch will be named
after the major version.
:return: Current major version
"""
version = get_current_branch(CROWSNEST_DIR)
if version is None:
return 0
if version == "master":
return 4
return int(version.removeprefix("v"))
def install_crowsnest_packages() -> None:
Logger.print_status("Parsing Crowsnest system dependencies ...")
crowsnest_deps = []
crowsnest_version = get_crowsnest_version()
if crowsnest_version >= 5 and CROWSNEST_DEPS_JSON_FILE.exists():
Logger.print_info(
f"Parsing system dependencies from {CROWSNEST_DEPS_JSON_FILE.name} ..."
)
parser = SysDepsParser()
sysdeps = load_sysdeps_json(CROWSNEST_DEPS_JSON_FILE)
crowsnest_deps.extend(parser.parse_dependencies(sysdeps))
elif crowsnest_version <= 4 and CROWSNEST_INSTALL_SCRIPT.exists():
Logger.print_info(
f"Parsing system dependencies from {CROWSNEST_INSTALL_SCRIPT.name} ..."
)
crowsnest_deps = parse_packages_from_file(CROWSNEST_INSTALL_SCRIPT)
if not crowsnest_deps:
raise ValueError("Error parsing crowsnest dependencies!")
check_install_dependencies({*crowsnest_deps})
def remove_crowsnest() -> None: def remove_crowsnest() -> None: