diff --git a/extensions/Servers/Proxmox/Livewire/Storage.php b/extensions/Servers/Proxmox/Livewire/Storage.php index d05792aaa..72b73c3ba 100644 --- a/extensions/Servers/Proxmox/Livewire/Storage.php +++ b/extensions/Servers/Proxmox/Livewire/Storage.php @@ -820,12 +820,11 @@ class Storage extends Component // Check VM status if ($this->status && $this->status->status !== 'stopped') { - $this->notify('VM must be stopped to move drives.', 'error'); + $this->notify('VM must be stopped to change device bus.', 'error'); return; } $drive = $this->drives[$this->movingDriveKey]; - $sourceBus = $drive['bus']; $targetBus = $this->moveDriveTargetBus; // Get next available index on target bus @@ -839,22 +838,86 @@ class Storage extends Component $proxmox = new Proxmox; $targetKey = $targetBus . $targetIndex; - // Use Proxmox move_disk API + // Get current config to find next unused slot + $config = $proxmox->request( + '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/config' + ); + + // Find the next available unused slot + $unusedIndex = 0; + while (isset($config['data']['unused' . $unusedIndex])) { + $unusedIndex++; + } + + // Step 1: Detach - assign the volume to an unused slot to preserve it $proxmox->request( - '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/move_disk', - 'post', + '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/config', + 'put', [ - 'disk' => $this->movingDriveKey, - 'storage' => $this->storagePool, - 'target-disk' => $targetKey, + 'unused' . $unusedIndex => $drive['volume'], ] ); + // Step 2: Remove the old drive configuration + $proxmox->request( + '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/config', + 'put', + [ + $this->movingDriveKey => 'none', + ] + ); + + // Step 3: Reattach - build the new disk configuration + $configParts = [$drive['volume']]; + + // Add settings + $configParts[] = 'cache=' . ($drive['cache'] ?? 'none'); + $configParts[] = 'aio=' . ($drive['aio'] ?? 'io_uring'); + + // Add IO thread for supported bus types + if ($this->busTypes[$targetBus]['iothread_support'] && ($drive['iothread'] ?? false)) { + $configParts[] = 'iothread=1'; + } + + // Add SSD emulation for supported bus types + if ($this->busTypes[$targetBus]['ssd_support'] && ($drive['ssd'] ?? false)) { + $configParts[] = 'ssd=1'; + } + + // Add discard if enabled + if ($drive['discard'] ?? false) { + $configParts[] = 'discard=on'; + } + + $diskConfig = implode(',', $configParts); + + // Attach to the new bus + $proxmox->request( + '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/config', + 'put', + [ + $targetKey => $diskConfig, + ] + ); + + // Step 4: Clean up the unused entry + try { + $proxmox->request( + '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/config', + 'put', + [ + 'delete' => 'unused' . $unusedIndex, + ] + ); + } catch (\Exception $e) { + // Unused entry might already be cleaned up, ignore + } + $this->notify("Drive moved from {$this->movingDriveKey} to {$targetKey} successfully.", 'success'); $this->closeMoveDriveModal(); $this->loadStorageConfiguration(false); } catch (\Exception $e) { - $this->notify('Failed to move drive: ' . $e->getMessage(), 'error'); + $this->notify('Failed to change device bus: ' . $e->getMessage(), 'error'); } }