mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-09-30 10:36:41 +00:00
ProxMenux 1.2.6.2-beta: OCI containers in the Monitor, docs and fixes
OCI manager Apps - App tab: containers installed from an OCI image are identified from their installation record; the application and image versions are shown and an update is detected by image digest; repository link; Refresh data. - Updates tab for OCI containers: Update and Recreate run the same flow as the OCI menu in the Monitor terminal; the pre-update backup can be kept in a backup storage; scheduled image updates with an optional minimum age. - Logs tab: console output of the application, kept on the host (lxc.console.logfile + logrotate) and followed live. - The Proxmox console opens a shell (cmode: shell) when the image has one. - A damaged image download is fetched again before failing. - Multi-container applications open at their LAN address; volume mount points on block storage report their usage. Monitor - Proxmox notifications are delivered to a loopback-only HTTP listener when HTTPS is enabled, so they no longer fail certificate verification. - Log persistence counts recurring patterns only; an ended burst is not reported as persistent and its warning clears on its own (#386). - Proxmox notification config backups are deduplicated and capped at three. - The update icon on the Apps page opens the container on its Updates tab. - Version 1.2.6.2-beta and its release notes in every Monitor language. Docs - OCI manager Apps and Audit & Report rebuilt as per-page message files, with a new page for OCI containers in the Monitor. - Seven pages fixed where rich-text tags were missing from t.rich. Translations - Spanish fixes across the OCI engine, the Monitor and the TUI menus. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
386d33df6e
commit
4437a671d2
@@ -304,21 +304,56 @@ def _df_via_host_pid(host_pid: str, ct_target: str) -> dict[str, Optional[int]]:
|
||||
["df", "-B1", "--output=size,used,avail", full],
|
||||
capture_output=True, text=True, timeout=_STAT_TIMEOUT,
|
||||
)
|
||||
except subprocess.TimeoutExpired:
|
||||
# A filesystem that does not answer df will not answer statfs
|
||||
# either; asking again would only double the wait.
|
||||
return empty
|
||||
except OSError:
|
||||
return empty
|
||||
if proc.returncode == 0:
|
||||
lines = [ln for ln in proc.stdout.strip().splitlines() if ln.strip()]
|
||||
parts = lines[-1].split() if len(lines) >= 2 else []
|
||||
if len(parts) >= 3:
|
||||
try:
|
||||
return {
|
||||
"total_bytes": int(parts[0]),
|
||||
"used_bytes": int(parts[1]),
|
||||
"available_bytes": int(parts[2]),
|
||||
}
|
||||
except ValueError:
|
||||
pass
|
||||
return _statfs_via_host(full)
|
||||
|
||||
|
||||
def _statfs_via_host(full: str) -> dict[str, Optional[int]]:
|
||||
"""Capacity of a path read from its filesystem rather than the mount table.
|
||||
|
||||
df names a path by finding the mount that holds it in the host's own
|
||||
table, and a volume of a native OCI container is not in that table: df
|
||||
answers "no file systems processed" and the tab showed no usage for any
|
||||
of its volumes. statfs asks the filesystem of the path directly and
|
||||
returns the same three figures df prints. It is only reached when df
|
||||
completes without an answer, so every mount df can measure keeps the
|
||||
value it had.
|
||||
"""
|
||||
empty = {"total_bytes": None, "used_bytes": None, "available_bytes": None}
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
["stat", "-f", "-c", "%S %b %f %a", full],
|
||||
capture_output=True, text=True, timeout=_STAT_TIMEOUT,
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
return empty
|
||||
lines = [ln for ln in proc.stdout.strip().splitlines() if ln.strip()]
|
||||
if len(lines) < 2:
|
||||
return empty
|
||||
parts = lines[-1].split()
|
||||
if len(parts) < 3:
|
||||
return empty
|
||||
return {
|
||||
"total_bytes": int(parts[0]),
|
||||
"used_bytes": int(parts[1]),
|
||||
"available_bytes": int(parts[2]),
|
||||
}
|
||||
block, total, free, available = (int(value) for value in proc.stdout.split())
|
||||
except (subprocess.TimeoutExpired, OSError, ValueError):
|
||||
return empty
|
||||
if block <= 0 or total <= 0:
|
||||
return empty
|
||||
return {
|
||||
"total_bytes": total * block,
|
||||
"used_bytes": (total - free) * block,
|
||||
"available_bytes": available * block,
|
||||
}
|
||||
|
||||
|
||||
def _df_via_pct_exec(vmid: str, ct_target: str,
|
||||
|
||||
Reference in New Issue
Block a user