diff --git a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java index 8a111f928680..a0916cb54bba 100644 --- a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java +++ b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java @@ -41,6 +41,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.X509TrustManager; +import com.cloud.utils.UuidUtils; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.backup.Backup; @@ -906,7 +907,9 @@ public Pair restoreVMToDifferentLocation(String restorePointId, if (restoreLocation == null) { restoreLocation = RESTORE_VM_SUFFIX + UUID.randomUUID().toString(); } - final String datastoreId = dataStoreUuid.replace("-",""); + final String datastoreId = UuidUtils.isUuid(dataStoreUuid) ? + dataStoreUuid.replace("-","") : + dataStoreUuid; final List cmds = Arrays.asList( "$points = Get-VBRRestorePoint", String.format("foreach($point in $points) { if ($point.Id -eq '%s') { $restorePoint = $point; break; } }", restorePointId), diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java index ec87980e03a4..f375286bf98b 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -1391,7 +1391,8 @@ public boolean restoreBackupToVM(final Long backupId, final Long vmId) throws Cl if (!"nas".equals(offering.getProvider())) { Pair restoreInfo = getRestoreVolumeHostAndDatastore(vm); host = restoreInfo.first().getPrivateIpAddress(); - dataStore = restoreInfo.second().getUuid(); + String[] datastorePossibleValues = getDatastorePossibleValues(restoreInfo.second()); + dataStore = datastorePossibleValues[0]; } result = backupProvider.restoreBackupToVM(vm, backup, host, dataStore); @@ -1481,7 +1482,7 @@ public boolean restoreBackupVolumeAndAttachToVM(final String backedUpVolumeUuid, logger.debug(String.format("Trying to restore volume using host private IP address: [%s].", host.getPrivateIpAddress())); String[] hostPossibleValues = {host.getPrivateIpAddress(), host.getName()}; - String[] datastoresPossibleValues = {datastore.getUuid(), datastore.getName()}; + String[] datastoresPossibleValues = getDatastorePossibleValues(datastore); Pair result = restoreBackedUpVolume(backupVolumeInfo, backup, backupProvider, hostPossibleValues, datastoresPossibleValues, vm); @@ -1496,6 +1497,20 @@ public boolean restoreBackupVolumeAndAttachToVM(final String backedUpVolumeUuid, return true; } + /** + * For VMFS datastores, the identifier to be used for Veeam restore is the datastore name. + * Otherwise, possible values are the datastore UUID and the datastore name.. + */ + protected String[] getDatastorePossibleValues(StoragePoolVO datastore) { + if (datastore == null) { + return new String[0]; + } + if (Storage.StoragePoolType.VMFS == datastore.getPoolType()) { + return new String[]{datastore.getName()}; + } + return new String[]{datastore.getUuid(), datastore.getName()}; + } + protected Pair restoreBackedUpVolume(final Backup.VolumeInfo backupVolumeInfo, final BackupVO backup, BackupProvider backupProvider, String[] hostPossibleValues, String[] datastoresPossibleValues, VMInstanceVO vm) { Pair result = new Pair<>(false, ""); diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java index db75602b600d..30f0a5ab4b86 100644 --- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java +++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java @@ -2242,4 +2242,33 @@ public void testRestoreBackupVolumeMismatch() { verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId); verify(volumeDao, times(1)).findByInstance(vmId); } + + @Test + public void testGetDatastorePossibleValuesNFS() { + String poolName = "NFS-Pool-Name"; + String poolUuid = UUID.randomUUID().toString(); + + StoragePoolVO pool = Mockito.mock(StoragePoolVO.class); + when(pool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem); + when(pool.getName()).thenReturn(poolName); + when(pool.getUuid()).thenReturn(poolUuid); + + String[] datastorePossibleValues = backupManager.getDatastorePossibleValues(pool); + Assert.assertEquals(2, datastorePossibleValues.length); + Assert.assertEquals(poolUuid, datastorePossibleValues[0]); + Assert.assertEquals(poolName, datastorePossibleValues[1]); + } + + @Test + public void testGetDatastorePossibleValuesVSAN() { + String poolName = "VSAN-Pool-Name"; + + StoragePoolVO pool = Mockito.mock(StoragePoolVO.class); + when(pool.getPoolType()).thenReturn(Storage.StoragePoolType.VMFS); + when(pool.getName()).thenReturn(poolName); + + String[] datastorePossibleValues = backupManager.getDatastorePossibleValues(pool); + Assert.assertEquals(1, datastorePossibleValues.length); + Assert.assertEquals(poolName, datastorePossibleValues[0]); + } }