fix: name the guest in VM/CT health alerts, refresh AI models, propose the recipe's volume choice

- A health problem of a VM or CT names the guest in its title and in the
  Quiet Hours summary; a recovery shows its category by name in the
  reader's language.
- AI model lists reviewed against each provider: Gemini adds 3.6/3.7/3.8
  Flash, Groq adds gpt-oss-120b, and Groq/OpenRouter models no longer
  served are removed.
- OCI installer proposes the volume choice the recipe declares, so a path
  meant for a host directory is proposed as one; Duplicati /source is
  proposed on a host directory.
This commit is contained in:
MacRimi
2026-10-26 18:47:09 +01:00
parent b6500c147e
commit 7b1736fe3e
21 changed files with 160 additions and 24 deletions
+1 -1
View File
@@ -117,7 +117,7 @@
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"default": "host-bind",
"managed_volume": {
"backup": true,
"default_size_gb": 8
+1 -1
View File
@@ -166,7 +166,7 @@
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"default": "host-bind",
"managed_volume": {
"backup": true,
"default_size_gb": 8
+1 -1
View File
@@ -117,7 +117,7 @@
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"default": "host-bind",
"managed_volume": {
"backup": true,
"default_size_gb": 8
+50
View File
@@ -58,6 +58,56 @@
"prompt": "Password of the Duplicati web interface",
"source": "linuxserver-compose"
}
],
"volumes": [
{
"id": "volume-0",
"container_path": "/config",
"compose_source_example": "/path/to/duplicati/config",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 4
}
},
{
"id": "volume-1",
"container_path": "/backups",
"compose_source_example": "/path/to/backups",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "volume-2",
"container_path": "/source",
"compose_source_example": "/path/to/source",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "host-bind",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
}
]
},
"proxmox": {
@@ -45,7 +45,8 @@
"container_path": "/backups"
},
{
"container_path": "/source"
"container_path": "/source",
"default": "host-bind"
}
],
"restart": "unless-stopped"
+2
View File
@@ -147,6 +147,8 @@ def _recommended_storage(volume: dict[str, Any]) -> str:
default = volume.get("default")
if {"managed-volume", "host-bind"} <= choices:
both = f"{translate('Container volume')} / {translate('Host directory')}"
if default == "host-bind":
both = f"{translate('Host directory')} / {translate('Container volume')}"
return f"{translate('Optional')}: {both}" if default == "skip" else both
if default == "skip":
return translate("Optional, not mounted by default")
+2 -2
View File
@@ -507,8 +507,8 @@ def build_deployment(
offered = list(choices)
chosen = advanced or {"managed-volume", "host-bind"} <= set(choices)
if chosen and len(offered) > 1:
# The answer is the user's: a host directory is never proposed.
proposed = "managed-volume" if item["default"] == "host-bind" else item["default"]
# The answer is the user's; the choice of the oci-compose is proposed.
proposed = item["default"]
volume_mode = ui.choose(f"{translate('Where to store')} {item['container_path']}",
[(choice, labels[choice]) for choice in offered], proposed)
if volume_mode is None:
@@ -104,6 +104,15 @@ class DefaultInstallEssentialsTests(unittest.TestCase):
self.assertEqual({m["source"] for m in plan["mounts"] if m["type"] == "managed-volume"} - {"Public"},
set(), app)
def test_the_files_to_back_up_are_proposed_on_a_host_directory(self, *_):
for app in ("duplicati", "duplicati-official"):
ui, plan = self.build(app)
source = next(m for m in plan["mounts"] if m["container_path"] == "/source")
self.assertEqual(source["type"], "host-bind", app)
self.assertIn("Host path for /source", ui.asked, app)
backups = next(m for m in plan["mounts"] if m["container_path"] == "/backups")
self.assertEqual(backups["type"], "managed-volume", app)
def test_the_members_of_a_stack_ask_nothing_of_their_own(self, *_):
for app in ("linkwarden", "suite-arr"):
ui, _plan = self.build(app)