Skip to content

Commit ae5308b

Browse files
authored
Fix issue when restoring backup after migration of volume (#12549)
1 parent d8230c9 commit ae5308b

File tree

4 files changed

+53
-41
lines changed

4 files changed

+53
-41
lines changed

core/src/main/java/org/apache/cloudstack/backup/RestoreBackupCommand.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public class RestoreBackupCommand extends Command {
3131
private String backupRepoType;
3232
private String backupRepoAddress;
3333
private List<String> volumePaths;
34+
private List<String> backupFiles;
3435
private String diskType;
3536
private Boolean vmExists;
36-
private String restoreVolumeUUID;
3737
private VirtualMachine.State vmState;
3838

3939
protected RestoreBackupCommand() {
@@ -80,6 +80,14 @@ public void setVolumePaths(List<String> volumePaths) {
8080
this.volumePaths = volumePaths;
8181
}
8282

83+
public List<String> getBackupFiles() {
84+
return backupFiles;
85+
}
86+
87+
public void setBackupFiles(List<String> backupFiles) {
88+
this.backupFiles = backupFiles;
89+
}
90+
8391
public Boolean isVmExists() {
8492
return vmExists;
8593
}
@@ -104,14 +112,6 @@ public void setMountOptions(String mountOptions) {
104112
this.mountOptions = mountOptions;
105113
}
106114

107-
public String getRestoreVolumeUUID() {
108-
return restoreVolumeUUID;
109-
}
110-
111-
public void setRestoreVolumeUUID(String restoreVolumeUUID) {
112-
this.restoreVolumeUUID = restoreVolumeUUID;
113-
}
114-
115115
public VirtualMachine.State getVmState() {
116116
return vmState;
117117
}

plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
import java.util.Map;
5959
import java.util.HashMap;
6060
import java.util.Objects;
61-
import java.util.Optional;
6261
import java.util.UUID;
6362
import java.util.stream.Collectors;
6463

@@ -230,6 +229,7 @@ public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) {
230229
restoreCommand.setMountOptions(backupRepository.getMountOptions());
231230
restoreCommand.setVmName(vm.getName());
232231
restoreCommand.setVolumePaths(getVolumePaths(volumes));
232+
restoreCommand.setBackupFiles(getBackupFiles(backedVolumes));
233233
restoreCommand.setVmExists(vm.getRemoved() == null);
234234
restoreCommand.setVmState(vm.getState());
235235

@@ -244,6 +244,14 @@ public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) {
244244
return answer.getResult();
245245
}
246246

247+
private List<String> getBackupFiles(List<Backup.VolumeInfo> backedVolumes) {
248+
List<String> backupFiles = new ArrayList<>();
249+
for (Backup.VolumeInfo backedVolume : backedVolumes) {
250+
backupFiles.add(backedVolume.getPath());
251+
}
252+
return backupFiles;
253+
}
254+
247255
private List<String> getVolumePaths(List<VolumeVO> volumes) {
248256
List<String> volumePaths = new ArrayList<>();
249257
for (VolumeVO volume : volumes) {
@@ -271,8 +279,11 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeU
271279
final StoragePoolHostVO dataStore = storagePoolHostDao.findByUuid(dataStoreUuid);
272280
final HostVO hostVO = hostDao.findByIp(hostIp);
273281

274-
Optional<Backup.VolumeInfo> matchingVolume = getBackedUpVolumeInfo(backupSourceVm.getBackupVolumeList(), volumeUuid);
275-
Long backedUpVolumeSize = matchingVolume.isPresent() ? matchingVolume.get().getSize() : 0L;
282+
Backup.VolumeInfo matchingVolume = getBackedUpVolumeInfo(backup.getBackedUpVolumes(), volumeUuid);
283+
if (matchingVolume == null) {
284+
throw new CloudRuntimeException(String.format("Unable to find volume %s in the list of backed up volumes for backup %s, cannot proceed with restore", volumeUuid, backup));
285+
}
286+
Long backedUpVolumeSize = matchingVolume.getSize();
276287

277288
LOG.debug("Restoring vm volume {} from backup {} on the NAS Backup Provider", volume, backup);
278289
BackupRepository backupRepository = getBackupRepository(backupSourceVm, backup);
@@ -300,11 +311,11 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeU
300311
restoreCommand.setBackupRepoAddress(backupRepository.getAddress());
301312
restoreCommand.setVmName(vmNameAndState.first());
302313
restoreCommand.setVolumePaths(Collections.singletonList(String.format("%s/%s", dataStore.getLocalPath(), volumeUUID)));
314+
restoreCommand.setBackupFiles(Collections.singletonList(matchingVolume.getPath()));
303315
restoreCommand.setDiskType(volume.getVolumeType().name().toLowerCase(Locale.ROOT));
304316
restoreCommand.setMountOptions(backupRepository.getMountOptions());
305317
restoreCommand.setVmExists(null);
306318
restoreCommand.setVmState(vmNameAndState.second());
307-
restoreCommand.setRestoreVolumeUUID(volumeUuid);
308319

309320
BackupAnswer answer = null;
310321
try {
@@ -339,10 +350,11 @@ private BackupRepository getBackupRepository(VirtualMachine vm, Backup backup) {
339350
return backupRepository;
340351
}
341352

342-
private Optional<Backup.VolumeInfo> getBackedUpVolumeInfo(List<Backup.VolumeInfo> backedUpVolumes, String volumeUuid) {
353+
private Backup.VolumeInfo getBackedUpVolumeInfo(List<Backup.VolumeInfo> backedUpVolumes, String volumeUuid) {
343354
return backedUpVolumes.stream()
344355
.filter(v -> v.getUuid().equals(volumeUuid))
345-
.findFirst();
356+
.findFirst()
357+
.orElse(null);
346358
}
347359

348360
@Override

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRestoreBackupCommandWrapper.java

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.apache.cloudstack.backup.RestoreBackupCommand;
3232
import org.apache.commons.lang3.RandomStringUtils;
3333

34-
import java.io.File;
3534
import java.io.IOException;
3635
import java.nio.file.Files;
3736
import java.nio.file.Paths;
@@ -59,20 +58,21 @@ public Answer execute(RestoreBackupCommand command, LibvirtComputingResource ser
5958
Boolean vmExists = command.isVmExists();
6059
String diskType = command.getDiskType();
6160
List<String> volumePaths = command.getVolumePaths();
62-
String restoreVolumeUuid = command.getRestoreVolumeUUID();
61+
List<String> backupFiles = command.getBackupFiles();
6362

6463
String newVolumeId = null;
6564
try {
6665
if (Objects.isNull(vmExists)) {
6766
String volumePath = volumePaths.get(0);
67+
String backupFile = backupFiles.get(0);
6868
int lastIndex = volumePath.lastIndexOf("/");
6969
newVolumeId = volumePath.substring(lastIndex + 1);
70-
restoreVolume(backupPath, backupRepoType, backupRepoAddress, volumePath, diskType, restoreVolumeUuid,
70+
restoreVolume(backupPath, backupRepoType, backupRepoAddress, volumePath, diskType, backupFile,
7171
new Pair<>(vmName, command.getVmState()), mountOptions);
7272
} else if (Boolean.TRUE.equals(vmExists)) {
73-
restoreVolumesOfExistingVM(volumePaths, backupPath, backupRepoType, backupRepoAddress, mountOptions);
73+
restoreVolumesOfExistingVM(volumePaths, backupPath, backupFiles, backupRepoType, backupRepoAddress, mountOptions);
7474
} else {
75-
restoreVolumesOfDestroyedVMs(volumePaths, vmName, backupPath, backupRepoType, backupRepoAddress, mountOptions);
75+
restoreVolumesOfDestroyedVMs(volumePaths, vmName, backupPath, backupFiles, backupRepoType, backupRepoAddress, mountOptions);
7676
}
7777
} catch (CloudRuntimeException e) {
7878
String errorMessage = "Failed to restore backup for VM: " + vmName + ".";
@@ -86,17 +86,18 @@ public Answer execute(RestoreBackupCommand command, LibvirtComputingResource ser
8686
return new BackupAnswer(command, true, newVolumeId);
8787
}
8888

89-
private void restoreVolumesOfExistingVM(List<String> volumePaths, String backupPath,
89+
private void restoreVolumesOfExistingVM(List<String> volumePaths, String backupPath, List<String> backupFiles,
9090
String backupRepoType, String backupRepoAddress, String mountOptions) {
9191
String diskType = "root";
9292
String mountDirectory = mountBackupDirectory(backupRepoAddress, backupRepoType, mountOptions);
9393
try {
9494
for (int idx = 0; idx < volumePaths.size(); idx++) {
9595
String volumePath = volumePaths.get(idx);
96-
Pair<String, String> bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, null);
96+
String backupFile = backupFiles.get(idx);
97+
String bkpPath = getBackupPath(mountDirectory, backupPath, backupFile, diskType);
9798
diskType = "datadisk";
98-
if (!replaceVolumeWithBackup(volumePath, bkpPathAndVolUuid.first())) {
99-
throw new CloudRuntimeException(String.format("Unable to restore backup for volume [%s].", bkpPathAndVolUuid.second()));
99+
if (!replaceVolumeWithBackup(volumePath, bkpPath)) {
100+
throw new CloudRuntimeException(String.format("Unable to restore backup from volume [%s].", volumePath));
100101
}
101102
}
102103
} finally {
@@ -106,17 +107,18 @@ private void restoreVolumesOfExistingVM(List<String> volumePaths, String backupP
106107

107108
}
108109

109-
private void restoreVolumesOfDestroyedVMs(List<String> volumePaths, String vmName, String backupPath,
110+
private void restoreVolumesOfDestroyedVMs(List<String> volumePaths, String vmName, String backupPath, List<String> backupFiles,
110111
String backupRepoType, String backupRepoAddress, String mountOptions) {
111112
String mountDirectory = mountBackupDirectory(backupRepoAddress, backupRepoType, mountOptions);
112113
String diskType = "root";
113114
try {
114-
for (int i = 0; i < volumePaths.size(); i++) {
115-
String volumePath = volumePaths.get(i);
116-
Pair<String, String> bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, null);
115+
for (int idx = 0; idx < volumePaths.size(); idx++) {
116+
String volumePath = volumePaths.get(idx);
117+
String backupFile = backupFiles.get(idx);
118+
String bkpPath = getBackupPath(mountDirectory, backupPath, backupFile, diskType);
117119
diskType = "datadisk";
118-
if (!replaceVolumeWithBackup(volumePath, bkpPathAndVolUuid.first())) {
119-
throw new CloudRuntimeException(String.format("Unable to restore backup for volume [%s].", bkpPathAndVolUuid.second()));
120+
if (!replaceVolumeWithBackup(volumePath, bkpPath)) {
121+
throw new CloudRuntimeException(String.format("Unable to restore backup from volume [%s].", volumePath));
120122
}
121123
}
122124
} finally {
@@ -126,13 +128,13 @@ private void restoreVolumesOfDestroyedVMs(List<String> volumePaths, String vmNam
126128
}
127129

128130
private void restoreVolume(String backupPath, String backupRepoType, String backupRepoAddress, String volumePath,
129-
String diskType, String volumeUUID, Pair<String, VirtualMachine.State> vmNameAndState, String mountOptions) {
131+
String diskType, String backupFile, Pair<String, VirtualMachine.State> vmNameAndState, String mountOptions) {
130132
String mountDirectory = mountBackupDirectory(backupRepoAddress, backupRepoType, mountOptions);
131-
Pair<String, String> bkpPathAndVolUuid;
133+
String bkpPath;
132134
try {
133-
bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, volumeUUID);
134-
if (!replaceVolumeWithBackup(volumePath, bkpPathAndVolUuid.first())) {
135-
throw new CloudRuntimeException(String.format("Unable to restore backup for volume [%s].", bkpPathAndVolUuid.second()));
135+
bkpPath = getBackupPath(mountDirectory, backupPath, backupFile, diskType);
136+
if (!replaceVolumeWithBackup(volumePath, bkpPath)) {
137+
throw new CloudRuntimeException(String.format("Unable to restore backup from volume [%s].", volumePath));
136138
}
137139
if (VirtualMachine.State.Running.equals(vmNameAndState.second())) {
138140
if (!attachVolumeToVm(vmNameAndState.first(), volumePath)) {
@@ -188,13 +190,11 @@ private void deleteTemporaryDirectory(String backupDirectory) {
188190
}
189191
}
190192

191-
private Pair<String, String> getBackupPath(String mountDirectory, String volumePath, String backupPath, String diskType, String volumeUuid) {
193+
private String getBackupPath(String mountDirectory, String backupPath, String backupFile, String diskType) {
192194
String bkpPath = String.format(FILE_PATH_PLACEHOLDER, mountDirectory, backupPath);
193-
int lastIndex = volumePath.lastIndexOf(File.separator);
194-
String volUuid = Objects.isNull(volumeUuid) ? volumePath.substring(lastIndex + 1) : volumeUuid;
195-
String backupFileName = String.format("%s.%s.qcow2", diskType.toLowerCase(Locale.ROOT), volUuid);
195+
String backupFileName = String.format("%s.%s.qcow2", diskType.toLowerCase(Locale.ROOT), backupFile);
196196
bkpPath = String.format(FILE_PATH_PLACEHOLDER, bkpPath, backupFileName);
197-
return new Pair<>(bkpPath, volUuid);
197+
return bkpPath;
198198
}
199199

200200
private boolean replaceVolumeWithBackup(String volumePath, String backupPath) {

server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ public boolean restoreBackupVolumeAndAttachToVM(final String backedUpVolumeUuid,
826826
throw new CloudRuntimeException(String.format("Error restoring volume [%s] of VM [%s] to host [%s] using backup provider [%s] due to: [%s].",
827827
backedUpVolumeUuid, vm.getUuid(), host.getUuid(), backupProvider.getName(), result.second()));
828828
}
829-
if (!attachVolumeToVM(vm.getDataCenterId(), result.second(), vmFromBackup.getBackupVolumeList(),
829+
if (!attachVolumeToVM(vm.getDataCenterId(), result.second(), backup.getBackedUpVolumes(),
830830
backedUpVolumeUuid, vm, datastore.getUuid(), backup)) {
831831
throw new CloudRuntimeException(String.format("Error attaching volume [%s] to VM [%s]." + backedUpVolumeUuid, vm.getUuid()));
832832
}

0 commit comments

Comments
 (0)