diff --git a/plugins/backup/backroll/pom.xml b/plugins/backup/backroll/pom.xml
index 37b2c1572ed..acf9f6a77fb 100644
--- a/plugins/backup/backroll/pom.xml
+++ b/plugins/backup/backroll/pom.xml
@@ -25,7 +25,7 @@
cloudstack-plugins
org.apache.cloudstack
- 4.20.0.0-SNAPSHOT
+ 4.21.0.0-SNAPSHOT
../../pom.xml
diff --git a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/BackrollBackupProvider.java b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/BackrollBackupProvider.java
index a74bfc5e931..892b594fe3b 100644
--- a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/BackrollBackupProvider.java
+++ b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/BackrollBackupProvider.java
@@ -31,7 +31,6 @@ import javax.inject.Inject;
import org.apache.cloudstack.backup.Backup.Metric;
import org.apache.cloudstack.backup.backroll.BackrollClient;
-import org.apache.cloudstack.backup.backroll.BackrollService;
import org.apache.cloudstack.backup.backroll.model.BackrollBackupMetrics;
import org.apache.cloudstack.backup.backroll.model.BackrollTaskStatus;
import org.apache.cloudstack.backup.backroll.model.BackrollVmBackup;
@@ -44,6 +43,8 @@ import org.apache.cloudstack.framework.config.Configurable;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.ParseException;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.joda.time.DateTime;
import com.cloud.utils.Pair;
@@ -79,6 +80,15 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
@Inject
private VMInstanceDao vmInstanceDao;
+ public BackrollBackupProvider(BackupDao backupDao, VMInstanceDao vmInstanceDao, BackrollClient client, Logger logger){
+ this.backupDao = backupDao;
+ this.vmInstanceDao = vmInstanceDao;
+ this.backrollClient = client;
+ this.logger = logger;
+ }
+
+ public BackrollBackupProvider(){}
+
@Override
public String getName() {
return "backroll";
@@ -209,7 +219,7 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
syncBackups(vm, null);
return result;
}
- } catch (KeyManagementException | NoSuchAlgorithmException | ParseException | InterruptedException | IOException e) {
+ } catch (ParseException | BackrollApiException | IOException e) {
throw new CloudRuntimeException("Failed to take backup");
}
return false;
@@ -254,7 +264,6 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
backupToUpdate.setSize(backupMetrics.getDeduplicated()); // real size
backupToUpdate.setProtectedSize(backupMetrics.getSize()); // total size
}
- } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
} catch (BackrollApiException | IOException e) {
logger.error(e);
throw new CloudRuntimeException("Failed to get backup metrics");
diff --git a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/BackrollClient.java b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/BackrollClient.java
index 21e7fca2ac7..cd831295e5e 100644
--- a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/BackrollClient.java
+++ b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/BackrollClient.java
@@ -24,8 +24,6 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.backup.BackupOffering;
import org.apache.cloudstack.backup.Backup.Metric;
-import org.apache.cloudstack.backup.backroll.BackrollService.NotOkBodyException;
-import org.apache.cloudstack.backup.backroll.model.BackrollBackup;
import org.apache.cloudstack.backup.backroll.model.BackrollBackupMetrics;
import org.apache.cloudstack.backup.backroll.model.BackrollOffering;
import org.apache.cloudstack.backup.backroll.model.BackrollTaskStatus;
@@ -161,6 +159,11 @@ public class BackrollClient {
return isBackupDeleted;
}
+ public void triggerTaskStatus(String urlToRequest)
+ throws IOException, BackrollApiException{
+ httpProvider.waitGetWithoutParseResponse(urlToRequest);
+ }
+
public Metric getVirtualMachineMetrics(final String vmId) throws IOException, BackrollApiException {
logger.info("Trying to retrieve virtual machine metric from Backroll for vm {}", vmId);
diff --git a/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/BackrollBackupProviderTest.java b/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/BackrollBackupProviderTest.java
index 1dde11d8479..1143e5b4e4a 100644
--- a/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/BackrollBackupProviderTest.java
+++ b/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/BackrollBackupProviderTest.java
@@ -16,404 +16,153 @@
// under the License.
package org.apache.cloudstack.backup;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Arrays;
+import java.util.Date;
import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
+import java.util.UUID;
-import javax.inject.Inject;
-
-import org.apache.cloudstack.backup.Backup.Metric;
-import org.apache.cloudstack.backup.backroll.BackrollClientTest;
-import org.apache.cloudstack.backup.backroll.model.BackrollBackupMetrics;
+import org.apache.cloudstack.backup.backroll.BackrollClient;
+import org.apache.cloudstack.backup.backroll.utils.BackrollApiException;
import org.apache.cloudstack.backup.backroll.model.BackrollTaskStatus;
import org.apache.cloudstack.backup.backroll.model.BackrollVmBackup;
+import org.apache.cloudstack.backup.backroll.model.BackrollBackupMetrics;
+import org.apache.cloudstack.backup.backroll.model.response.TaskState;
import org.apache.cloudstack.backup.dao.BackupDao;
-import org.apache.cloudstack.framework.config.ConfigKey;
-import org.apache.cloudstack.framework.config.Configurable;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
import org.apache.http.ParseException;
-import org.joda.time.DateTime;
+import org.apache.logging.log4j.Logger;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
-import com.cloud.utils.Pair;
-import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDao;
-public class BackrollBackupProviderTest extends AdapterBase implements BackupProvider, Configurable {
+import net.bytebuddy.agent.VirtualMachine;
- public static final String BACKUP_IDENTIFIER = "-CSBKP-";
+public class BackrollBackupProviderTest {
+ @Mock
+ BackrollClient clientMock;
- public ConfigKey BackrollUrlConfigKey = new ConfigKey<>("Advanced", String.class,
- "backup.plugin.backroll.config.url",
- "http://api.backup.demo.ccc:5050/api/v1",
- "Url for backroll plugin.", true, ConfigKey.Scope.Zone);
+ @Spy
+ @InjectMocks
+ BackrollBackupProvider backupProvider;
- public ConfigKey BackrollAppNameConfigKey = new ConfigKey<>("Advanced", String.class,
- "backup.plugin.backroll.config.appname",
- "backroll-api",
- "App Name for backroll plugin.", true, ConfigKey.Scope.Zone);
+ @Mock
+ BackrollBackupProvider backupProviderMock;
- public ConfigKey BackrollPasswordConfigKey = new ConfigKey<>("Advanced", String.class,
- "backup.plugin.backroll.config.password",
- "VviX8dALauSyYJMqVYJqf3UyZOpO3joS",
- "Password for backroll plugin.", true, ConfigKey.Scope.Zone);
+ @Mock
+ VMInstanceDao vmInstanceDao;
- private BackrollClientTest backrollClient;
+ @Mock
+ BackupDao backupDao;
- @Inject
- private BackupDao backupDao;
- @Inject
- private VMInstanceDao vmInstanceDao;
+ @Before
+ public void setUp() throws Exception {
+ vmInstanceDao = mock(VMInstanceDao.class);
+ clientMock = mock(BackrollClient.class);
+ backupDao = mock(BackupDao.class);
+ backupProviderMock = mock(BackrollBackupProvider.class);
+ backupProvider = new BackrollBackupProvider(backupDao, vmInstanceDao, clientMock, Mockito.mock(Logger.class));
+ }
+ @Test
+ public void syncBackups_Test() throws BackrollApiException, IOException {
+ VMInstanceVO vmInstanceVO = new VMInstanceVO();
+ vmInstanceVO.setInstanceName("test");
+ vmInstanceVO.setDataCenterId(2l);
+ vmInstanceVO.setBackupOfferingId(2l);
+ Backup.Metric metric = new Backup.Metric(2L, 3L);
- @Override
- public String getName() {
- return "backroll";
+ BackupVO backupBackingUp = new BackupVO();
+ backupBackingUp.setVmId(1l);
+ backupBackingUp.setExternalId("abc,defgh");
+ backupBackingUp.setType("Full");
+ backupBackingUp.setSize(2L);
+ backupBackingUp.setZoneId(2l);
+ backupBackingUp.setStatus(Backup.Status.BackingUp);
+
+ BackupVO backupBackedUp = new BackupVO();
+ backupBackedUp.setVmId(6l);
+ backupBackedUp.setExternalId("abc,defgh");
+ backupBackedUp.setType("Full");
+ backupBackedUp.setZoneId(2l);
+ backupBackedUp.setSize(2L);
+ backupBackedUp.setStatus(Backup.Status.BackedUp);
+
+ BackupVO backupFailed = new BackupVO();
+ backupFailed.setVmId(6l);
+ backupFailed.setExternalId("abc,defgh");
+ backupFailed.setType("Full");
+ backupFailed.setZoneId(2l);
+ backupFailed.setSize(2L);
+ backupFailed.setStatus(Backup.Status.Failed);
+
+ BackrollTaskStatus backupStatus = new BackrollTaskStatus();
+ backupStatus.setState(TaskState.SUCCESS);
+
+ BackrollBackupMetrics metrics = new BackrollBackupMetrics(2L, 3L);
+
+ List backupsFromBackroll = Arrays.asList(
+ new BackrollVmBackup("OK","OK", new Date()));
+
+ List backupsInDb = Arrays.asList(backupBackingUp, backupBackedUp, backupFailed);
+ Mockito.doReturn(backupsInDb).when(backupDao).listByVmId(Mockito.anyLong(), Mockito.anyLong());
+ Mockito.doReturn(backupStatus).when(clientMock).checkBackupTaskStatus(Mockito.anyString());
+ Mockito.doReturn(metrics).when(clientMock).getBackupMetrics(Mockito.anyString(), Mockito.anyString());
+ Mockito.doReturn(new BackupVO()).when(backupDao).persist(Mockito.any(BackupVO.class));
+ Mockito.doReturn(backupsFromBackroll).when(clientMock).getAllBackupsfromVirtualMachine(Mockito.anyString());
+ Mockito.doReturn(true).when(backupDao).remove(Mockito.anyLong());
+
+ backupProvider.syncBackups(vmInstanceVO, metric);
}
- @Override
- public String getDescription() {
- return "Backroll Backup Plugin";
+
+ @Test
+ public void getClient_Test() {
+ BackrollClient client = backupProvider.getClient(2L);
+ assertEquals(client, clientMock);
}
- @Override
- public List listBackupOfferings(Long zoneId) {
- logger.debug("Listing backup policies on backroll B&R Plugin");
- logger.info("Listing backup policies on backroll B&R Plugin");
- BackrollClientTest client = getClient(zoneId);
- try{
- String urlToRequest = client.getBackupOfferingUrl();
- logger.info("BackrollProvider: urlToRequest: " + urlToRequest);
- if (!StringUtils.isEmpty(urlToRequest)){
- List results = new ArrayList();
- // return client.getBackupOfferings(urlToRequest);
- results = client.getBackupOfferings(urlToRequest);
- if(results.size()>0) {
- logger.info("BackrollProvider: results > 0");
- } else {
- logger.info("BackrollProvider: results <= 0");
- }
- return results;
- }
- } catch (KeyManagementException | ParseException | NoSuchAlgorithmException | IOException e) {
- logger.info("BackrollProvider: catch erreur!!!!!!!!!!!!!!!!!!!!!!!!");
- throw new CloudRuntimeException("Failed to load backup offerings");
- }
- return new ArrayList();
+ @Test
+ public void deleteBackupTestSuccess_Test() throws BackrollApiException, IOException {
+ VMInstanceVO vmInstanceVO = new VMInstanceVO();
+ vmInstanceVO.setInstanceName("test");
+ vmInstanceVO.setDataCenterId(2l);
+ vmInstanceVO.setUuid(UUID.randomUUID().toString());
+ BackupVO backup = new BackupVO();
+ backup.setVmId(1l);
+ backup.setExternalId("abc,defgh");
+ backup.setType("Full");
+ backup.setZoneId(2l);
+ backup.setStatus(Backup.Status.Removed);
+ Boolean deleteBackupResponse = true;
+ Mockito.doReturn(vmInstanceVO).when(vmInstanceDao).findByIdIncludingRemoved(Mockito.anyLong());
+ Mockito.doReturn(deleteBackupResponse).when(clientMock).deleteBackup(Mockito.anyString(), Mockito.anyString());
+ Mockito.doReturn(new BackupVO()).when(backupDao).persist(Mockito.any(BackupVO.class));
+ boolean result = backupProvider.deleteBackup(backup, true);
+ assertEquals(true, result);
}
- @Override
- public boolean isValidProviderOffering(Long zoneId, String uuid) {
- logger.info("Checking if backup offering exists on the Backroll Backup Provider");
- return true;
- }
-
- @Override
- public boolean assignVMToBackupOffering(VirtualMachine vm, BackupOffering backupOffering) {
- logger.info("Creating VM backup for VM {} from backup offering {}", vm.getInstanceName(), backupOffering.getName());
- ((VMInstanceVO) vm).setBackupExternalId(backupOffering.getUuid());
- return true;
- }
-
- @Override
- public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) {
- logger.debug("Restoring vm {} from backup {} on the backroll Backup Provider", vm.getUuid(), backup.getUuid());
- boolean isSuccess;
+ @Test
+ public void deleteBackupBackinUp_Test() {
+ BackupVO backup = new BackupVO();
+ backup.setStatus(Backup.Status.BackingUp);
try {
- isSuccess = getClient(vm.getDataCenterId()).restoreVMFromBackup(vm.getUuid(), getBackupName(backup));
- } catch (KeyManagementException | ParseException | NoSuchAlgorithmException | IOException e) {
- throw new CloudRuntimeException("Failed to restore VM from Backrup");
- }
- return isSuccess;
- }
-
- @Override
- public Map getBackupMetrics(Long zoneId, List vms) {
- final Map metrics = new HashMap<>();
- if (CollectionUtils.isEmpty(vms)) {
- logger.warn("Unable to get VM Backup Metrics because the list of VMs is empty.");
- return metrics;
- }
-
- List vmUuids = vms.stream().filter(Objects::nonNull).map(VirtualMachine::getUuid).collect(Collectors.toList());
- logger.debug("Get Backup Metrics for VMs: {}.", String.join(", ", vmUuids));
-
- for (final VirtualMachine vm : vms) {
- if (vm == null) {
- continue;
- }
-
- Metric metric;
- try {
- metric = getClient(zoneId).getVirtualMachineMetrics(vm.getUuid());
- } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
- throw new CloudRuntimeException("Failed to retrieve backup metrics");
- }
- logger.debug("Metrics for VM [uuid: {}, name: {}] is [backup size: {}, data size: {}].", vm.getUuid(),
- vm.getInstanceName(), metric.getBackupSize(), metric.getDataSize());
- metrics.put(vm, metric);
- }
- return metrics;
- }
-
- @Override
- public boolean removeVMFromBackupOffering(VirtualMachine vm) {
- return true;
- }
-
- @Override
- public boolean willDeleteBackupsOnOfferingRemoval() {
- return false;
- }
-
- @Override
- public boolean takeBackup(VirtualMachine vm) {
- logger.info("Starting backup for VM ID {} on backroll provider", vm.getUuid());
- final BackrollClientTest client = getClient(vm.getDataCenterId());
-
- try {
- String urlToRequest = client.startBackupJob(vm.getUuid());
-
- String backupJob = urlToRequest.replace("/status/", "");
- if (!StringUtils.isEmpty(backupJob)) {
- BackupVO backup = new BackupVO();
- backup.setVmId(vm.getId());
- backup.setExternalId(backupJob);
- backup.setType("INCREMENTAL");
- backup.setDate(new DateTime().toDate());
- backup.setSize(0L);
- backup.setProtectedSize(0L);
- backup.setStatus(Backup.Status.BackingUp);
- backup.setBackupOfferingId(vm.getBackupOfferingId());
- backup.setAccountId(vm.getAccountId());
- backup.setDomainId(vm.getDomainId());
- backup.setZoneId(vm.getDataCenterId());
- Boolean result = backupDao.persist(backup) != null;
- client.triggerTaskStatus(urlToRequest);
- syncBackups(vm, null);
- return result;
- }
- } catch (KeyManagementException | NoSuchAlgorithmException | ParseException | InterruptedException | IOException e) {
- throw new CloudRuntimeException("Failed to take backup");
- }
- return false;
- }
-
-
- @Override
- public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
- logger.info("Starting sync backup for VM ID " + vm.getUuid() + " on backroll provider");
-
- final BackrollClientTest client = getClient(vm.getDataCenterId());
- List backupsInDb = backupDao.listByVmId(null, vm.getId());
-
- for (Backup backup : backupsInDb) {
- if (backup.getStatus().equals(Backup.Status.BackingUp)) {
- BackrollTaskStatus response;
- try {
- response = client.checkBackupTaskStatus(backup.getExternalId());
- } catch (KeyManagementException | ParseException | NoSuchAlgorithmException | IOException e) {
- throw new CloudRuntimeException("Failed to sync backups");
- }
-
- if (response != null) {
- logger.debug("backroll backup id: {}", backup.getExternalId());
- logger.debug("backroll backup status: {}", response.getState());
-
- BackupVO backupToUpdate = new BackupVO();
- backupToUpdate.setVmId(backup.getVmId());
- backupToUpdate.setExternalId(backup.getExternalId());
- backupToUpdate.setType(backup.getType());
- backupToUpdate.setDate(backup.getDate());
- backupToUpdate.setSize(backup.getSize());
- backupToUpdate.setProtectedSize(backup.getProtectedSize());
- backupToUpdate.setBackupOfferingId(vm.getBackupOfferingId());
- backupToUpdate.setAccountId(backup.getAccountId());
- backupToUpdate.setDomainId(backup.getDomainId());
- backupToUpdate.setZoneId(backup.getZoneId());
-
- if (response.getState().equals("PENDING")) {
- backupToUpdate.setStatus(Backup.Status.BackingUp);
- } else if (response.getState().equals("FAILURE")) {
- backupToUpdate.setStatus(Backup.Status.Failed);
- } else if (response.getState().equals("SUCCESS")) {
- backupToUpdate.setStatus(Backup.Status.BackedUp);
- backupToUpdate.setExternalId(backup.getExternalId() + "," + response.getInfo());
-
- BackrollBackupMetrics backupMetrics = null;
- try {
- backupMetrics = client.getBackupMetrics(vm.getUuid() , response.getInfo());
- if (backupMetrics != null) {
- backupToUpdate.setSize(backupMetrics.getDeduplicated()); // real size
- backupToUpdate.setProtectedSize(backupMetrics.getSize()); // total size
- }
- } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
- throw new CloudRuntimeException("Failed to get backup metrics");
- }
- } else {
- backupToUpdate.setStatus(Backup.Status.BackingUp);
- }
-
- if (backupDao.persist(backupToUpdate) != null) {
- logger.info("Backroll mise à jour enregistrée");
- backupDao.remove(backup.getId());
- }
- }
- } else if (backup.getStatus().equals(Backup.Status.BackedUp) && backup.getSize().equals(0L)) {
- String backupId = backup.getExternalId().contains(",") ? backup.getExternalId().split(",")[1] : backup.getExternalId();
- BackrollBackupMetrics backupMetrics;
- try {
- backupMetrics = client.getBackupMetrics(vm.getUuid() , backupId);
- } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
- throw new CloudRuntimeException("Failed to get backup metrics");
- }
-
- if (backupMetrics != null) {
- BackupVO backupToUpdate = ((BackupVO) backup);
- backupToUpdate.setSize(backupMetrics.getDeduplicated()); // real size
- backupToUpdate.setProtectedSize(backupMetrics.getSize()); // total size
- backupDao.persist(backupToUpdate);
- }
- }
- }
-
- // Backups synchronisation between Backroll ad CS Db
- List backupsFromBackroll = client.getAllBackupsfromVirtualMachine(vm.getUuid());
- backupsInDb = backupDao.listByVmId(null, vm.getId());
-
- // insert new backroll backup in CS
- for (BackrollVmBackup backupInBackroll : backupsFromBackroll) {
- Backup backupToFind = backupsInDb.stream()
- .filter(backupInDb -> backupInDb.getExternalId().contains(backupInBackroll.getName()))
- .findAny()
- .orElse(null);
-
- if (backupToFind == null) {
- BackupVO backupToInsert = new BackupVO();
- backupToInsert.setVmId(vm.getId());
- backupToInsert.setExternalId(backupInBackroll.getId() + "," + backupInBackroll.getName());
- backupToInsert.setType("INCREMENTAL");
- backupToInsert.setDate(backupInBackroll.getDate());
- backupToInsert.setSize(0L);
- backupToInsert.setProtectedSize(0L);
- backupToInsert.setStatus(Backup.Status.BackedUp);
- backupToInsert.setBackupOfferingId(vm.getBackupOfferingId());
- backupToInsert.setAccountId(vm.getAccountId());
- backupToInsert.setDomainId(vm.getDomainId());
- backupToInsert.setZoneId(vm.getDataCenterId());
- backupDao.persist(backupToInsert);
- }
- if (backupToFind != null && backupToFind.getStatus() == Backup.Status.Removed) {
- BackupVO backupToUpdate = ((BackupVO) backupToFind);
- backupToUpdate.setStatus(Backup.Status.BackedUp);
- if (backupDao.persist(backupToUpdate) != null) {
- logger.info("Backroll update saved");
- backupDao.remove(backupToFind.getId());
- }
- }
- }
-
- // delete deleted backroll backup in CS
- backupsInDb = backupDao.listByVmId(null, vm.getId());
- for (Backup backup : backupsInDb) {
- String backupName = backup.getExternalId().contains(",") ? backup.getExternalId().split(",")[1] : backup.getExternalId();
- BackrollVmBackup backupToFind = backupsFromBackroll.stream()
- .filter(backupInBackroll -> backupInBackroll.getName().contains(backupName))
- .findAny()
- .orElse(null);
-
- if (backupToFind == null) {
- BackupVO backupToUpdate = ((BackupVO) backup);
- backupToUpdate.setStatus(Backup.Status.Removed);
- if (backupDao.persist(backupToUpdate) != null) {
- logger.debug("Backroll delete saved (sync)");
- }
- }
+ backupProvider.deleteBackup(backup, false);
+ } catch (Exception e) {
+ assertEquals(CloudRuntimeException.class, e.getClass());
+ String expected = String.format("You can't delete a backup while it still BackingUp");
+ assertEquals(expected , e.getMessage());
}
}
-
- @Override
- public String getConfigComponentName() {
- return BackupService.class.getSimpleName();
- }
-
- @Override
- public ConfigKey>[] getConfigKeys() {
- return new ConfigKey[]{
- BackrollUrlConfigKey,
- BackrollAppNameConfigKey,
- BackrollPasswordConfigKey
- };
- }
-
- @Override
- public boolean deleteBackup(Backup backup, boolean forced) {
- logger.info("backroll delete backup id: {}", backup.getExternalId());
- if (backup.getStatus().equals(Backup.Status.BackingUp)) {
- throw new CloudRuntimeException("You can't delete a backup while it still BackingUp");
- } else {
- logger.debug("backroll - try delete backup");
- VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(backup.getVmId());
-
- if (backup.getStatus().equals(Backup.Status.Removed) || backup.getStatus().equals(Backup.Status.Failed)){
- return deleteBackupInDb(backup);
- } else {
- try {
- if (getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup))) {
- logger.debug("Backup deletion for backup {} complete on backroll side.", backup.getUuid());
- return deleteBackupInDb(backup);
- }
- } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
- throw new CloudRuntimeException("Failed to delete backup");
- }
- }
- }
- return false;
- }
-
- private boolean deleteBackupInDb(Backup backup) {
- BackupVO backupToUpdate = ((BackupVO) backup);
- backupToUpdate.setStatus(Backup.Status.Removed);
- if (backupDao.persist(backupToUpdate) != null) {
- logger.debug("Backroll backup {} deleted in database.", backup.getUuid());
- return true;
- }
- return false;
- }
-
- protected BackrollClientTest getClient(final Long zoneId) {
- logger.debug("Backroll Provider GetClient with zone id {}", zoneId);
- try {
- if (backrollClient == null) {
- logger.debug("backroll client null - instanciation of new one ");
- backrollClient = new BackrollClientTest(BackrollUrlConfigKey.valueIn(zoneId), BackrollAppNameConfigKey.valueIn(zoneId), BackrollPasswordConfigKey.valueIn(zoneId), true, 300, 600);
- }
- return backrollClient;
- } catch (URISyntaxException e) {
- throw new CloudRuntimeException("Failed to parse Backroll API URL: " + e.getMessage());
- } catch (NoSuchAlgorithmException | KeyManagementException e) {
- logger.info("Failed to build Backroll API client due to: ", e);
- }
- throw new CloudRuntimeException("Failed to build Backroll API client");
- }
-
- private String getBackupName(Backup backup) {
- return backup.getExternalId().substring(backup.getExternalId().indexOf(",") + 1);
- }
-
- @Override
- public Pair restoreBackedUpVolume(Backup backup, String volumeUuid, String hostIp, String dataStoreUuid, Pair vmNameAndState) {
- logger.debug("Restoring volume {} from backup {} on the Backroll Backup Provider", volumeUuid, backup.getUuid());
- throw new CloudRuntimeException("Backroll plugin does not support this feature");
- }
-}
+}
\ No newline at end of file
diff --git a/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/backroll/BackrollClientTest.java b/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/backroll/BackrollClientTest.java
index 437277adffe..1ce259749d0 100644
--- a/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/backroll/BackrollClientTest.java
+++ b/plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/backroll/BackrollClientTest.java
@@ -16,45 +16,49 @@
// under the License.
package org.apache.cloudstack.backup.backroll;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
+import java.io.IOException;
+import java.util.Arrays;
import java.util.List;
-import org.apache.cloudstack.backup.BackupService;
+import org.apache.cloudstack.backup.Backup.Metric;
+import org.apache.cloudstack.backup.BackupOffering;
+import org.apache.cloudstack.backup.backroll.model.BackrollBackupMetrics;
+import org.apache.cloudstack.backup.backroll.model.BackrollTaskStatus;
import org.apache.cloudstack.backup.backroll.model.BackrollVmBackup;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.StatusLine;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.util.EntityUtils;
-
+import org.apache.cloudstack.backup.backroll.model.response.BackrollTaskRequestResponse;
+import org.apache.cloudstack.backup.backroll.model.response.TaskState;
+import org.apache.cloudstack.backup.backroll.model.response.archive.BackrollBackupsFromVMResponse;
+import org.apache.cloudstack.backup.backroll.model.response.metrics.backup.BackrollBackupMetricsResponse;
+import org.apache.cloudstack.backup.backroll.model.response.metrics.backup.BackupMetricsInfo;
+import org.apache.cloudstack.backup.backroll.model.response.metrics.virtualMachine.BackrollVmMetricsResponse;
+import org.apache.cloudstack.backup.backroll.model.response.metrics.virtualMachine.CacheStats;
+import org.apache.cloudstack.backup.backroll.model.response.metrics.virtualMachine.InfosCache;
+import org.apache.cloudstack.backup.backroll.model.response.metrics.virtualMachine.MetricsInfos;
+import org.apache.cloudstack.backup.backroll.model.response.metrics.virtualMachineBackups.VirtualMachineBackupsResponse;
+import org.apache.cloudstack.backup.backroll.model.response.policy.BackrollBackupPolicyResponse;
+import org.apache.cloudstack.backup.backroll.model.response.policy.BackupPoliciesResponse;
+import org.apache.cloudstack.backup.backroll.utils.BackrollApiException;
+import org.apache.cloudstack.backup.backroll.utils.BackrollHttpClientProvider;
import org.apache.logging.log4j.Logger;
-
-import org.junit.Assert;
+import org.json.JSONObject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+
import org.mockito.Mock;
import org.mockito.Mockito;
-
-import com.cloud.utils.exception.CloudRuntimeException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
public class BackrollClientTest {
private BackrollClient client;
@Mock
- private BackrollService mockBackrollService;
+ private BackrollHttpClientProvider backrollHttpClientProviderMock;
@Rule
@@ -62,101 +66,174 @@ public class BackrollClientTest {
@Before
public void setUp() throws Exception {
- mockBackrollService = mock(BackrollService.class);
- mockBackrollService.logger = Mockito.mock(Logger.class);
- client = new BackrollClient("http://localhost:5050/api/v1/", "backroll", "password", true, 300, 600, mockBackrollService);
+ backrollHttpClientProviderMock = mock(BackrollHttpClientProvider.class);
+ client = new BackrollClient(backrollHttpClientProviderMock);
+ client.logger = Mockito.mock(Logger.class);
}
@Test
public void getAllBackupsfromVirtualMachine_test() throws Exception {
String vmId = "TEST-vm_uuid";
- CloseableHttpResponse mockHttpResponse = mock(CloseableHttpResponse.class);
- CloseableHttpResponse mockHttpResponse2 = mock(CloseableHttpResponse.class);
-
- // Define mock behavior for first HTTP response
- String responseContent1 = "{\"Location\":\"/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782\"}";
-
- // Define mock behavior for second HTTP response
- String responseContent2 = "{ \"state\": \"SUCCESS\", \"info\": { \"archives\": [ { \"archive\": \"ROOT-00000\", \"barchive\": \"ROOT-00000\", \"id\": \"25d55ad283aa400af464c76d713c07ad7d163abdd3b8fbcdbdc46b827e5e0457\", \"name\": \"ROOT-00000\", \"start\": \"2024-11-08T18:24:48.000000\", \"time\": \"2024-11-08T18:24:48.000000\" } ], \"encryption\": { \"mode\": \"none\" }, \"repository\": { \"id\": \"36a11ebc0775a097c927735cc7015d19be7309be69fc15b896c5b1fd87fcbd79\", \"last_modified\": \"2024-11-29T09:53:09.000000\", \"location\": \"/mnt/backup/backup1\" } } }";
+ String virtualMachineResponseString = "{ \"state\": \"SUCCESS\", \"info\": { \"archives\": [ { \"archive\": \"ROOT-00000\", \"barchive\": \"ROOT-00000\", \"id\": \"25d55ad283aa400af464c76d713c07ad7d163abdd3b8fbcdbdc46b827e5e0457\", \"name\": \"ROOT-00000\", \"start\": \"2024-11-08T18:24:48.000000\", \"time\": \"2024-11-08T18:24:48.000000\" } ], \"encryption\": { \"mode\": \"none\" }, \"repository\": { \"id\": \"36a11ebc0775a097c927735cc7015d19be7309be69fc15b896c5b1fd87fcbd79\", \"last_modified\": \"2024-11-29T09:53:09.000000\", \"location\": \"/mnt/backup/backup1\" } } }";
+ BackrollTaskRequestResponse backrollTaskReqResponseMock = new BackrollTaskRequestResponse();
+ backrollTaskReqResponseMock.location = "/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782";
+ VirtualMachineBackupsResponse virtualMachineBackupsResponseMock = new ObjectMapper().readValue(virtualMachineResponseString, VirtualMachineBackupsResponse.class);
// Mocking client responses
- doReturn(mockHttpResponse).when(mockBackrollService).get(Mockito.any(URI.class), Mockito.matches(".*/virtualmachines/.*"));
- doReturn(responseContent1).when(mockBackrollService).okBody(mockHttpResponse);
- doReturn(responseContent2).when(mockBackrollService).waitGet(Mockito.any(URI.class), Mockito.anyString());
- doReturn(mockHttpResponse2).when(mockBackrollService).get(Mockito.any(URI.class), Mockito.matches(".*/status/.*"));
-
- // Assuming getAllBackupsfromVirtualMachine belongs to a class named BackupService
-
+ doReturn(backrollTaskReqResponseMock).when(backrollHttpClientProviderMock).get(Mockito.matches(".*/virtualmachines/.*"), Mockito.any());
+ doReturn(virtualMachineBackupsResponseMock).when(backrollHttpClientProviderMock).waitGet(Mockito.anyString(), Mockito.any());
// Run the method under test
List backupsTestList = client.getAllBackupsfromVirtualMachine(vmId);
// Check results
assertEquals(1, backupsTestList.size()); // Should be 1 based on provided mock data
-
- // Optional: Verifications
- verify(mockHttpResponse).close();
}
- // @Test
- // public void getAllBackupsfromVirtualMachine_test2() throws Exception {
- // String vmId = "TEST-vm_uuid";
- // CloseableHttpResponse mockHttpResponse = mock(CloseableHttpResponse.class);
- // CloseableHttpResponse mockHttpResponse2 = mock(CloseableHttpResponse.class);
- // StatusLine mockStatusLine = mock(StatusLine.class);
- // HttpEntity mockEntity = mock(HttpEntity.class);
- // HttpEntity mockEntity2 = mock(HttpEntity.class);
- // //InputStream mockInputStream = new ByteArrayInputStream("{\"Location\":\"/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782\"}".getBytes());
+ @Test
+ public void getBackupMetrics_Test() throws IOException, BackrollApiException {
+ BackrollTaskRequestResponse backrollTaskReqResponseMock = new BackrollTaskRequestResponse();
+ backrollTaskReqResponseMock.location = "/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782";
+ BackrollBackupMetricsResponse mockResponse = new BackrollBackupMetricsResponse();
+ mockResponse.info = new BackupMetricsInfo();
+ mockResponse.info.originalSize = "1000";
+ mockResponse.info.deduplicatedSize = "800";
- // // Define mock behavior
- // when(mockHttpResponse.getStatusLine()).thenReturn(mockStatusLine);
- // when(mockStatusLine.getStatusCode()).thenReturn(200);
- // when(mockHttpResponse.getEntity()).thenReturn(mockEntity);
- // when(mockEntity.getContentLength()).thenReturn(400L);
+ doReturn(backrollTaskReqResponseMock).when(backrollHttpClientProviderMock).get(Mockito.matches(".*/virtualmachines/.*"), Mockito.any());
+ doReturn(mockResponse).when(backrollHttpClientProviderMock).waitGet(Mockito.anyString(), Mockito.any());
- // String responseContent = "{\"Location\":\"/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782\"}";
- // InputStream stream = new ByteArrayInputStream(responseContent.getBytes());
- // when(mockEntity.getContent()).thenReturn(stream);
+ BackrollBackupMetrics metrics = client.getBackupMetrics("dummyVMId", "dummyBackupId");
- // when(mockHttpResponse2.getStatusLine()).thenReturn(mockStatusLine);
- // when(mockStatusLine.getStatusCode()).thenReturn(200);
- // when(mockHttpResponse2.getEntity()).thenReturn(mockEntity2);
- // when(mockEntity2.getContentLength()).thenReturn(400L);
+ assertEquals(1000L, metrics.getSize());
+ assertEquals(800L, metrics.getDeduplicated());
+ }
- // String responseContent2 = "{\r\n" + //
- // " \"state\": \"SUCCESS\",\r\n" + //
- // " \"info\": {\r\n" + //
- // " \"archives\": [\r\n" + //
- // " {\r\n" + //
- // " \"archive\": \"ROOT-00000\",\r\n" + //
- // " \"barchive\": \"ROOT-00000\",\r\n" + //
- // " \"id\": \"25d55ad283aa400af464c76d713c07ad7d163abdd3b8fbcdbdc46b827e5e0457\",\r\n" + //
- // " \"name\": \"ROOT-00000\",\r\n" + //
- // " \"start\": \"2024-11-08T18:24:48.000000\",\r\n" + //
- // " \"time\": \"2024-11-08T18:24:48.000000\"\r\n" + //
- // " }\r\n" + //
- // " ],\r\n" + //
- // " \"encryption\": {\r\n" + //
- // " \"mode\": \"none\"\r\n" + //
- // " },\r\n" + //
- // " \"repository\": {\r\n" + //
- // " \"id\": \"36a11ebc0775a097c927735cc7015d19be7309be69fc15b896c5b1fd87fcbd79\",\r\n" + //
- // " \"last_modified\": \"2024-11-29T09:53:09.000000\",\r\n" + //
- // " \"location\": \"/mnt/backup/backup1\"\r\n" + //
- // " }\r\n" + //
- // " }\r\n" + //
- // "}";
- // InputStream stream2 = new ByteArrayInputStream(responseContent2.getBytes());
- // when(mockEntity2.getContent()).thenReturn(stream2);
+ @Test
+ public void getVirtualMachineMetrics_Test() throws IOException, BackrollApiException {
+ BackrollTaskRequestResponse backrollTaskReqResponseMock = new BackrollTaskRequestResponse();
+ backrollTaskReqResponseMock.location = "/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782";
- // try {
- // Mockito.doReturn(mockHttpResponse).when(mockClient).get(Mockito.matches(".*/virtualmachines/.*"));
- // Mockito.doReturn(mockHttpResponse2).when(mockClient).get(Mockito.matches(".*/api/v1.*"));
- // List backupsTesList = mockClient.getAllBackupsfromVirtualMachine(vmId);
- // Assert.assertTrue(backupsTesList.size() > 0);
- // fail();
- // } catch (Exception e) {
- // Assert.assertEquals(CloudRuntimeException.class, e.getClass());
- // Assert.assertEquals("Failed to get Repository Name from Job [name: TEST-BACKUP].", e.getMessage());
- // }
- // }
+ BackrollVmMetricsResponse mockResponse = new BackrollVmMetricsResponse();
+ mockResponse.state = TaskState.SUCCESS;
+ mockResponse.infos = new MetricsInfos();
+ mockResponse.infos.cache = new InfosCache();
+ mockResponse.infos.cache.stats = new CacheStats();
+ mockResponse.infos.cache.stats.totalSize = "10000";
+
+ doReturn(backrollTaskReqResponseMock).when(backrollHttpClientProviderMock).get(Mockito.matches(".*/virtualmachines/.*"), Mockito.any());
+ doReturn(mockResponse).when(backrollHttpClientProviderMock).waitGet(Mockito.anyString(), Mockito.any());
+
+ Metric metrics = client.getVirtualMachineMetrics("dummyVMId");
+
+ assertEquals(10000L, (long)metrics.getBackupSize());
+ assertEquals(10000L, (long)metrics.getDataSize());
+ }
+ @Test
+ public void deleteBackup_Test() throws IOException, BackrollApiException{
+ BackrollTaskRequestResponse backrollTaskReqResponseMock = new BackrollTaskRequestResponse();
+ backrollTaskReqResponseMock.location = "/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782";
+
+ BackrollBackupsFromVMResponse mockResponse = new BackrollBackupsFromVMResponse();
+ mockResponse.state = TaskState.SUCCESS;
+
+ doReturn(backrollTaskReqResponseMock).when(backrollHttpClientProviderMock).delete(Mockito.matches(".*/virtualmachines/.*"), Mockito.any());
+ doReturn(mockResponse).when(backrollHttpClientProviderMock).waitGet(Mockito.anyString(), Mockito.any());
+
+ Boolean isBackupDeleted = client.deleteBackup("dummyVMId", "dummyBackUpName");
+
+ assertTrue(isBackupDeleted);
+ }
+ @Test
+ public void checkBackupTaskStatusSuccess_Test() throws IOException, BackrollApiException {
+ String backupResponse = "{\"state\":\"SUCCESS\",\"info\":\"test\"}";
+ doReturn(backupResponse).when(backrollHttpClientProviderMock).getWithoutParseResponse(Mockito.matches(".*status/.*"));
+
+ BackrollTaskStatus status = client.checkBackupTaskStatus("dummytaskid");
+
+ assertEquals(TaskState.SUCCESS, status.getState());
+ assertEquals("test", status.getInfo());
+ }
+
+ @Test
+ public void checkBackupTaskStatus_Test() throws IOException, BackrollApiException {
+ String backupResponse = "{\"state\":\"PENDING\",\"current\":0,\"total\":1,\"status\":\"Pending...\"}";
+ doReturn(backupResponse).when(backrollHttpClientProviderMock).getWithoutParseResponse(Mockito.matches(".*/status/.*"));
+
+ BackrollTaskStatus status = client.checkBackupTaskStatus("dummytaskid");
+
+ assertEquals(TaskState.PENDING, status.getState());
+ }
+ @Test
+ public void restoreVMFromBackup_Test() throws IOException, BackrollApiException {
+ BackrollTaskRequestResponse backrollTaskReqResponseMock = new BackrollTaskRequestResponse();
+ backrollTaskReqResponseMock.location = "/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782";
+ String resultMock = "SUCCESS WOW YOUHOU";
+ doReturn(backrollTaskReqResponseMock).when(backrollHttpClientProviderMock).post(Mockito.matches(".*/tasks/restore/.*"), Mockito.any(JSONObject.class),Mockito.any());
+ doReturn(resultMock).when(backrollHttpClientProviderMock).waitGetWithoutParseResponse(Mockito.anyString());
+
+ Boolean isRestoreOk = client.restoreVMFromBackup("dummyVMId", "dummyBackUpName");
+
+ assertTrue(isRestoreOk);
+ }
+
+ @Test
+ public void startBackupJob_Test() throws IOException, BackrollApiException {
+
+ BackrollTaskRequestResponse backrollTaskReqResponseMock = new BackrollTaskRequestResponse();
+ backrollTaskReqResponseMock.location = "/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782";
+ doReturn(backrollTaskReqResponseMock).when(backrollHttpClientProviderMock).post(Mockito.matches(".*/tasks/singlebackup/.*"), Mockito.nullable(JSONObject.class),Mockito.any());
+
+ String response = client.startBackupJob("dummyJobId");
+
+ assertEquals("f32092e4-3e8a-461b-8733-ed93e23fa782", response);
+ }
+
+ @Test
+ public void getBackupOfferingUrl_Test() throws IOException, BackrollApiException {
+ BackrollTaskRequestResponse backrollTaskReqResponseMock = new BackrollTaskRequestResponse();
+ backrollTaskReqResponseMock.location = "/api/v1/status/f32092e4-3e8a-461b-8733-ed93e23fa782";
+ doReturn(backrollTaskReqResponseMock).when(backrollHttpClientProviderMock).get(Mockito.matches(".*/backup_policies.*"), Mockito.any());
+
+ String response = client.getBackupOfferingUrl();
+
+ assertEquals("/status/f32092e4-3e8a-461b-8733-ed93e23fa782", response);
+ }
+
+ @Test
+ public void getBackupOfferings_Test() throws BackrollApiException, IOException {
+
+ BackrollBackupPolicyResponse policy1 = new BackrollBackupPolicyResponse();
+ policy1.name = "User-Policy-1";
+ policy1.retentionDay = 6;
+ policy1.schedule = "0 0 * * 1";
+ policy1.retentionMonth = 0;
+ policy1.storage = "f32092e4-3e8a-461b-8733-ed93e23fa782";
+ policy1.enabled = false;
+ policy1.description = "User's policy 1 description";
+ policy1.id = "f32092e4-3e8a-461b-8733-ed93e23fa782";
+ policy1.retentionWeek = 0;
+ policy1.retentionYear = 0;
+ policy1.externalHook = null;
+
+ BackrollBackupPolicyResponse policy2 = new BackrollBackupPolicyResponse();
+ policy1.name = "User-Policy-2";
+ policy1.retentionDay = 6;
+ policy1.schedule = "0 0 * * 1";
+ policy1.retentionMonth = 0;
+ policy1.storage = "f32092e4-3e8a-461b-8733-ed93e23fa782";
+ policy1.enabled = false;
+ policy1.description = "User's policy 2 description";
+ policy1.id = "f32092e4-3e8a-461b-8733-ed93e23fa782";
+ policy1.retentionWeek = 0;
+ policy1.retentionYear = 0;
+ policy1.externalHook = null;
+ BackupPoliciesResponse backupPoliciesResponseMock = new BackupPoliciesResponse();
+ backupPoliciesResponseMock.backupPolicies = Arrays.asList(policy1, policy2);
+
+ doReturn(backupPoliciesResponseMock).when(backrollHttpClientProviderMock).waitGet(Mockito.matches("/status/f32092e4-3e8a-461b-8733-ed93e23fa782"), Mockito.any());
+
+ List response = client.getBackupOfferings("/status/f32092e4-3e8a-461b-8733-ed93e23fa782");
+
+ assertEquals(response.size(), 2);
+
+ }
}
\ No newline at end of file