refactor: align storage calculations with Storage page logic for consistency
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user