This is an automated email from the ASF dual-hosted git repository.
sureshanaparti 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 e993a20 [Veeam] Force ACS to use the template repository to clone job
(#5774)
e993a20 is described below
commit e993a20e5a86827a288ee31870543f1acdf305a3
Author: SadiJr <[email protected]>
AuthorDate: Fri Jan 7 02:42:57 2022 -0300
[Veeam] Force ACS to use the template repository to clone job (#5774)
* [Veeam] Force ACS to use the repository of the template to clone job
* Address reviews
* Fix checkstyle
Co-authored-by: SadiJr <[email protected]>
---
.../cloudstack/backup/veeam/VeeamClient.java | 34 +++++++++++--
.../cloudstack/backup/veeam/VeeamClientTest.java | 57 ++++++++++++++++++++++
2 files changed, 86 insertions(+), 5 deletions(-)
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 1012d5e..e8efc4f 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
@@ -337,25 +337,44 @@ public class VeeamClient {
//////////////// Public Veeam APIs /////////////////////
////////////////////////////////////////////////////////
- public Ref listBackupRepository(final String backupServerId) {
- LOG.debug("Trying to list backup repository for backup server id: " +
backupServerId);
+ public Ref listBackupRepository(final String backupServerId, final String
backupName) {
+ LOG.debug(String.format("Trying to list backup repository for backup
job [name: %s] in server [id: %s].", backupName, backupServerId));
try {
+ String repositoryName = getRepositoryNameFromJob(backupName);
final HttpResponse response =
get(String.format("/backupServers/%s/repositories", backupServerId));
checkResponseOK(response);
final ObjectMapper objectMapper = new XmlMapper();
final EntityReferences references =
objectMapper.readValue(response.getEntity().getContent(),
EntityReferences.class);
for (final Ref ref : references.getRefs()) {
- if (ref.getType().equals("RepositoryReference")) {
+ if (ref.getType().equals("RepositoryReference") &&
ref.getName().equals(repositoryName)) {
return ref;
}
}
} catch (final IOException e) {
- LOG.error("Failed to list Veeam jobs due to:", e);
+ LOG.error(String.format("Failed to list Veeam backup repository
used by backup job [name: %s] due to: [%s].", backupName, e.getMessage()), e);
checkResponseTimeOut(e);
}
return null;
}
+ protected String getRepositoryNameFromJob(String backupName) {
+ final List<String> cmds = Arrays.asList(
+ String.format("$Job = Get-VBRJob -name \"%s\"", backupName),
+ "$Job.GetBackupTargetRepository() ^| select Name | Format-List"
+ );
+ Pair<Boolean, String> result = executePowerShellCommands(cmds);
+ if (result == null || !result.first()) {
+ throw new CloudRuntimeException(String.format("Failed to get
Repository Name from Job [name: %s].", backupName));
+ }
+
+ for (String block : result.second().split("\n\n")) {
+ if (block.matches("Name(\\s)+:(.)*")) {
+ return block.split(":")[1].trim();
+ }
+ }
+ throw new CloudRuntimeException(String.format("Can't find any
repository name for Job [name: %s].", backupName));
+ }
+
public void listAllBackups() {
LOG.debug("Trying to list Veeam backups");
try {
@@ -439,7 +458,12 @@ public class VeeamClient {
public boolean cloneVeeamJob(final Job parentJob, final String
clonedJobName) {
LOG.debug("Trying to clone veeam job: " + parentJob.getUid() + " with
backup uuid: " + clonedJobName);
try {
- final Ref repositoryRef =
listBackupRepository(parentJob.getBackupServerId());
+ final Ref repositoryRef =
listBackupRepository(parentJob.getBackupServerId(), parentJob.getName());
+ if (repositoryRef == null) {
+ throw new CloudRuntimeException(String.format("Failed to clone
backup job because couldn't find any "
+ + "repository associated with backup job [id: %s, uid:
%s, backupServerId: %s, name: %s].",
+ parentJob.getId(), parentJob.getUid(),
parentJob.getBackupServerId(), parentJob.getName()));
+ }
final BackupJobCloneInfo cloneInfo = new BackupJobCloneInfo();
cloneInfo.setJobName(clonedJobName);
cloneInfo.setFolderName(clonedJobName);
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 3af81d0..7269abb 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
@@ -24,6 +24,7 @@ import static
com.github.tomakehurst.wiremock.client.WireMock.post;
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 java.util.List;
@@ -32,7 +33,10 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.mockito.Mockito;
+import com.cloud.utils.Pair;
+import com.cloud.utils.exception.CloudRuntimeException;
import com.github.tomakehurst.wiremock.client.BasicCredentials;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
@@ -41,6 +45,7 @@ public class VeeamClientTest {
private String adminUsername = "administrator";
private String adminPassword = "password";
private VeeamClient client;
+ private VeeamClient mockClient;
@Rule
public WireMockRule wireMockRule = new WireMockRule(9399);
@@ -53,6 +58,8 @@ public class VeeamClientTest {
.withHeader("X-RestSvcSessionId",
"some-session-auth-id")
.withBody("")));
client = new VeeamClient("http://localhost:9399/api/", adminUsername,
adminPassword, true, 60);
+ mockClient = Mockito.mock(VeeamClient.class);
+
Mockito.when(mockClient.getRepositoryNameFromJob(Mockito.anyString())).thenCallRealMethod();
}
@Test
@@ -82,4 +89,54 @@ public class VeeamClientTest {
Assert.assertEquals(policies.size(), 1);
Assert.assertEquals(policies.get(0).getName(), "ZONE1-GOLD");
}
+
+ @Test
+ public void getRepositoryNameFromJobTestExceptionCmdWithoutResult() throws
Exception {
+ String backupName = "TEST-BACKUP";
+ try {
+
Mockito.doReturn(null).when(mockClient).executePowerShellCommands(Mockito.anyList());
+ mockClient.getRepositoryNameFromJob(backupName);
+ fail();
+ } catch (Exception e) {
+ Assert.assertEquals(CloudRuntimeException.class, e.getClass());
+ Assert.assertEquals("Failed to get Repository Name from Job [name:
TEST-BACKUP].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void getRepositoryNameFromJobTestExceptionCmdWithFalseResult() {
+ String backupName = "TEST-BACKUP2";
+ Pair<Boolean, String> response = new Pair<Boolean,
String>(Boolean.FALSE, "");
+
Mockito.doReturn(response).when(mockClient).executePowerShellCommands(Mockito.anyList());
+ try {
+ mockClient.getRepositoryNameFromJob(backupName);
+ fail();
+ } catch (Exception e) {
+ Assert.assertEquals(CloudRuntimeException.class, e.getClass());
+ Assert.assertEquals("Failed to get Repository Name from Job [name:
TEST-BACKUP2].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void
getRepositoryNameFromJobTestExceptionWhenResultIsInWrongFormat() {
+ String backupName = "TEST-BACKUP3";
+ Pair<Boolean, String> response = new Pair<Boolean,
String>(Boolean.TRUE, "\nName:\n\nName-test");
+
Mockito.doReturn(response).when(mockClient).executePowerShellCommands(Mockito.anyList());
+ try {
+ mockClient.getRepositoryNameFromJob(backupName);
+ fail();
+ } catch (Exception e) {
+ Assert.assertEquals(CloudRuntimeException.class, e.getClass());
+ Assert.assertEquals("Can't find any repository name for Job [name:
TEST-BACKUP3].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void getRepositoryNameFromJobTestSuccess() throws Exception {
+ String backupName = "TEST-BACKUP3";
+ Pair<Boolean, String> response = new Pair<Boolean,
String>(Boolean.TRUE, "\n\nName : test");
+
Mockito.doReturn(response).when(mockClient).executePowerShellCommands(Mockito.anyList());
+ String repositoryNameFromJob =
mockClient.getRepositoryNameFromJob(backupName);
+ Assert.assertEquals("test", repositoryNameFromJob);
+ }
}
\ No newline at end of file