refactor: align storage calculations with Storage page logic for consistency

This commit is contained in:
2025-12-05 07:02:50 -05:00
parent fc21cbe802
commit d24fa0140f

View File

@@ -127,6 +127,7 @@ class Component extends BaseComponent
/** /**
* Calculate total storage from VM config (including unused/detached drives). * Calculate total storage from VM config (including unused/detached drives).
* Uses the same calculation method as the Storage page.
*/ */
protected function calculateTotalStorage(array $config): float protected function calculateTotalStorage(array $config): float
{ {
@@ -159,66 +160,93 @@ class Component extends BaseComponent
/** /**
* Check if a disk should be excluded (cloud-init, EFI, TPM). * Check if a disk should be excluded (cloud-init, EFI, TPM).
* Uses regex patterns matching the Storage page implementation.
*/ */
protected function isExcludedDisk(string $value): bool protected function isExcludedDisk(string $value): bool
{ {
$excludePatterns = ['cloudinit', 'efidisk', 'tpmstate']; $excludePatterns = [
'cloudinit',
'vm-\d+-cloudinit',
'efidisk',
'tpmstate',
];
foreach ($excludePatterns as $pattern) { foreach ($excludePatterns as $pattern) {
if (str_contains(strtolower($value), $pattern)) { if (preg_match('/' . $pattern . '/i', $value)) {
return true; return true;
} }
} }
return false; return false;
} }
/** /**
* Extract disk size in GB from a disk configuration string. * Extract disk size in GB from a disk configuration string.
* Matches the Storage page parseDiskString logic.
*/ */
protected function extractDiskSize(string $value): float protected function extractDiskSize(string $value): float
{ {
// Example: cephpool:vm-100-disk-0,cache=writeback,size=50G // Example: cephpool:vm-100-disk-0,size=32G,cache=none,ssd=1
if (preg_match('/size=(\d+)([GMTK])?/i', $value, $matches)) { $parts = explode(',', $value);
$size = (float) $matches[1];
$unit = strtoupper($matches[2] ?? 'G'); foreach ($parts as $part) {
if (preg_match('/^size=(\d+)([KMGT]?)$/i', $part, $sizeMatch)) {
return match ($unit) { $size = (float) $sizeMatch[1];
'T' => $size * 1024, $unit = strtoupper($sizeMatch[2] ?? 'G');
'G' => $size,
'M' => $size / 1024, switch ($unit) {
'K' => $size / 1024 / 1024, case 'K':
default => $size, return $size / (1024 * 1024);
}; case 'M':
return $size / 1024;
case 'G':
case '':
return $size;
case 'T':
return $size * 1024;
}
}
} }
return 0; return 0;
} }
/** /**
* Extract size from unused disk by querying Proxmox. * Extract size from unused disk by querying Proxmox storage content.
* Matches the Storage page parseUnusedDiskString logic.
*/ */
protected function extractUnusedDiskSize(string $value): float protected function extractUnusedDiskSize(string $value): float
{ {
// For unused disks, we need to query the volume info // Unused disks typically just have the volume reference
// Format: storage:volume (e.g., cephpool:vm-100-disk-1) // Example: cephpool:vm-100-disk-1
$volume = trim($value);
// Extract storage name from volume (format: storage:volume-name)
$storageName = 'cephpool';
if (str_contains($volume, ':')) {
[$storageName, ] = explode(':', $volume, 2);
}
try { try {
if (!preg_match('/^([^:]+):(.+)$/', $value, $matches)) {
return 0;
}
$storage = $matches[1];
$volume = $matches[2];
$proxmox = new Proxmox; $proxmox = new Proxmox;
$response = $proxmox->request( $storageContent = $proxmox->request(
'/nodes/' . $this->server->node->name . '/storage/' . $storage . '/content/' . $storage . ':' . $volume '/nodes/' . $this->server->node->name . '/storage/' . $storageName . '/content',
data: ['vmid' => $this->server->vm_id]
); );
if ($response->successful()) { if (isset($storageContent['data']) && is_array($storageContent['data'])) {
$data = $response->json()['data'] ?? []; foreach ($storageContent['data'] as $item) {
$sizeBytes = $data['size'] ?? 0; if (isset($item['volid']) && $item['volid'] === $volume) {
return $sizeBytes / 1024 / 1024 / 1024; // Convert to GB // Size is in bytes
if (isset($item['size'])) {
return round($item['size'] / (1024 * 1024 * 1024), 2);
}
break;
}
}
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
// Ignore errors, return 0 // If we can't fetch size, return 0
} }
return 0; return 0;