mirror of https://github.com/apache/cloudstack.git
WIP error handling
This commit is contained in:
parent
8e3c8f7be5
commit
01c2238e45
|
|
@ -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.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<String> 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<String> 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<String> 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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
@Override
|
||||
public List<BackupOffering> 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<BackupOffering>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -104,7 +105,8 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
|
||||
@Override
|
||||
public boolean assignVMToBackupOffering(VirtualMachine vm, BackupOffering backupOffering) {
|
||||
logger.info("Creating VM backup for VM {} from backup offering {}", vm.getInstanceName(), backupOffering.getName());
|
||||
logger.info("Creating VM backup for VM {} from backup offering {}", vm.getInstanceName(),
|
||||
backupOffering.getName());
|
||||
((VMInstanceVO) vm).setBackupExternalId(backupOffering.getUuid());
|
||||
return true;
|
||||
}
|
||||
|
|
@ -112,8 +114,13 @@ 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));
|
||||
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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
return metrics;
|
||||
}
|
||||
|
||||
List<String> vmUuids = vms.stream().filter(Objects::nonNull).map(VirtualMachine::getUuid).collect(Collectors.toList());
|
||||
List<String> 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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
continue;
|
||||
}
|
||||
|
||||
Metric metric = getClient(zoneId).getVirtualMachineMetrics(vm.getUuid());
|
||||
logger.debug("Metrics for VM [uuid: {}, name: {}] is [backup size: {}, data size: {}].", vm.getUuid(),
|
||||
vm.getInstanceName(), metric.getBackupSize(), metric.getDataSize());
|
||||
metrics.put(vm, metric);
|
||||
try {
|
||||
Metric metric = getClient(zoneId).getVirtualMachineMetrics(vm.getUuid());
|
||||
logger.debug("Metrics for VM [uuid: {}, name: {}] is [backup size: {}, data size: {}].", vm.getUuid(),
|
||||
vm.getInstanceName(), metric.getBackupSize(), metric.getDataSize());
|
||||
metrics.put(vm, metric);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to get backup metrics for VM {} due to {}.", vm.getName(), e);
|
||||
}
|
||||
}
|
||||
return metrics;
|
||||
}
|
||||
|
|
@ -144,28 +156,30 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
public boolean removeVMFromBackupOffering(VirtualMachine vm) {
|
||||
logger.info("Removing VM ID {} from Backrool backup offering ", vm.getUuid());
|
||||
|
||||
boolean isAnyProblemWhileRemovingBackups = false;
|
||||
boolean everythingIsOk = true;
|
||||
|
||||
List<Backup> 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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
@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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
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<Backup> 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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
backupToUpdate.setStatus(Backup.Status.BackedUp);
|
||||
backupToUpdate.setExternalId(backup.getExternalId() + "," + response.getInfo());
|
||||
|
||||
BackrollBackupMetrics backupMetrics = client.getBackupMetrics(vm.getUuid() , response.getInfo());
|
||||
BackrollBackupMetrics backupMetrics = client.getBackupMetrics(vm.getUuid(),
|
||||
response.getInfo());
|
||||
if (backupMetrics != null) {
|
||||
backupToUpdate.setSize(backupMetrics.getDeduplicated()); // real size
|
||||
backupToUpdate.setProtectedSize(backupMetrics.getSize()); // total size
|
||||
|
|
@ -244,16 +268,19 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
logger.info("Backroll mise à jour enregistrée");
|
||||
backupDao.remove(backup.getId());
|
||||
}
|
||||
}
|
||||
} else if (backup.getStatus().equals(Backup.Status.BackedUp) && backup.getSize().equals(0L)) {
|
||||
String backupId = backup.getExternalId().contains(",") ? backup.getExternalId().split(",")[1] : backup.getExternalId();
|
||||
BackrollBackupMetrics backupMetrics = client.getBackupMetrics(vm.getUuid() , backupId);
|
||||
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 class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
// insert new backroll backup in CS
|
||||
for (BackrollVmBackup backupInBackroll : backupsFromBackroll) {
|
||||
Backup backupToFind = backupsInDb.stream()
|
||||
.filter(backupInDb -> backupInDb.getExternalId().contains(backupInBackroll.getName()))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
.filter(backupInDb -> backupInDb.getExternalId().contains(backupInBackroll.getName()))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
|
||||
if (backupToFind == null) {
|
||||
BackupVO backupToInsert = new BackupVO();
|
||||
|
|
@ -296,11 +323,12 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
// delete deleted backroll backup in CS
|
||||
backupsInDb = backupDao.listByVmId(null, vm.getId());
|
||||
for (Backup backup : backupsInDb) {
|
||||
String backupName = backup.getExternalId().contains(",") ? backup.getExternalId().split(",")[1] : backup.getExternalId();
|
||||
String backupName = backup.getExternalId().contains(",") ? backup.getExternalId().split(",")[1]
|
||||
: backup.getExternalId();
|
||||
BackrollVmBackup backupToFind = backupsFromBackroll.stream()
|
||||
.filter(backupInBackroll -> backupInBackroll.getName().contains(backupName))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
.filter(backupInBackroll -> backupInBackroll.getName().contains(backupName))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
|
||||
if (backupToFind == null) {
|
||||
BackupVO backupToUpdate = ((BackupVO) backup);
|
||||
|
|
@ -319,10 +347,10 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey[]{
|
||||
BackrollUrlConfigKey,
|
||||
BackrollAppNameConfigKey,
|
||||
BackrollPasswordConfigKey
|
||||
return new ConfigKey[] {
|
||||
BackrollUrlConfigKey,
|
||||
BackrollAppNameConfigKey,
|
||||
BackrollPasswordConfigKey
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -330,21 +358,24 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
public boolean deleteBackup(Backup backup, boolean forced) {
|
||||
logger.info("backroll delete backup id: {}", backup.getExternalId());
|
||||
if (backup.getStatus().equals(Backup.Status.BackingUp)) {
|
||||
throw new CloudRuntimeException("You can't delete a backup while it still 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 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
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 @@ public class BackrollBackupProvider extends AdapterBase implements BackupProvide
|
|||
}
|
||||
|
||||
@Override
|
||||
public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeUuid, String hostIp, String dataStoreUuid, Pair<String, VirtualMachine.State> vmNameAndState) {
|
||||
logger.debug("Restoring volume {} from backup {} on the Backroll Backup Provider", volumeUuid, backup.getUuid());
|
||||
public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeUuid, String hostIp,
|
||||
String dataStoreUuid, Pair<String, VirtualMachine.State> 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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,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.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 class BackrollClient {
|
|||
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.<BackrollTaskRequestResponse>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.<BackrollTaskRequestResponse>parse(okBody(get("/backup_policies"))).location.replace("/api/v1",
|
||||
"");
|
||||
}
|
||||
|
||||
public List<BackupOffering> getBackupOfferings(String idTask) {
|
||||
public List<BackupOffering> 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<BackupOffering> 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<BackupOffering> policies = new ArrayList<>();
|
||||
for (final BackrollBackupPolicyResponse policy : backupPoliciesResponse.backupPolicies) {
|
||||
policies.add(new BackrollOffering(policy.name, policy.id));
|
||||
}
|
||||
return new ArrayList<BackupOffering>();
|
||||
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");
|
||||
JSONObject jsonBody = new JSONObject();
|
||||
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());
|
||||
}
|
||||
String urlToRequest = this
|
||||
.<BackrollTaskRequestResponse>parse(okBody(
|
||||
post(String.format("/tasks/restore/%s", vmId), jsonBody))).location
|
||||
.replace("/api/v1", "");
|
||||
|
||||
String urlToRequest = this
|
||||
.<BackrollTaskRequestResponse>parse(okBody(
|
||||
post(String.format("/tasks/restore/%s", vmId), jsonBody))).location
|
||||
.replace("/api/v1", "");
|
||||
TaskStateResponse response = waitGet(urlToRequest);
|
||||
logger.debug("RESTORE {}", response.state);
|
||||
|
||||
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());
|
||||
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();
|
||||
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);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
} catch (final NotOkBodyException e) {
|
||||
// throw new CloudRuntimeException("Failed to retrieve backups status for this
|
||||
// VM via Backroll");
|
||||
logger.error("Failed to retrieve backups status for this VM via Backroll");
|
||||
|
||||
} catch (final IOException e) {
|
||||
logger.error("Failed to check backups status due to: {}", e.getMessage());
|
||||
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 class BackrollClient {
|
|||
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 class BackrollClient {
|
|||
|
||||
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 class BackrollClient {
|
|||
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.<BackrollTaskRequestResponse>parse(okBody(get(
|
||||
String.format("/virtualmachines/%s/backups/%s", vmId, backupId)))).location.replace("/api/v1", "");
|
||||
logger.debug(urlToRequest);
|
||||
|
||||
String urlToRequest = this.<BackrollTaskRequestResponse>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<BackrollVmBackup> getAllBackupsfromVirtualMachine(String vmId) {
|
||||
|
|
@ -380,7 +351,8 @@ public class BackrollClient {
|
|||
|
||||
final HttpResponse response = httpClient.execute(request);
|
||||
|
||||
logger.debug("Response received in POST request with body {} is: {} for URL {}.", xml, response.toString(), url);
|
||||
logger.debug("Response received in POST request with body {} is: {} for URL {}.", xml, response.toString(),
|
||||
url);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
|
@ -411,7 +383,17 @@ public class BackrollClient {
|
|||
|| 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 @@ public class BackrollClient {
|
|||
EntityUtils.consumeQuietly(bodyEntity);
|
||||
}
|
||||
default:
|
||||
throw new NotOkBodyException();
|
||||
throw new NotOkBodyException(response);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -436,24 +418,23 @@ public class BackrollClient {
|
|||
});
|
||||
}
|
||||
|
||||
private <T> T waitGet(String url)
|
||||
throws IOException, InterruptedException {
|
||||
// int threshold = 30; // 5 minutes
|
||||
int maxAttempts = 12; // 2 minutes
|
||||
private <T> 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 @@ public class BackrollClient {
|
|||
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 @@ public class BackrollClient {
|
|||
JSONObject jsonBody = new JSONObject();
|
||||
StringEntity params;
|
||||
|
||||
jsonBody.put("app_id", appname);
|
||||
jsonBody.put("app_secret", appsecret);
|
||||
params = new StringEntity(jsonBody.toString());
|
||||
request.setEntity(params);
|
||||
|
||||
final HttpResponse response = httpClient.execute(request);
|
||||
try {
|
||||
jsonBody.put("app_id", appname);
|
||||
jsonBody.put("app_secret", appsecret);
|
||||
params = new StringEntity(jsonBody.toString());
|
||||
request.setEntity(params);
|
||||
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<BackrollBackup> getBackrollBackups(final String vmId) {
|
||||
try {
|
||||
logger.info("start to list Backroll backups for vm {}", vmId);
|
||||
String urlToRequest = this
|
||||
.<BackrollTaskRequestResponse>parse(okBody(get("/virtualmachines/" + vmId + "/backups"))).location
|
||||
.replace("/api/v1", "");
|
||||
logger.debug(urlToRequest);
|
||||
BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
|
||||
private List<BackrollBackup> getBackrollBackups(final String vmId) throws JsonMappingException,
|
||||
JsonProcessingException, ParseException, IOException, NotOkBodyException, InterruptedException {
|
||||
|
||||
final List<BackrollBackup> 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
|
||||
.<BackrollTaskRequestResponse>parse(okBody(get("/virtualmachines/" + vmId + "/backups"))).location
|
||||
.replace("/api/v1", "");
|
||||
logger.debug(urlToRequest);
|
||||
BackrollBackupsFromVMResponse backrollBackupsFromVMResponse = waitGet(urlToRequest);
|
||||
|
||||
final List<BackrollBackup> backups = new ArrayList<>();
|
||||
for (final BackrollArchiveResponse archive : backrollBackupsFromVMResponse.archives.archives) {
|
||||
backups.add(new BackrollBackup(archive.name));
|
||||
logger.debug(archive.name);
|
||||
}
|
||||
return new ArrayList<BackrollBackup>();
|
||||
return backups;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue