feat: collect individual disk config and onboot flag per VM
_get_vm_disk_and_boot() now returns a list of disk dicts (name, size_mb)
instead of a single total. Each disk entry is read from the VM config
via /qemu/{vmid}/config or /lxc/{vmid}/config. The onboot flag is also
read from the same config endpoint.
Both QEMU VMs and LXC containers are covered. The 'disks' and 'onboot'
keys are added to every entry in the vms_snapshot.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
50ccf654ba
commit
08d02d285a
@@ -255,6 +255,7 @@ class ProxmoxVMMixin:
|
||||
"",
|
||||
)
|
||||
|
||||
disks, onboot = self._get_vm_disk_and_boot(vmid, "qemu")
|
||||
result.append({
|
||||
"vmid": vmid,
|
||||
"name": name,
|
||||
@@ -270,6 +271,8 @@ class ProxmoxVMMixin:
|
||||
"ipv4": ipv4,
|
||||
"agent_enabled": agent_enabled,
|
||||
"agent_running": agent_running,
|
||||
"disks": disks,
|
||||
"onboot": onboot,
|
||||
})
|
||||
except Exception as exc:
|
||||
logger.warning("get_vms: failed to list QEMU VMs: %s", exc)
|
||||
@@ -296,6 +299,7 @@ class ProxmoxVMMixin:
|
||||
"",
|
||||
)
|
||||
|
||||
disks, onboot = self._get_vm_disk_and_boot(vmid, "lxc")
|
||||
result.append({
|
||||
"vmid": vmid,
|
||||
"name": name,
|
||||
@@ -311,12 +315,67 @@ class ProxmoxVMMixin:
|
||||
"ipv4": ipv4,
|
||||
"agent_enabled": agent_enabled,
|
||||
"agent_running": agent_running,
|
||||
"disks": disks,
|
||||
"onboot": onboot,
|
||||
})
|
||||
except Exception as exc:
|
||||
logger.warning("get_vms: failed to list LXC containers: %s", exc)
|
||||
|
||||
return sorted(result, key=lambda x: x["vmid"])
|
||||
|
||||
# Disk-key prefixes for QEMU: scsi, virtio, ide, sata (exclude cdrom/none entries)
|
||||
_DISK_KEYS_VM = re.compile(r"^(scsi|virtio|ide|sata)\d+$")
|
||||
# Disk-key prefix for LXC: rootfs, mp (mount points)
|
||||
_DISK_KEYS_CT = re.compile(r"^(rootfs|mp\d+)$")
|
||||
|
||||
def _get_vm_disk_and_boot(
|
||||
self, vmid: int, vm_type: str
|
||||
) -> tuple[list[dict], bool]:
|
||||
"""Return (disks, onboot) for a VM or container.
|
||||
|
||||
Fetches config from /nodes/{node}/{qemu|lxc}/{vmid}/config.
|
||||
Each disk entry is a dict with 'name' and 'size_mb'.
|
||||
Returns ([], False) on any error.
|
||||
"""
|
||||
try:
|
||||
if vm_type == "qemu":
|
||||
cfg = self._node_api().qemu(vmid).config.get() or {}
|
||||
disk_re = self._DISK_KEYS_VM
|
||||
else:
|
||||
cfg = self._node_api().lxc(vmid).config.get() or {}
|
||||
disk_re = self._DISK_KEYS_CT
|
||||
|
||||
onboot = bool(int(cfg.get("onboot", 0) or 0))
|
||||
|
||||
disks: list[dict] = []
|
||||
for key, value in sorted(cfg.items()):
|
||||
if not disk_re.match(key):
|
||||
continue
|
||||
val_str = str(value or "")
|
||||
# Skip CD-ROM / none entries
|
||||
if "media=cdrom" in val_str or val_str.startswith("none"):
|
||||
continue
|
||||
# Extract size=NNX from the value string
|
||||
m = re.search(r"\bsize=(\d+)([GMK]?)", val_str, re.I)
|
||||
if not m:
|
||||
continue
|
||||
num = int(m.group(1))
|
||||
unit = m.group(2).upper()
|
||||
if unit == "G" or unit == "":
|
||||
size_mb = num * 1024
|
||||
elif unit == "M":
|
||||
size_mb = num
|
||||
elif unit == "K":
|
||||
size_mb = num // 1024
|
||||
else:
|
||||
size_mb = num * 1024
|
||||
disks.append({"name": key, "size_mb": size_mb})
|
||||
|
||||
return disks, onboot
|
||||
except Exception as exc:
|
||||
logger.debug("Failed to fetch disk/boot config for vmid %s: %s", vmid, exc)
|
||||
return [], False
|
||||
|
||||
_POWER_ACTIONS_VM = {'start', 'stop', 'shutdown', 'reboot', 'reset'}
|
||||
_POWER_ACTIONS_CT = {'start', 'stop', 'shutdown', 'reboot'}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user