Update oci_manager.py

This commit is contained in:
MacRimi
2026-03-16 17:58:04 +01:00
parent b6780ba876
commit b7c800b550

View File

@@ -271,37 +271,57 @@ def get_available_storages() -> List[Dict[str, Any]]:
storages = [] storages = []
try: try:
# Use pvesm status to get all storages # Use pvesm status to get all storages (parse text output for compatibility)
rc, out, err = _run_pve_cmd(["pvesm", "status", "--output-format", "json"]) rc, out, err = _run_pve_cmd(["pvesm", "status"])
if rc != 0: if rc != 0:
logger.error(f"Failed to get storage status: {err}") logger.error(f"Failed to get storage status: {err}")
return storages return storages
storage_list = json.loads(out) if out.strip() else [] # Parse text output: Name Type Status Total Used Available %
# Example: local-lvm lvmthin active 464031744 15491072 448540672 3.34%
for storage in storage_list: lines = out.strip().split('\n')
storage_name = storage.get("storage", "") for line in lines[1:]: # Skip header
storage_type = storage.get("type", "") parts = line.split()
if len(parts) < 4:
# Skip if storage is not active
if storage.get("active", 0) != 1:
continue continue
# Check if storage supports rootdir content (for LXC) storage_name = parts[0]
rc2, out2, _ = _run_pve_cmd(["pvesm", "show", storage_name, "--output-format", "json"]) storage_type = parts[1]
if rc2 == 0 and out2.strip(): status = parts[2]
# Skip if storage is not active
if status != "active":
continue
# Get capacity info
total_bytes = int(parts[3]) * 1024 if len(parts) > 3 and parts[3].isdigit() else 0
used_bytes = int(parts[4]) * 1024 if len(parts) > 4 and parts[4].isdigit() else 0
avail_bytes = int(parts[5]) * 1024 if len(parts) > 5 and parts[5].isdigit() else total_bytes - used_bytes
# Check if storage supports rootdir/images content (for LXC)
# Read from /etc/pve/storage.cfg directly for compatibility
content = ""
try: try:
config = json.loads(out2) with open("/etc/pve/storage.cfg", "r") as f:
content = config.get("content", "") cfg_content = f.read()
# Find the storage section
import re
pattern = rf'{storage_type}:\s*{re.escape(storage_name)}\s*\n((?:\s+[^\n]+\n)*)'
match = re.search(pattern, cfg_content)
if match:
section = match.group(1)
content_match = re.search(r'content\s+(\S+)', section)
if content_match:
content = content_match.group(1)
except Exception:
# Fallback: assume block storages support images
if storage_type in ("lvm", "lvmthin", "zfspool", "rbd"):
content = "images,rootdir"
elif storage_type in ("dir", "nfs", "cifs", "btrfs"):
content = "rootdir,images"
# Storage must support "images" or "rootdir" for LXC rootfs # Storage must support "images" or "rootdir" for LXC rootfs
# - "rootdir" is for directory-based storage (ZFS, BTRFS, NFS, etc.)
# - "images" is for block storage (LVM, LVM-thin, etc.)
if "images" in content or "rootdir" in content: if "images" in content or "rootdir" in content:
total_bytes = storage.get("total", 0)
used_bytes = storage.get("used", 0)
avail_bytes = storage.get("avail", total_bytes - used_bytes)
# Determine recommendation priority # Determine recommendation priority
# Prefer: zfspool > lvmthin > btrfs > lvm > others # Prefer: zfspool > lvmthin > btrfs > lvm > others
priority = 99 priority = 99
@@ -323,12 +343,10 @@ def get_available_storages() -> List[Dict[str, Any]]:
"used": used_bytes, "used": used_bytes,
"avail": avail_bytes, "avail": avail_bytes,
"active": True, "active": True,
"enabled": storage.get("enabled", 0) == 1, "enabled": True,
"priority": priority, "priority": priority,
"recommended": False # Will be set after sorting "recommended": False # Will be set after sorting
}) })
except json.JSONDecodeError:
pass
# Sort by priority (lower = better), then by available space # Sort by priority (lower = better), then by available space
storages.sort(key=lambda s: (s.get("priority", 99), -s.get("avail", 0))) storages.sort(key=lambda s: (s.get("priority", 99), -s.get("avail", 0)))