feat: implement drive detachment limits and storage quota checks in Proxmox configuration
This commit is contained in:
@@ -759,6 +759,12 @@ class Storage extends Component
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if already at maximum detached drives (2)
|
||||
if (count($this->unusedDrives) >= 2) {
|
||||
$this->notify('Maximum of 2 detached drives allowed. Please reattach or delete existing detached drives first.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
$driveKey = $this->detachingDriveKey;
|
||||
$drive = $this->drives[$driveKey];
|
||||
|
||||
@@ -1070,6 +1076,20 @@ class Storage extends Component
|
||||
$unusedDrive = $this->unusedDrives[$this->reattachingDriveKey];
|
||||
$targetBus = $this->reattachTargetBus;
|
||||
|
||||
// Check if reattaching this drive would exceed the storage quota
|
||||
// Calculate attached drives total (excluding the detached drive being reattached)
|
||||
$attachedDrivesTotal = 0;
|
||||
foreach ($this->drives as $drive) {
|
||||
$attachedDrivesTotal += $drive['size'] ?? 0;
|
||||
}
|
||||
|
||||
// The drive being reattached is already counted in totalAllocatedStorage (which includes unused drives)
|
||||
// So we just need to check if the total exceeds the max
|
||||
if ($this->totalAllocatedStorage > $this->maxAllowedStorage && $this->maxAllowedStorage > 0) {
|
||||
$this->notify('Storage quota exceeded. Total storage (' . number_format($this->totalAllocatedStorage, 1) . ' GB) exceeds your plan allocation (' . number_format($this->maxAllowedStorage, 1) . ' GB). Please upgrade your service or delete drives to allow this configuration.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$proxmox = new Proxmox;
|
||||
|
||||
|
||||
@@ -285,6 +285,14 @@
|
||||
<x-ri-arrow-left-right-line class="size-3.5" />
|
||||
Device Bus
|
||||
</button>
|
||||
@if(count($unusedDrives) >= 2)
|
||||
<button disabled
|
||||
title="Maximum of 2 detached drives allowed"
|
||||
style="display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.75rem; font-size: 0.75rem; font-weight: 500; border-radius: 0.5rem; border: 1px solid rgb(150 150 150 / 0.3); background-color: rgb(150 150 150 / 0.1); color: rgb(150 150 150); cursor: not-allowed; opacity: 0.6;">
|
||||
<x-ri-eject-line class="size-3.5" />
|
||||
Detach
|
||||
</button>
|
||||
@else
|
||||
<button wire:click="openDetachModal('{{ $driveKey }}')"
|
||||
style="display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.75rem; font-size: 0.75rem; font-weight: 500; border-radius: 0.5rem; border: 1px solid rgb(234 179 8 / 0.5); background-color: rgb(234 179 8 / 0.1); color: rgb(234 179 8); transition: background-color 0.15s ease;"
|
||||
onmouseover="this.style.backgroundColor='rgb(234 179 8 / 0.2)'"
|
||||
@@ -292,6 +300,7 @@
|
||||
<x-ri-eject-line class="size-3.5" />
|
||||
Detach
|
||||
</button>
|
||||
@endif
|
||||
<button wire:click="openDeleteModal('{{ $driveKey }}')"
|
||||
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-danger/50 bg-danger/10 text-danger hover:bg-danger/20 transition-colors">
|
||||
<x-ri-delete-bin-line class="size-3.5" />
|
||||
@@ -309,12 +318,33 @@
|
||||
@if(count($unusedDrives) > 0)
|
||||
<div class="bg-background-secondary border border-neutral rounded-lg overflow-hidden">
|
||||
<div class="p-5 border-b border-neutral">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<x-ri-eject-line class="size-5 text-warning" />
|
||||
<h3 class="text-lg font-semibold">Detached Drives</h3>
|
||||
<span class="px-2 py-0.5 text-xs font-medium rounded {{ count($unusedDrives) >= 2 ? 'bg-danger/20 text-danger' : 'bg-warning/20 text-warning' }}">{{ count($unusedDrives) }}/2</span>
|
||||
</div>
|
||||
<p class="text-sm text-base/60 mt-1">These drives have been detached but their data is preserved. You can reattach them or delete them permanently.</p>
|
||||
</div>
|
||||
</div>
|
||||
@if(count($unusedDrives) >= 2)
|
||||
<div class="mt-3 p-3 rounded-lg bg-danger/10 border border-danger/30">
|
||||
<p class="text-xs text-danger flex items-center gap-2">
|
||||
<x-ri-error-warning-line class="size-4 flex-shrink-0" />
|
||||
Maximum detached drives reached. Please reattach or delete drives before detaching more.
|
||||
</p>
|
||||
</div>
|
||||
@endif
|
||||
@if($totalAllocatedStorage > $maxAllowedStorage && $maxAllowedStorage > 0)
|
||||
<div class="mt-3 p-3 rounded-lg bg-danger/10 border border-danger/30">
|
||||
<p class="text-xs text-danger flex items-center gap-2">
|
||||
<x-ri-error-warning-line class="size-4 flex-shrink-0" />
|
||||
Storage quota exceeded ({{ number_format($totalAllocatedStorage, 1) }} GB / {{ number_format($maxAllowedStorage, 1) }} GB). Reattaching drives is disabled. Please upgrade your service or delete drives to allow this configuration.
|
||||
</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="divide-y divide-neutral">
|
||||
@foreach($unusedDrives as $unusedKey => $unusedDrive)
|
||||
@@ -342,11 +372,20 @@
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2 flex-shrink-0">
|
||||
@if($totalAllocatedStorage > $maxAllowedStorage && $maxAllowedStorage > 0)
|
||||
<button disabled
|
||||
title="Storage quota exceeded - please upgrade your service or delete drives"
|
||||
style="display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.75rem; font-size: 0.75rem; font-weight: 500; border-radius: 0.5rem; border: 1px solid rgb(150 150 150 / 0.3); background-color: rgb(150 150 150 / 0.1); color: rgb(150 150 150); cursor: not-allowed; opacity: 0.6;">
|
||||
<x-ri-link class="size-3.5" />
|
||||
Reattach
|
||||
</button>
|
||||
@else
|
||||
<button wire:click="openReattachModal('{{ $unusedKey }}')"
|
||||
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-success/50 bg-success/10 text-success hover:bg-success/20 transition-colors">
|
||||
<x-ri-link class="size-3.5" />
|
||||
Reattach
|
||||
</button>
|
||||
@endif
|
||||
<button wire:click="deleteUnusedDrive('{{ $unusedKey }}')"
|
||||
wire:confirm="Are you sure you want to permanently delete this detached drive? This action cannot be undone."
|
||||
style="display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.75rem; font-size: 0.75rem; font-weight: 500; border-radius: 0.5rem; border: 1px solid rgb(239 68 68 / 0.5); background-color: rgb(239 68 68 / 0.1); color: rgb(239 68 68); transition: background-color 0.15s ease;"
|
||||
|
||||
Reference in New Issue
Block a user