You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ha...@apache.org on 2022/07/21 06:47:20 UTC
[cloudstack] branch main updated: [Veeam] externalize restore timeout (#6320)
This is an automated email from the ASF dual-hosted git repository.
harikrishna pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new 61e4e862c4 [Veeam] externalize restore timeout (#6320)
61e4e862c4 is described below
commit 61e4e862c4d4828d5e4e5089c9db034fb4d427b9
Author: SadiJr <sa...@gmail.com>
AuthorDate: Thu Jul 21 03:47:13 2022 -0300
[Veeam] externalize restore timeout (#6320)
* [Veeam] add global timeout configuration for backup restore process
* Use 'this'
* Address reviews
* Address reviews
Co-authored-by: SadiJr <sa...@scclouds.com.br>
---
.../cloudstack/backup/VeeamBackupProvider.java | 8 +++--
.../cloudstack/backup/veeam/VeeamClient.java | 38 +++++++++++++---------
.../cloudstack/backup/veeam/VeeamClientTest.java | 25 +++++++++++++-
3 files changed, 53 insertions(+), 18 deletions(-)
diff --git a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java
index 3781e208d3..072431c4a9 100644
--- a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java
+++ b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java
@@ -77,6 +77,9 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider,
private ConfigKey<Integer> VeeamApiRequestTimeout = new ConfigKey<>("Advanced", Integer.class, "backup.plugin.veeam.request.timeout", "300",
"The Veeam B&R API request timeout in seconds.", true, ConfigKey.Scope.Zone);
+ private static ConfigKey<Integer> VeeamRestoreTimeout = new ConfigKey<>("Advanced", Integer.class, "backup.plugin.veeam.restore.timeout", "600",
+ "The Veeam B&R API restore backup timeout in seconds.", true, ConfigKey.Scope.Zone);
+
@Inject
private VmwareDatacenterZoneMapDao vmwareDatacenterZoneMapDao;
@Inject
@@ -87,7 +90,7 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider,
private VeeamClient getClient(final Long zoneId) {
try {
return new VeeamClient(VeeamUrl.valueIn(zoneId), VeeamUsername.valueIn(zoneId), VeeamPassword.valueIn(zoneId),
- VeeamValidateSSLSecurity.valueIn(zoneId), VeeamApiRequestTimeout.valueIn(zoneId));
+ VeeamValidateSSLSecurity.valueIn(zoneId), VeeamApiRequestTimeout.valueIn(zoneId), VeeamRestoreTimeout.valueIn(zoneId));
} catch (URISyntaxException e) {
throw new CloudRuntimeException("Failed to parse Veeam API URL: " + e.getMessage());
} catch (NoSuchAlgorithmException | KeyManagementException e) {
@@ -318,7 +321,8 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider,
VeeamUsername,
VeeamPassword,
VeeamValidateSSLSecurity,
- VeeamApiRequestTimeout
+ VeeamApiRequestTimeout,
+ VeeamRestoreTimeout
};
}
diff --git a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java
index e8efc4fb67..2b80ca6654 100644
--- a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java
+++ b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamClient.java
@@ -94,10 +94,13 @@ public class VeeamClient {
private String veeamServerUsername;
private String veeamServerPassword;
private String veeamSessionId = null;
+ private int restoreTimeout;
private final int veeamServerPort = 22;
- public VeeamClient(final String url, final String username, final String password, final boolean validateCertificate, final int timeout) throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException {
+ public VeeamClient(final String url, final String username, final String password, final boolean validateCertificate, final int timeout,
+ final int restoreTimeout) throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException {
this.apiURI = new URI(url);
+ this.restoreTimeout = restoreTimeout;
final RequestConfig config = RequestConfig.custom()
.setConnectTimeout(timeout * 1000)
@@ -173,7 +176,7 @@ public class VeeamClient {
}
}
- private HttpResponse get(final String path) throws IOException {
+ protected HttpResponse get(final String path) throws IOException {
String url = apiURI.toString() + path;
final HttpGet request = new HttpGet(url);
request.setHeader(SESSION_HEADER, veeamSessionId);
@@ -274,7 +277,7 @@ public class VeeamClient {
return objectMapper.readValue(response.getEntity().getContent(), Task.class);
}
- private RestoreSession parseRestoreSessionResponse(HttpResponse response) throws IOException {
+ protected RestoreSession parseRestoreSessionResponse(HttpResponse response) throws IOException {
checkResponseOK(response);
final ObjectMapper objectMapper = new XmlMapper();
return objectMapper.readValue(response.getEntity().getContent(), RestoreSession.class);
@@ -297,18 +300,7 @@ public class VeeamClient {
String type = pair.second();
String path = url.replace(apiURI.toString(), "");
if (type.equals("RestoreSession")) {
- for (int j = 0; j < 120; j++) {
- HttpResponse relatedResponse = get(path);
- RestoreSession session = parseRestoreSessionResponse(relatedResponse);
- if (session.getResult().equals("Success")) {
- return true;
- }
- try {
- Thread.sleep(5000);
- } catch (InterruptedException ignored) {
- }
- }
- throw new CloudRuntimeException("Related job type: " + type + " was not successful");
+ return checkIfRestoreSessionFinished(type, path);
}
}
return true;
@@ -324,6 +316,22 @@ public class VeeamClient {
return false;
}
+ protected boolean checkIfRestoreSessionFinished(String type, String path) throws IOException {
+ for (int j = 0; j < this.restoreTimeout; j++) {
+ HttpResponse relatedResponse = get(path);
+ RestoreSession session = parseRestoreSessionResponse(relatedResponse);
+ if (session.getResult().equals("Success")) {
+ return true;
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ignored) {
+ LOG.trace(String.format("Ignoring InterruptedException [%s] when waiting for restore session finishes.", ignored.getMessage()));
+ }
+ }
+ throw new CloudRuntimeException("Related job type: " + type + " was not successful");
+ }
+
private Pair<String, String> getRelatedLinkPair(List<Link> links) {
for (Link link : links) {
if (link.getRel().equals("Related")) {
diff --git a/plugins/backup/veeam/src/test/java/org/apache/cloudstack/backup/veeam/VeeamClientTest.java b/plugins/backup/veeam/src/test/java/org/apache/cloudstack/backup/veeam/VeeamClientTest.java
index 7269abb249..7733384e4b 100644
--- a/plugins/backup/veeam/src/test/java/org/apache/cloudstack/backup/veeam/VeeamClientTest.java
+++ b/plugins/backup/veeam/src/test/java/org/apache/cloudstack/backup/veeam/VeeamClientTest.java
@@ -25,15 +25,20 @@ import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.times;
+import java.io.IOException;
import java.util.List;
import org.apache.cloudstack.backup.BackupOffering;
+import org.apache.cloudstack.backup.veeam.api.RestoreSession;
+import org.apache.http.HttpResponse;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
@@ -57,7 +62,7 @@ public class VeeamClientTest {
.withStatus(201)
.withHeader("X-RestSvcSessionId", "some-session-auth-id")
.withBody("")));
- client = new VeeamClient("http://localhost:9399/api/", adminUsername, adminPassword, true, 60);
+ client = new VeeamClient("http://localhost:9399/api/", adminUsername, adminPassword, true, 60, 600);
mockClient = Mockito.mock(VeeamClient.class);
Mockito.when(mockClient.getRepositoryNameFromJob(Mockito.anyString())).thenCallRealMethod();
}
@@ -139,4 +144,22 @@ public class VeeamClientTest {
String repositoryNameFromJob = mockClient.getRepositoryNameFromJob(backupName);
Assert.assertEquals("test", repositoryNameFromJob);
}
+
+ @Test
+ public void checkIfRestoreSessionFinishedTestTimeoutException() throws IOException {
+ try {
+ ReflectionTestUtils.setField(mockClient, "restoreTimeout", 10);
+ RestoreSession restoreSession = Mockito.mock(RestoreSession.class);
+ HttpResponse httpResponse = Mockito.mock(HttpResponse.class);
+ Mockito.when(mockClient.get(Mockito.anyString())).thenReturn(httpResponse);
+ Mockito.when(mockClient.parseRestoreSessionResponse(httpResponse)).thenReturn(restoreSession);
+ Mockito.when(restoreSession.getResult()).thenReturn("No Success");
+ Mockito.when(mockClient.checkIfRestoreSessionFinished(Mockito.eq("RestoreTest"), Mockito.eq("any"))).thenCallRealMethod();
+ mockClient.checkIfRestoreSessionFinished("RestoreTest", "any");
+ fail();
+ } catch (Exception e) {
+ Assert.assertEquals("Related job type: RestoreTest was not successful", e.getMessage());
+ }
+ Mockito.verify(mockClient, times(10)).get(Mockito.anyString());
+ }
}
\ No newline at end of file