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

Reply via email to