*
@@ -150,7 +150,7 @@ export default {
selectedAccounts: [],
selectedProjects: [],
selectedAccountsList: '',
- selectedOperation: this.$t('label.add'),
+ selectedOperation: 'add',
selectedShareWith: this.$t('label.account'),
accountError: false,
projectError: false,
@@ -163,7 +163,7 @@ export default {
accountsList () {
return this.accounts.length > 0 ? this.accounts
.filter(a =>
- this.selectedOperation === this.$t('label.add')
+ this.selectedOperation === 'add'
? !this.permittedAccounts.includes(a.name)
: this.permittedAccounts.includes(a.name)
) : this.accounts
@@ -171,7 +171,7 @@ export default {
projectsList () {
return this.projects > 0 ? this.projects
.filter(p =>
- this.selectedOperation === this.$t('label.add')
+ this.selectedOperation === 'add'
? !this.permittedProjects.includes(p.id)
: this.permittedProjects.includes(p.id)
) : this.projects
@@ -252,7 +252,7 @@ export default {
})
},
handleChange (selectedItems) {
- if (this.selectedOperation === this.$t('label.add') || this.selectedOperation === this.$t('label.remove')) {
+ if (this.selectedOperation === 'add' || this.selectedOperation === 'remove') {
if (this.selectedShareWith === this.$t('label.account')) {
this.selectedAccounts = selectedItems
} else {
From 50a993c4866dcbe88f7a42e458a5187cac5e554b Mon Sep 17 00:00:00 2001
From: Matthias Dhellin
Date: Mon, 7 Oct 2024 12:25:42 +0200
Subject: [PATCH 13/57] Factorized duplicated code
---
.../backup/backroll/BackrollClient.java | 254 ++++++++----------
1 file changed, 114 insertions(+), 140 deletions(-)
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 926c3899e537..12a3e0da69b4 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
@@ -59,6 +59,7 @@
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.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpDelete;
@@ -81,7 +82,9 @@
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.nio.TrustAllManager;
-
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class BackrollClient {
@@ -138,17 +141,9 @@ public String startBackupJob(final String jobId) {
try {
loginIfAuthenticationFailed();
-
- final HttpResponse response = post(String.format("/tasks/singlebackup/%s", jobId), null);
- if (isResponseOk(response)) {
- HttpEntity body = response.getEntity();
- String bodyStr = EntityUtils.toString(body);
- BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollTaskRequestResponse.class);
- String idBackupTask = backupTaskRequestResponse.location.replace("/api/v1/status/", "");
- EntityUtils.consumeQuietly(response.getEntity());
- return idBackupTask;
- }
- } catch (final IOException e) {
+ return this.ok(
+ post(String.format("/tasks/singlebackup/%s", jobId), null)).location.replace("/api/v1/status/", "");
+ } catch (final Exception e) {
LOG.error("Failed to start Backroll backup job due to: {}", e.getMessage());
}
return null;
@@ -160,17 +155,8 @@ public String getBackupOfferingUrl() {
loginIfAuthenticationFailed();
try {
-
- final HttpResponse backupPoliciesRequestResponse = get("/backup_policies");
-
- if (isResponseOk(backupPoliciesRequestResponse)) {
- HttpEntity body = backupPoliciesRequestResponse.getEntity();
- String bodyStr = EntityUtils.toString(body);
- BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollTaskRequestResponse.class);
- EntityUtils.consumeQuietly(backupPoliciesRequestResponse.getEntity());
- return backupTaskRequestResponse.location.replace("/api/v1", "");
- }
- } catch (final IOException e) {
+ return this.ok(get("/backup_policies")).location.replace("/api/v1", "");
+ } catch (final Exception e) {
LOG.error("Failed to list Backroll jobs due to: {}", e.getMessage());
}
return null;
@@ -184,14 +170,15 @@ public List getBackupOfferings(String idTask) {
try {
String bodyStr = waitForGetRequestResponse(idTask);
- BackupPoliciesResponse backupPoliciesResponse = new ObjectMapper().readValue(bodyStr, BackupPoliciesResponse.class);
+ BackupPoliciesResponse backupPoliciesResponse = new ObjectMapper().readValue(bodyStr,
+ BackupPoliciesResponse.class);
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) {
+ } catch (final IOException | InterruptedException e) {
LOG.error("Failed to list Backroll jobs due to: {}", e.getMessage());
}
return new ArrayList();
@@ -214,32 +201,24 @@ public boolean restoreVMFromBackup(final String vmId, final String backupName) {
LOG.error("Backroll Error: {}", e.getMessage());
}
- final HttpResponse response = post(String.format("/tasks/restore/%s", vmId), jsonBody);
- LOG.debug(response.toString());
-
- if (isResponseOk(response)) {
- HttpEntity body = response.getEntity();
- String bodyStr = EntityUtils.toString(body);
- LOG.debug(bodyStr);
-
- BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollTaskRequestResponse.class);
- String urlToRequest = backupTaskRequestResponse.location.replace("/api/v1", "");
- EntityUtils.consumeQuietly(response.getEntity());
+ String urlToRequest = this
+ .ok(post(String.format("/tasks/restore/%s", vmId), jsonBody)).location
+ .replace("/api/v1", "");
- String responseStatus = waitForGetRequestResponse(urlToRequest);
- LOG.debug("RESTORE {}", responseStatus);
- if(responseStatus.contains("SUCCESS")) {
- LOG.debug("RESTORE SUCCESS");
- return true;
- } else {
- return false;
- }
+ String responseStatus = waitForGetRequestResponse(urlToRequest);
+ LOG.debug("RESTORE {}", responseStatus);
+ if (responseStatus.contains("SUCCESS")) {
+ LOG.debug("RESTORE SUCCESS");
+ return true;
+ } else {
+ return false;
}
+ } catch (final NotOkException e) {
+ return false;
} catch (final IOException | InterruptedException e) {
LOG.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());
}
- return false;
}
public BackrollTaskStatus checkBackupTaskStatus(String taskId) {
@@ -257,11 +236,13 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId) {
String bodyStr = EntityUtils.toString(body);
if (bodyStr.contains("FAILURE") || bodyStr.contains("PENDING")) {
- BackrollBackupStatusResponse backupStatusRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollBackupStatusResponse.class);
+ BackrollBackupStatusResponse backupStatusRequestResponse = new ObjectMapper().readValue(bodyStr,
+ BackrollBackupStatusResponse.class);
EntityUtils.consumeQuietly(backupStatusResponse.getEntity());
status.setState(backupStatusRequestResponse.state);
} else {
- BackrollBackupStatusSuccessResponse backupStatusSuccessRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollBackupStatusSuccessResponse.class);
+ BackrollBackupStatusSuccessResponse backupStatusSuccessRequestResponse = new ObjectMapper()
+ .readValue(bodyStr, BackrollBackupStatusSuccessResponse.class);
EntityUtils.consumeQuietly(backupStatusResponse.getEntity());
status.setState(backupStatusSuccessRequestResponse.state);
status.setInfo(backupStatusSuccessRequestResponse.info);
@@ -270,7 +251,8 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId) {
return status;
} else {
EntityUtils.consumeQuietly(backupStatusResponse.getEntity());
- // throw new CloudRuntimeException("Failed to retrieve backups status for this VM via Backroll");
+ // throw new CloudRuntimeException("Failed to retrieve backups status for this
+ // VM via Backroll");
LOG.error("Failed to retrieve backups status for this VM via Backroll");
}
} catch (final IOException e) {
@@ -285,30 +267,21 @@ public boolean deleteBackup(final String vmId, final String backupName) {
loginIfAuthenticationFailed();
try {
- final HttpResponse response = delete(String.format("/virtualmachines/%s/backups/%s", vmId, backupName));
- LOG.debug(response.toString());
- if (isResponseOk(response)) {
- HttpEntity body = response.getEntity();
- String bodyStr = EntityUtils.toString(body);
- LOG.debug(bodyStr);
- BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollTaskRequestResponse.class);
- String urlToRequest = backupTaskRequestResponse.location.replace("/api/v1", "");
- EntityUtils.consumeQuietly(response.getEntity());
-
- String responseStatus = waitForGetRequestResponse(urlToRequest);
- LOG.debug(responseStatus);
- BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = new ObjectMapper().readValue(responseStatus, BackrollBackupsFromVMResponse.class);
- if (backrollBackupsFromVMResponse.state.equals("SUCCESS")) {
- EntityUtils.consumeQuietly(response.getEntity());
- return true;
- } else {
- EntityUtils.consumeQuietly(response.getEntity());
- return false;
- }
+ String urlToRequest = this.ok(delete(
+ String.format("/virtualmachines/%s/backups/%s", vmId, backupName))).location.replace("/api/v1", "");
+
+ String responseStatus = waitForGetRequestResponse(urlToRequest);
+ LOG.debug(responseStatus);
+ BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = new ObjectMapper()
+ .readValue(responseStatus, BackrollBackupsFromVMResponse.class);
+ if (backrollBackupsFromVMResponse.state.equals("SUCCESS")) {
+ return true;
+ } else {
+ return false;
}
- EntityUtils.consumeQuietly(response.getEntity());
+ } catch (final NotOkException e) {
return false;
- } catch (final IOException | InterruptedException e) {
+ } catch (final Exception e) {
LOG.error("Failed to delete backup using Backroll due to: {}", e.getMessage());
}
return false;
@@ -319,44 +292,36 @@ public Metric getVirtualMachineMetrics(final String vmId) {
loginIfAuthenticationFailed();
- Metric metric = new Metric(0L,0L);
+ Metric metric = new Metric(0L, 0L);
try {
- final HttpResponse metricsRequestResponse = get(String.format("/virtualmachines/%s/repository", vmId));
+ String urlToRequest = this.ok(
+ get(String.format("/virtualmachines/%s/repository", vmId))).location.replace("/api/v1", "");
+ LOG.debug(urlToRequest);
- if (isResponseOk(metricsRequestResponse)) {
- HttpEntity body = metricsRequestResponse.getEntity();
- String bodyStr = EntityUtils.toString(body);
- LOG.debug(bodyStr);
- BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollTaskRequestResponse.class);
- String urlToRequest = backupTaskRequestResponse.location.replace("/api/v1", "");
- LOG.debug(urlToRequest);
- EntityUtils.consumeQuietly(metricsRequestResponse.getEntity());
- bodyStr = waitForGetRequestResponse(urlToRequest);
- LOG.debug(bodyStr);
+ String bodyStr = waitForGetRequestResponse(urlToRequest);
+ LOG.debug(bodyStr);
- BackrollVmMetricsResponse vmMetricsResponse = new ObjectMapper().readValue(bodyStr, BackrollVmMetricsResponse.class);
+ BackrollVmMetricsResponse vmMetricsResponse = new ObjectMapper().readValue(bodyStr,
+ BackrollVmMetricsResponse.class);
- if (vmMetricsResponse != null) {
+ if (vmMetricsResponse != null) {
- if (vmMetricsResponse.state.equals("SUCCESS")) {
- LOG.debug("SUCCESS ok");
- if (vmMetricsResponse.infos != null) {
- if (vmMetricsResponse.infos.cache != null) {
- if (vmMetricsResponse.infos.cache.stats != null) {
- CacheStats stats = vmMetricsResponse.infos.cache.stats;
- long size = Long.parseLong(stats.totalSize);
- return new Metric(size,size);
- }
+ if (vmMetricsResponse.state.equals("SUCCESS")) {
+ LOG.debug("SUCCESS ok");
+ if (vmMetricsResponse.infos != null) {
+ if (vmMetricsResponse.infos.cache != null) {
+ if (vmMetricsResponse.infos.cache.stats != null) {
+ CacheStats stats = vmMetricsResponse.infos.cache.stats;
+ long size = Long.parseLong(stats.totalSize);
+ return new Metric(size, size);
}
}
}
}
-
- EntityUtils.consumeQuietly(metricsRequestResponse.getEntity());
}
- } catch (final IOException | InterruptedException e) {
+ } catch (final Exception e) {
LOG.error("Failed to retrieve virtual machine metrics with Backroll due to: {}", e.getMessage());
}
@@ -369,28 +334,22 @@ public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) {
loginIfAuthenticationFailed();
try {
- final HttpResponse backupMetricsResponse = get(String.format("/virtualmachines/%s/backups/%s", vmId, backupId));
- if (isResponseOk(backupMetricsResponse)) {
- HttpEntity body = backupMetricsResponse.getEntity();
- String bodyStr = EntityUtils.toString(body);
+ String urlToRequest = this.ok(get(
+ String.format("/virtualmachines/%s/backups/%s", vmId, backupId))).location.replace("/api/v1", "");
+ LOG.debug(urlToRequest);
- BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollTaskRequestResponse.class);
- String urlToRequest = backupTaskRequestResponse.location.replace("/api/v1", "");
- LOG.debug(urlToRequest);
- EntityUtils.consumeQuietly(backupMetricsResponse.getEntity());
- bodyStr = waitForGetRequestResponse(urlToRequest);
- LOG.debug(bodyStr);
+ String bodyStr = waitForGetRequestResponse(urlToRequest);
+ LOG.debug(bodyStr);
- BackrollBackupMetricsResponse metrics = new ObjectMapper().readValue(bodyStr, BackrollBackupMetricsResponse.class);
- EntityUtils.consumeQuietly(backupMetricsResponse.getEntity());
- if (metrics.info != null) {
- return new BackrollBackupMetrics(Long.parseLong(metrics.info.originalSize), Long.parseLong(metrics.info.deduplicatedSize));
- }
- } else {
- EntityUtils.consumeQuietly(backupMetricsResponse.getEntity());
- throw new CloudRuntimeException("Failed to retrieve backups status for this VM via Backroll");
+ BackrollBackupMetricsResponse metrics = new ObjectMapper().readValue(bodyStr,
+ BackrollBackupMetricsResponse.class);
+ if (metrics.info != null) {
+ return new BackrollBackupMetrics(Long.parseLong(metrics.info.originalSize),
+ Long.parseLong(metrics.info.deduplicatedSize));
}
+ } catch (final NotOkException e) {
+ throw new CloudRuntimeException("Failed to retrieve backups status for this VM via Backroll");
} catch (final IOException | InterruptedException e) {
LOG.error("Failed to check backups status due to: {}", e.getMessage());
}
@@ -403,33 +362,27 @@ public List getAllBackupsfromVirtualMachine(String vmId) {
List backups = new ArrayList();
try {
- HttpResponse backupsResponse = get(String.format("/virtualmachines/%s/backups", vmId));
-
- if (isResponseOk(backupsResponse)) {
- HttpEntity body = backupsResponse.getEntity();
- String bodyStr = EntityUtils.toString(body);
- BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollTaskRequestResponse.class);
- String urlToRequest = backupTaskRequestResponse.location.replace("/api/v1", "");
- LOG.debug(urlToRequest);
- EntityUtils.consumeQuietly(backupsResponse.getEntity());
+ String urlToRequest = this
+ .ok(get(String.format("/virtualmachines/%s/backups", vmId))).location
+ .replace("/api/v1", "");
+ LOG.debug(urlToRequest);
- bodyStr = waitForGetRequestResponse(urlToRequest);
+ String bodyStr = waitForGetRequestResponse(urlToRequest);
- VirtualMachineBackupsResponse response = new ObjectMapper().readValue(bodyStr, VirtualMachineBackupsResponse.class);
- EntityUtils.consumeQuietly(backupsResponse.getEntity());
+ VirtualMachineBackupsResponse response = new ObjectMapper().readValue(bodyStr,
+ VirtualMachineBackupsResponse.class);
- if (response.state.equals("SUCCESS")) {
- if (response.info.archives.size() > 0) {
- for (BackupInfos infos : response.info.archives) {
- var dateStart = new DateTime(infos.start);
- backups.add(new BackrollVmBackup(infos.id, infos.name, dateStart.toDate()));
- }
+ if (response.state.equals("SUCCESS")) {
+ if (response.info.archives.size() > 0) {
+ for (BackupInfos infos : response.info.archives) {
+ var dateStart = new DateTime(infos.start);
+ backups.add(new BackrollVmBackup(infos.id, infos.name, dateStart.toDate()));
}
}
}
- } catch (IOException | InterruptedException e) {
+ } catch (Exception e) {
e.printStackTrace();
}
@@ -484,7 +437,7 @@ protected HttpResponse delete(final String path) throws IOException {
private boolean isResponseOk(final HttpResponse response) {
if ((response.getStatusLine().getStatusCode() == HttpStatus.SC_OK ||
- response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED)) {
+ response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED)) {
return true;
} else {
return false;
@@ -492,18 +445,37 @@ private boolean isResponseOk(final HttpResponse response) {
}
private boolean isResponseAuthorized(final HttpResponse response) {
- return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK || response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED;
+ return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK
+ || response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED;
+ }
+
+ private class NotOkException extends Exception {
+ }
+
+ private T ok(final HttpResponse response)
+ throws ParseException, IOException, JsonMappingException, JsonProcessingException, NotOkException {
+ switch (response.getStatusLine().getStatusCode()) {
+ case HttpStatus.SC_OK:
+ case HttpStatus.SC_ACCEPTED:
+ HttpEntity bodyEntity = response.getEntity();
+ String bodyString = EntityUtils.toString(bodyEntity); // TODO try and finally close resource ?
+ EntityUtils.consumeQuietly(bodyEntity);
+ return new ObjectMapper().readValue(bodyString, new TypeReference() {
+ });
+ default:
+ throw new NotOkException();
+ }
}
private String waitForGetRequestResponse(String urlToRequest) throws IOException, InterruptedException {
HttpEntity body;
String bodyStr = "";
int cpt = 0;
- //int threshold = 30; // 5 minutes
+ // int threshold = 30; // 5 minutes
int threshold = 12; // 2 minutes
do {
- if (cpt == threshold){
+ if (cpt == threshold) {
break;
} else {
final HttpResponse response = get(urlToRequest);
@@ -523,7 +495,7 @@ private String waitForGetRequestResponse(String urlToRequest) throws IOException
} while (bodyStr.contains("PENDING"));
- if (cpt == threshold){
+ if (cpt == threshold) {
bodyStr = "ERROR";
}
@@ -605,13 +577,15 @@ private List getBackrollBackups(final String vmId) {
if (isResponseOk(backupsAskingResponse)) {
HttpEntity body = backupsAskingResponse.getEntity();
String bodyStr = EntityUtils.toString(body);
- BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr, BackrollTaskRequestResponse.class);
+ BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr,
+ BackrollTaskRequestResponse.class);
String urlToRequest = backupTaskRequestResponse.location.replace("/api/v1", "");
LOG.debug(urlToRequest);
EntityUtils.consumeQuietly(backupsAskingResponse.getEntity());
bodyStr = waitForGetRequestResponse(urlToRequest);
LOG.debug(bodyStr);
- BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = new ObjectMapper().readValue(bodyStr, BackrollBackupsFromVMResponse.class);
+ BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = new ObjectMapper().readValue(bodyStr,
+ BackrollBackupsFromVMResponse.class);
final List backups = new ArrayList<>();
for (final BackrollArchiveResponse archive : backrollBackupsFromVMResponse.archives.archives) {
From 63bdc0ffa234ef466297a75e7f26739578603982 Mon Sep 17 00:00:00 2001
From: Matthias Dhellin
Date: Mon, 7 Oct 2024 16:57:27 +0200
Subject: [PATCH 14/57] Factorized duplicated code
---
.../backup/backroll/BackrollClient.java | 243 +++++++-----------
.../model/response/StateResponse.java | 24 ++
.../archive/BackrollArchiveResponse.java | 1 +
.../virtualMachineBackups/BackupInfos.java | 1 +
4 files changed, 116 insertions(+), 153 deletions(-)
create mode 100644 plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/StateResponse.java
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 12a3e0da69b4..2634dcd13d55 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
@@ -39,6 +39,7 @@
import org.apache.cloudstack.backup.backroll.model.BackrollTaskStatus;
import org.apache.cloudstack.backup.backroll.model.BackrollVmBackup;
import org.apache.cloudstack.backup.backroll.model.response.BackrollTaskRequestResponse;
+import org.apache.cloudstack.backup.backroll.model.response.StateResponse;
import org.apache.cloudstack.backup.backroll.model.response.api.LoginApiResponse;
import org.apache.cloudstack.backup.backroll.model.response.archive.BackrollArchiveResponse;
import org.apache.cloudstack.backup.backroll.model.response.archive.BackrollBackupsFromVMResponse;
@@ -141,8 +142,9 @@ public String startBackupJob(final String jobId) {
try {
loginIfAuthenticationFailed();
- return this.ok(
- post(String.format("/tasks/singlebackup/%s", jobId), null)).location.replace("/api/v1/status/", "");
+ return this.parse(okBody(
+ post(String.format("/tasks/singlebackup/%s", jobId), null))).location
+ .replace("/api/v1/status/", "");
} catch (final Exception e) {
LOG.error("Failed to start Backroll backup job due to: {}", e.getMessage());
}
@@ -155,7 +157,8 @@ public String getBackupOfferingUrl() {
loginIfAuthenticationFailed();
try {
- return this.ok(get("/backup_policies")).location.replace("/api/v1", "");
+ return this.parse(okBody(get("/backup_policies"))).location.replace("/api/v1",
+ "");
} catch (final Exception e) {
LOG.error("Failed to list Backroll jobs due to: {}", e.getMessage());
}
@@ -168,10 +171,7 @@ public List getBackupOfferings(String idTask) {
loginIfAuthenticationFailed();
try {
- String bodyStr = waitForGetRequestResponse(idTask);
-
- BackupPoliciesResponse backupPoliciesResponse = new ObjectMapper().readValue(bodyStr,
- BackupPoliciesResponse.class);
+ BackupPoliciesResponse backupPoliciesResponse = waitGet(idTask);
final List policies = new ArrayList<>();
for (final BackrollBackupPolicyResponse policy : backupPoliciesResponse.backupPolicies) {
@@ -202,18 +202,14 @@ public boolean restoreVMFromBackup(final String vmId, final String backupName) {
}
String urlToRequest = this
- .ok(post(String.format("/tasks/restore/%s", vmId), jsonBody)).location
+ .parse(okBody(
+ post(String.format("/tasks/restore/%s", vmId), jsonBody))).location
.replace("/api/v1", "");
- String responseStatus = waitForGetRequestResponse(urlToRequest);
- LOG.debug("RESTORE {}", responseStatus);
- if (responseStatus.contains("SUCCESS")) {
- LOG.debug("RESTORE SUCCESS");
- return true;
- } else {
- return false;
- }
- } catch (final NotOkException e) {
+ StateResponse response = waitGet(urlToRequest);
+ LOG.debug("RESTORE {}", response.state);
+ return response.state.equals("SUCCESS");
+ } catch (final NotOkBodyException e) {
return false;
} catch (final IOException | InterruptedException e) {
LOG.error("Ouch! Failed to restore VM with Backroll due to: {}", e.getMessage());
@@ -227,34 +223,26 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId) {
loginIfAuthenticationFailed();
try {
- final HttpResponse backupStatusResponse = get("/status/" + taskId);
+ BackrollTaskStatus status = new BackrollTaskStatus();
- if (isResponseOk(backupStatusResponse)) {
- BackrollTaskStatus status = new BackrollTaskStatus();
+ String body = okBody(get("/status/" + taskId));
- HttpEntity body = backupStatusResponse.getEntity();
- String bodyStr = EntityUtils.toString(body);
-
- if (bodyStr.contains("FAILURE") || bodyStr.contains("PENDING")) {
- BackrollBackupStatusResponse backupStatusRequestResponse = new ObjectMapper().readValue(bodyStr,
- BackrollBackupStatusResponse.class);
- EntityUtils.consumeQuietly(backupStatusResponse.getEntity());
- status.setState(backupStatusRequestResponse.state);
- } else {
- BackrollBackupStatusSuccessResponse backupStatusSuccessRequestResponse = new ObjectMapper()
- .readValue(bodyStr, BackrollBackupStatusSuccessResponse.class);
- EntityUtils.consumeQuietly(backupStatusResponse.getEntity());
- status.setState(backupStatusSuccessRequestResponse.state);
- status.setInfo(backupStatusSuccessRequestResponse.info);
- }
-
- return status;
+ if (body.contains("FAILURE") || body.contains("PENDING")) {
+ BackrollBackupStatusResponse backupStatusRequestResponse = parse(body);
+ status.setState(backupStatusRequestResponse.state);
} else {
- EntityUtils.consumeQuietly(backupStatusResponse.getEntity());
- // throw new CloudRuntimeException("Failed to retrieve backups status for this
- // VM via Backroll");
- LOG.error("Failed to retrieve backups status for this VM via Backroll");
+ 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");
+ LOG.error("Failed to retrieve backups status for this VM via Backroll");
+
} catch (final IOException e) {
LOG.error("Failed to check backups status due to: {}", e.getMessage());
}
@@ -267,19 +255,14 @@ public boolean deleteBackup(final String vmId, final String backupName) {
loginIfAuthenticationFailed();
try {
- String urlToRequest = this.ok(delete(
- String.format("/virtualmachines/%s/backups/%s", vmId, backupName))).location.replace("/api/v1", "");
-
- String responseStatus = waitForGetRequestResponse(urlToRequest);
- LOG.debug(responseStatus);
- BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = new ObjectMapper()
- .readValue(responseStatus, BackrollBackupsFromVMResponse.class);
- if (backrollBackupsFromVMResponse.state.equals("SUCCESS")) {
- return true;
- } else {
- return false;
- }
- } catch (final NotOkException e) {
+ String urlToRequest = this.parse(okBody(delete(
+ String.format("/virtualmachines/%s/backups/%s", vmId, backupName)))).location
+ .replace("/api/v1", "");
+
+ BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
+ LOG.debug(backrollBackupsFromVMResponse.state);
+ return backrollBackupsFromVMResponse.state.equals("SUCCESS");
+ } catch (final NotOkBodyException e) {
return false;
} catch (final Exception e) {
LOG.error("Failed to delete backup using Backroll due to: {}", e.getMessage());
@@ -296,18 +279,13 @@ public Metric getVirtualMachineMetrics(final String vmId) {
try {
- String urlToRequest = this.ok(
- get(String.format("/virtualmachines/%s/repository", vmId))).location.replace("/api/v1", "");
+ String urlToRequest = this.parse(okBody(
+ get(String.format("/virtualmachines/%s/repository", vmId)))).location.replace("/api/v1", "");
LOG.debug(urlToRequest);
- String bodyStr = waitForGetRequestResponse(urlToRequest);
- LOG.debug(bodyStr);
-
- BackrollVmMetricsResponse vmMetricsResponse = new ObjectMapper().readValue(bodyStr,
- BackrollVmMetricsResponse.class);
+ BackrollVmMetricsResponse vmMetricsResponse = waitGet(urlToRequest);
if (vmMetricsResponse != null) {
-
if (vmMetricsResponse.state.equals("SUCCESS")) {
LOG.debug("SUCCESS ok");
if (vmMetricsResponse.infos != null) {
@@ -335,20 +313,16 @@ public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) {
try {
- String urlToRequest = this.ok(get(
- String.format("/virtualmachines/%s/backups/%s", vmId, backupId))).location.replace("/api/v1", "");
+ String urlToRequest = this.parse(okBody(get(
+ String.format("/virtualmachines/%s/backups/%s", vmId, backupId)))).location.replace("/api/v1", "");
LOG.debug(urlToRequest);
- String bodyStr = waitForGetRequestResponse(urlToRequest);
- LOG.debug(bodyStr);
-
- BackrollBackupMetricsResponse metrics = new ObjectMapper().readValue(bodyStr,
- BackrollBackupMetricsResponse.class);
+ BackrollBackupMetricsResponse metrics = waitGet(urlToRequest);
if (metrics.info != null) {
return new BackrollBackupMetrics(Long.parseLong(metrics.info.originalSize),
Long.parseLong(metrics.info.deduplicatedSize));
}
- } catch (final NotOkException e) {
+ } catch (final NotOkBodyException e) {
throw new CloudRuntimeException("Failed to retrieve backups status for this VM via Backroll");
} catch (final IOException | InterruptedException e) {
LOG.error("Failed to check backups status due to: {}", e.getMessage());
@@ -364,14 +338,12 @@ public List getAllBackupsfromVirtualMachine(String vmId) {
try {
String urlToRequest = this
- .ok(get(String.format("/virtualmachines/%s/backups", vmId))).location
+ .parse(okBody(
+ get(String.format("/virtualmachines/%s/backups", vmId)))).location
.replace("/api/v1", "");
LOG.debug(urlToRequest);
- String bodyStr = waitForGetRequestResponse(urlToRequest);
-
- VirtualMachineBackupsResponse response = new ObjectMapper().readValue(bodyStr,
- VirtualMachineBackupsResponse.class);
+ VirtualMachineBackupsResponse response = waitGet(urlToRequest);
if (response.state.equals("SUCCESS")) {
if (response.info.archives.size() > 0) {
@@ -435,71 +407,54 @@ protected HttpResponse delete(final String path) throws IOException {
return response;
}
- private boolean isResponseOk(final HttpResponse response) {
- if ((response.getStatusLine().getStatusCode() == HttpStatus.SC_OK ||
- response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED)) {
- return true;
- } else {
- return false;
- }
- }
-
private boolean isResponseAuthorized(final HttpResponse response) {
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK
|| response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED;
}
- private class NotOkException extends Exception {
+ private class NotOkBodyException extends Exception {
}
- private T ok(final HttpResponse response)
- throws ParseException, IOException, JsonMappingException, JsonProcessingException, NotOkException {
+ private String okBody(final HttpResponse response)
+ throws ParseException, IOException, NotOkBodyException {
switch (response.getStatusLine().getStatusCode()) {
case HttpStatus.SC_OK:
case HttpStatus.SC_ACCEPTED:
HttpEntity bodyEntity = response.getEntity();
- String bodyString = EntityUtils.toString(bodyEntity); // TODO try and finally close resource ?
- EntityUtils.consumeQuietly(bodyEntity);
- return new ObjectMapper().readValue(bodyString, new TypeReference() {
- });
+ try {
+ return EntityUtils.toString(bodyEntity);
+ } finally {
+ EntityUtils.consumeQuietly(bodyEntity);
+ }
default:
- throw new NotOkException();
+ throw new NotOkBodyException();
}
}
- private String waitForGetRequestResponse(String urlToRequest) throws IOException, InterruptedException {
- HttpEntity body;
- String bodyStr = "";
- int cpt = 0;
+ private T parse(final String json)
+ throws JsonMappingException, JsonProcessingException {
+ return new ObjectMapper().readValue(json, new TypeReference() {
+ });
+ }
+
+ private T waitGet(String url)
+ throws IOException, InterruptedException {
// int threshold = 30; // 5 minutes
- int threshold = 12; // 2 minutes
+ int maxAttempts = 12; // 2 minutes
- do {
- if (cpt == threshold) {
- break;
- } else {
- final HttpResponse response = get(urlToRequest);
- LOG.debug("Backroll!!! {}", response);
- if (isResponseOk(response)) {
-
- body = response.getEntity();
- bodyStr = EntityUtils.toString(body);
- LOG.debug(bodyStr);
- EntityUtils.consumeQuietly(response.getEntity());
- } else {
- throw new CloudRuntimeException("An error occured with Backroll");
+ for (int attempt = 1; attempt <= maxAttempts; attempt++) {
+ try {
+ String body = okBody(get(url));
+ if (!body.contains("PENDING")) {
+ return parse(body);
}
- cpt++;
- TimeUnit.SECONDS.sleep(10);
+ } catch (final NotOkBodyException e) {
+ throw new CloudRuntimeException("An error occured with Backroll");
}
-
- } while (bodyStr.contains("PENDING"));
-
- if (cpt == threshold) {
- bodyStr = "ERROR";
+ TimeUnit.SECONDS.sleep(10);
}
- return bodyStr;
+ return null;
}
private boolean isAuthenticated() {
@@ -536,22 +491,15 @@ private void login(final String appname, final String appsecret) {
request.setEntity(params);
final HttpResponse response = httpClient.execute(request);
-
- if (isResponseOk(response)) {
- HttpEntity body = response.getEntity();
- String bodyStr = EntityUtils.toString(body);
-
- LoginApiResponse loginResponse = new ObjectMapper().readValue(bodyStr, LoginApiResponse.class);
+ try {
+ LoginApiResponse loginResponse = parse(okBody(response));
backrollToken = loginResponse.accessToken;
LOG.debug("Backroll client - Token : {}", backrollToken);
- EntityUtils.consumeQuietly(response.getEntity());
-
if (StringUtils.isEmpty(loginResponse.accessToken)) {
throw new CloudRuntimeException("Backroll token is not available to perform API requests");
}
- } else {
- EntityUtils.consumeQuietly(response.getEntity());
+ } 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.");
@@ -560,7 +508,6 @@ private void login(final String appname, final String appsecret) {
"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) {
@@ -572,30 +519,20 @@ private void login(final String appname, final String appsecret) {
private List getBackrollBackups(final String vmId) {
try {
LOG.info("start to list Backroll backups for vm {}", vmId);
- final HttpResponse backupsAskingResponse = get("/virtualmachines/" + vmId + "/backups");
-
- if (isResponseOk(backupsAskingResponse)) {
- HttpEntity body = backupsAskingResponse.getEntity();
- String bodyStr = EntityUtils.toString(body);
- BackrollTaskRequestResponse backupTaskRequestResponse = new ObjectMapper().readValue(bodyStr,
- BackrollTaskRequestResponse.class);
- String urlToRequest = backupTaskRequestResponse.location.replace("/api/v1", "");
- LOG.debug(urlToRequest);
- EntityUtils.consumeQuietly(backupsAskingResponse.getEntity());
- bodyStr = waitForGetRequestResponse(urlToRequest);
- LOG.debug(bodyStr);
- BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = new ObjectMapper().readValue(bodyStr,
- BackrollBackupsFromVMResponse.class);
-
- final List backups = new ArrayList<>();
- for (final BackrollArchiveResponse archive : backrollBackupsFromVMResponse.archives.archives) {
- backups.add(new BackrollBackup(archive.name));
- LOG.debug(archive.name);
- }
- return backups;
- } else {
- throw new CloudRuntimeException("Failed to retrieve backups for this VM via Backroll");
+ String urlToRequest = this
+ .parse(okBody(get("/virtualmachines/" + vmId + "/backups"))).location
+ .replace("/api/v1", "");
+ LOG.debug(urlToRequest);
+ BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
+
+ final List backups = new ArrayList<>();
+ for (final BackrollArchiveResponse archive : backrollBackupsFromVMResponse.archives.archives) {
+ backups.add(new BackrollBackup(archive.name));
+ LOG.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) {
LOG.error("Failed to list backup form vm with Backroll due to: {}", e);
} catch (InterruptedException e) {
diff --git a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/StateResponse.java b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/StateResponse.java
new file mode 100644
index 000000000000..67694eac932d
--- /dev/null
+++ b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/StateResponse.java
@@ -0,0 +1,24 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.backup.backroll.model.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class StateResponse {
+ @JsonProperty("state")
+ public String state;
+}
diff --git a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/archive/BackrollArchiveResponse.java b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/archive/BackrollArchiveResponse.java
index 98b706db4df6..92c2f1c927ba 100644
--- a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/archive/BackrollArchiveResponse.java
+++ b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/archive/BackrollArchiveResponse.java
@@ -24,6 +24,7 @@ public class BackrollArchiveResponse {
@JsonProperty("archive")
public String archive;
+ // TODO Merged typo ?
@JsonProperty("barchive")
public String barchive;
diff --git a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/metrics/virtualMachineBackups/BackupInfos.java b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/metrics/virtualMachineBackups/BackupInfos.java
index b31213c02df0..87d9a7269b18 100644
--- a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/metrics/virtualMachineBackups/BackupInfos.java
+++ b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/metrics/virtualMachineBackups/BackupInfos.java
@@ -22,6 +22,7 @@ public class BackupInfos {
@JsonProperty("archive")
public String archive;
+ // TODO Merged typo ?
@JsonProperty("barchive")
public String barchive;
From e4b212f30ef00a779fcad13aa35067d696601d6b Mon Sep 17 00:00:00 2001
From: Matthias Dhellin
Date: Mon, 7 Oct 2024 17:17:17 +0200
Subject: [PATCH 15/57] Extracted string constants
---
.../backup/backroll/BackrollClient.java | 17 +++++++++--------
.../backroll/model/response/TaskState.java | 7 +++++++
...tateResponse.java => TaskStateResponse.java} | 2 +-
3 files changed, 17 insertions(+), 9 deletions(-)
create mode 100644 plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/TaskState.java
rename plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/{StateResponse.java => TaskStateResponse.java} (96%)
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 2634dcd13d55..fe462830853c 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
@@ -39,7 +39,8 @@
import org.apache.cloudstack.backup.backroll.model.BackrollTaskStatus;
import org.apache.cloudstack.backup.backroll.model.BackrollVmBackup;
import org.apache.cloudstack.backup.backroll.model.response.BackrollTaskRequestResponse;
-import org.apache.cloudstack.backup.backroll.model.response.StateResponse;
+import org.apache.cloudstack.backup.backroll.model.response.TaskState;
+import org.apache.cloudstack.backup.backroll.model.response.TaskStateResponse;
import org.apache.cloudstack.backup.backroll.model.response.api.LoginApiResponse;
import org.apache.cloudstack.backup.backroll.model.response.archive.BackrollArchiveResponse;
import org.apache.cloudstack.backup.backroll.model.response.archive.BackrollBackupsFromVMResponse;
@@ -206,9 +207,9 @@ public boolean restoreVMFromBackup(final String vmId, final String backupName) {
post(String.format("/tasks/restore/%s", vmId), jsonBody))).location
.replace("/api/v1", "");
- StateResponse response = waitGet(urlToRequest);
+ TaskStateResponse response = waitGet(urlToRequest);
LOG.debug("RESTORE {}", response.state);
- return response.state.equals("SUCCESS");
+ return response.state.equals(TaskState.SUCCESS);
} catch (final NotOkBodyException e) {
return false;
} catch (final IOException | InterruptedException e) {
@@ -227,7 +228,7 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId) {
String body = okBody(get("/status/" + taskId));
- if (body.contains("FAILURE") || body.contains("PENDING")) {
+ if (body.contains(TaskState.FAILURE) || body.contains(TaskState.PENDING)) {
BackrollBackupStatusResponse backupStatusRequestResponse = parse(body);
status.setState(backupStatusRequestResponse.state);
} else {
@@ -261,7 +262,7 @@ public boolean deleteBackup(final String vmId, final String backupName) {
BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
LOG.debug(backrollBackupsFromVMResponse.state);
- return backrollBackupsFromVMResponse.state.equals("SUCCESS");
+ return backrollBackupsFromVMResponse.state.equals(TaskState.SUCCESS);
} catch (final NotOkBodyException e) {
return false;
} catch (final Exception e) {
@@ -286,7 +287,7 @@ public Metric getVirtualMachineMetrics(final String vmId) {
BackrollVmMetricsResponse vmMetricsResponse = waitGet(urlToRequest);
if (vmMetricsResponse != null) {
- if (vmMetricsResponse.state.equals("SUCCESS")) {
+ if (vmMetricsResponse.state.equals(TaskState.SUCCESS)) {
LOG.debug("SUCCESS ok");
if (vmMetricsResponse.infos != null) {
if (vmMetricsResponse.infos.cache != null) {
@@ -345,7 +346,7 @@ public List getAllBackupsfromVirtualMachine(String vmId) {
VirtualMachineBackupsResponse response = waitGet(urlToRequest);
- if (response.state.equals("SUCCESS")) {
+ if (response.state.equals(TaskState.SUCCESS)) {
if (response.info.archives.size() > 0) {
for (BackupInfos infos : response.info.archives) {
var dateStart = new DateTime(infos.start);
@@ -445,7 +446,7 @@ private T waitGet(String url)
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
try {
String body = okBody(get(url));
- if (!body.contains("PENDING")) {
+ if (!body.contains(TaskState.PENDING)) {
return parse(body);
}
} catch (final NotOkBodyException e) {
diff --git a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/TaskState.java b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/TaskState.java
new file mode 100644
index 000000000000..e934b2ba6217
--- /dev/null
+++ b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/TaskState.java
@@ -0,0 +1,7 @@
+package org.apache.cloudstack.backup.backroll.model.response;
+
+public class TaskState {
+ public static final String PENDING = "PENDING";
+ public static final String FAILURE = "FAILURE";
+ public static final String SUCCESS = "SUCCESS";
+}
diff --git a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/StateResponse.java b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/TaskStateResponse.java
similarity index 96%
rename from plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/StateResponse.java
rename to plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/TaskStateResponse.java
index 67694eac932d..10bd25d98039 100644
--- a/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/StateResponse.java
+++ b/plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/model/response/TaskStateResponse.java
@@ -18,7 +18,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
-public class StateResponse {
+public class TaskStateResponse {
@JsonProperty("state")
public String state;
}
From 561b9b6a1ff2a4782fb693b038a609f01ef34257 Mon Sep 17 00:00:00 2001
From: Matthias Dhellin
Date: Mon, 7 Oct 2024 17:32:12 +0200
Subject: [PATCH 16/57] Refactored some null checks
---
.../backup/backroll/BackrollClient.java | 22 +++++++++----------
1 file changed, 10 insertions(+), 12 deletions(-)
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 fe462830853c..a9dc0deebdcd 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
@@ -286,18 +286,16 @@ public Metric getVirtualMachineMetrics(final String vmId) {
BackrollVmMetricsResponse vmMetricsResponse = waitGet(urlToRequest);
- if (vmMetricsResponse != null) {
- if (vmMetricsResponse.state.equals(TaskState.SUCCESS)) {
- LOG.debug("SUCCESS ok");
- if (vmMetricsResponse.infos != null) {
- if (vmMetricsResponse.infos.cache != null) {
- if (vmMetricsResponse.infos.cache.stats != null) {
- CacheStats stats = vmMetricsResponse.infos.cache.stats;
- long size = Long.parseLong(stats.totalSize);
- return new Metric(size, size);
- }
- }
- }
+ if (vmMetricsResponse != null && vmMetricsResponse.state.equals(TaskState.SUCCESS)) {
+ LOG.debug("SUCCESS ok");
+ CacheStats stats = null;
+ try {
+ stats = vmMetricsResponse.infos.cache.stats;
+ } catch (NullPointerException e) {
+ }
+ if (stats != null) {
+ long size = Long.parseLong(stats.totalSize);
+ return new Metric(size, size);
}
}
} catch (final Exception e) {
From 8e3c8f7be54c748dde38da2236b89f2745398082 Mon Sep 17 00:00:00 2001
From: Matthias Dhellin
Date: Mon, 7 Oct 2024 18:02:56 +0200
Subject: [PATCH 17/57] Naming
---
.../backup/backroll/BackrollClient.java | 80 +++++++++----------
1 file changed, 40 insertions(+), 40 deletions(-)
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 a9dc0deebdcd..e7021d4276b8 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
@@ -91,7 +91,7 @@
public class BackrollClient {
- private Logger LOG = LogManager.getLogger(BackrollClient.class);
+ private Logger logger = LogManager.getLogger(BackrollClient.class);
private int restoreTimeout;
@@ -139,7 +139,7 @@ public BackrollClient(final String url, final String appname, final String passw
}
public String startBackupJob(final String jobId) {
- LOG.info("Trying to start backup for Backroll job: {}", jobId);
+ logger.info("Trying to start backup for Backroll job: {}", jobId);
try {
loginIfAuthenticationFailed();
@@ -147,13 +147,13 @@ public String startBackupJob(final String jobId) {
post(String.format("/tasks/singlebackup/%s", jobId), null))).location
.replace("/api/v1/status/", "");
} catch (final Exception e) {
- LOG.error("Failed to start Backroll backup job due to: {}", e.getMessage());
+ logger.error("Failed to start Backroll backup job due to: {}", e.getMessage());
}
return null;
}
public String getBackupOfferingUrl() {
- LOG.info("Trying to list backroll backup policies");
+ logger.info("Trying to list backroll backup policies");
loginIfAuthenticationFailed();
@@ -161,13 +161,13 @@ public String getBackupOfferingUrl() {
return this.parse(okBody(get("/backup_policies"))).location.replace("/api/v1",
"");
} catch (final Exception e) {
- LOG.error("Failed to list Backroll jobs due to: {}", e.getMessage());
+ logger.error("Failed to list Backroll jobs due to: {}", e.getMessage());
}
return null;
}
public List getBackupOfferings(String idTask) {
- LOG.info("Trying to list backroll backup policies");
+ logger.info("Trying to list backroll backup policies");
loginIfAuthenticationFailed();
@@ -180,13 +180,13 @@ public List getBackupOfferings(String idTask) {
}
return policies;
} catch (final IOException | InterruptedException e) {
- LOG.error("Failed to list Backroll jobs due to: {}", e.getMessage());
+ logger.error("Failed to list Backroll jobs due to: {}", e.getMessage());
}
return new ArrayList();
}
public boolean restoreVMFromBackup(final String vmId, final String backupName) {
- LOG.info("Start restore backup with backroll with backup {} for vm {}", backupName, vmId);
+ logger.info("Start restore backup with backroll with backup {} for vm {}", backupName, vmId);
loginIfAuthenticationFailed();
@@ -199,7 +199,7 @@ public boolean restoreVMFromBackup(final String vmId, final String backupName) {
jsonBody.put("mode", "single");
} catch (JSONException e) {
- LOG.error("Backroll Error: {}", e.getMessage());
+ logger.error("Backroll Error: {}", e.getMessage());
}
String urlToRequest = this
@@ -208,18 +208,18 @@ public boolean restoreVMFromBackup(final String vmId, final String backupName) {
.replace("/api/v1", "");
TaskStateResponse response = waitGet(urlToRequest);
- LOG.debug("RESTORE {}", response.state);
+ logger.debug("RESTORE {}", response.state);
return response.state.equals(TaskState.SUCCESS);
} catch (final NotOkBodyException e) {
return false;
} catch (final IOException | InterruptedException e) {
- LOG.error("Ouch! Failed to restore VM with Backroll due to: {}", e.getMessage());
+ 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) {
- LOG.info("Trying to get backup status for Backroll task: {}", taskId);
+ logger.info("Trying to get backup status for Backroll task: {}", taskId);
loginIfAuthenticationFailed();
@@ -242,16 +242,16 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId) {
} catch (final NotOkBodyException e) {
// throw new CloudRuntimeException("Failed to retrieve backups status for this
// VM via Backroll");
- LOG.error("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) {
- LOG.error("Failed to check backups status due to: {}", e.getMessage());
+ logger.error("Failed to check backups status due to: {}", e.getMessage());
}
return null;
}
public boolean deleteBackup(final String vmId, final String backupName) {
- LOG.info("Trying to delete backup {} for vm {} using Backroll", vmId, backupName);
+ logger.info("Trying to delete backup {} for vm {} using Backroll", vmId, backupName);
loginIfAuthenticationFailed();
@@ -261,18 +261,18 @@ public boolean deleteBackup(final String vmId, final String backupName) {
.replace("/api/v1", "");
BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
- LOG.debug(backrollBackupsFromVMResponse.state);
+ logger.debug(backrollBackupsFromVMResponse.state);
return backrollBackupsFromVMResponse.state.equals(TaskState.SUCCESS);
} catch (final NotOkBodyException e) {
return false;
} catch (final Exception e) {
- LOG.error("Failed to delete backup using Backroll due to: {}", e.getMessage());
+ logger.error("Failed to delete backup using Backroll due to: {}", e.getMessage());
}
return false;
}
public Metric getVirtualMachineMetrics(final String vmId) {
- LOG.info("Trying to retrieve virtual machine metric from Backroll for vm {}", vmId);
+ logger.info("Trying to retrieve virtual machine metric from Backroll for vm {}", vmId);
loginIfAuthenticationFailed();
@@ -282,12 +282,12 @@ public Metric getVirtualMachineMetrics(final String vmId) {
String urlToRequest = this.parse(okBody(
get(String.format("/virtualmachines/%s/repository", vmId)))).location.replace("/api/v1", "");
- LOG.debug(urlToRequest);
+ logger.debug(urlToRequest);
BackrollVmMetricsResponse vmMetricsResponse = waitGet(urlToRequest);
if (vmMetricsResponse != null && vmMetricsResponse.state.equals(TaskState.SUCCESS)) {
- LOG.debug("SUCCESS ok");
+ logger.debug("SUCCESS ok");
CacheStats stats = null;
try {
stats = vmMetricsResponse.infos.cache.stats;
@@ -299,14 +299,14 @@ public Metric getVirtualMachineMetrics(final String vmId) {
}
}
} catch (final Exception e) {
- LOG.error("Failed to retrieve virtual machine metrics with Backroll due to: {}", e.getMessage());
+ logger.error("Failed to retrieve virtual machine metrics with Backroll due to: {}", e.getMessage());
}
return metric;
}
public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) {
- LOG.info("Trying to get backup metrics for VM: {}, and backup: {}", vmId, backupId);
+ logger.info("Trying to get backup metrics for VM: {}, and backup: {}", vmId, backupId);
loginIfAuthenticationFailed();
@@ -314,7 +314,7 @@ public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) {
String urlToRequest = this.parse(okBody(get(
String.format("/virtualmachines/%s/backups/%s", vmId, backupId)))).location.replace("/api/v1", "");
- LOG.debug(urlToRequest);
+ logger.debug(urlToRequest);
BackrollBackupMetricsResponse metrics = waitGet(urlToRequest);
if (metrics.info != null) {
@@ -324,13 +324,13 @@ public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) {
} catch (final NotOkBodyException e) {
throw new CloudRuntimeException("Failed to retrieve backups status for this VM via Backroll");
} catch (final IOException | InterruptedException e) {
- LOG.error("Failed to check backups status due to: {}", e.getMessage());
+ logger.error("Failed to check backups status due to: {}", e.getMessage());
}
return null;
}
public List getAllBackupsfromVirtualMachine(String vmId) {
- LOG.info("Trying to retrieve all backups for vm {}", vmId);
+ logger.info("Trying to retrieve all backups for vm {}", vmId);
List backups = new ArrayList();
@@ -340,7 +340,7 @@ public List getAllBackupsfromVirtualMachine(String vmId) {
.parse(okBody(
get(String.format("/virtualmachines/%s/backups", vmId)))).location
.replace("/api/v1", "");
- LOG.debug(urlToRequest);
+ logger.debug(urlToRequest);
VirtualMachineBackupsResponse response = waitGet(urlToRequest);
@@ -364,7 +364,7 @@ private HttpResponse post(final String path, final JSONObject json) throws IOExc
String xml = null;
StringEntity params = null;
if (json != null) {
- LOG.debug("JSON {}", json.toString());
+ logger.debug("JSON {}", json.toString());
params = new StringEntity(json.toString(), ContentType.APPLICATION_JSON);
}
@@ -380,19 +380,19 @@ private HttpResponse post(final String path, final JSONObject json) throws IOExc
final HttpResponse response = httpClient.execute(request);
- LOG.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;
}
protected HttpResponse get(final String path) throws IOException {
String url = apiURI.toString() + path;
- LOG.debug("Backroll URL {}", url);
+ logger.debug("Backroll URL {}", url);
final HttpGet request = new HttpGet(url);
request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + backrollToken);
request.setHeader("Content-type", "application/json");
final HttpResponse response = httpClient.execute(request);
- LOG.debug("Response received in GET request is: {} for URL: {}.", response.toString(), url);
+ logger.debug("Response received in GET request is: {} for URL: {}.", response.toString(), url);
return response;
}
@@ -402,7 +402,7 @@ protected HttpResponse delete(final String path) throws IOException {
request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + backrollToken);
request.setHeader("Content-type", "application/json");
final HttpResponse response = httpClient.execute(request);
- LOG.debug("Response received in GET request is: {} for URL: {}.", response.toString(), url);
+ logger.debug("Response received in GET request is: {} for URL: {}.", response.toString(), url);
return response;
}
@@ -463,7 +463,7 @@ private boolean isAuthenticated() {
result = isResponseAuthorized(response);
EntityUtils.consumeQuietly(response.getEntity());
} catch (IOException e) {
- LOG.error("Failed to authenticate to Backroll due to: {}", e.getMessage());
+ logger.error("Failed to authenticate to Backroll due to: {}", e.getMessage());
}
return result;
}
@@ -475,7 +475,7 @@ private void loginIfAuthenticationFailed() {
}
private void login(final String appname, final String appsecret) {
- LOG.debug("Backroll client - start login");
+ logger.debug("Backroll client - start login");
final HttpPost request = new HttpPost(apiURI.toString() + "/login");
request.addHeader("content-type", "application/json");
@@ -493,7 +493,7 @@ private void login(final String appname, final String appsecret) {
try {
LoginApiResponse loginResponse = parse(okBody(response));
backrollToken = loginResponse.accessToken;
- LOG.debug("Backroll client - Token : {}", backrollToken);
+ logger.debug("Backroll client - Token : {}", backrollToken);
if (StringUtils.isEmpty(loginResponse.accessToken)) {
throw new CloudRuntimeException("Backroll token is not available to perform API requests");
@@ -512,30 +512,30 @@ private void login(final String appname, final String appsecret) {
} catch (JSONException e) {
e.printStackTrace();
}
- LOG.debug("Backroll client - end login");
+ logger.debug("Backroll client - end login");
}
private List getBackrollBackups(final String vmId) {
try {
- LOG.info("start to list Backroll backups for vm {}", vmId);
+ logger.info("start to list Backroll backups for vm {}", vmId);
String urlToRequest = this
.parse(okBody(get("/virtualmachines/" + vmId + "/backups"))).location
.replace("/api/v1", "");
- LOG.debug(urlToRequest);
+ 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));
- LOG.debug(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) {
- LOG.error("Failed to list backup form vm with Backroll due to: {}", e);
+ logger.error("Failed to list backup form vm with Backroll due to: {}", e);
} catch (InterruptedException e) {
- LOG.error("Backroll Error: {}", e);
+ logger.error("Backroll Error: {}", e);
}
return new ArrayList();
}
From 01c2238e45107c74d8c7d2d8e4c648be9de756fe Mon Sep 17 00:00:00 2001
From: Matthias Dhellin
Date: Tue, 15 Oct 2024 18:52:29 +0200
Subject: [PATCH 18/57] WIP error handling
---
.../backup/BackrollBackupProvider.java | 175 ++++++-----
.../backup/backroll/BackrollClient.java | 273 ++++++++----------
2 files changed, 226 insertions(+), 222 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 96452d5a8034..080f31a4531e 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,6 +16,7 @@
// under the License.
package org.apache.cloudstack.backup;
+import java.io.IOException;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
@@ -39,7 +40,7 @@
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;
@@ -54,19 +55,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;
@@ -88,12 +89,12 @@ public String getDescription() {
@Override
public List listBackupOfferings(Long zoneId) {
logger.debug("Listing backup policies on backroll B&R Plugin");
- BackrollClient client = getClient(zoneId);
- String urlToRequest = client.getBackupOfferingUrl();
- if (!StringUtils.isEmpty(urlToRequest)){
- return client.getBackupOfferings(urlToRequest);
+ 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);
}
- return new ArrayList();
}
@Override
@@ -104,7 +105,8 @@ public boolean isValidProviderOffering(Long zoneId, String uuid) {
@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;
}
@@ -112,8 +114,13 @@ public boolean assignVMToBackupOffering(VirtualMachine vm, BackupOffering backup
@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 = getClient(vm.getDataCenterId()).restoreVMFromBackup(vm.getUuid(), getBackupName(backup));
- return isSuccess;
+ 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;
}
@Override
@@ -124,7 +131,8 @@ public Map getBackupMetrics(Long zoneId, 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) {
@@ -132,10 +140,14 @@ public Map getBackupMetrics(Long zoneId, List getBackupMetrics(Long zoneId, List backupsInCs = backupDao.listByVmId(null, vm.getId());
for (Backup backup : backupsInCs) {
logger.debug("Trying to remove backup with id {}", backup.getId());
- if (getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup))) {
+ try {
+ 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())){
- isAnyProblemWhileRemovingBackups = true;
+ if (!backupDao.remove(backup.getId())) {
+ everythingIsOk = false;
}
logger.info("Backup {} deleted in CS for virtual machine {}", backup.getId(), vm.getName());
- } else {
- isAnyProblemWhileRemovingBackups = false;
+ } catch (Exception e) {
+ logger.error("Failed to remove backup {} for VM {}.", backup.getName(), vm.getName());
+ everythingIsOk = false;
}
}
- if (isAnyProblemWhileRemovingBackups) {
+ if (!everythingIsOk) {
logger.info("Problems occured while removing some backups for virtual machine {}", vm.getName());
}
- return isAnyProblemWhileRemovingBackups;
+ return everythingIsOk;
}
@Override
@@ -176,10 +190,9 @@ public boolean willDeleteBackupsOnOfferingRemoval() {
@Override
public boolean takeBackup(VirtualMachine vm) {
logger.info("Starting backup for VM ID {} on backroll provider", vm.getUuid());
- final BackrollClient client = getClient(vm.getDataCenterId());
-
- String idBackupTask = client.startBackupJob(vm.getUuid());
- if (!StringUtils.isEmpty(idBackupTask)) {
+ try {
+ final BackrollClient client = getClient(vm.getDataCenterId());
+ String idBackupTask = client.startBackupJob(vm.getUuid());
BackupVO backup = new BackupVO();
backup.setVmId(vm.getId());
backup.setExternalId(idBackupTask);
@@ -192,22 +205,32 @@ public boolean takeBackup(VirtualMachine vm) {
backup.setAccountId(vm.getAccountId());
backup.setDomainId(vm.getDomainId());
backup.setZoneId(vm.getDataCenterId());
- return backupDao.persist(backup) != null;
+ 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 false;
+ return true;
}
@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 = getClient(vm.getDataCenterId());
+ 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()));
+ }
+
List backupsInDb = backupDao.listByVmId(null, vm.getId());
for (Backup backup : backupsInDb) {
- if (backup.getStatus().equals(Backup.Status.BackingUp)) {
- BackrollTaskStatus response = client.checkBackupTaskStatus(backup.getExternalId());
- if (response != null) {
+ try {
+ if (backup.getStatus().equals(Backup.Status.BackingUp)) {
+ BackrollTaskStatus response = client.checkBackupTaskStatus(backup.getExternalId());
+
logger.debug("backroll backup id: {}", backup.getExternalId());
logger.debug("backroll backup status: {}", response.getState());
@@ -231,7 +254,8 @@ public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
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
@@ -244,16 +268,19 @@ public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
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);
- if (backupMetrics != null) {
+
+ } 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);
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());
}
}
@@ -264,9 +291,9 @@ public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
// 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();
@@ -296,11 +323,12 @@ public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
// 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);
@@ -319,10 +347,10 @@ public String getConfigComponentName() {
@Override
public ConfigKey>[] getConfigKeys() {
- return new ConfigKey[]{
- BackrollUrlConfigKey,
- BackrollAppNameConfigKey,
- BackrollPasswordConfigKey
+ return new ConfigKey[] {
+ BackrollUrlConfigKey,
+ BackrollAppNameConfigKey,
+ BackrollPasswordConfigKey
};
}
@@ -330,21 +358,24 @@ public ConfigKey>[] getConfigKeys() {
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");
+ throw new CloudRuntimeException("You can't delete a backup while it still backing up.");
} 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) {
@@ -357,12 +388,14 @@ private boolean deleteBackupInDb(Backup backup) {
return false;
}
- protected BackrollClient getClient(final Long zoneId) {
+ protected BackrollClient getClient(final Long zoneId) throws ClientProtocolException, IOException {
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) {
@@ -378,8 +411,10 @@ private String getBackupName(Backup backup) {
}
@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 e7021d4276b8..cfdcf566646c 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,6 +62,7 @@
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;
@@ -106,7 +107,8 @@ 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 {
+ throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException, ClientProtocolException,
+ IOException {
this.apiURI = new URI(url);
this.restoreTimeout = restoreTimeout;
this.appname = appname;
@@ -152,105 +154,79 @@ public String startBackupJob(final String jobId) {
return null;
}
- public String getBackupOfferingUrl() {
+ public String getBackupOfferingUrl()
+ throws ClientProtocolException, IOException, ParseException, NotOkBodyException {
logger.info("Trying to list backroll backup policies");
loginIfAuthenticationFailed();
- 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 null;
+ return this.parse(okBody(get("/backup_policies"))).location.replace("/api/v1",
+ "");
}
- public List getBackupOfferings(String idTask) {
+ public List getBackupOfferings(String idTask)
+ throws ParseException, NotOkBodyException, ClientProtocolException, IOException, InterruptedException {
logger.info("Trying to list backroll backup policies");
loginIfAuthenticationFailed();
- try {
- BackupPoliciesResponse backupPoliciesResponse = waitGet(idTask);
+ 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());
+ final List policies = new ArrayList<>();
+ for (final BackrollBackupPolicyResponse policy : backupPoliciesResponse.backupPolicies) {
+ policies.add(new BackrollOffering(policy.name, policy.id));
}
- return new ArrayList();
+ return policies;
}
- public boolean restoreVMFromBackup(final String vmId, final String backupName) {
+ public void restoreVMFromBackup(final String vmId, final String backupName) throws Exception {
logger.info("Start restore backup with backroll with backup {} for vm {}", backupName, vmId);
loginIfAuthenticationFailed();
- try {
- JSONObject jsonBody = new JSONObject();
- try {
- jsonBody.put("virtual_machine_id", vmId);
- jsonBody.put("backup_name", backupName);
- jsonBody.put("storage", "");
- jsonBody.put("mode", "single");
-
- } catch (JSONException e) {
- logger.error("Backroll Error: {}", e.getMessage());
- }
+ JSONObject jsonBody = new JSONObject();
+ 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", "");
+ String urlToRequest = this
+ .parse(okBody(
+ post(String.format("/tasks/restore/%s", vmId), jsonBody))).location
+ .replace("/api/v1", "");
- 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());
+ TaskStateResponse response = waitGet(urlToRequest);
+ logger.debug("RESTORE {}", response.state);
+
+ if (!response.state.equals(TaskState.SUCCESS)) {
+ throw new Exception("Backroll task failed.");
}
}
- public BackrollTaskStatus checkBackupTaskStatus(String taskId) {
+ public BackrollTaskStatus checkBackupTaskStatus(String taskId)
+ throws ParseException, IOException, NotOkBodyException {
logger.info("Trying to get backup status for Backroll task: {}", taskId);
loginIfAuthenticationFailed();
- try {
- BackrollTaskStatus status = new BackrollTaskStatus();
-
- 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);
- }
-
- return status;
+ BackrollTaskStatus status = new BackrollTaskStatus();
- } 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");
+ String body = okBody(get("/status/" + taskId));
- } catch (final IOException e) {
- logger.error("Failed to check backups status due to: {}", e.getMessage());
+ 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 null;
+
+ return status;
}
- public boolean deleteBackup(final String vmId, final String backupName) {
+ public boolean deleteBackup(final String vmId, final String backupName)
+ throws ClientProtocolException, IOException {
logger.info("Trying to delete backup {} for vm {} using Backroll", vmId, backupName);
loginIfAuthenticationFailed();
@@ -271,7 +247,7 @@ public boolean deleteBackup(final String vmId, final String backupName) {
return false;
}
- public Metric getVirtualMachineMetrics(final String vmId) {
+ public Metric getVirtualMachineMetrics(final String vmId) throws ClientProtocolException, IOException {
logger.info("Trying to retrieve virtual machine metric from Backroll for vm {}", vmId);
loginIfAuthenticationFailed();
@@ -286,7 +262,7 @@ public Metric getVirtualMachineMetrics(final String vmId) {
BackrollVmMetricsResponse vmMetricsResponse = waitGet(urlToRequest);
- if (vmMetricsResponse != null && vmMetricsResponse.state.equals(TaskState.SUCCESS)) {
+ if (vmMetricsResponse.state.equals(TaskState.SUCCESS)) {
logger.debug("SUCCESS ok");
CacheStats stats = null;
try {
@@ -305,28 +281,23 @@ public Metric getVirtualMachineMetrics(final String vmId) {
return metric;
}
- public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) {
+ public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) throws JsonMappingException,
+ JsonProcessingException, ParseException, IOException, NotOkBodyException, InterruptedException {
logger.info("Trying to get backup metrics for VM: {}, and backup: {}", vmId, backupId);
loginIfAuthenticationFailed();
- try {
+ String urlToRequest = this.parse(okBody(get(
+ String.format("/virtualmachines/%s/backups/%s", vmId, backupId)))).location.replace("/api/v1", "");
+ logger.debug(urlToRequest);
- 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());
+ BackrollBackupMetricsResponse metrics = waitGet(urlToRequest);
+ if (metrics.info != null) {
+ return new BackrollBackupMetrics(Long.parseLong(metrics.info.originalSize),
+ Long.parseLong(metrics.info.deduplicatedSize));
}
- return null;
+
+ throw new CloudRuntimeException("Backup %s of VM %s has null info in its metrics.");
}
public List getAllBackupsfromVirtualMachine(String vmId) {
@@ -380,7 +351,8 @@ private HttpResponse post(final String path, final JSONObject json) throws IOExc
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;
}
@@ -411,7 +383,17 @@ private boolean isResponseAuthorized(final HttpResponse response) {
|| response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED;
}
- private class NotOkBodyException extends Exception {
+ 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 String okBody(final HttpResponse response)
@@ -426,7 +408,7 @@ private String okBody(final HttpResponse response)
EntityUtils.consumeQuietly(bodyEntity);
}
default:
- throw new NotOkBodyException();
+ throw new NotOkBodyException(response);
}
}
@@ -436,24 +418,23 @@ private T parse(final String json)
});
}
- private T waitGet(String url)
- throws IOException, InterruptedException {
- // int threshold = 30; // 5 minutes
- int maxAttempts = 12; // 2 minutes
+ private T waitGet(String url) throws InterruptedException, ParseException, IOException, NotOkBodyException {
+ int waitingTimeMinutes = 2;
+ int refreshingPeriodSeconds = 10;
- 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");
+ 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);
}
- TimeUnit.SECONDS.sleep(10);
}
-
- return null;
+ throw new CloudRuntimeException(String.format("Unable to fetch %s."));
}
private boolean isAuthenticated() {
@@ -468,13 +449,13 @@ private boolean isAuthenticated() {
return result;
}
- private void loginIfAuthenticationFailed() {
+ private void loginIfAuthenticationFailed() throws ClientProtocolException, IOException {
if (!isAuthenticated()) {
login(appname, password);
}
}
- private void login(final String appname, final String appsecret) {
+ private void login(final String appname, final String appsecret) throws ClientProtocolException, IOException {
logger.debug("Backroll client - start login");
final HttpPost request = new HttpPost(apiURI.toString() + "/login");
@@ -483,60 +464,48 @@ private void login(final String appname, final String appsecret) {
JSONObject jsonBody = new JSONObject();
StringEntity params;
- try {
- jsonBody.put("app_id", appname);
- jsonBody.put("app_secret", appsecret);
- params = new StringEntity(jsonBody.toString());
- request.setEntity(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);
+ 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.");
- }
+ 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) {
- 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);
+ private List getBackrollBackups(final String vmId) throws JsonMappingException,
+ JsonProcessingException, ParseException, IOException, NotOkBodyException, InterruptedException {
- 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);
+ 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);
}
- return new ArrayList();
+ return backups;
}
}
From d37a35b48977641c23e371ed3e5d9f09d8ae6e08 Mon Sep 17 00:00:00 2001
From: Matthias Dhellin
Date: Tue, 15 Oct 2024 22:53:13 +0200
Subject: [PATCH 19/57] Refactoring error handling
---
.../backup/BackrollBackupProvider.java | 43 ++++---
.../backup/backroll/BackrollClient.java | 109 ++++++++----------
2 files changed, 69 insertions(+), 83 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 080f31a4531e..cc425dc038ef 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
@@ -20,7 +20,6 @@
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -39,7 +38,6 @@
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;
@@ -205,7 +203,10 @@ public boolean takeBackup(VirtualMachine vm) {
backup.setAccountId(vm.getAccountId());
backup.setDomainId(vm.getDomainId());
backup.setZoneId(vm.getDataCenterId());
- assert backupDao.persist(backup) != null;
+ if (backupDao.persist(backup) == null) {// TODO is null a failure ?
+ throw new Exception("Failed to persist backup.");
+ }
+ ;
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to take a backup of VM %s.", vm.getName()), e);
}
@@ -359,33 +360,31 @@ 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.");
- } 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);
- }
+ logger.debug("backroll - try delete backup");
+ VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(backup.getVmId());
- try {
- getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup));
- } catch (Exception e) {
- throw new CloudRuntimeException(String.format("Failed to delete backup %s", backup.getName()));
- }
+ if (backup.getStatus().equals(Backup.Status.Removed) || backup.getStatus().equals(Backup.Status.Failed)) {
+ deleteBackupInDb(backup);
+ return true;
+ }
- 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());
+ deleteBackupInDb(backup);
+ return true;
}
- private boolean deleteBackupInDb(Backup backup) {
+ private void 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;
+ backupDao.persist(backupToUpdate); // TODO is null a failure ?
}
protected BackrollClient getClient(final Long zoneId) throws ClientProtocolException, IOException {
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 cfdcf566646c..e57d9c5e73de 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
@@ -80,7 +80,6 @@
import org.joda.time.DateTime;
-import org.json.JSONException;
import org.json.JSONObject;
import com.cloud.utils.exception.CloudRuntimeException;
@@ -140,25 +139,22 @@ public BackrollClient(final String url, final String appname, final String passw
}
}
- public String startBackupJob(final String jobId) {
+ public String startBackupJob(final String jobId)
+ throws ClientProtocolException, IOException, ParseException, NotOkBodyException {
logger.info("Trying to start backup for Backroll job: {}", jobId);
- try {
- loginIfAuthenticationFailed();
- return this.parse(okBody(
- post(String.format("/tasks/singlebackup/%s", jobId), null))).location
- .replace("/api/v1/status/", "");
- } catch (final Exception e) {
- logger.error("Failed to start Backroll backup job due to: {}", e.getMessage());
- }
- return null;
+ ensureLoggedIn();
+
+ return this.parse(okBody(
+ post(String.format("/tasks/singlebackup/%s", jobId), null))).location
+ .replace("/api/v1/status/", "");
}
public String getBackupOfferingUrl()
throws ClientProtocolException, IOException, ParseException, NotOkBodyException {
logger.info("Trying to list backroll backup policies");
- loginIfAuthenticationFailed();
+ ensureLoggedIn();
return this.parse(okBody(get("/backup_policies"))).location.replace("/api/v1",
"");
@@ -168,7 +164,7 @@ public List getBackupOfferings(String idTask)
throws ParseException, NotOkBodyException, ClientProtocolException, IOException, InterruptedException {
logger.info("Trying to list backroll backup policies");
- loginIfAuthenticationFailed();
+ ensureLoggedIn();
BackupPoliciesResponse backupPoliciesResponse = waitGet(idTask);
@@ -182,7 +178,7 @@ public List getBackupOfferings(String idTask)
public void restoreVMFromBackup(final String vmId, final String backupName) throws Exception {
logger.info("Start restore backup with backroll with backup {} for vm {}", backupName, vmId);
- loginIfAuthenticationFailed();
+ ensureLoggedIn();
JSONObject jsonBody = new JSONObject();
jsonBody.put("virtual_machine_id", vmId);
@@ -207,7 +203,7 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId)
throws ParseException, IOException, NotOkBodyException {
logger.info("Trying to get backup status for Backroll task: {}", taskId);
- loginIfAuthenticationFailed();
+ ensureLoggedIn();
BackrollTaskStatus status = new BackrollTaskStatus();
@@ -225,32 +221,27 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId)
return status;
}
- public boolean deleteBackup(final String vmId, final String backupName)
- throws ClientProtocolException, IOException {
+ public void deleteBackup(final String vmId, final String backupName)
+ throws Exception {
logger.info("Trying to delete backup {} for vm {} using Backroll", vmId, backupName);
- loginIfAuthenticationFailed();
+ ensureLoggedIn();
- try {
- String urlToRequest = this.parse(okBody(delete(
- String.format("/virtualmachines/%s/backups/%s", vmId, backupName)))).location
- .replace("/api/v1", "");
+ String urlToRequest = this.parse(okBody(delete(
+ String.format("/virtualmachines/%s/backups/%s", vmId, backupName)))).location
+ .replace("/api/v1", "");
- BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
- logger.debug(backrollBackupsFromVMResponse.state);
- return backrollBackupsFromVMResponse.state.equals(TaskState.SUCCESS);
- } catch (final NotOkBodyException e) {
- return false;
- } catch (final Exception e) {
- logger.error("Failed to delete backup using Backroll due to: {}", e.getMessage());
+ BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
+ logger.debug(backrollBackupsFromVMResponse.state);
+ if (!backrollBackupsFromVMResponse.state.equals(TaskState.SUCCESS)) {
+ throw new Exception("Backroll task failed.");
}
- return false;
}
public Metric getVirtualMachineMetrics(final String vmId) throws ClientProtocolException, IOException {
logger.info("Trying to retrieve virtual machine metric from Backroll for vm {}", vmId);
- loginIfAuthenticationFailed();
+ ensureLoggedIn();
Metric metric = new Metric(0L, 0L);
@@ -285,7 +276,7 @@ public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) thro
JsonProcessingException, ParseException, IOException, NotOkBodyException, InterruptedException {
logger.info("Trying to get backup metrics for VM: {}, and backup: {}", vmId, backupId);
- loginIfAuthenticationFailed();
+ ensureLoggedIn();
String urlToRequest = this.parse(okBody(get(
String.format("/virtualmachines/%s/backups/%s", vmId, backupId)))).location.replace("/api/v1", "");
@@ -332,26 +323,20 @@ public List getAllBackupsfromVirtualMachine(String vmId) {
}
private HttpResponse post(final String path, final JSONObject json) throws IOException {
- String xml = null;
- StringEntity params = null;
- if (json != null) {
- logger.debug("JSON {}", json.toString());
- params = new StringEntity(json.toString(), ContentType.APPLICATION_JSON);
- }
-
String url = apiURI.toString() + path;
final HttpPost request = new HttpPost(url);
- if (params != null) {
- request.setEntity(params);
- }
-
request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + backrollToken);
request.setHeader("Content-type", "application/json");
+ if (json != null) {
+ logger.debug("JSON {}", json.toString());
+ request.setEntity(new StringEntity(json.toString(), ContentType.APPLICATION_JSON));
+ }
+
final HttpResponse response = httpClient.execute(request);
- logger.debug("Response received in POST request with body {} is: {} for URL {}.", xml, response.toString(),
+ logger.debug("Response received in POST request with body {} is: {} for URL {}.", json, response.toString(),
url);
return response;
@@ -378,9 +363,14 @@ protected HttpResponse delete(final String path) throws IOException {
return response;
}
- private boolean isResponseAuthorized(final HttpResponse response) {
- return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK
- || response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED;
+ private boolean isResponseOk(final HttpResponse response) {
+ switch (response.getStatusLine().getStatusCode()) {
+ case HttpStatus.SC_OK:
+ case HttpStatus.SC_ACCEPTED:
+ return true;
+ default:
+ return false;
+ }
}
public class NotOkBodyException extends Exception {
@@ -398,18 +388,15 @@ public HttpResponse getResponse() {
private String okBody(final HttpResponse response)
throws ParseException, IOException, NotOkBodyException {
- switch (response.getStatusLine().getStatusCode()) {
- case HttpStatus.SC_OK:
- case HttpStatus.SC_ACCEPTED:
- HttpEntity bodyEntity = response.getEntity();
- try {
- return EntityUtils.toString(bodyEntity);
- } finally {
- EntityUtils.consumeQuietly(bodyEntity);
- }
- default:
- throw new NotOkBodyException(response);
+ if (isResponseOk(response)) {
+ HttpEntity bodyEntity = response.getEntity();
+ try {
+ return EntityUtils.toString(bodyEntity);
+ } finally {
+ EntityUtils.consumeQuietly(bodyEntity);
+ }
}
+ throw new NotOkBodyException(response);
}
private T parse(final String json)
@@ -441,15 +428,15 @@ private boolean isAuthenticated() {
boolean result = false;
try {
final HttpResponse response = post("/auth", null);
- result = isResponseAuthorized(response);
- EntityUtils.consumeQuietly(response.getEntity());
+ result = isResponseOk(response);
+ EntityUtils.consumeQuietly(response.getEntity()); // TODO Move to a finally clause ?
} catch (IOException e) {
logger.error("Failed to authenticate to Backroll due to: {}", e.getMessage());
}
return result;
}
- private void loginIfAuthenticationFailed() throws ClientProtocolException, IOException {
+ private void ensureLoggedIn() throws ClientProtocolException, IOException {
if (!isAuthenticated()) {
login(appname, password);
}
From e9cbe0ed6a1de239865d1f1ce9f42897f821ea4c Mon Sep 17 00:00:00 2001
From: Pierre Charton
Date: Mon, 21 Oct 2024 17:33:21 +0200
Subject: [PATCH 20/57] Revert "Refactoring error handling"
This reverts commit d37a35b48977641c23e371ed3e5d9f09d8ae6e08.
---
.../backup/BackrollBackupProvider.java | 43 +++----
.../backup/backroll/BackrollClient.java | 109 ++++++++++--------
2 files changed, 83 insertions(+), 69 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 cc425dc038ef..080f31a4531e 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
@@ -20,6 +20,7 @@
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -38,6 +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;
@@ -203,10 +205,7 @@ public boolean takeBackup(VirtualMachine vm) {
backup.setAccountId(vm.getAccountId());
backup.setDomainId(vm.getDomainId());
backup.setZoneId(vm.getDataCenterId());
- if (backupDao.persist(backup) == null) {// TODO is null a failure ?
- throw new Exception("Failed to persist backup.");
- }
- ;
+ assert backupDao.persist(backup) != null;
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Failed to take a backup of VM %s.", vm.getName()), e);
}
@@ -360,31 +359,33 @@ 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.");
- }
+ } else {
+ logger.debug("backroll - try delete backup");
+ VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(backup.getVmId());
- 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);
+ }
- if (backup.getStatus().equals(Backup.Status.Removed) || backup.getStatus().equals(Backup.Status.Failed)) {
- deleteBackupInDb(backup);
- return true;
- }
+ try {
+ getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup));
+ } catch (Exception e) {
+ throw new CloudRuntimeException(String.format("Failed to delete backup %s", backup.getName()));
+ }
- 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);
}
-
- logger.debug("Backup deletion for backup {} complete on backroll side.", backup.getUuid());
- deleteBackupInDb(backup);
- return true;
}
- private void deleteBackupInDb(Backup backup) {
+ private boolean deleteBackupInDb(Backup backup) {
BackupVO backupToUpdate = ((BackupVO) backup);
backupToUpdate.setStatus(Backup.Status.Removed);
- backupDao.persist(backupToUpdate); // TODO is null a failure ?
+ if (backupDao.persist(backupToUpdate) != null) {
+ logger.debug("Backroll backup {} deleted in database.", backup.getUuid());
+ return true;
+ }
+ return false;
}
protected BackrollClient getClient(final Long zoneId) throws ClientProtocolException, IOException {
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 e57d9c5e73de..cfdcf566646c 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
@@ -80,6 +80,7 @@
import org.joda.time.DateTime;
+import org.json.JSONException;
import org.json.JSONObject;
import com.cloud.utils.exception.CloudRuntimeException;
@@ -139,22 +140,25 @@ public BackrollClient(final String url, final String appname, final String passw
}
}
- public String startBackupJob(final String jobId)
- throws ClientProtocolException, IOException, ParseException, NotOkBodyException {
+ public String startBackupJob(final String jobId) {
logger.info("Trying to start backup for Backroll job: {}", jobId);
- ensureLoggedIn();
-
- return this.parse(okBody(
- post(String.format("/tasks/singlebackup/%s", jobId), null))).location
- .replace("/api/v1/status/", "");
+ try {
+ loginIfAuthenticationFailed();
+ return this.parse(okBody(
+ post(String.format("/tasks/singlebackup/%s", jobId), null))).location
+ .replace("/api/v1/status/", "");
+ } catch (final Exception e) {
+ logger.error("Failed to start Backroll backup job due to: {}", e.getMessage());
+ }
+ return null;
}
public String getBackupOfferingUrl()
throws ClientProtocolException, IOException, ParseException, NotOkBodyException {
logger.info("Trying to list backroll backup policies");
- ensureLoggedIn();
+ loginIfAuthenticationFailed();
return this.parse(okBody(get("/backup_policies"))).location.replace("/api/v1",
"");
@@ -164,7 +168,7 @@ public List getBackupOfferings(String idTask)
throws ParseException, NotOkBodyException, ClientProtocolException, IOException, InterruptedException {
logger.info("Trying to list backroll backup policies");
- ensureLoggedIn();
+ loginIfAuthenticationFailed();
BackupPoliciesResponse backupPoliciesResponse = waitGet(idTask);
@@ -178,7 +182,7 @@ public List getBackupOfferings(String idTask)
public void restoreVMFromBackup(final String vmId, final String backupName) throws Exception {
logger.info("Start restore backup with backroll with backup {} for vm {}", backupName, vmId);
- ensureLoggedIn();
+ loginIfAuthenticationFailed();
JSONObject jsonBody = new JSONObject();
jsonBody.put("virtual_machine_id", vmId);
@@ -203,7 +207,7 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId)
throws ParseException, IOException, NotOkBodyException {
logger.info("Trying to get backup status for Backroll task: {}", taskId);
- ensureLoggedIn();
+ loginIfAuthenticationFailed();
BackrollTaskStatus status = new BackrollTaskStatus();
@@ -221,27 +225,32 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId)
return status;
}
- public void deleteBackup(final String vmId, final String backupName)
- throws Exception {
+ public boolean deleteBackup(final String vmId, final String backupName)
+ throws ClientProtocolException, IOException {
logger.info("Trying to delete backup {} for vm {} using Backroll", vmId, backupName);
- ensureLoggedIn();
+ loginIfAuthenticationFailed();
- String urlToRequest = this.parse(okBody(delete(
- String.format("/virtualmachines/%s/backups/%s", vmId, backupName)))).location
- .replace("/api/v1", "");
+ try {
+ String urlToRequest = this.parse(okBody(delete(
+ String.format("/virtualmachines/%s/backups/%s", vmId, backupName)))).location
+ .replace("/api/v1", "");
- BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
- logger.debug(backrollBackupsFromVMResponse.state);
- if (!backrollBackupsFromVMResponse.state.equals(TaskState.SUCCESS)) {
- throw new Exception("Backroll task failed.");
+ BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
+ logger.debug(backrollBackupsFromVMResponse.state);
+ return backrollBackupsFromVMResponse.state.equals(TaskState.SUCCESS);
+ } catch (final NotOkBodyException e) {
+ return false;
+ } catch (final Exception e) {
+ logger.error("Failed to delete backup using Backroll due to: {}", e.getMessage());
}
+ return false;
}
public Metric getVirtualMachineMetrics(final String vmId) throws ClientProtocolException, IOException {
logger.info("Trying to retrieve virtual machine metric from Backroll for vm {}", vmId);
- ensureLoggedIn();
+ loginIfAuthenticationFailed();
Metric metric = new Metric(0L, 0L);
@@ -276,7 +285,7 @@ public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) thro
JsonProcessingException, ParseException, IOException, NotOkBodyException, InterruptedException {
logger.info("Trying to get backup metrics for VM: {}, and backup: {}", vmId, backupId);
- ensureLoggedIn();
+ loginIfAuthenticationFailed();
String urlToRequest = this.parse(okBody(get(
String.format("/virtualmachines/%s/backups/%s", vmId, backupId)))).location.replace("/api/v1", "");
@@ -323,20 +332,26 @@ public List getAllBackupsfromVirtualMachine(String vmId) {
}
private HttpResponse post(final String path, final JSONObject json) throws IOException {
+ String xml = null;
+ StringEntity params = null;
+ if (json != null) {
+ logger.debug("JSON {}", json.toString());
+ params = new StringEntity(json.toString(), ContentType.APPLICATION_JSON);
+ }
+
String url = apiURI.toString() + path;
final HttpPost request = new HttpPost(url);
+ if (params != null) {
+ request.setEntity(params);
+ }
+
request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + backrollToken);
request.setHeader("Content-type", "application/json");
- if (json != null) {
- logger.debug("JSON {}", json.toString());
- request.setEntity(new StringEntity(json.toString(), ContentType.APPLICATION_JSON));
- }
-
final HttpResponse response = httpClient.execute(request);
- logger.debug("Response received in POST request with body {} is: {} for URL {}.", json, response.toString(),
+ logger.debug("Response received in POST request with body {} is: {} for URL {}.", xml, response.toString(),
url);
return response;
@@ -363,14 +378,9 @@ protected HttpResponse delete(final String path) throws IOException {
return response;
}
- private boolean isResponseOk(final HttpResponse response) {
- switch (response.getStatusLine().getStatusCode()) {
- case HttpStatus.SC_OK:
- case HttpStatus.SC_ACCEPTED:
- return true;
- default:
- return false;
- }
+ private boolean isResponseAuthorized(final HttpResponse response) {
+ return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK
+ || response.getStatusLine().getStatusCode() == HttpStatus.SC_ACCEPTED;
}
public class NotOkBodyException extends Exception {
@@ -388,15 +398,18 @@ public HttpResponse getResponse() {
private String okBody(final HttpResponse response)
throws ParseException, IOException, NotOkBodyException {
- if (isResponseOk(response)) {
- HttpEntity bodyEntity = response.getEntity();
- try {
- return EntityUtils.toString(bodyEntity);
- } finally {
- EntityUtils.consumeQuietly(bodyEntity);
- }
+ switch (response.getStatusLine().getStatusCode()) {
+ case HttpStatus.SC_OK:
+ case HttpStatus.SC_ACCEPTED:
+ HttpEntity bodyEntity = response.getEntity();
+ try {
+ return EntityUtils.toString(bodyEntity);
+ } finally {
+ EntityUtils.consumeQuietly(bodyEntity);
+ }
+ default:
+ throw new NotOkBodyException(response);
}
- throw new NotOkBodyException(response);
}
private T parse(final String json)
@@ -428,15 +441,15 @@ private boolean isAuthenticated() {
boolean result = false;
try {
final HttpResponse response = post("/auth", null);
- result = isResponseOk(response);
- EntityUtils.consumeQuietly(response.getEntity()); // TODO Move to a finally clause ?
+ result = isResponseAuthorized(response);
+ EntityUtils.consumeQuietly(response.getEntity());
} catch (IOException e) {
logger.error("Failed to authenticate to Backroll due to: {}", e.getMessage());
}
return result;
}
- private void ensureLoggedIn() throws ClientProtocolException, IOException {
+ private void loginIfAuthenticationFailed() throws ClientProtocolException, IOException {
if (!isAuthenticated()) {
login(appname, password);
}
From 6a690b74310ba43bd09a38b0908a4688280cec20 Mon Sep 17 00:00:00 2001
From: Pierre Charton
Date: Mon, 21 Oct 2024 17:33:48 +0200
Subject: [PATCH 21/57] Revert "WIP error handling"
This reverts commit 01c2238e45107c74d8c7d2d8e4c648be9de756fe.
---
.../backup/BackrollBackupProvider.java | 175 +++++------
.../backup/backroll/BackrollClient.java | 273 ++++++++++--------
2 files changed, 222 insertions(+), 226 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 080f31a4531e..96452d5a8034 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.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 String getDescription() {
@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 boolean isValidProviderOffering(Long zoneId, String uuid) {
@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 boolean assignVMToBackupOffering(VirtualMachine vm, BackupOffering backup
@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 Map getBackupMetrics(Long zoneId, 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 Map getBackupMetrics(Long zoneId, List getBackupMetrics(Long zoneId, 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 boolean willDeleteBackupsOnOfferingRemoval() {
@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 boolean takeBackup(VirtualMachine vm) {
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 void syncBackups(VirtualMachine vm, Backup.Metric metric) {
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 void syncBackups(VirtualMachine vm, Backup.Metric metric) {
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 void syncBackups(VirtualMachine vm, Backup.Metric metric) {
// 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 void syncBackups(VirtualMachine vm, Backup.Metric metric) {
// 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 String getConfigComponentName() {
@Override
public ConfigKey>[] getConfigKeys() {
- return new ConfigKey[] {
- BackrollUrlConfigKey,
- BackrollAppNameConfigKey,
- BackrollPasswordConfigKey
+ return new ConfigKey[]{
+ BackrollUrlConfigKey,
+ BackrollAppNameConfigKey,
+ BackrollPasswordConfigKey
};
}
@@ -358,24 +330,21 @@ public ConfigKey>[] getConfigKeys() {
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 @@ private boolean deleteBackupInDb(Backup backup) {
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 @@ private String getBackupName(Backup backup) {
}
@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 cfdcf566646c..e7021d4276b8 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.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 String startBackupJob(final String jobId) {
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",
- "");
+ 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 null;
}
- public List getBackupOfferings(String idTask)
- throws ParseException, NotOkBodyException, ClientProtocolException, IOException, InterruptedException {
+ public List getBackupOfferings(String idTask) {
logger.info("Trying to list backroll backup policies");
loginIfAuthenticationFailed();
- BackupPoliciesResponse backupPoliciesResponse = waitGet(idTask);
+ try {
+ BackupPoliciesResponse backupPoliciesResponse = waitGet(idTask);
- final List policies = new ArrayList<>();
- for (final BackrollBackupPolicyResponse policy : backupPoliciesResponse.backupPolicies) {
- policies.add(new BackrollOffering(policy.name, policy.id));
+ 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 policies;
+ return new ArrayList();
}
- public void restoreVMFromBackup(final String vmId, final String backupName) throws Exception {
+ 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");
-
- String urlToRequest = this
- .parse(okBody(
- post(String.format("/tasks/restore/%s", vmId), jsonBody))).location
- .replace("/api/v1", "");
+ try {
+ JSONObject jsonBody = new JSONObject();
+ try {
+ jsonBody.put("virtual_machine_id", vmId);
+ jsonBody.put("backup_name", backupName);
+ jsonBody.put("storage", "");
+ jsonBody.put("mode", "single");
+
+ } 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");
- return status;
+ } catch (final IOException e) {
+ logger.error("Failed to check backups status due to: {}", e.getMessage());
+ }
+ 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 boolean deleteBackup(final String vmId, final String backupName)
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 Metric getVirtualMachineMetrics(final String vmId) throws ClientProtocolE
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 Metric getVirtualMachineMetrics(final String vmId) throws ClientProtocolE
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);
- throw new CloudRuntimeException("Backup %s of VM %s has null info in its metrics.");
+ 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());
+ }
+ return null;
}
public List getAllBackupsfromVirtualMachine(String vmId) {
@@ -351,8 +380,7 @@ private HttpResponse post(final String path, final JSONObject json) throws IOExc
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 @@ private boolean isResponseAuthorized(final HttpResponse response) {
|| 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 @@ private String okBody(final HttpResponse response)
EntityUtils.consumeQuietly(bodyEntity);
}
default:
- throw new NotOkBodyException(response);
+ throw new NotOkBodyException();
}
}
@@ -418,23 +436,24 @@ private T parse(final String json)
});
}
- 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 @@ private boolean isAuthenticated() {
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 @@ private void login(final String appname, final String appsecret) throws ClientPr
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 {
-
- 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);
+ 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);
- 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();
}
}
From 3e90f8e4607e590ce502a50f14021256fad0a14a Mon Sep 17 00:00:00 2001
From: Pierre Charton
Date: Mon, 28 Oct 2024 20:38:20 +0100
Subject: [PATCH 22/57] WIP
---
.../backup/BackrollBackupProvider.java | 89 +++--
.../backup/backroll/BackrollClient.java | 318 ++++++++++++------
.../backroll/model/response/TaskState.java | 16 +
3 files changed, 298 insertions(+), 125 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 96452d5a8034..a245a3f8be6c 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,6 +16,7 @@
// under the License.
package org.apache.cloudstack.backup;
+import java.io.IOException;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
@@ -39,7 +40,7 @@
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-
+import org.apache.http.ParseException;
import org.joda.time.DateTime;
import com.cloud.utils.Pair;
@@ -60,7 +61,7 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
public ConfigKey BackrollAppNameConfigKey = new ConfigKey<>("Advanced", String.class,
"backup.plugin.backroll.config.appname",
- "backroll_api",
+ "backroll-api",
"App Name for backroll plugin.", true, ConfigKey.Scope.Zone);
public ConfigKey BackrollPasswordConfigKey = new ConfigKey<>("Advanced", String.class,
@@ -89,9 +90,14 @@ public String getDescription() {
public List listBackupOfferings(Long zoneId) {
logger.debug("Listing backup policies on backroll B&R Plugin");
BackrollClient client = getClient(zoneId);
- String urlToRequest = client.getBackupOfferingUrl();
- if (!StringUtils.isEmpty(urlToRequest)){
- return client.getBackupOfferings(urlToRequest);
+ try{
+ String urlToRequest = client.getBackupOfferingUrl();
+ if (!StringUtils.isEmpty(urlToRequest)){
+ return client.getBackupOfferings(urlToRequest);
+
+ }
+ } catch (KeyManagementException | ParseException | NoSuchAlgorithmException | IOException e) {
+ throw new CloudRuntimeException("Failed to load backup offerings");
}
return new ArrayList();
}
@@ -112,7 +118,12 @@ public boolean assignVMToBackupOffering(VirtualMachine vm, BackupOffering backup
@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 = getClient(vm.getDataCenterId()).restoreVMFromBackup(vm.getUuid(), getBackupName(backup));
+ boolean isSuccess;
+ 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;
}
@@ -132,7 +143,12 @@ public Map getBackupMetrics(Long zoneId, Listparse(okBody(
- post(String.format("/tasks/singlebackup/%s", jobId), null))).location
- .replace("/api/v1/status/", "");
+ CloseableHttpResponse response = post(String.format("/tasks/singlebackup/%s", jobId), null);
+ String result = okBody(response);
+ BackrollTaskRequestResponse requestResponse = parse(result);
+ response.close();
+ backupJob = requestResponse.location.replace("/api/v1/status/", "");
} catch (final Exception e) {
logger.error("Failed to start Backroll backup job due to: {}", e.getMessage());
}
- return null;
+ return StringUtils.isEmpty(backupJob) ? null : backupJob;
}
- public String getBackupOfferingUrl() {
+ public String getBackupOfferingUrl() throws KeyManagementException, NoSuchAlgorithmException, IOException {
logger.info("Trying to list backroll backup policies");
loginIfAuthenticationFailed();
+ String url = "";
try {
- return this.parse(okBody(get("/backup_policies"))).location.replace("/api/v1",
- "");
+ CloseableHttpResponse response = get("/backup_policies");
+ String result = okBody(response);
+ BackrollTaskRequestResponse requestResponse = parse(result);
+ response.close();
+ url = requestResponse.location.replace("/api/v1", "");
} catch (final Exception e) {
logger.error("Failed to list Backroll jobs due to: {}", e.getMessage());
}
- return null;
+ return StringUtils.isEmpty(url) ? null : url;
}
- public List getBackupOfferings(String idTask) {
+ public List getBackupOfferings(String idTask) throws KeyManagementException, ParseException, NoSuchAlgorithmException, IOException {
logger.info("Trying to list backroll backup policies");
loginIfAuthenticationFailed();
+ final List policies = new ArrayList<>();
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();
+ return policies;
}
- public boolean restoreVMFromBackup(final String vmId, final String backupName) {
+ public boolean restoreVMFromBackup(final String vmId, final String backupName) throws KeyManagementException, ParseException, NoSuchAlgorithmException, IOException {
logger.info("Start restore backup with backroll with backup {} for vm {}", backupName, vmId);
loginIfAuthenticationFailed();
+ boolean isRestoreOk = false;
try {
JSONObject jsonBody = new JSONObject();
@@ -202,29 +212,31 @@ public boolean restoreVMFromBackup(final String vmId, final String backupName) {
logger.error("Backroll Error: {}", e.getMessage());
}
- String urlToRequest = this
- .