feat: add vcenter_vm_disk_provisioned_gb metric for DR sizing

Extend collector to pull total provisioned virtual disk capacity per VM
using VirtualDisk device enumeration, and expose it as a Prometheus gauge.
Used by the zroc-ui Planner page for mirror volume storage estimates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Justin
2026-04-12 20:29:46 -04:00
parent 796bafac63
commit 0f988fa449
2 changed files with 26 additions and 1 deletions
+21 -1
View File
@@ -165,6 +165,18 @@ def _get_vm_labels(vm: vim.VirtualMachine) -> dict:
} }
def _get_vm_provisioned_gb(vm: vim.VirtualMachine) -> float:
"""Return total provisioned virtual disk capacity in GB for a VM."""
total_kb = 0
try:
for device in vm.config.hardware.device:
if isinstance(device, vim.vm.device.VirtualDisk):
total_kb += device.capacityInKB
except Exception as exc:
log.debug("Could not read disk capacity for VM %s: %s", vm._moId, exc)
return total_kb / (1024 * 1024) # KB -> GB
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Performance counter ID cache # Performance counter ID cache
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -236,6 +248,7 @@ def _parse_results(
results: list, results: list,
label_cache: dict[str, dict], label_cache: dict[str, dict],
label_to_counter_id: dict[str, int], label_to_counter_id: dict[str, int],
provisioned_gb_cache: Optional[dict[str, float]] = None,
) -> None: ) -> None:
"""Parse EntityMetric results and update the global MetricStore.""" """Parse EntityMetric results and update the global MetricStore."""
# Build reverse map: counter_id -> label # Build reverse map: counter_id -> label
@@ -279,6 +292,9 @@ def _parse_results(
else: else:
metrics[lbl] = total metrics[lbl] = total
if provisioned_gb_cache:
metrics["disk_provisioned_gb"] = provisioned_gb_cache.get(moref, 0.0)
store.update(moref, labels, metrics) store.update(moref, labels, metrics)
@@ -342,6 +358,9 @@ class VCenterCollector:
if vm.runtime and vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn if vm.runtime and vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn
] ]
self._label_cache = {vm._moId: _get_vm_labels(vm) for vm in self._vm_cache} self._label_cache = {vm._moId: _get_vm_labels(vm) for vm in self._vm_cache}
self._provisioned_gb_cache: dict[str, float] = {
vm._moId: _get_vm_provisioned_gb(vm) for vm in self._vm_cache
}
self._vm_cache_ts = now self._vm_cache_ts = now
log.info("VM inventory: %d powered-on VMs", len(self._vm_cache)) log.info("VM inventory: %d powered-on VMs", len(self._vm_cache))
@@ -378,7 +397,8 @@ class VCenterCollector:
results = _query_batch( results = _query_batch(
self._pm, batch, counter_id_list, config.PERF_INTERVAL_ID self._pm, batch, counter_id_list, config.PERF_INTERVAL_ID
) )
_parse_results(results, self._label_cache, self._counter_ids) _parse_results(results, self._label_cache, self._counter_ids,
self._provisioned_gb_cache)
collected += len(batch) collected += len(batch)
except Exception as exc: except Exception as exc:
errors += len(batch) errors += len(batch)
+5
View File
@@ -37,6 +37,10 @@ _METRIC_HELP = {
"gauge", "gauge",
"Virtual disk write latency in milliseconds (totalWriteLatency.average, mean across disk instances)", "Virtual disk write latency in milliseconds (totalWriteLatency.average, mean across disk instances)",
), ),
"vcenter_vm_disk_provisioned_gb": (
"gauge",
"Total provisioned virtual disk capacity in GB (sum of all VirtualDisk devices)",
),
} }
# Maps our collector metric keys to Prometheus metric names # Maps our collector metric keys to Prometheus metric names
@@ -44,6 +48,7 @@ _METRIC_NAME_MAP = {
"disk_write_iops": "vcenter_vm_disk_write_iops", "disk_write_iops": "vcenter_vm_disk_write_iops",
"disk_write_throughput": "vcenter_vm_disk_write_throughput_mbps", "disk_write_throughput": "vcenter_vm_disk_write_throughput_mbps",
"disk_write_latency": "vcenter_vm_disk_write_latency_ms", "disk_write_latency": "vcenter_vm_disk_write_latency_ms",
"disk_provisioned_gb": "vcenter_vm_disk_provisioned_gb",
} }