Skip to content

Commit fa8faf5

Browse files
committed
Update BackrollProvider from BackupProvider
1 parent cfad834 commit fa8faf5

File tree

3 files changed

+127
-42
lines changed

3 files changed

+127
-42
lines changed

plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/BackrollBackupProvider.java

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929

3030
import javax.inject.Inject;
3131

32+
3233
import org.apache.cloudstack.backup.Backup.Metric;
34+
import org.apache.cloudstack.backup.Backup.RestorePoint;
3335
import org.apache.cloudstack.backup.backroll.BackrollClient;
3436
import org.apache.cloudstack.backup.backroll.model.BackrollBackupMetrics;
3537
import org.apache.cloudstack.backup.backroll.model.BackrollTaskStatus;
@@ -153,6 +155,9 @@ public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) {
153155

154156
@Override
155157
public Map<VirtualMachine, Backup.Metric> getBackupMetrics(Long zoneId, List<VirtualMachine> vms) {
158+
Long vmBackupSize=0L;
159+
Long vmBackupProtectedSize=0L;
160+
156161
final Map<VirtualMachine, Backup.Metric> metrics = new HashMap<>();
157162
if (CollectionUtils.isEmpty(vms)) {
158163
logger.warn("Unable to get VM Backup Metrics because the list of VMs is empty.");
@@ -170,7 +175,13 @@ public Map<VirtualMachine, Backup.Metric> getBackupMetrics(Long zoneId, List<Vir
170175

171176
Metric metric;
172177
try {
173-
metric = client.getVirtualMachineMetrics(vm.getUuid());
178+
final List<BackrollVmBackup> backups = client.getAllBackupsfromVirtualMachine(vm.getUuid());
179+
for (BackrollVmBackup backup : backups ) {
180+
BackrollBackupMetrics backupMetric = client.getBackupMetrics(vm.getUuid(), backup.getId());
181+
vmBackupProtectedSize += backupMetric.getDeduplicated();
182+
vmBackupSize += backupMetric.getSize();
183+
}
184+
metric = new Metric(vmBackupSize, vmBackupProtectedSize);
174185
} catch (BackrollApiException | IOException e) {
175186
throw new CloudRuntimeException("Failed to retrieve backup metrics");
176187
}
@@ -192,7 +203,7 @@ public boolean willDeleteBackupsOnOfferingRemoval() {
192203
}
193204

194205
@Override
195-
public boolean takeBackup(VirtualMachine vm) {
206+
public Pair<Boolean, Backup> takeBackup(VirtualMachine vm) {
196207
logger.info("Starting backup for VM ID {} on backroll provider", vm.getUuid());
197208
final BackrollClient client = getClient(vm.getDataCenterId());
198209

@@ -215,18 +226,16 @@ public boolean takeBackup(VirtualMachine vm) {
215226
backup.setZoneId(vm.getDataCenterId());
216227
Boolean result = backupDao.persist(backup) != null;
217228
client.triggerTaskStatus(urlToRequest);
218-
syncBackups(vm, null);
219-
return result;
229+
return new Pair<Boolean,Backup>(result, backup);
220230
}
221231
} catch (ParseException | BackrollApiException | IOException e) {
222232
logger.debug(e.getMessage());
223233
throw new CloudRuntimeException("Failed to take backup");
224234
}
225-
return false;
235+
return new Pair<Boolean,Backup>(false, null);
226236
}
227237

228238

229-
@Override
230239
public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
231240
logger.info("Starting sync backup for VM ID " + vm.getUuid() + " on backroll provider");
232241

@@ -401,6 +410,7 @@ private boolean deleteBackupInDb(Backup backup) {
401410
backupToUpdate.setStatus(Backup.Status.Removed);
402411
if (backupDao.persist(backupToUpdate) != null) {
403412
logger.debug("Backroll backup {} deleted in database.", backup.getUuid());
413+
VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(backup.getVmId());
404414
return true;
405415
}
406416
return false;
@@ -433,4 +443,47 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeU
433443
logger.debug("Restoring volume {} from backup {} on the Backroll Backup Provider", volumeUuid, backup.getUuid());
434444
throw new CloudRuntimeException("Backroll plugin does not support this feature");
435445
}
446+
447+
@Override
448+
public List<RestorePoint> listRestorePoints(VirtualMachine vm) {
449+
try {
450+
final BackrollClient client = getClient(vm.getDataCenterId());
451+
return client.listRestorePoints(vm.getUuid());
452+
} catch (BackrollApiException | IOException e) {
453+
logger.error(e);
454+
throw new CloudRuntimeException("Failed to delete backup");
455+
}
456+
}
457+
458+
@Override
459+
public Backup createNewBackupEntryForRestorePoint(RestorePoint restorePoint, VirtualMachine vm, Metric metric) {
460+
final BackrollClient client = getClient(vm.getDataCenterId());
461+
BackupVO backupToInsert = new BackupVO();
462+
backupToInsert.setVmId(vm.getId());
463+
backupToInsert.setExternalId(restorePoint.getId());
464+
backupToInsert.setType("INCREMENTAL");
465+
backupToInsert.setDate(restorePoint.getCreated());
466+
backupToInsert.setStatus(Backup.Status.BackedUp);
467+
backupToInsert.setBackupOfferingId(vm.getBackupOfferingId());
468+
backupToInsert.setAccountId(vm.getAccountId());
469+
backupToInsert.setDomainId(vm.getDomainId());
470+
backupToInsert.setZoneId(vm.getDataCenterId());
471+
if(metric == null || metric.getBackupSize().equals(0L)){
472+
try {
473+
BackrollBackupMetrics backupMetrics = client.getBackupMetrics(vm.getUuid() , restorePoint.getId());
474+
if (backupMetrics != null) {
475+
backupToInsert.setSize(backupMetrics.getDeduplicated()); // real size
476+
backupToInsert.setProtectedSize(backupMetrics.getSize()); // total size
477+
}
478+
} catch (BackrollApiException | IOException e) {
479+
logger.error(e);
480+
throw new CloudRuntimeException("Failed to get backup metrics");
481+
}
482+
}else{
483+
backupToInsert.setSize(metric.getBackupSize());
484+
backupToInsert.setProtectedSize(metric.getDataSize());
485+
}
486+
backupDao.persist(backupToInsert);
487+
return backupToInsert;
488+
}
436489
}

plugins/backup/backroll/src/main/java/org/apache/cloudstack/backup/backroll/BackrollClient.java

Lines changed: 66 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.security.NoSuchAlgorithmException;
2323
import java.util.ArrayList;
2424
import java.util.List;
25+
26+
import org.apache.cloudstack.backup.Backup;
2527
import org.apache.cloudstack.backup.BackupOffering;
2628
import org.apache.cloudstack.backup.Backup.Metric;
2729
import org.apache.cloudstack.backup.backroll.model.BackrollBackupMetrics;
@@ -42,7 +44,6 @@
4244
import org.apache.cloudstack.backup.backroll.model.response.policy.BackupPoliciesResponse;
4345
import org.apache.cloudstack.backup.backroll.utils.BackrollApiException;
4446
import org.apache.cloudstack.backup.backroll.utils.BackrollHttpClientProvider;
45-
4647
import org.apache.commons.lang3.StringUtils;
4748

4849
import org.apache.logging.log4j.LogManager;
@@ -54,8 +55,6 @@
5455
import org.json.JSONObject;
5556
import com.fasterxml.jackson.databind.ObjectMapper;
5657

57-
58-
5958
public class BackrollClient {
6059

6160
protected Logger logger = LogManager.getLogger(BackrollClient.class);
@@ -71,16 +70,18 @@ public BackrollClient(BackrollHttpClientProvider httpProvider)
7170
public String startBackupJob(final String jobId) throws IOException, BackrollApiException {
7271
logger.info("startBackupJob : Trying to start backup for Backroll job: {}", jobId);
7372
String backupJob = "";
74-
BackrollTaskRequestResponse requestResponse = httpProvider.post(String.format("/tasks/singlebackup/%s", jobId), null, BackrollTaskRequestResponse.class);
73+
BackrollTaskRequestResponse requestResponse = httpProvider.post(String.format("/tasks/singlebackup/%s", jobId),
74+
null, BackrollTaskRequestResponse.class);
7575
logger.info("startBackupJob : BackupJob status link: {}", requestResponse.location);
7676
backupJob = requestResponse.location.replace("/api/v1", "");
7777
return StringUtils.isEmpty(backupJob) ? null : backupJob;
7878
}
7979

80-
public String getBackupOfferingUrl() throws IOException, BackrollApiException {
80+
public String getBackupOfferingUrl() throws IOException, BackrollApiException {
8181
logger.info("Trying to get backroll backup policies url");
8282
String url = "";
83-
BackrollTaskRequestResponse requestResponse = httpProvider.get("/backup_policies", BackrollTaskRequestResponse.class);
83+
BackrollTaskRequestResponse requestResponse = httpProvider.get("/backup_policies",
84+
BackrollTaskRequestResponse.class);
8485
logger.info("BackrollClient:getBackupOfferingUrl:Apres Parse: " + requestResponse.location);
8586
url = requestResponse.location.replace("/api/v1", "");
8687
return StringUtils.isEmpty(url) ? null : url;
@@ -90,15 +91,17 @@ public List<BackupOffering> getBackupOfferings(String idTask) throws BackrollApi
9091
logger.info("Trying to list backroll backup policies");
9192
final List<BackupOffering> policies = new ArrayList<>();
9293
BackupPoliciesResponse backupPoliciesResponse = httpProvider.waitGet(idTask, BackupPoliciesResponse.class);
93-
logger.info("BackrollClient:getBackupOfferings:Apres Parse: " + backupPoliciesResponse.backupPolicies.get(0).name);
94+
logger.info(
95+
"BackrollClient:getBackupOfferings:Apres Parse: " + backupPoliciesResponse.backupPolicies.get(0).name);
9496
for (final BackrollBackupPolicyResponse policy : backupPoliciesResponse.backupPolicies) {
9597
policies.add(new BackrollOffering(policy.name, policy.id));
9698
}
9799

98100
return policies;
99101
}
100102

101-
public boolean restoreVMFromBackup(final String vmId, final String backupName) throws IOException, BackrollApiException {
103+
public boolean restoreVMFromBackup(final String vmId, final String backupName)
104+
throws IOException, BackrollApiException {
102105
logger.info("Start restore backup with backroll with backup {} for vm {}", backupName, vmId);
103106

104107
boolean isRestoreOk = false;
@@ -114,11 +117,12 @@ public boolean restoreVMFromBackup(final String vmId, final String backupName) t
114117
logger.error("Backroll Error: {}", e.getMessage());
115118
}
116119

117-
BackrollTaskRequestResponse requestResponse = httpProvider.post(String.format("/tasks/restore/%s", vmId), jsonBody, BackrollTaskRequestResponse.class);
120+
BackrollTaskRequestResponse requestResponse = httpProvider.post(String.format("/tasks/restore/%s", vmId),
121+
jsonBody, BackrollTaskRequestResponse.class);
118122
String urlToRequest = requestResponse.location.replace("/api/v1", "");
119123

120124
String result = httpProvider.waitGetWithoutParseResponse(urlToRequest);
121-
if(result.contains("SUCCESS")) {
125+
if (result.contains("SUCCESS")) {
122126
logger.debug("RESTORE SUCCESS content : " + result);
123127
logger.debug("RESTORE SUCCESS");
124128
isRestoreOk = true;
@@ -135,46 +139,52 @@ public BackrollTaskStatus checkBackupTaskStatus(String taskId) throws IOExceptio
135139
String backupResponse = httpProvider.getWithoutParseResponse("/status/" + taskId);
136140

137141
if (backupResponse.contains(TaskState.FAILURE) || backupResponse.contains(TaskState.PENDING)) {
138-
BackrollBackupStatusResponse backupStatusRequestResponse = new ObjectMapper().readValue(backupResponse, BackrollBackupStatusResponse.class);
142+
BackrollBackupStatusResponse backupStatusRequestResponse = new ObjectMapper().readValue(backupResponse,
143+
BackrollBackupStatusResponse.class);
139144
status.setState(backupStatusRequestResponse.state);
140145
} else {
141-
BackrollBackupStatusSuccessResponse backupStatusSuccessRequestResponse = new ObjectMapper().readValue(backupResponse, BackrollBackupStatusSuccessResponse.class);
146+
BackrollBackupStatusSuccessResponse backupStatusSuccessRequestResponse = new ObjectMapper()
147+
.readValue(backupResponse, BackrollBackupStatusSuccessResponse.class);
142148
status.setState(backupStatusSuccessRequestResponse.state);
143149
status.setInfo(backupStatusSuccessRequestResponse.info);
144150
}
145151

146152
return StringUtils.isEmpty(status.getState()) ? null : status;
147153
}
148154

149-
public boolean deleteBackup(final String vmId, final String backupName) throws IOException, BackrollApiException{
155+
public boolean deleteBackup(final String vmId, final String backupName) throws IOException, BackrollApiException {
150156
logger.info("Trying to delete backup {} for vm {} using Backroll", vmId, backupName);
151157
boolean isBackupDeleted = false;
152158

153-
BackrollTaskRequestResponse requestResponse = httpProvider.delete(String.format("/virtualmachines/%s/backups/%s", vmId, backupName), BackrollTaskRequestResponse.class);
159+
BackrollTaskRequestResponse requestResponse = httpProvider.delete(
160+
String.format("/virtualmachines/%s/backups/%s", vmId, backupName), BackrollTaskRequestResponse.class);
154161
String urlToRequest = requestResponse.location.replace("/api/v1", "");
155162

156-
BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = httpProvider.waitGet(urlToRequest, BackrollBackupsFromVMResponse.class);
163+
BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = httpProvider.waitGet(urlToRequest,
164+
BackrollBackupsFromVMResponse.class);
157165
logger.debug(backrollBackupsFromVMResponse.state);
158166
isBackupDeleted = backrollBackupsFromVMResponse.state.equals(TaskState.SUCCESS);
159167

160168
return isBackupDeleted;
161169
}
162170

163171
public void triggerTaskStatus(String urlToRequest)
164-
throws IOException, BackrollApiException{
165-
httpProvider.waitGetWithoutParseResponse(urlToRequest);
172+
throws IOException, BackrollApiException {
173+
httpProvider.waitGetWithoutParseResponse(urlToRequest);
166174
}
167175

168176
public Metric getVirtualMachineMetrics(final String vmId) throws IOException, BackrollApiException {
169177
logger.info("Trying to retrieve virtual machine metric from Backroll for vm {}", vmId);
170178

171179
Metric metric = new Metric(0L, 0L);
172180

173-
BackrollTaskRequestResponse requestResponse = httpProvider.get(String.format("/virtualmachines/%s/repository", vmId), BackrollTaskRequestResponse.class);
181+
BackrollTaskRequestResponse requestResponse = httpProvider
182+
.get(String.format("/virtualmachines/%s/repository", vmId), BackrollTaskRequestResponse.class);
174183

175184
String urlToRequest = requestResponse.location.replace("/api/v1", "");
176185

177-
BackrollVmMetricsResponse vmMetricsResponse = httpProvider.waitGet(urlToRequest, BackrollVmMetricsResponse.class);
186+
BackrollVmMetricsResponse vmMetricsResponse = httpProvider.waitGet(urlToRequest,
187+
BackrollVmMetricsResponse.class);
178188

179189
if (vmMetricsResponse != null && vmMetricsResponse.state.equals(TaskState.SUCCESS)) {
180190
logger.debug("SUCCESS ok");
@@ -192,45 +202,67 @@ public Metric getVirtualMachineMetrics(final String vmId) throws IOException, Ba
192202
return metric;
193203
}
194204

195-
public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId) throws IOException, BackrollApiException {
205+
public BackrollBackupMetrics getBackupMetrics(String vmId, String backupId)
206+
throws IOException, BackrollApiException {
196207
logger.info("Trying to get backup metrics for VM: {}, and backup: {}", vmId, backupId);
197208

198209
BackrollBackupMetrics metrics = null;
199210

200-
BackrollTaskRequestResponse requestResponse = httpProvider.get(String.format("/virtualmachines/%s/backups/%s", vmId, backupId), BackrollTaskRequestResponse.class);
211+
BackrollTaskRequestResponse requestResponse = httpProvider.get(
212+
String.format("/virtualmachines/%s/backups/%s", vmId, backupId), BackrollTaskRequestResponse.class);
201213

202214
String urlToRequest = requestResponse.location.replace("/api/v1", "");
203215

204216
logger.debug(urlToRequest);
205217

206-
BackrollBackupMetricsResponse metricsResponse = httpProvider.waitGet(urlToRequest, BackrollBackupMetricsResponse.class);
218+
BackrollBackupMetricsResponse metricsResponse = httpProvider.waitGet(urlToRequest,
219+
BackrollBackupMetricsResponse.class);
207220
if (metricsResponse.info != null) {
208221
metrics = new BackrollBackupMetrics(Long.parseLong(metricsResponse.info.originalSize),
209222
Long.parseLong(metricsResponse.info.deduplicatedSize));
210223
}
211224
return metrics;
212225
}
213226

214-
public List<BackrollVmBackup> getAllBackupsfromVirtualMachine(String vmId) throws BackrollApiException, IOException {
215-
logger.info("Trying to retrieve all backups for vm {}", vmId);
216-
227+
public List<BackrollVmBackup> getAllBackupsfromVirtualMachine(String vmId)
228+
throws BackrollApiException, IOException {
217229
List<BackrollVmBackup> backups = new ArrayList<BackrollVmBackup>();
230+
List<BackupInfos> backupInfos = getBackupInfosFromVm(vmId);
231+
if (backupInfos != null && backupInfos.size() > 0) {
232+
for (BackupInfos infos : backupInfos) {
233+
var dateStart = new DateTime(infos.start);
234+
backups.add(new BackrollVmBackup(infos.id, infos.name, dateStart.toDate()));
235+
}
236+
}
237+
return backups;
238+
}
218239

219-
BackrollTaskRequestResponse requestResponse = httpProvider.get(String.format("/virtualmachines/%s/backups", vmId), BackrollTaskRequestResponse.class);
240+
private List<BackupInfos> getBackupInfosFromVm(String vmId)
241+
throws BackrollApiException, IOException {
242+
logger.info("Trying to retrieve all backups for vm {}", vmId);
243+
BackrollTaskRequestResponse requestResponse = httpProvider
244+
.get(String.format("/virtualmachines/%s/backups", vmId), BackrollTaskRequestResponse.class);
220245

221246
String urlToRequest = requestResponse.location.replace("/api/v1", "");
222247
logger.debug(urlToRequest);
223-
VirtualMachineBackupsResponse virtualMachineBackupsResponse = httpProvider.waitGet(urlToRequest, VirtualMachineBackupsResponse.class);
224-
248+
VirtualMachineBackupsResponse virtualMachineBackupsResponse = httpProvider.waitGet(urlToRequest,
249+
VirtualMachineBackupsResponse.class);
225250
if (virtualMachineBackupsResponse.state.equals(TaskState.SUCCESS)) {
226-
if (virtualMachineBackupsResponse.info.archives.size() > 0) {
227-
for (BackupInfos infos : virtualMachineBackupsResponse.info.archives) {
228-
var dateStart = new DateTime(infos.start);
229-
backups.add(new BackrollVmBackup(infos.id, infos.name, dateStart.toDate()));
230-
}
231-
}
251+
return virtualMachineBackupsResponse.info.archives;
232252
}
253+
return null;
233254

255+
}
256+
257+
public List<Backup.RestorePoint> listRestorePoints(String vmId) throws BackrollApiException, IOException {
258+
List<Backup.RestorePoint> backups = new ArrayList<Backup.RestorePoint>();
259+
List<BackupInfos> backupInfos = getBackupInfosFromVm(vmId);
260+
if (backupInfos != null && backupInfos.size() > 0) {
261+
for (BackupInfos infos : backupInfos) {
262+
var dateStart = new DateTime(infos.start);
263+
backups.add(new Backup.RestorePoint(infos.id, dateStart.toDate(), "INCREMENTAL"));
264+
}
265+
}
234266
return backups;
235267
}
236268
}

plugins/backup/backroll/src/test/java/org/apache/cloudstack/backup/BackrollBackupProviderTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ public void takeBackup_Test() throws BackrollApiException, IOException {
110110
Mockito.doReturn(new BackupVO()).when(backupDao).persist(Mockito.any(BackupVO.class));
111111
Mockito.doNothing().when(clientMock).triggerTaskStatus(Mockito.anyString());
112112
syncBackups_Test();
113-
Boolean result = backupProvider.takeBackup(vmInstanceVO);
114-
assertTrue(result);
113+
Pair<Boolean, Backup> result = backupProvider.takeBackup(vmInstanceVO);
114+
assertTrue(result.first());
115115
}
116116

117117
@Test

0 commit comments

Comments
 (0)