feat: support PBS hosts and remote PBS monitoring

This commit is contained in:
Jonatan
2026-10-16 21:46:26 +02:00
parent 3000c1cd66
commit 511bfe52ea
26 changed files with 1355 additions and 15 deletions
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
# Canonical detection is shared with the Monitor; never infer PBS from a client package.
pmx_platform_field() {
python3 "$(dirname "${BASH_SOURCE[0]}")/proxmox_platform.py" --field "$1"
}
pmx_is_pbs() {
[[ "$(pmx_platform_field product)" == pbs ]]
}
pmx_require_pve() {
if [[ "$(pmx_platform_field product)" != pve ]]; then
msg_error "$(translate 'This operation requires a Proxmox VE host. Use the PBS menu on Proxmox Backup Server.')"
return 1
fi
}
+56
View File
@@ -0,0 +1,56 @@
"""Shared PVE/PBS platform detection for the menus and the Monitor (stdlib only)."""
import argparse
import json
from pathlib import Path
import re
import subprocess
OS_RELEASE = Path("/etc/os-release")
SUPPORTED = {("pve", 8): "bookworm", ("pve", 9): "trixie",
("pbs", 3): "bookworm", ("pbs", 4): "trixie"}
def detect_platform():
codename = ""
try:
match = re.search(r'^VERSION_CODENAME=["\']?([a-z0-9-]+)', OS_RELEASE.read_text(), re.M)
codename = match.group(1) if match else ""
except OSError:
pass
installed = {}
try:
result = subprocess.run(
["dpkg-query", "-W", "-f=${Package}\t${Status}\t${Version}\n",
"pve-manager", "proxmox-backup-server"], capture_output=True, text=True, timeout=5,
)
# dpkg returns nonzero if ONE requested package is missing; its other
# installed rows remain authoritative. A PBS client alone is not PBS.
for line in result.stdout.splitlines():
columns = line.split("\t")
if len(columns) == 3 and columns[1] == "install ok installed":
installed[columns[0]] = columns[2]
except (OSError, subprocess.TimeoutExpired):
pass
for package, product in (("pve-manager", "pve"), ("proxmox-backup-server", "pbs")):
version = installed.get(package, "")
match = re.fullmatch(r"(?:[0-9]+:)?([0-9]+)\.[0-9]+(?:\.[0-9]+)?(?:[-+~.a-zA-Z0-9]*)", version)
if match:
major = int(match.group(1))
return {"product": product, "version": version, "major": major,
"codename": codename, "supported": SUPPORTED.get((product, major)) == codename}
return {"product": "unknown", "version": None, "major": None,
"codename": codename, "supported": False}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--field", choices=("product", "version", "major", "codename", "supported"))
arguments = parser.parse_args()
data = detect_platform()
value = data.get(arguments.field) if arguments.field else data
print(value if isinstance(value, str) else json.dumps(value))
if __name__ == "__main__":
main()
+9
View File
@@ -2,12 +2,21 @@
# Shared repository policy for package-install and safe-update flows.
# Proxmox's own repository API parses .list/.sources and edits individual
# entries. No shell rewriting of operator-maintained APT files.
source "$(dirname "${BASH_SOURCE[0]}")/platform-functions.sh"
repository_policy() {
python3 "$(dirname "${BASH_SOURCE[0]}")/repository_policy.py" "$@"
}
ensure_repositories() {
local version suite decision refresh_status
if pmx_is_pbs; then
if [[ "$(pmx_platform_field supported)" != true ]]; then
msg_error "$(translate 'This operation supports PBS 3 on Debian 12 and PBS 4 on Debian 13.')"
return 1
fi
msg_info "$(translate 'PBS: using the configured APT repositories without changing sources.')"
return 0
fi
version=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+' | head -1)
case "$version" in
8) suite=bookworm ;;