From 6a690b74310ba43bd09a38b0908a4688280cec20 Mon Sep 17 00:00:00 2001 From: Pierre Charton Date: Mon, 21 Oct 2024 17:33:48 +0200 Subject: [PATCH] Revert "WIP error handling" This reverts commit 01c2238e45107c74d8c7d2d8e4c648be9de756fe. --- .../backup/BackrollBackupProvider.java | 175 +++++------ .../backup/backroll/BackrollClient.java | 285 ++++++++++-------- 2 files changed, 228 insertions(+), 232 deletions(-) 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 080f31a4531..96452d5a803 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 @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.backup; -import java.io.IOException; import java.net.URISyntaxException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; @@ -40,7 +39,7 @@ import org.apache.cloudstack.framework.config.Configurable; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.ClientProtocolException; + import org.joda.time.DateTime; import com.cloud.utils.Pair; @@ -55,19 +54,19 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide public static final String BACKUP_IDENTIFIER = "-CSBKP-"; 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); + "backup.plugin.backroll.config.url", + "http://api.backup.demo.ccc:5050/api/v1", + "Url for backroll plugin.", true, ConfigKey.Scope.Zone); public ConfigKey BackrollAppNameConfigKey = new ConfigKey<>("Advanced", String.class, - "backup.plugin.backroll.config.appname", - "backroll_api", - "App Name for backroll plugin.", true, ConfigKey.Scope.Zone); + "backup.plugin.backroll.config.appname", + "backroll_api", + "App Name for backroll plugin.", true, ConfigKey.Scope.Zone); public ConfigKey BackrollPasswordConfigKey = new ConfigKey<>("Advanced", String.class, - "backup.plugin.backroll.config.password", - "VviX8dALauSyYJMqVYJqf3UyZOpO3joS", - "Password for backroll plugin.", true, ConfigKey.Scope.Zone); + "backup.plugin.backroll.config.password", + "VviX8dALauSyYJMqVYJqf3UyZOpO3joS", + "Password for backroll plugin.", true, ConfigKey.Scope.Zone); private BackrollClient backrollClient; @@ -89,12 +88,12 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide @Override public List listBackupOfferings(Long zoneId) { logger.debug("Listing backup policies on backroll B&R Plugin"); - try { - BackrollClient client = getClient(zoneId); - return client.getBackupOfferings(client.getBackupOfferingUrl()); // TODO Embed URL in method ? - } catch (Exception e) { - throw new CloudRuntimeException(String.format("Failed to list backup offerings for zone %s.", zoneId), e); + BackrollClient client = getClient(zoneId); + String urlToRequest = client.getBackupOfferingUrl(); + if (!StringUtils.isEmpty(urlToRequest)){ + return client.getBackupOfferings(urlToRequest); } + return new ArrayList(); } @Override @@ -105,8 +104,7 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide @Override public boolean assignVMToBackupOffering(VirtualMachine vm, BackupOffering backupOffering) { - logger.info("Creating VM backup for VM {} from backup offering {}", vm.getInstanceName(), - backupOffering.getName()); + logger.info("Creating VM backup for VM {} from backup offering {}", vm.getInstanceName(), backupOffering.getName()); ((VMInstanceVO) vm).setBackupExternalId(backupOffering.getUuid()); return true; } @@ -114,13 +112,8 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide @Override public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) { logger.debug("Restoring vm {} from backup {} on the backroll Backup Provider", vm.getUuid(), backup.getUuid()); - try { - getClient(vm.getDataCenterId()).restoreVMFromBackup(vm.getUuid(), getBackupName(backup)); - } catch (Exception e) { - throw new CloudRuntimeException( - String.format("Failed to restore backup %s to VM %s.", backup.getName(), vm.getName()), e); - } - return true; + boolean isSuccess = getClient(vm.getDataCenterId()).restoreVMFromBackup(vm.getUuid(), getBackupName(backup)); + return isSuccess; } @Override @@ -131,8 +124,7 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide return metrics; } - List vmUuids = vms.stream().filter(Objects::nonNull).map(VirtualMachine::getUuid) - .collect(Collectors.toList()); + 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) { @@ -140,14 +132,10 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide continue; } - try { - Metric metric = getClient(zoneId).getVirtualMachineMetrics(vm.getUuid()); - logger.debug("Metrics for VM [uuid: {}, name: {}] is [backup size: {}, data size: {}].", vm.getUuid(), - vm.getInstanceName(), metric.getBackupSize(), metric.getDataSize()); - metrics.put(vm, metric); - } catch (Exception e) { - logger.error("Failed to get backup metrics for VM {} due to {}.", vm.getName(), e); - } + Metric metric = getClient(zoneId).getVirtualMachineMetrics(vm.getUuid()); + 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; } @@ -156,30 +144,28 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide public boolean removeVMFromBackupOffering(VirtualMachine vm) { logger.info("Removing VM ID {} from Backrool backup offering ", vm.getUuid()); - boolean everythingIsOk = true; + boolean isAnyProblemWhileRemovingBackups = false; List backupsInCs = backupDao.listByVmId(null, vm.getId()); for (Backup backup : backupsInCs) { logger.debug("Trying to remove backup with id {}", backup.getId()); - try { - getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup)); + if (getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup))) { logger.info("Backup {} deleted in Backroll for virtual machine {}", backup.getId(), vm.getName()); - if (!backupDao.remove(backup.getId())) { - everythingIsOk = false; + if (!backupDao.remove(backup.getId())){ + isAnyProblemWhileRemovingBackups = true; } logger.info("Backup {} deleted in CS for virtual machine {}", backup.getId(), vm.getName()); - } catch (Exception e) { - logger.error("Failed to remove backup {} for VM {}.", backup.getName(), vm.getName()); - everythingIsOk = false; + } else { + isAnyProblemWhileRemovingBackups = false; } } - if (!everythingIsOk) { + if (isAnyProblemWhileRemovingBackups) { logger.info("Problems occured while removing some backups for virtual machine {}", vm.getName()); } - return everythingIsOk; + return isAnyProblemWhileRemovingBackups; } @Override @@ -190,9 +176,10 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide @Override public boolean takeBackup(VirtualMachine vm) { logger.info("Starting backup for VM ID {} on backroll provider", vm.getUuid()); - try { - final BackrollClient client = getClient(vm.getDataCenterId()); - String idBackupTask = client.startBackupJob(vm.getUuid()); + final BackrollClient client = getClient(vm.getDataCenterId()); + + String idBackupTask = client.startBackupJob(vm.getUuid()); + if (!StringUtils.isEmpty(idBackupTask)) { BackupVO backup = new BackupVO(); backup.setVmId(vm.getId()); backup.setExternalId(idBackupTask); @@ -205,32 +192,22 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide backup.setAccountId(vm.getAccountId()); backup.setDomainId(vm.getDomainId()); backup.setZoneId(vm.getDataCenterId()); - assert backupDao.persist(backup) != null; - } catch (Exception e) { - throw new CloudRuntimeException(String.format("Failed to take a backup of VM %s.", vm.getName()), e); + return backupDao.persist(backup) != null; } - return true; + 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 BackrollClient client; - try { - client = getClient(vm.getDataCenterId()); - } catch (Exception e) { - throw new CloudRuntimeException( - String.format("Failed to get Backroll client while syncing backups for VM %s.", vm.getName())); - } - + final BackrollClient client = getClient(vm.getDataCenterId()); List backupsInDb = backupDao.listByVmId(null, vm.getId()); for (Backup backup : backupsInDb) { - try { - if (backup.getStatus().equals(Backup.Status.BackingUp)) { - BackrollTaskStatus response = client.checkBackupTaskStatus(backup.getExternalId()); - + if (backup.getStatus().equals(Backup.Status.BackingUp)) { + BackrollTaskStatus response = client.checkBackupTaskStatus(backup.getExternalId()); + if (response != null) { logger.debug("backroll backup id: {}", backup.getExternalId()); logger.debug("backroll backup status: {}", response.getState()); @@ -254,8 +231,7 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide backupToUpdate.setStatus(Backup.Status.BackedUp); backupToUpdate.setExternalId(backup.getExternalId() + "," + response.getInfo()); - BackrollBackupMetrics backupMetrics = client.getBackupMetrics(vm.getUuid(), - response.getInfo()); + BackrollBackupMetrics backupMetrics = client.getBackupMetrics(vm.getUuid() , response.getInfo()); if (backupMetrics != null) { backupToUpdate.setSize(backupMetrics.getDeduplicated()); // real size backupToUpdate.setProtectedSize(backupMetrics.getSize()); // total size @@ -268,19 +244,16 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide 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 = client.getBackupMetrics(vm.getUuid(), backupId); + } + } 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 = client.getBackupMetrics(vm.getUuid() , backupId); + if (backupMetrics != null) { BackupVO backupToUpdate = ((BackupVO) backup); backupToUpdate.setSize(backupMetrics.getDeduplicated()); // real size backupToUpdate.setProtectedSize(backupMetrics.getSize()); // total size backupDao.persist(backupToUpdate); } - } catch (Exception e) { - logger.error("Failed to sync backup {}.", backup.getName()); } } @@ -291,9 +264,9 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide // insert new backroll backup in CS for (BackrollVmBackup backupInBackroll : backupsFromBackroll) { Backup backupToFind = backupsInDb.stream() - .filter(backupInDb -> backupInDb.getExternalId().contains(backupInBackroll.getName())) - .findAny() - .orElse(null); + .filter(backupInDb -> backupInDb.getExternalId().contains(backupInBackroll.getName())) + .findAny() + .orElse(null); if (backupToFind == null) { BackupVO backupToInsert = new BackupVO(); @@ -323,12 +296,11 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide // 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(); + String backupName = backup.getExternalId().contains(",") ? backup.getExternalId().split(",")[1] : backup.getExternalId(); BackrollVmBackup backupToFind = backupsFromBackroll.stream() - .filter(backupInBackroll -> backupInBackroll.getName().contains(backupName)) - .findAny() - .orElse(null); + .filter(backupInBackroll -> backupInBackroll.getName().contains(backupName)) + .findAny() + .orElse(null); if (backupToFind == null) { BackupVO backupToUpdate = ((BackupVO) backup); @@ -347,10 +319,10 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] { - BackrollUrlConfigKey, - BackrollAppNameConfigKey, - BackrollPasswordConfigKey + return new ConfigKey[]{ + BackrollUrlConfigKey, + BackrollAppNameConfigKey, + BackrollPasswordConfigKey }; } @@ -358,24 +330,21 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide 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 backing up."); + 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)) { + if (backup.getStatus().equals(Backup.Status.Removed) || backup.getStatus().equals(Backup.Status.Failed)){ return deleteBackupInDb(backup); + } else { + if (getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup))) { + logger.debug("Backup deletion for backup {} complete on backroll side.", backup.getUuid()); + return deleteBackupInDb(backup); + } } - - try { - getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup)); - } catch (Exception e) { - throw new CloudRuntimeException(String.format("Failed to delete backup %s", backup.getName())); - } - - logger.debug("Backup deletion for backup {} complete on backroll side.", backup.getUuid()); - return deleteBackupInDb(backup); } + return false; } private boolean deleteBackupInDb(Backup backup) { @@ -388,14 +357,12 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide return false; } - protected BackrollClient getClient(final Long zoneId) throws ClientProtocolException, IOException { + protected BackrollClient 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 BackrollClient(BackrollUrlConfigKey.valueIn(zoneId), - BackrollAppNameConfigKey.valueIn(zoneId), BackrollPasswordConfigKey.valueIn(zoneId), true, 300, - 600); + backrollClient = new BackrollClient(BackrollUrlConfigKey.valueIn(zoneId), BackrollAppNameConfigKey.valueIn(zoneId), BackrollPasswordConfigKey.valueIn(zoneId), true, 300, 600); } return backrollClient; } catch (URISyntaxException e) { @@ -411,10 +378,8 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide } @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()); + 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"); } } 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 cfdcf566646..e7021d4276b 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 @@ -62,7 +62,6 @@ import org.apache.http.HttpHeaders; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.ParseException; -import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpDelete; @@ -107,8 +106,7 @@ public class BackrollClient { public BackrollClient(final String url, final String appname, final String password, final boolean validateCertificate, final int timeout, final int restoreTimeout) - throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException, ClientProtocolException, - IOException { + throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException { this.apiURI = new URI(url); this.restoreTimeout = restoreTimeout; this.appname = appname; @@ -154,79 +152,105 @@ public class BackrollClient { return null; } - public String getBackupOfferingUrl() - throws ClientProtocolException, IOException, ParseException, NotOkBodyException { + public String getBackupOfferingUrl() { logger.info("Trying to list backroll backup policies"); loginIfAuthenticationFailed(); - return this.parse(okBody(get("/backup_policies"))).location.replace("/api/v1", - ""); - } - - public List getBackupOfferings(String idTask) - throws ParseException, NotOkBodyException, ClientProtocolException, IOException, InterruptedException { - logger.info("Trying to list backroll backup policies"); - - loginIfAuthenticationFailed(); - - BackupPoliciesResponse backupPoliciesResponse = waitGet(idTask); - - final List policies = new ArrayList<>(); - for (final BackrollBackupPolicyResponse policy : backupPoliciesResponse.backupPolicies) { - policies.add(new BackrollOffering(policy.name, policy.id)); + try { + return this.parse(okBody(get("/backup_policies"))).location.replace("/api/v1", + ""); + } catch (final Exception e) { + logger.error("Failed to list Backroll jobs due to: {}", e.getMessage()); } - return policies; + return null; } - public void restoreVMFromBackup(final String vmId, final String backupName) throws Exception { + public List getBackupOfferings(String idTask) { + logger.info("Trying to list backroll backup policies"); + + loginIfAuthenticationFailed(); + + try { + BackupPoliciesResponse backupPoliciesResponse = waitGet(idTask); + + final List policies = new ArrayList<>(); + for (final BackrollBackupPolicyResponse policy : backupPoliciesResponse.backupPolicies) { + policies.add(new BackrollOffering(policy.name, policy.id)); + } + return policies; + } catch (final IOException | InterruptedException e) { + logger.error("Failed to list Backroll jobs due to: {}", e.getMessage()); + } + return new ArrayList(); + } + + public boolean restoreVMFromBackup(final String vmId, final String backupName) { logger.info("Start restore backup with backroll with backup {} for vm {}", backupName, vmId); loginIfAuthenticationFailed(); - JSONObject jsonBody = new JSONObject(); - jsonBody.put("virtual_machine_id", vmId); - jsonBody.put("backup_name", backupName); - jsonBody.put("storage", ""); - jsonBody.put("mode", "single"); + try { + JSONObject jsonBody = new JSONObject(); + try { + jsonBody.put("virtual_machine_id", vmId); + jsonBody.put("backup_name", backupName); + jsonBody.put("storage", ""); + jsonBody.put("mode", "single"); - String urlToRequest = this - .parse(okBody( - post(String.format("/tasks/restore/%s", vmId), jsonBody))).location - .replace("/api/v1", ""); + } catch (JSONException e) { + logger.error("Backroll Error: {}", e.getMessage()); + } - TaskStateResponse response = waitGet(urlToRequest); - logger.debug("RESTORE {}", response.state); + String urlToRequest = this + .parse(okBody( + post(String.format("/tasks/restore/%s", vmId), jsonBody))).location + .replace("/api/v1", ""); - if (!response.state.equals(TaskState.SUCCESS)) { - throw new Exception("Backroll task failed."); + TaskStateResponse response = waitGet(urlToRequest); + logger.debug("RESTORE {}", response.state); + return response.state.equals(TaskState.SUCCESS); + } catch (final NotOkBodyException e) { + return false; + } catch (final IOException | InterruptedException e) { + logger.error("Ouch! Failed to restore VM with Backroll due to: {}", e.getMessage()); + throw new CloudRuntimeException("Ouch! Failed to restore VM with Backroll due to: {}" + e.getMessage()); } } - public BackrollTaskStatus checkBackupTaskStatus(String taskId) - throws ParseException, IOException, NotOkBodyException { + public BackrollTaskStatus checkBackupTaskStatus(String taskId) { logger.info("Trying to get backup status for Backroll task: {}", taskId); loginIfAuthenticationFailed(); - BackrollTaskStatus status = new BackrollTaskStatus(); + try { + BackrollTaskStatus status = new BackrollTaskStatus(); - String body = okBody(get("/status/" + taskId)); + String body = okBody(get("/status/" + taskId)); - if (body.contains(TaskState.FAILURE) || body.contains(TaskState.PENDING)) { - BackrollBackupStatusResponse backupStatusRequestResponse = parse(body); - status.setState(backupStatusRequestResponse.state); - } else { - BackrollBackupStatusSuccessResponse backupStatusSuccessRequestResponse = parse(body); - status.setState(backupStatusSuccessRequestResponse.state); - status.setInfo(backupStatusSuccessRequestResponse.info); + if (body.contains(TaskState.FAILURE) || body.contains(TaskState.PENDING)) { + BackrollBackupStatusResponse backupStatusRequestResponse = parse(body); + status.setState(backupStatusRequestResponse.state); + } else { + BackrollBackupStatusSuccessResponse backupStatusSuccessRequestResponse = parse(body); + status.setState(backupStatusSuccessRequestResponse.state); + status.setInfo(backupStatusSuccessRequestResponse.info); + } + + return status; + + } catch (final NotOkBodyException e) { + // throw new CloudRuntimeException("Failed to retrieve backups status for this + // VM via Backroll"); + logger.error("Failed to retrieve backups status for this VM via Backroll"); + + } catch (final IOException e) { + logger.error("Failed to check backups status due to: {}", e.getMessage()); } - - return status; + return null; } - public boolean deleteBackup(final String vmId, final String backupName) - throws ClientProtocolException, IOException { + public boolean deleteBackup(final String vmId, final String backupName) { logger.info("Trying to delete backup {} for vm {} using Backroll", vmId, backupName); loginIfAuthenticationFailed(); @@ -247,7 +271,7 @@ public class BackrollClient { return false; } - public Metric getVirtualMachineMetrics(final String vmId) throws ClientProtocolException, IOException { + public Metric getVirtualMachineMetrics(final String vmId) { logger.info("Trying to retrieve virtual machine metric from Backroll for vm {}", vmId); loginIfAuthenticationFailed(); @@ -262,7 +286,7 @@ public class BackrollClient { BackrollVmMetricsResponse vmMetricsResponse = waitGet(urlToRequest); - if (vmMetricsResponse.state.equals(TaskState.SUCCESS)) { + if (vmMetricsResponse != null && vmMetricsResponse.state.equals(TaskState.SUCCESS)) { logger.debug("SUCCESS ok"); CacheStats stats = null; try { @@ -281,23 +305,28 @@ public class BackrollClient { return metric; } - public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) throws JsonMappingException, - JsonProcessingException, ParseException, IOException, NotOkBodyException, InterruptedException { + public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) { logger.info("Trying to get backup metrics for VM: {}, and backup: {}", vmId, backupId); loginIfAuthenticationFailed(); - String urlToRequest = this.parse(okBody(get( - String.format("/virtualmachines/%s/backups/%s", vmId, backupId)))).location.replace("/api/v1", ""); - logger.debug(urlToRequest); + try { - BackrollBackupMetricsResponse metrics = waitGet(urlToRequest); - if (metrics.info != null) { - return new BackrollBackupMetrics(Long.parseLong(metrics.info.originalSize), - Long.parseLong(metrics.info.deduplicatedSize)); + String urlToRequest = this.parse(okBody(get( + String.format("/virtualmachines/%s/backups/%s", vmId, backupId)))).location.replace("/api/v1", ""); + logger.debug(urlToRequest); + + BackrollBackupMetricsResponse metrics = waitGet(urlToRequest); + if (metrics.info != null) { + return new BackrollBackupMetrics(Long.parseLong(metrics.info.originalSize), + Long.parseLong(metrics.info.deduplicatedSize)); + } + } catch (final NotOkBodyException e) { + throw new CloudRuntimeException("Failed to retrieve backups status for this VM via Backroll"); + } catch (final IOException | InterruptedException e) { + logger.error("Failed to check backups status due to: {}", e.getMessage()); } - - throw new CloudRuntimeException("Backup %s of VM %s has null info in its metrics."); + return null; } public List getAllBackupsfromVirtualMachine(String vmId) { @@ -351,8 +380,7 @@ public class BackrollClient { final HttpResponse response = httpClient.execute(request); - logger.debug("Response received in POST request with body {} is: {} for URL {}.", xml, response.toString(), - url); + logger.debug("Response received in POST request with body {} is: {} for URL {}.", xml, response.toString(), url); return response; } @@ -383,17 +411,7 @@ public class BackrollClient { || response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED; } - public class NotOkBodyException extends Exception { - private HttpResponse response; - - public NotOkBodyException(HttpResponse response) { - super(String.format("HTTP response is not ok: %s", response)); - this.response = response; - } - - public HttpResponse getResponse() { - return this.response; - } + private class NotOkBodyException extends Exception { } private String okBody(final HttpResponse response) @@ -408,7 +426,7 @@ public class BackrollClient { EntityUtils.consumeQuietly(bodyEntity); } default: - throw new NotOkBodyException(response); + throw new NotOkBodyException(); } } @@ -418,23 +436,24 @@ public class BackrollClient { }); } - private T waitGet(String url) throws InterruptedException, ParseException, IOException, NotOkBodyException { - int waitingTimeMinutes = 2; - int refreshingPeriodSeconds = 10; + private T waitGet(String url) + throws IOException, InterruptedException { + // int threshold = 30; // 5 minutes + int maxAttempts = 12; // 2 minutes - int waitMillis = waitingTimeMinutes * 60000; - - long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < waitMillis) { - String body = okBody(get(url)); - if (!body.contains(TaskState.PENDING)) { - return parse(body); - } else { - TimeUnit.SECONDS - .sleep(refreshingPeriodSeconds); + for (int attempt = 1; attempt <= maxAttempts; attempt++) { + try { + String body = okBody(get(url)); + if (!body.contains(TaskState.PENDING)) { + return parse(body); + } + } catch (final NotOkBodyException e) { + throw new CloudRuntimeException("An error occured with Backroll"); } + TimeUnit.SECONDS.sleep(10); } - throw new CloudRuntimeException(String.format("Unable to fetch %s.")); + + return null; } private boolean isAuthenticated() { @@ -449,13 +468,13 @@ public class BackrollClient { return result; } - private void loginIfAuthenticationFailed() throws ClientProtocolException, IOException { + private void loginIfAuthenticationFailed() { if (!isAuthenticated()) { login(appname, password); } } - private void login(final String appname, final String appsecret) throws ClientProtocolException, IOException { + private void login(final String appname, final String appsecret) { logger.debug("Backroll client - start login"); final HttpPost request = new HttpPost(apiURI.toString() + "/login"); @@ -464,48 +483,60 @@ public class BackrollClient { JSONObject jsonBody = new JSONObject(); StringEntity params; - jsonBody.put("app_id", appname); - jsonBody.put("app_secret", appsecret); - params = new StringEntity(jsonBody.toString()); - request.setEntity(params); - - final HttpResponse response = httpClient.execute(request); try { - LoginApiResponse loginResponse = parse(okBody(response)); - backrollToken = loginResponse.accessToken; - logger.debug("Backroll client - Token : {}", backrollToken); + jsonBody.put("app_id", appname); + jsonBody.put("app_secret", appsecret); + params = new StringEntity(jsonBody.toString()); + request.setEntity(params); - if (StringUtils.isEmpty(loginResponse.accessToken)) { - throw new CloudRuntimeException("Backroll token is not available to perform API requests"); - } - } catch (final NotOkBodyException e) { - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED) { - throw new CloudRuntimeException( - "Failed to create and authenticate Backroll client, please check the settings."); - } else { - throw new ServerApiException(ApiErrorCode.UNAUTHORIZED, - "Backroll API call unauthorized, please ask your administrator to fix integration issues."); + final HttpResponse response = httpClient.execute(request); + try { + LoginApiResponse loginResponse = parse(okBody(response)); + backrollToken = loginResponse.accessToken; + logger.debug("Backroll client - Token : {}", backrollToken); + + if (StringUtils.isEmpty(loginResponse.accessToken)) { + throw new CloudRuntimeException("Backroll token is not available to perform API requests"); + } + } catch (final NotOkBodyException e) { + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED) { + throw new CloudRuntimeException( + "Failed to create and authenticate Backroll client, please check the settings."); + } else { + throw new ServerApiException(ApiErrorCode.UNAUTHORIZED, + "Backroll API call unauthorized, please ask your administrator to fix integration issues."); + } } + } catch (final IOException e) { + throw new CloudRuntimeException("Failed to authenticate Backroll API service due to:" + e.getMessage()); + } catch (JSONException e) { + e.printStackTrace(); } - logger.debug("Backroll client - end login"); } - private List getBackrollBackups(final String vmId) throws JsonMappingException, - JsonProcessingException, ParseException, IOException, NotOkBodyException, InterruptedException { + private List getBackrollBackups(final String vmId) { + try { + logger.info("start to list Backroll backups for vm {}", vmId); + String urlToRequest = this + .parse(okBody(get("/virtualmachines/" + vmId + "/backups"))).location + .replace("/api/v1", ""); + logger.debug(urlToRequest); + BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest); - logger.info("start to list Backroll backups for vm {}", vmId); - String urlToRequest = this - .parse(okBody(get("/virtualmachines/" + vmId + "/backups"))).location - .replace("/api/v1", ""); - logger.debug(urlToRequest); - BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest); - - final List backups = new ArrayList<>(); - for (final BackrollArchiveResponse archive : backrollBackupsFromVMResponse.archives.archives) { - backups.add(new BackrollBackup(archive.name)); - logger.debug(archive.name); + final List backups = new ArrayList<>(); + for (final BackrollArchiveResponse archive : backrollBackupsFromVMResponse.archives.archives) { + backups.add(new BackrollBackup(archive.name)); + logger.debug(archive.name); + } + return backups; + } catch (final NotOkBodyException e) { + throw new CloudRuntimeException("Failed to retrieve backups for this VM via Backroll"); + } catch (final IOException e) { + logger.error("Failed to list backup form vm with Backroll due to: {}", e); + } catch (InterruptedException e) { + logger.error("Backroll Error: {}", e); } - return backups; + return new ArrayList(); } }