Skip to content

Commit 5f6ebd3

Browse files
committed
properly point to the right source and destination volume paths during restore operation
1 parent fe764c0 commit 5f6ebd3

File tree

5 files changed

+76
-68
lines changed

5 files changed

+76
-68
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
import com.cloud.agent.api.LogLevel;
2424
import com.cloud.vm.VirtualMachine;
2525

26-
import java.util.List;
26+
import java.util.Map;
2727

2828
public class RestoreBackupCommand extends Command {
2929
private String vmName;
3030
private String backupPath;
3131
private String backupRepoType;
3232
private String backupRepoAddress;
33-
private List<String> volumePaths;
33+
private Map<String, String> volumePathsAndUuids;
3434
private String diskType;
3535
private Boolean vmExists;
3636
private String restoreVolumeUUID;
@@ -72,12 +72,12 @@ public void setBackupRepoAddress(String backupRepoAddress) {
7272
this.backupRepoAddress = backupRepoAddress;
7373
}
7474

75-
public List<String> getVolumePaths() {
76-
return volumePaths;
75+
public Map<String, String> getVolumePathsAndUuids() {
76+
return volumePathsAndUuids;
7777
}
7878

79-
public void setVolumePaths(List<String> volumePaths) {
80-
this.volumePaths = volumePaths;
79+
public void setVolumePathsAndUuids(Map<String, String> volumePathsAndUuids) {
80+
this.volumePathsAndUuids = volumePathsAndUuids;
8181
}
8282

8383
public Boolean isVmExists() {

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
import com.cloud.agent.api.Command;
2323
import com.cloud.agent.api.LogLevel;
2424

25-
import java.util.List;
25+
import java.util.Map;
2626

2727
public class TakeBackupCommand extends Command {
2828
private String vmName;
2929
private String backupPath;
3030
private String backupRepoType;
3131
private String backupRepoAddress;
32-
private List<String> volumePaths;
32+
private Map<String, String> volumePathsAndUuids;
3333
@LogLevel(LogLevel.Log4jLevel.Off)
3434
private String mountOptions;
3535

@@ -79,12 +79,12 @@ public void setMountOptions(String mountOptions) {
7979
this.mountOptions = mountOptions;
8080
}
8181

82-
public List<String> getVolumePaths() {
83-
return volumePaths;
82+
public Map<String, String> getVolumePathsAndUuids() {
83+
return volumePathsAndUuids;
8484
}
8585

86-
public void setVolumePaths(List<String> volumePaths) {
87-
this.volumePaths = volumePaths;
86+
public void setVolumePathsAndUuids(Map<String, String> volumePathsAndUuids) {
87+
this.volumePathsAndUuids = volumePathsAndUuids;
8888
}
8989

9090
@Override

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

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
import java.util.UUID;
6363
import java.util.stream.Collectors;
6464

65-
public class NASBackupProvider extends AdapterBase implements BackupProvider, Configurable {
65+
public class NASBackupProvider extends AdapterBase implements org.apache.cloudstack.backup.BackupProvider, Configurable {
6666
private static final Logger LOG = LogManager.getLogger(NASBackupProvider.class);
6767

6868
@Inject
@@ -146,7 +146,7 @@ protected Host getVMHypervisorHost(VirtualMachine vm) {
146146
public boolean takeBackup(final VirtualMachine vm) {
147147
final Host host = getVMHypervisorHost(vm);
148148

149-
final BackupRepository backupRepository = backupRepositoryDao.findByBackupOfferingId(vm.getBackupOfferingId());
149+
final org.apache.cloudstack.backup.BackupRepository backupRepository = backupRepositoryDao.findByBackupOfferingId(vm.getBackupOfferingId());
150150
if (backupRepository == null) {
151151
throw new CloudRuntimeException("No valid backup repository found for the VM, please check the attached backup offering");
152152
}
@@ -164,8 +164,8 @@ public boolean takeBackup(final VirtualMachine vm) {
164164
if (VirtualMachine.State.Stopped.equals(vm.getState())) {
165165
List<VolumeVO> vmVolumes = volumeDao.findByInstance(vm.getId());
166166
vmVolumes.sort(Comparator.comparing(Volume::getDeviceId));
167-
List<String> volumePaths = getVolumePaths(vmVolumes, Collections.emptyList());
168-
command.setVolumePaths(volumePaths);
167+
Map<String, String> volumePaths = getVolumePaths(vmVolumes, Collections.emptyList());
168+
command.setVolumePathsAndUuids(volumePaths);
169169
}
170170

171171
BackupAnswer answer = null;
@@ -180,11 +180,11 @@ public boolean takeBackup(final VirtualMachine vm) {
180180
if (answer != null && answer.getResult()) {
181181
backupVO.setDate(new Date());
182182
backupVO.setSize(answer.getSize());
183-
backupVO.setStatus(Backup.Status.BackedUp);
183+
backupVO.setStatus(org.apache.cloudstack.backup.Backup.Status.BackedUp);
184184
backupVO.setBackedUpVolumes(BackupManagerImpl.createVolumeInfoFromVolumes(volumeDao.findByInstance(vm.getId())));
185185
return backupDao.update(backupVO.getId(), backupVO);
186186
} else {
187-
backupVO.setStatus(Backup.Status.Failed);
187+
backupVO.setStatus(org.apache.cloudstack.backup.Backup.Status.Failed);
188188
backupDao.remove(backupVO.getId());
189189
}
190190
return Objects.nonNull(answer) && answer.getResult();
@@ -203,7 +203,7 @@ private BackupVO createBackupObject(VirtualMachine vm, String backupPath) {
203203
}
204204
}
205205
backup.setProtectedSize(Long.valueOf(virtualSize));
206-
backup.setStatus(Backup.Status.BackingUp);
206+
backup.setStatus(org.apache.cloudstack.backup.Backup.Status.BackingUp);
207207
backup.setBackupOfferingId(vm.getBackupOfferingId());
208208
backup.setAccountId(vm.getAccountId());
209209
backup.setDomainId(vm.getDomainId());
@@ -212,15 +212,15 @@ private BackupVO createBackupObject(VirtualMachine vm, String backupPath) {
212212
}
213213

214214
@Override
215-
public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) {
216-
List<Backup.VolumeInfo> backedVolumes = backup.getBackedUpVolumes();
215+
public boolean restoreVMFromBackup(VirtualMachine vm, org.apache.cloudstack.backup.Backup backup) {
216+
List<org.apache.cloudstack.backup.Backup.VolumeInfo> backedVolumes = backup.getBackedUpVolumes();
217217
List<VolumeVO> volumes = backedVolumes.stream()
218218
.map(volume -> volumeDao.findByUuid(volume.getUuid()))
219219
.sorted((v1, v2) -> Long.compare(v1.getDeviceId(), v2.getDeviceId()))
220220
.collect(Collectors.toList());
221221

222222
LOG.debug("Restoring vm {} from backup {} on the NAS Backup Provider", vm, backup);
223-
BackupRepository backupRepository = getBackupRepository(vm, backup);
223+
org.apache.cloudstack.backup.BackupRepository backupRepository = getBackupRepository(vm, backup);
224224

225225
final Host host = getLastVMHypervisorHost(vm);
226226
RestoreBackupCommand restoreCommand = new RestoreBackupCommand();
@@ -229,7 +229,7 @@ public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) {
229229
restoreCommand.setBackupRepoAddress(backupRepository.getAddress());
230230
restoreCommand.setMountOptions(backupRepository.getMountOptions());
231231
restoreCommand.setVmName(vm.getName());
232-
restoreCommand.setVolumePaths(getVolumePaths(volumes, backedVolumes));
232+
restoreCommand.setVolumePathsAndUuids(getVolumePaths(volumes, backedVolumes));
233233
restoreCommand.setVmExists(vm.getRemoved() == null);
234234
restoreCommand.setVmState(vm.getState());
235235

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

247-
private List<String> getVolumePaths(List<VolumeVO> volumes, List<Backup.VolumeInfo> backedVolumes) {
248-
List<String> volumePaths = new ArrayList<>();
247+
private Map<String, String> getVolumePaths(List<VolumeVO> volumes, List<org.apache.cloudstack.backup.Backup.VolumeInfo> backedVolumes) {
248+
Map<String, String> volumePaths = new HashMap<>();
249249
for (VolumeVO volume : volumes) {
250250
StoragePoolVO storagePool = primaryDataStoreDao.findById(volume.getPoolId());
251251
if (Objects.isNull(storagePool)) {
@@ -259,37 +259,42 @@ private List<String> getVolumePaths(List<VolumeVO> volumes, List<Backup.VolumeIn
259259
} else {
260260
volumePathPrefix = String.format("/mnt/%s", storagePool.getUuid());
261261
}
262+
// Build current volume path (destination for restore)
263+
String currentVolumePath = String.format("%s/%s", volumePathPrefix, volume.getPath());
264+
265+
// Find backed volume path (used for backup filename lookup)
266+
String backedVolumePath = volume.getPath();
262267
boolean hasBackedVolumes = backedVolumes != null && !backedVolumes.isEmpty();
263268
if (hasBackedVolumes) {
264-
Optional<Backup.VolumeInfo> opt = backedVolumes.stream()
269+
Optional<org.apache.cloudstack.backup.Backup.VolumeInfo> opt = backedVolumes.stream()
265270
.filter(bv -> bv.getUuid().equals(volume.getUuid())).findFirst();
266271
if (opt.isPresent()) {
267-
Backup.VolumeInfo backedVolume = opt.get();
272+
org.apache.cloudstack.backup.Backup.VolumeInfo backedVolume = opt.get();
268273
if (backedVolume.getPath() != null && !backedVolume.getPath().isEmpty()) {
269-
volumePaths.add(String.format("%s/%s", volumePathPrefix, backedVolume.getPath()));
270-
continue;
274+
// Use the backed volume path (path at time of backup) for filename lookup
275+
backedVolumePath = backedVolume.getPath();
271276
}
272277
}
273278
}
274279

275-
volumePaths.add(String.format("%s/%s", volumePathPrefix, volume.getPath()));
280+
volumePaths.put(currentVolumePath, backedVolumePath);
276281
}
277282

278283
return volumePaths;
279284
}
280285

281286
@Override
282-
public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeUuid, String hostIp, String dataStoreUuid, Pair<String, VirtualMachine.State> vmNameAndState) {
287+
public Pair<Boolean, String> restoreBackedUpVolume(org.apache.cloudstack.backup.Backup backup, String volumeUuid, String hostIp, String dataStoreUuid, Pair<String, VirtualMachine.State> vmNameAndState) {
283288
final VolumeVO volume = volumeDao.findByUuid(volumeUuid);
284289
final VirtualMachine backupSourceVm = vmInstanceDao.findById(backup.getVmId());
285290
final StoragePoolHostVO dataStore = storagePoolHostDao.findByUuid(dataStoreUuid);
286291
final HostVO hostVO = hostDao.findByIp(hostIp);
287292

288-
Optional<Backup.VolumeInfo> matchingVolume = getBackedUpVolumeInfo(backupSourceVm.getBackupVolumeList(), volumeUuid);
293+
Optional<org.apache.cloudstack.backup.Backup.VolumeInfo> matchingVolume = getBackedUpVolumeInfo(backupSourceVm.getBackupVolumeList(), volumeUuid);
289294
Long backedUpVolumeSize = matchingVolume.isPresent() ? matchingVolume.get().getSize() : 0L;
290295

291296
LOG.debug("Restoring vm volume {} from backup {} on the NAS Backup Provider", volume, backup);
292-
BackupRepository backupRepository = getBackupRepository(backupSourceVm, backup);
297+
org.apache.cloudstack.backup.BackupRepository backupRepository = getBackupRepository(backupSourceVm, backup);
293298

294299
VolumeVO restoredVolume = new VolumeVO(Volume.Type.DATADISK, null, backup.getZoneId(),
295300
backup.getDomainId(), backup.getAccountId(), 0, null,
@@ -313,7 +318,7 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeU
313318
restoreCommand.setBackupRepoType(backupRepository.getType());
314319
restoreCommand.setBackupRepoAddress(backupRepository.getAddress());
315320
restoreCommand.setVmName(vmNameAndState.first());
316-
restoreCommand.setVolumePaths(Collections.singletonList(String.format("%s/%s", dataStore.getLocalPath(), volumeUUID)));
321+
restoreCommand.setVolumePathsAndUuids(Collections.singletonMap(String.format("%s/%s", dataStore.getLocalPath(), volumeUUID), volumeUUID));
317322
restoreCommand.setDiskType(volume.getVolumeType().name().toLowerCase(Locale.ROOT));
318323
restoreCommand.setMountOptions(backupRepository.getMountOptions());
319324
restoreCommand.setVmExists(null);
@@ -340,8 +345,8 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeU
340345
return new Pair<>(answer.getResult(), answer.getDetails());
341346
}
342347

343-
private BackupRepository getBackupRepository(VirtualMachine vm, Backup backup) {
344-
BackupRepository backupRepository = backupRepositoryDao.findByBackupOfferingId(vm.getBackupOfferingId());
348+
private org.apache.cloudstack.backup.BackupRepository getBackupRepository(VirtualMachine vm, Backup backup) {
349+
org.apache.cloudstack.backup.BackupRepository backupRepository = backupRepositoryDao.findByBackupOfferingId(vm.getBackupOfferingId());
345350
final String errorMessage = "No valid backup repository found for the VM, please check the attached backup offering";
346351
if (backupRepository == null) {
347352
logger.warn(errorMessage + "Re-attempting with the backup offering associated with the backup");
@@ -353,15 +358,15 @@ private BackupRepository getBackupRepository(VirtualMachine vm, Backup backup) {
353358
return backupRepository;
354359
}
355360

356-
private Optional<Backup.VolumeInfo> getBackedUpVolumeInfo(List<Backup.VolumeInfo> backedUpVolumes, String volumeUuid) {
361+
private Optional<org.apache.cloudstack.backup.Backup.VolumeInfo> getBackedUpVolumeInfo(List<org.apache.cloudstack.backup.Backup.VolumeInfo> backedUpVolumes, String volumeUuid) {
357362
return backedUpVolumes.stream()
358363
.filter(v -> v.getUuid().equals(volumeUuid))
359364
.findFirst();
360365
}
361366

362367
@Override
363-
public boolean deleteBackup(Backup backup, boolean forced) {
364-
final BackupRepository backupRepository = backupRepositoryDao.findByBackupOfferingId(backup.getBackupOfferingId());
368+
public boolean deleteBackup(org.apache.cloudstack.backup.Backup backup, boolean forced) {
369+
final org.apache.cloudstack.backup.BackupRepository backupRepository = backupRepositoryDao.findByBackupOfferingId(backup.getBackupOfferingId());
365370
if (backupRepository == null) {
366371
throw new CloudRuntimeException("No valid backup repository found for the VM, please check the attached backup offering");
367372
}
@@ -389,8 +394,8 @@ public boolean deleteBackup(Backup backup, boolean forced) {
389394
}
390395

391396
@Override
392-
public Map<VirtualMachine, Backup.Metric> getBackupMetrics(Long zoneId, List<VirtualMachine> vms) {
393-
final Map<VirtualMachine, Backup.Metric> metrics = new HashMap<>();
397+
public Map<VirtualMachine, org.apache.cloudstack.backup.Backup.Metric> getBackupMetrics(Long zoneId, List<VirtualMachine> vms) {
398+
final Map<VirtualMachine, org.apache.cloudstack.backup.Backup.Metric> metrics = new HashMap<>();
394399
if (CollectionUtils.isEmpty(vms)) {
395400
LOG.warn("Unable to get VM Backup Metrics because the list of VMs is empty.");
396401
return metrics;
@@ -407,15 +412,15 @@ public Map<VirtualMachine, Backup.Metric> getBackupMetrics(Long zoneId, List<Vir
407412
vmBackupProtectedSize += backup.getProtectedSize();
408413
}
409414
}
410-
Backup.Metric vmBackupMetric = new Backup.Metric(vmBackupSize,vmBackupProtectedSize);
415+
org.apache.cloudstack.backup.Backup.Metric vmBackupMetric = new org.apache.cloudstack.backup.Backup.Metric(vmBackupSize,vmBackupProtectedSize);
411416
LOG.debug("Metrics for VM {} is [backup size: {}, data size: {}].", vm, vmBackupMetric.getBackupSize(), vmBackupMetric.getDataSize());
412417
metrics.put(vm, vmBackupMetric);
413418
}
414419
return metrics;
415420
}
416421

417422
@Override
418-
public boolean assignVMToBackupOffering(VirtualMachine vm, BackupOffering backupOffering) {
423+
public boolean assignVMToBackupOffering(VirtualMachine vm, org.apache.cloudstack.backup.BackupOffering backupOffering) {
419424
return Hypervisor.HypervisorType.KVM.equals(vm.getHypervisorType());
420425
}
421426

@@ -430,15 +435,15 @@ public boolean willDeleteBackupsOnOfferingRemoval() {
430435
}
431436

432437
@Override
433-
public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
438+
public void syncBackups(VirtualMachine vm, org.apache.cloudstack.backup.Backup.Metric metric) {
434439
// TODO: check and sum/return backups metrics on per VM basis
435440
}
436441

437442
@Override
438-
public List<BackupOffering> listBackupOfferings(Long zoneId) {
439-
final List<BackupRepository> repositories = backupRepositoryDao.listByZoneAndProvider(zoneId, getName());
440-
final List<BackupOffering> offerings = new ArrayList<>();
441-
for (final BackupRepository repository : repositories) {
443+
public List<org.apache.cloudstack.backup.BackupOffering> listBackupOfferings(Long zoneId) {
444+
final List<org.apache.cloudstack.backup.BackupRepository> repositories = backupRepositoryDao.listByZoneAndProvider(zoneId, getName());
445+
final List<org.apache.cloudstack.backup.BackupOffering> offerings = new ArrayList<>();
446+
for (final org.apache.cloudstack.backup.BackupRepository repository : repositories) {
442447
offerings.add(new NasBackupOffering(repository.getName(), repository.getUuid()));
443448
}
444449
return offerings;
@@ -467,6 +472,6 @@ public String getDescription() {
467472

468473
@Override
469474
public String getConfigComponentName() {
470-
return BackupService.class.getSimpleName();
475+
return org.apache.cloudstack.backup.BackupService.class.getSimpleName();
471476
}
472477
}

0 commit comments

Comments
 (0)