From 3e90f8e4607e590ce502a50f14021256fad0a14a Mon Sep 17 00:00:00 2001
From: Pierre Charton
Date: Mon, 28 Oct 2024 20:38:20 +0100
Subject: [PATCH] WIP
---
.../backup/BackrollBackupProvider.java | 89 +++--
.../backup/backroll/BackrollClient.java | 322 ++++++++++++------
.../backroll/model/response/TaskState.java | 16 +
3 files changed, 300 insertions(+), 127 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 96452d5a803..a245a3f8be6 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.cloudstack.framework.config.Configurable;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-
+import org.apache.http.ParseException;
import org.joda.time.DateTime;
import 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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
@Override
public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) {
logger.debug("Restoring vm {} from backup {} on the backroll Backup Provider", vm.getUuid(), backup.getUuid());
- 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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
continue;
}
- Metric metric = getClient(zoneId).getVirtualMachineMetrics(vm.getUuid());
+ Metric metric;
+ try {
+ metric = getClient(zoneId).getVirtualMachineMetrics(vm.getUuid());
+ } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
+ throw new CloudRuntimeException("Failed to retrieve backup metrics");
+ }
logger.debug("Metrics for VM [uuid: {}, name: {}] is [backup size: {}, data size: {}].", vm.getUuid(),
vm.getInstanceName(), metric.getBackupSize(), metric.getDataSize());
metrics.put(vm, metric);
@@ -151,14 +167,18 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
for (Backup backup : backupsInCs) {
logger.debug("Trying to remove backup with id {}", backup.getId());
- 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())){
- isAnyProblemWhileRemovingBackups = true;
+ try {
+ 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())){
+ isAnyProblemWhileRemovingBackups = true;
+ }
+ logger.info("Backup {} deleted in CS for virtual machine {}", backup.getId(), vm.getName());
+ } else {
+ isAnyProblemWhileRemovingBackups = false;
}
- logger.info("Backup {} deleted in CS for virtual machine {}", backup.getId(), vm.getName());
- } else {
- isAnyProblemWhileRemovingBackups = false;
+ } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
+ throw new CloudRuntimeException("Failed to remove VM from backup offering");
}
}
@@ -178,7 +198,12 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
logger.info("Starting backup for VM ID {} on backroll provider", vm.getUuid());
final BackrollClient client = getClient(vm.getDataCenterId());
- String idBackupTask = client.startBackupJob(vm.getUuid());
+ String idBackupTask;
+ try {
+ idBackupTask = client.startBackupJob(vm.getUuid());
+ } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
+ throw new CloudRuntimeException("Failed to take backup");
+ }
if (!StringUtils.isEmpty(idBackupTask)) {
BackupVO backup = new BackupVO();
backup.setVmId(vm.getId());
@@ -206,7 +231,13 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
for (Backup backup : backupsInDb) {
if (backup.getStatus().equals(Backup.Status.BackingUp)) {
- BackrollTaskStatus response = client.checkBackupTaskStatus(backup.getExternalId());
+ BackrollTaskStatus response;
+ try {
+ response = client.checkBackupTaskStatus(backup.getExternalId());
+ } catch (KeyManagementException | ParseException | NoSuchAlgorithmException | IOException e) {
+ throw new CloudRuntimeException("Failed to sync backups");
+ }
+
if (response != null) {
logger.debug("backroll backup id: {}", backup.getExternalId());
logger.debug("backroll backup status: {}", response.getState());
@@ -231,7 +262,13 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
backupToUpdate.setStatus(Backup.Status.BackedUp);
backupToUpdate.setExternalId(backup.getExternalId() + "," + response.getInfo());
- BackrollBackupMetrics backupMetrics = client.getBackupMetrics(vm.getUuid() , response.getInfo());
+ BackrollBackupMetrics backupMetrics = null;
+ try {
+ backupMetrics = client.getBackupMetrics(vm.getUuid() , response.getInfo());
+ } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
+ throw new CloudRuntimeException("Failed to get backup metrics");
+ }
+
if (backupMetrics != null) {
backupToUpdate.setSize(backupMetrics.getDeduplicated()); // real size
backupToUpdate.setProtectedSize(backupMetrics.getSize()); // total size
@@ -247,7 +284,13 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
}
} 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);
+ BackrollBackupMetrics backupMetrics;
+ try {
+ backupMetrics = client.getBackupMetrics(vm.getUuid() , backupId);
+ } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
+ throw new CloudRuntimeException("Failed to get backup metrics");
+ }
+
if (backupMetrics != null) {
BackupVO backupToUpdate = ((BackupVO) backup);
backupToUpdate.setSize(backupMetrics.getDeduplicated()); // real size
@@ -338,9 +381,13 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
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 {
+ if (getClient(backup.getZoneId()).deleteBackup(vm.getUuid(), getBackupName(backup))) {
+ logger.debug("Backup deletion for backup {} complete on backroll side.", backup.getUuid());
+ return deleteBackupInDb(backup);
+ }
+ } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
+ throw new CloudRuntimeException("Failed to delete backup");
}
}
}
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 e7021d4276b..345777ff06a 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,8 +62,8 @@ 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.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
@@ -71,6 +71,7 @@ import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
@@ -93,15 +94,15 @@ public class BackrollClient {
private Logger logger = LogManager.getLogger(BackrollClient.class);
- private int restoreTimeout;
-
private final URI apiURI;
- private final HttpClient httpClient;
-
private String backrollToken = null;
private String appname = null;
private String password = null;
+ private boolean validateCertificate = false;
+ private RequestConfig config = null;
+
+ private int restoreTimeout;
public BackrollClient(final String url, final String appname, final String password,
final boolean validateCertificate, final int timeout,
@@ -112,83 +113,92 @@ public class BackrollClient {
this.appname = appname;
this.password = password;
- final RequestConfig config = RequestConfig.custom()
- .setConnectTimeout(timeout * 1000)
- .setConnectionRequestTimeout(timeout * 1000)
- .setSocketTimeout(timeout * 1000)
+ this.config = RequestConfig.custom()
+ .setConnectTimeout(timeout * 1000)
+ .setConnectionRequestTimeout(timeout * 1000)
+ .setSocketTimeout(timeout * 1000)
+ .build();
+ }
+
+ private CloseableHttpClient createHttpClient() throws KeyManagementException, NoSuchAlgorithmException {
+ if(!validateCertificate) {
+ SSLContext sslContext = SSLUtils.getSSLContext();
+ sslContext.init(null, new X509TrustManager[] { new TrustAllManager() }, new SecureRandom());
+ final SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
+ return HttpClientBuilder.create()
+ .setDefaultRequestConfig(config)
+ .setSSLSocketFactory(factory)
.build();
-
- if (!validateCertificate) {
- final SSLContext sslcontext = SSLUtils.getSSLContext();
- sslcontext.init(null, new X509TrustManager[] { new TrustAllManager() }, new SecureRandom());
- final SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
- NoopHostnameVerifier.INSTANCE);
- this.httpClient = HttpClientBuilder.create()
- .setDefaultRequestConfig(config)
- .setSSLSocketFactory(factory)
- .build();
} else {
- this.httpClient = HttpClientBuilder.create()
- .setDefaultRequestConfig(config)
- .build();
- }
-
- if (StringUtils.isEmpty(backrollToken) || !isAuthenticated()) {
- login(appname, password);
+ return HttpClientBuilder.create()
+ .setDefaultRequestConfig(config)
+ .build();
}
}
- public String startBackupJob(final String jobId) {
+ private void closeConnection(CloseableHttpResponse closeableHttpResponse) throws IOException {
+ closeableHttpResponse.close();
+ }
+
+ public String startBackupJob(final String jobId) throws KeyManagementException, NoSuchAlgorithmException, IOException {
logger.info("Trying to start backup for Backroll job: {}", jobId);
+ String backupJob = "";
+
+ loginIfAuthenticationFailed();
try {
- loginIfAuthenticationFailed();
- return this.parse(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 class BackrollClient {
logger.error("Backroll Error: {}", e.getMessage());
}
- 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);
+ CloseableHttpResponse response = post(String.format("/tasks/restore/%s", vmId), jsonBody);
+ String result = okBody(response);
+ BackrollTaskRequestResponse requestResponse = parse(result);
+ response.close();
+ String urlToRequest = requestResponse.location.replace("/api/v1", "");
+ TaskStateResponse taskResponse = waitGet(urlToRequest);
+ logger.debug("RESTORE {}", taskResponse.state);
+ isRestoreOk = taskResponse.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());
}
+ return isRestoreOk;
}
- public BackrollTaskStatus checkBackupTaskStatus(String taskId) {
+ public BackrollTaskStatus checkBackupTaskStatus(String taskId) throws KeyManagementException, ParseException, NoSuchAlgorithmException, IOException {
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));
@@ -237,8 +249,6 @@ public class BackrollClient {
status.setInfo(backupStatusSuccessRequestResponse.info);
}
- return status;
-
} catch (final NotOkBodyException e) {
// throw new CloudRuntimeException("Failed to retrieve backups status for this
// VM via Backroll");
@@ -247,31 +257,37 @@ public class BackrollClient {
} catch (final IOException e) {
logger.error("Failed to check backups status due to: {}", e.getMessage());
}
- return null;
+ return StringUtils.isEmpty(status.getState()) ? null : status;
}
- public boolean deleteBackup(final String vmId, final String backupName) {
+ public boolean deleteBackup(final String vmId, final String backupName) throws KeyManagementException, NoSuchAlgorithmException, IOException {
logger.info("Trying to delete backup {} for vm {} using Backroll", vmId, backupName);
loginIfAuthenticationFailed();
+ boolean isBackupDeleted = false;
+
try {
- String urlToRequest = this.parse(okBody(delete(
- String.format("/virtualmachines/%s/backups/%s", vmId, backupName)))).location
- .replace("/api/v1", "");
+
+ CloseableHttpResponse response = delete(String.format("/virtualmachines/%s/backups/%s", vmId, backupName));
+ String result = okBody(response);
+ BackrollTaskRequestResponse requestResponse = parse(result);
+ response.close();
+ String urlToRequest = requestResponse.location.replace("/api/v1", "");
BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
logger.debug(backrollBackupsFromVMResponse.state);
- return backrollBackupsFromVMResponse.state.equals(TaskState.SUCCESS);
+ isBackupDeleted = backrollBackupsFromVMResponse.state.equals(TaskState.SUCCESS);
} catch (final NotOkBodyException e) {
- return false;
+ isBackupDeleted = false;
} catch (final Exception e) {
+ isBackupDeleted = false;
logger.error("Failed to delete backup using Backroll due to: {}", e.getMessage());
}
- return false;
+ return isBackupDeleted;
}
- public Metric getVirtualMachineMetrics(final String vmId) {
+ public Metric getVirtualMachineMetrics(final String vmId) throws KeyManagementException, NoSuchAlgorithmException, IOException {
logger.info("Trying to retrieve virtual machine metric from Backroll for vm {}", vmId);
loginIfAuthenticationFailed();
@@ -280,9 +296,11 @@ public class BackrollClient {
try {
- String urlToRequest = this.parse(okBody(
- get(String.format("/virtualmachines/%s/repository", vmId)))).location.replace("/api/v1", "");
- logger.debug(urlToRequest);
+ CloseableHttpResponse response = get(String.format("/virtualmachines/%s/repository", vmId));
+ String result = okBody(response);
+ BackrollTaskRequestResponse requestResponse = parse(result);
+ response.close();
+ String urlToRequest = requestResponse.location.replace("/api/v1", "");
BackrollVmMetricsResponse vmMetricsResponse = waitGet(urlToRequest);
@@ -295,7 +313,7 @@ public class BackrollClient {
}
if (stats != null) {
long size = Long.parseLong(stats.totalSize);
- return new Metric(size, size);
+ metric = new Metric(size, size);
}
}
} catch (final Exception e) {
@@ -305,28 +323,34 @@ public class BackrollClient {
return metric;
}
- public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) {
+ public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) throws KeyManagementException, NoSuchAlgorithmException, IOException {
logger.info("Trying to get backup metrics for VM: {}, and backup: {}", vmId, backupId);
loginIfAuthenticationFailed();
+ BackrollBackupMetrics metrics = null;
+
try {
- String urlToRequest = this.parse(okBody(get(
- String.format("/virtualmachines/%s/backups/%s", vmId, backupId)))).location.replace("/api/v1", "");
+ CloseableHttpResponse response = get(String.format("/virtualmachines/%s/backups/%s", vmId, backupId));
+ String result = okBody(response);
+ BackrollTaskRequestResponse requestResponse = parse(result);
+ response.close();
+ String urlToRequest = requestResponse.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));
+ BackrollBackupMetricsResponse metricsResponse = waitGet(urlToRequest);
+ if (metricsResponse.info != null) {
+ metrics = new BackrollBackupMetrics(Long.parseLong(metricsResponse.info.originalSize),
+ Long.parseLong(metricsResponse.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;
+ return metrics;
}
public List getAllBackupsfromVirtualMachine(String vmId) {
@@ -336,17 +360,19 @@ public class BackrollClient {
try {
- String urlToRequest = this
- .parse(okBody(
- get(String.format("/virtualmachines/%s/backups", vmId)))).location
- .replace("/api/v1", "");
+ CloseableHttpResponse response = get(String.format("/virtualmachines/%s/backups", vmId));
+ String result = okBody(response);
+ BackrollTaskRequestResponse requestResponse = parse(result);
+ response.close();
+ String urlToRequest = requestResponse.location.replace("/api/v1", "");
+
logger.debug(urlToRequest);
- VirtualMachineBackupsResponse response = waitGet(urlToRequest);
+ VirtualMachineBackupsResponse virtualMachineBackupsResponse = waitGet(urlToRequest);
- if (response.state.equals(TaskState.SUCCESS)) {
- if (response.info.archives.size() > 0) {
- for (BackupInfos infos : response.info.archives) {
+ if (virtualMachineBackupsResponse.state.equals(TaskState.SUCCESS)) {
+ if (virtualMachineBackupsResponse.info.archives.size() > 0) {
+ for (BackupInfos infos : virtualMachineBackupsResponse.info.archives) {
var dateStart = new DateTime(infos.start);
backups.add(new BackrollVmBackup(infos.id, infos.name, dateStart.toDate()));
}
@@ -356,11 +382,12 @@ public class BackrollClient {
} catch (Exception e) {
e.printStackTrace();
}
-
return backups;
}
- private HttpResponse post(final String path, final JSONObject json) throws IOException {
+ private CloseableHttpResponse post(final String path, final JSONObject json) throws IOException, KeyManagementException, NoSuchAlgorithmException {
+ CloseableHttpClient httpClient = createHttpClient();
+
String xml = null;
StringEntity params = null;
if (json != null) {
@@ -378,30 +405,35 @@ public class BackrollClient {
request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + backrollToken);
request.setHeader("Content-type", "application/json");
- final HttpResponse response = httpClient.execute(request);
+ final CloseableHttpResponse response = httpClient.execute(request);
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 {
+ protected CloseableHttpResponse get(String path) throws IOException, KeyManagementException, NoSuchAlgorithmException {
+ CloseableHttpClient httpClient = createHttpClient();
+
String url = apiURI.toString() + path;
logger.debug("Backroll URL {}", url);
- final HttpGet request = new HttpGet(url);
+
+ HttpGet request = new HttpGet(url);
request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + backrollToken);
request.setHeader("Content-type", "application/json");
- final HttpResponse response = httpClient.execute(request);
+ CloseableHttpResponse response = httpClient.execute(request);
logger.debug("Response received in GET request is: {} for URL: {}.", response.toString(), url);
return response;
}
- protected HttpResponse delete(final String path) throws IOException {
+ protected CloseableHttpResponse delete(String path) throws IOException, KeyManagementException, NoSuchAlgorithmException {
+ CloseableHttpClient httpClient = createHttpClient();
+
String url = apiURI.toString() + path;
final HttpDelete request = new HttpDelete(url);
request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + backrollToken);
request.setHeader("Content-type", "application/json");
- final HttpResponse response = httpClient.execute(request);
+ final CloseableHttpResponse response = httpClient.execute(request);
logger.debug("Response received in GET request is: {} for URL: {}.", response.toString(), url);
return response;
}
@@ -414,18 +446,23 @@ public class BackrollClient {
private class NotOkBodyException extends Exception {
}
- private String okBody(final HttpResponse response)
+ private String okBody(final CloseableHttpResponse response)
throws ParseException, IOException, NotOkBodyException {
+ String result = "";
switch (response.getStatusLine().getStatusCode()) {
case HttpStatus.SC_OK:
case HttpStatus.SC_ACCEPTED:
HttpEntity bodyEntity = response.getEntity();
try {
- return EntityUtils.toString(bodyEntity);
+ result = EntityUtils.toString(bodyEntity);
+ EntityUtils.consumeQuietly(bodyEntity);
+ closeConnection(response);
+ return result;
} finally {
EntityUtils.consumeQuietly(bodyEntity);
}
default:
+ closeConnection(response);
throw new NotOkBodyException();
}
}
@@ -437,7 +474,7 @@ public class BackrollClient {
}
private T waitGet(String url)
- throws IOException, InterruptedException {
+ throws IOException, InterruptedException, KeyManagementException, ParseException, NoSuchAlgorithmException {
// int threshold = 30; // 5 minutes
int maxAttempts = 12; // 2 minutes
@@ -456,28 +493,90 @@ public class BackrollClient {
return null;
}
- private boolean isAuthenticated() {
+ private boolean isAuthenticated() throws KeyManagementException, NoSuchAlgorithmException {
boolean result = false;
+
+ if(StringUtils.isEmpty(backrollToken)) {
+ return result;
+ }
+
try {
- final HttpResponse response = post("/auth", null);
+ CloseableHttpResponse response = post("/auth", null);
result = isResponseAuthorized(response);
EntityUtils.consumeQuietly(response.getEntity());
+ closeConnection(response);
} catch (IOException e) {
logger.error("Failed to authenticate to Backroll due to: {}", e.getMessage());
}
return result;
}
- private void loginIfAuthenticationFailed() {
+ private void loginIfAuthenticationFailed() throws KeyManagementException, NoSuchAlgorithmException, IOException {
if (!isAuthenticated()) {
login(appname, password);
}
}
- private void login(final String appname, final String appsecret) {
- logger.debug("Backroll client - start login");
- final HttpPost request = new HttpPost(apiURI.toString() + "/login");
+ // private void login(final String appname, final String appsecret) throws IOException, KeyManagementException, NoSuchAlgorithmException {
+ // logger.info("Backroll client - start login");
+ // CloseableHttpClient httpClient = createHttpClient();
+ // CloseableHttpResponse response = null;
+ // final HttpPost request = new HttpPost(apiURI.toString() + "/login");
+ // request.addHeader("content-type", "application/json");
+ // 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);
+
+ // response = httpClient.execute(request);
+
+ // try {
+ // HttpEntity body = response.getEntity();
+ // String bodyStr = EntityUtils.toString(body);
+
+ // LoginApiResponse loginResponse = new ObjectMapper().readValue(bodyStr, LoginApiResponse.class);
+ // backrollToken = loginResponse.accessToken;
+ // logger.debug(String.format("Backroll client - Token : %s", backrollToken));
+
+ // EntityUtils.consumeQuietly(response.getEntity());
+
+ // if (StringUtils.isEmpty(loginResponse.accessToken)) {
+ // throw new CloudRuntimeException("Backroll token is not available to perform API requests");
+ // }
+ // } catch (final Exception e) {
+ // EntityUtils.consumeQuietly(response.getEntity());
+ // 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();
+ // }
+ // finally {
+ // closeConnection(response);
+ // }
+ // logger.info("Backroll client - end login");
+ // }
+
+ private void login(final String appname, final String appsecret) throws IOException, KeyManagementException, NoSuchAlgorithmException {
+ logger.debug("Backroll client - start login");
+
+ CloseableHttpClient httpClient = createHttpClient();
+ CloseableHttpResponse response = null;
+
+ final HttpPost request = new HttpPost(apiURI.toString() + "/login");
request.addHeader("content-type", "application/json");
JSONObject jsonBody = new JSONObject();
@@ -489,9 +588,13 @@ public class BackrollClient {
params = new StringEntity(jsonBody.toString());
request.setEntity(params);
- final HttpResponse response = httpClient.execute(request);
+ response = httpClient.execute(request);
try {
- LoginApiResponse loginResponse = parse(okBody(response));
+ String toto = okBody(response);
+ ObjectMapper objectMapper = new ObjectMapper();
+ logger.info("BACKROLL: " + toto);
+ LoginApiResponse loginResponse = objectMapper.readValue(toto, LoginApiResponse.class);
+ logger.info("ok");
backrollToken = loginResponse.accessToken;
logger.debug("Backroll client - Token : {}", backrollToken);
@@ -512,15 +615,22 @@ public class BackrollClient {
} catch (JSONException e) {
e.printStackTrace();
}
+ finally {
+ closeConnection(response);
+ }
logger.debug("Backroll client - end login");
}
- private List getBackrollBackups(final String vmId) {
+ private List getBackrollBackups(final String vmId) throws KeyManagementException, ParseException, NoSuchAlgorithmException {
try {
logger.info("start to list Backroll backups for vm {}", vmId);
- String urlToRequest = this
- .parse(okBody(get("/virtualmachines/" + vmId + "/backups"))).location
- .replace("/api/v1", "");
+
+ CloseableHttpResponse response = get("/virtualmachines/" + vmId + "/backups");
+ String result = okBody(response);
+ BackrollTaskRequestResponse requestResponse = parse(result);
+ response.close();
+ String urlToRequest = requestResponse.location.replace("/api/v1", "");
+
logger.debug(urlToRequest);
BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
@@ -539,4 +649,4 @@ public class BackrollClient {
}
return new ArrayList();
}
-}
+}
\ No newline at end of file
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
index e934b2ba621..a9abd43fd8b 100644
--- 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
@@ -1,3 +1,19 @@
+// 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;
public class TaskState {