From f51e048f898f380c3e18fe42d4c7e9349ea6859f Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Thu, 29 Jan 2026 11:43:35 -0500 Subject: [PATCH 1/3] Fix issue when restoring backup after migration of volume --- .../java/org/apache/cloudstack/backup/NASBackupProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java index 9b5672e228fc..7561074dc54a 100644 --- a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java +++ b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java @@ -215,7 +215,7 @@ private BackupVO createBackupObject(VirtualMachine vm, String backupPath) { public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) { List backedVolumes = backup.getBackedUpVolumes(); List volumes = backedVolumes.stream() - .map(volume -> volumeDao.findByUuid(volume.getUuid())) + .map(volume -> volumeDao.findByUuid(volume.getPath())) .sorted((v1, v2) -> Long.compare(v1.getDeviceId(), v2.getDeviceId())) .collect(Collectors.toList()); From 348c9ee21f3b4f01b1ca4099399d3081d9c5bae8 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Fri, 30 Jan 2026 15:12:15 -0500 Subject: [PATCH 2/3] use the backed volume path to get the right location of backed volume to be restored --- .../cloudstack/backup/NASBackupProvider.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java index 7561074dc54a..a8ea10a819a5 100644 --- a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java +++ b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java @@ -164,7 +164,7 @@ public boolean takeBackup(final VirtualMachine vm) { if (VirtualMachine.State.Stopped.equals(vm.getState())) { List vmVolumes = volumeDao.findByInstance(vm.getId()); vmVolumes.sort(Comparator.comparing(Volume::getDeviceId)); - List volumePaths = getVolumePaths(vmVolumes); + List volumePaths = getVolumePaths(vmVolumes, Collections.emptyList()); command.setVolumePaths(volumePaths); } @@ -215,7 +215,7 @@ private BackupVO createBackupObject(VirtualMachine vm, String backupPath) { public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) { List backedVolumes = backup.getBackedUpVolumes(); List volumes = backedVolumes.stream() - .map(volume -> volumeDao.findByUuid(volume.getPath())) + .map(volume -> volumeDao.findByUuid(volume.getUuid())) .sorted((v1, v2) -> Long.compare(v1.getDeviceId(), v2.getDeviceId())) .collect(Collectors.toList()); @@ -229,7 +229,7 @@ public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) { restoreCommand.setBackupRepoAddress(backupRepository.getAddress()); restoreCommand.setMountOptions(backupRepository.getMountOptions()); restoreCommand.setVmName(vm.getName()); - restoreCommand.setVolumePaths(getVolumePaths(volumes)); + restoreCommand.setVolumePaths(getVolumePaths(volumes, backedVolumes)); restoreCommand.setVmExists(vm.getRemoved() == null); restoreCommand.setVmState(vm.getState()); @@ -244,7 +244,7 @@ public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) { return answer.getResult(); } - private List getVolumePaths(List volumes) { + private List getVolumePaths(List volumes, List backedVolumes) { List volumePaths = new ArrayList<>(); for (VolumeVO volume : volumes) { StoragePoolVO storagePool = primaryDataStoreDao.findById(volume.getPoolId()); @@ -259,7 +259,14 @@ private List getVolumePaths(List volumes) { } else { volumePathPrefix = String.format("/mnt/%s", storagePool.getUuid()); } - volumePaths.add(String.format("%s/%s", volumePathPrefix, volume.getPath())); + backedVolumes.stream().filter(backedVolume -> backedVolume.getUuid().equals(volume.getUuid())).findFirst() + .ifPresent(backedVolume -> { + if (backedVolume.getPath() != null && !backedVolume.getPath().isEmpty()) { + volumePaths.add(String.format("%s/%s", volumePathPrefix, backedVolume.getPath())); + } else { + volumePaths.add(String.format("%s/%s", volumePathPrefix, volume.getPath())); + } + }); } return volumePaths; } From 101e2a0005ea387955c5a05eb41704e35ef69198 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Mon, 2 Feb 2026 12:58:39 -0500 Subject: [PATCH 3/3] fix logic to prevent take backup from failing --- .../cloudstack/backup/NASBackupProvider.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java index a8ea10a819a5..8254be4f8ea7 100644 --- a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java +++ b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java @@ -259,15 +259,24 @@ private List getVolumePaths(List volumes, List backedVolume.getUuid().equals(volume.getUuid())).findFirst() - .ifPresent(backedVolume -> { + boolean hasBackedVolumes = backedVolumes != null && !backedVolumes.isEmpty(); + if (hasBackedVolumes) { + Optional opt = backedVolumes.stream() + .filter(bv -> bv.getUuid().equals(volume.getUuid())).findFirst(); + if (opt.isPresent()) { + Backup.VolumeInfo backedVolume = opt.get(); if (backedVolume.getPath() != null && !backedVolume.getPath().isEmpty()) { volumePaths.add(String.format("%s/%s", volumePathPrefix, backedVolume.getPath())); } else { volumePaths.add(String.format("%s/%s", volumePathPrefix, volume.getPath())); } - }); + continue; + } + } + + volumePaths.add(String.format("%s/%s", volumePathPrefix, volume.getPath())); } + return volumePaths; }