feat: update drive bus change logic to preserve volume data and improve error messaging
This commit is contained in:
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user