feat(oci): GPU selection per host and per image, one notification per update, and App tab for stack containers

- Immich asks what runs its video and its recognition in one menu, in both
  modes, and gives the GPU to the server and to Machine learning; AMD uses ROCm
- Frigate, Ollama, llama.cpp, Faster Whisper and Piper take the image built
  for the chosen GPU
- The acceleration menu offers only what the host can run
- An update or a recreation sends one notification with its result instead of
  the stop, backup and start of each container
- A private bridge with nothing connected is not reported as down
- Secondary containers of a stack appear in the App tab with their version and
  logo; Secure Gateway shows the same update state in both views
- A mistyped value in the wizard asks the same question again
This commit is contained in:
MacRimi
2026-10-02 21:45:38 +02:00
parent 20ee21c08f
commit 9b5cefb81a
55 changed files with 2294 additions and 113 deletions
+13
View File
@@ -545,6 +545,15 @@ def update_auth_key(app_id: str):
}), 500
def _sync_managed_registry(app_id: str) -> None:
"""Keep the Updates tab of the container in step with this page."""
try:
import managed_installs
managed_installs.refresh_oci_app(app_id)
except Exception as e:
logger.warning(f"Could not refresh the managed registry for {app_id}: {e}")
@oci_bp.route("/installed/<app_id>/update-check", methods=["GET"])
@require_auth
def installed_update_check(app_id: str):
@@ -558,6 +567,8 @@ def installed_update_check(app_id: str):
try:
force = request.args.get("force", "").lower() in ("1", "true", "yes")
result = oci_manager.check_app_update_available(app_id, force=force)
if force:
_sync_managed_registry(app_id)
return jsonify({"success": True, **result})
except Exception as e:
logger.error(f"Failed to check app update for {app_id}: {e}")
@@ -572,6 +583,8 @@ def installed_update_apply(app_id: str):
would cause an unnecessary brief disconnect."""
try:
result = oci_manager.update_app(app_id)
if result.get("success"):
_sync_managed_registry(app_id)
status_code = 200 if result.get("success") else 500
return jsonify(result), status_code
except Exception as e: