feat: update drive bus change logic to preserve volume data and improve error messaging

This commit is contained in:
2025-12-05 05:00:22 -05:00
parent 060c7182c9
commit f5a1fa6af5

View File

@@ -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');
}
}