diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/AddVMToBackupPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/AddVMToBackupPolicyCmd.java index f643cc07387..c6d12198a45 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/AddVMToBackupPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/AddVMToBackupPolicyCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.BackupPolicyResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.context.CallContext; @@ -66,10 +65,6 @@ public class AddVMToBackupPolicyCmd extends BaseCmd { description = "id of the backup policy") private Long policyId; - @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, - description = "the zone ID", required = true) - private Long zoneId; - ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -82,20 +77,6 @@ public class AddVMToBackupPolicyCmd extends BaseCmd { return policyId; } - public Long getZoneId() { - return zoneId; - } - - @Override - public String getCommandName() { - return AddVMToBackupPolicyCmd.APINAME.toLowerCase() + RESPONSE_SUFFIX; - } - - @Override - public long getEntityOwnerId() { - return CallContext.current().getCallingAccount().getId(); - } - ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -103,7 +84,7 @@ public class AddVMToBackupPolicyCmd extends BaseCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try { - boolean result = backupManager.addVMToBackupPolicy(getZoneId(), getPolicyId(), getVmId()); + boolean result = backupManager.addVMToBackupPolicy(getPolicyId(), getVmId()); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); response.setResponseName(getCommandName()); @@ -115,4 +96,14 @@ public class AddVMToBackupPolicyCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } + + @Override + public String getCommandName() { + return AddVMToBackupPolicyCmd.APINAME.toLowerCase() + RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/CreateVMBackupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/CreateVMBackupCmd.java index e09e0f95e31..6855c999a8f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/CreateVMBackupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/CreateVMBackupCmd.java @@ -59,6 +59,8 @@ public class CreateVMBackupCmd extends BaseCmd { description = "id of the VM") private Long vmId; + //FIXME: add name, description etc.? + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPoliciesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPoliciesCmd.java index 4ac21ac7158..293bb33bf6c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPoliciesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPoliciesCmd.java @@ -99,7 +99,7 @@ public class ListBackupPoliciesCmd extends BaseBackupListCmd { } private void validateParameters() { - if (external && zoneId == null) { + if (isExternal() && getZoneId() == null) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please provide the zone id when external option is specified"); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPoliciesVMsMappingsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPolicyVMMappingsCmd.java similarity index 81% rename from api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPoliciesVMsMappingsCmd.java rename to api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPolicyVMMappingsCmd.java index f7b816d7c35..00ed936c1d5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPoliciesVMsMappingsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPolicyVMMappingsCmd.java @@ -29,6 +29,7 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.BackupPolicyResponse; +import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.backup.BackupPolicyVMMap; @@ -40,12 +41,12 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.utils.exception.CloudRuntimeException; -@APICommand(name = ListBackupPoliciesVMsMappingsCmd.APINAME, +@APICommand(name = ListBackupPolicyVMMappingsCmd.APINAME, description = "Lists VMs mapped to a backup policy", responseObject = BackupPolicyResponse.class, since = "4.12.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) -public class ListBackupPoliciesVMsMappingsCmd extends BaseBackupListCmd { - public static final String APINAME = "listBackupPoliciesVirtualMachineMappings"; +public class ListBackupPolicyVMMappingsCmd extends BaseBackupListCmd { + public static final String APINAME = "listBackupPolicyVMMappings"; @Inject private BackupManager backupManager; @@ -54,6 +55,10 @@ public class ListBackupPoliciesVMsMappingsCmd extends BaseBackupListCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, + description = "The id of the VM") + private Long vmId; + @Parameter(name = ApiConstants.POLICY_ID, type = BaseCmd.CommandType.UUID, entityType = BackupPolicyResponse.class, description = "The backup policy ID") private Long policyId; @@ -62,6 +67,22 @@ public class ListBackupPoliciesVMsMappingsCmd extends BaseBackupListCmd { description = "The zone ID") private Long zoneId; + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getVmId() { + return vmId; + } + + public Long getPolicyId() { + return policyId; + } + + public Long getZoneId() { + return zoneId; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -69,7 +90,7 @@ public class ListBackupPoliciesVMsMappingsCmd extends BaseBackupListCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try { - List mappings = backupManager.listBackupPolicyVMMappings(zoneId, policyId); + List mappings = backupManager.listBackupPolicyVMMappings(getVmId(), getZoneId(), getPolicyId()); setupResponseBackupPolicyVMMappings(mappings); } catch (CloudRuntimeException e) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RemoveVMFromBackupPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RemoveVMFromBackupPolicyCmd.java index c7cb6788441..c9c5518152a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RemoveVMFromBackupPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RemoveVMFromBackupPolicyCmd.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.BackupPolicyResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.context.CallContext; @@ -67,12 +66,6 @@ public class RemoveVMFromBackupPolicyCmd extends BaseCmd { description = "id of the backup policy") private Long policyId; - @Parameter(name = ApiConstants.ZONE_ID, - type = CommandType.UUID, - entityType = ZoneResponse.class, - description = "the zone ID", required = true) - private Long zoneId; - ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -85,8 +78,24 @@ public class RemoveVMFromBackupPolicyCmd extends BaseCmd { return policyId; } - public Long getZoneId() { - return zoneId; + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + try { + boolean result = backupManager.removeVMFromBackupPolicy(getPolicyId(), getVmId()); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove VM from backup policy"); + } + } catch (Exception e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } } @Override @@ -99,23 +108,4 @@ public class RemoveVMFromBackupPolicyCmd extends BaseCmd { return CallContext.current().getCallingAccount().getId(); } - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - - @Override - public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { - try { - boolean result = backupManager.removeVMFromBackupPolicy(getZoneId(), getPolicyId(), getVmId()); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - response.setResponseName(getCommandName()); - setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove VM from backup policy"); - } - } catch (Exception e) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); - } - } } diff --git a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java index bb89f126f6e..0a83ee0d60b 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java @@ -52,7 +52,17 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer /** * Assign VM to existing backup policy */ - boolean addVMToBackupPolicy(Long zoneId, Long policyId, Long virtualMachineId); + boolean addVMToBackupPolicy(Long policyId, Long virtualMachineId); + + /** + * Remove a VM from a backup policy + */ + boolean removeVMFromBackupPolicy(Long policyId, Long vmId); + + /** + * Return mappings between backup policy and VMs + */ + List listBackupPolicyVMMappings(Long vmId, Long zoneId, Long policyId); /** * List existing backups for a VM @@ -95,14 +105,4 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer * Deletes a backup policy */ boolean deleteBackupPolicy(Long policyId); - - /** - * Remove a VM from a backup policy - */ - boolean removeVMFromBackupPolicy(Long zoneId, Long policyId, Long vmId); - - /** - * Return mappings between backup policy and VMs - */ - List listBackupPolicyVMMappings(Long zoneId, Long policyId); } diff --git a/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java b/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java index d58457afbbf..0e3980b805b 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java @@ -50,12 +50,20 @@ public interface BackupProvider { * Assign VM to backup policy * @return true if VM is successfully assigned, false if not */ - boolean addVMToBackupPolicy(Long zoneId, BackupPolicy policy, VirtualMachine vm); + boolean addVMToBackupPolicy(BackupPolicy policy, VirtualMachine vm); /** * Remove a VM form a backup policy */ - boolean removeVMFromBackupPolicy(Long zoneId, BackupPolicy policy, VirtualMachine vm); + boolean removeVMFromBackupPolicy(BackupPolicy policy, VirtualMachine vm); + + /** + * Starts ad-hoc backup of a VM assigned to a policy + * @param policy + * @param vm + * @return true if backup successfully starts + */ + boolean startBackup(BackupPolicy policy, VirtualMachine vm); /** * Restore VM from backup diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyDaoImpl.java index 03eb8c5c004..972672ea476 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyDaoImpl.java @@ -17,22 +17,22 @@ package org.apache.cloudstack.backup.dao; +import java.util.ArrayList; +import java.util.List; + import javax.annotation.PostConstruct; import javax.inject.Inject; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.utils.db.SearchCriteria; import org.apache.cloudstack.api.response.BackupPolicyResponse; import org.apache.cloudstack.backup.BackupPolicy; import org.apache.cloudstack.backup.BackupPolicyVO; import org.springframework.stereotype.Component; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.DataCenterDao; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; - -import java.util.ArrayList; -import java.util.List; +import com.cloud.utils.db.SearchCriteria; @Component public class BackupPolicyDaoImpl extends GenericDaoBase implements BackupPolicyDao { @@ -71,7 +71,9 @@ public class BackupPolicyDaoImpl extends GenericDaoBase im @Override public List listByZone(Long zoneId) { SearchCriteria sc = backupPoliciesSearch.create(); - sc.setParameters("zone_id", zoneId); + if (zoneId != null) { + sc.setParameters("zone_id", zoneId); + } return new ArrayList<>(listBy(sc)); } } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyVMMapDao.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyVMMapDao.java index 94a5abf449c..61b0fdf9043 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyVMMapDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyVMMapDao.java @@ -19,18 +19,19 @@ package org.apache.cloudstack.backup.dao; -import com.cloud.utils.db.GenericDao; +import java.util.List; + import org.apache.cloudstack.api.response.BackupPolicyVMMapResponse; import org.apache.cloudstack.backup.BackupPolicyVMMap; import org.apache.cloudstack.backup.BackupPolicyVMMapVO; -import java.util.List; +import com.cloud.utils.db.GenericDao; public interface BackupPolicyVMMapDao extends GenericDao { BackupPolicyVMMapVO findByVMId(long vmId); List listByPolicyId(long policyId); List listByPolicyIdAndVMId(long policyId, long vmId); - List listByZoneId(long zoneId); + List listByZoneId(Long zoneId); BackupPolicyVMMapResponse newBackupPolicyVMMappingResponse(BackupPolicyVMMap map); } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyVMMapDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyVMMapDaoImpl.java index e18f4b15590..a4b0a37dba5 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyVMMapDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupPolicyVMMapDaoImpl.java @@ -19,6 +19,18 @@ package org.apache.cloudstack.backup.dao; +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; + +import org.apache.cloudstack.api.response.BackupPolicyVMMapResponse; +import org.apache.cloudstack.backup.BackupPolicyVMMap; +import org.apache.cloudstack.backup.BackupPolicyVMMapVO; +import org.apache.cloudstack.backup.BackupPolicyVO; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.stereotype.Component; + import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.utils.db.GenericDaoBase; @@ -27,16 +39,6 @@ import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.dao.VMInstanceDao; -import org.apache.cloudstack.api.response.BackupPolicyVMMapResponse; -import org.apache.cloudstack.backup.BackupPolicyVMMap; -import org.apache.cloudstack.backup.BackupPolicyVMMapVO; -import org.apache.cloudstack.backup.BackupPolicyVO; -import org.apache.commons.collections.CollectionUtils; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; -import java.util.List; @Component public class BackupPolicyVMMapDaoImpl extends GenericDaoBase implements BackupPolicyVMMapDao { @@ -94,9 +96,11 @@ public class BackupPolicyVMMapDaoImpl extends GenericDaoBase listByZoneId(long zoneId) { + public List listByZoneId(Long zoneId) { SearchCriteria sc = mapSearch.create(); - sc.setParameters("zone_id", zoneId); + if (zoneId != null) { + sc.setParameters("zone_id", zoneId); + } return listBy(sc); } diff --git a/plugins/backup/dummy/src/main/java/org/apache/cloudstack/backup/DummyBackupProvider.java b/plugins/backup/dummy/src/main/java/org/apache/cloudstack/backup/DummyBackupProvider.java index e3090f3c7a5..89164519001 100644 --- a/plugins/backup/dummy/src/main/java/org/apache/cloudstack/backup/DummyBackupProvider.java +++ b/plugins/backup/dummy/src/main/java/org/apache/cloudstack/backup/DummyBackupProvider.java @@ -57,17 +57,22 @@ public class DummyBackupProvider extends AdapterBase implements BackupProvider { } @Override - public boolean addVMToBackupPolicy(Long zoneId, BackupPolicy policy, VirtualMachine vm) { + public boolean addVMToBackupPolicy(BackupPolicy policy, VirtualMachine vm) { s_logger.debug("Assigning VM " + vm.getInstanceName() + " to backup policy " + policy.getName()); return true; } @Override - public boolean removeVMFromBackupPolicy(Long zoneId, BackupPolicy policy, VirtualMachine vm) { + public boolean removeVMFromBackupPolicy(BackupPolicy policy, VirtualMachine vm) { s_logger.debug("Removing VM " + vm.getInstanceName() + " from backup policy " + policy.getName()); return true; } + @Override + public boolean startBackup(BackupPolicy policy, VirtualMachine vm) { + return true; + } + @Override public boolean restoreVMFromBackup(String vmUuid, String backupUuid) { s_logger.debug("Restoring vm " + vmUuid + "from backup " + backupUuid + " on the Dummy Backup Provider"); diff --git a/plugins/backup/veeam/pom.xml b/plugins/backup/veeam/pom.xml index 88f31ac1988..b4ed81f373d 100644 --- a/plugins/backup/veeam/pom.xml +++ b/plugins/backup/veeam/pom.xml @@ -43,11 +43,17 @@ commons-lang3 ${cs.commons-lang3.version} - - org.apache.cloudstack - cloud-plugin-hypervisor-vmware - ${project.version} - + + org.apache.cloudstack + cloud-plugin-hypervisor-vmware + ${project.version} + + + com.github.tomakehurst + wiremock-standalone + ${cs.wiremock.version} + test + 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 fdf0fa8360f..9bed15b3d6d 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 @@ -116,15 +116,20 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider, } @Override - public boolean addVMToBackupPolicy(final Long zoneId, final BackupPolicy policy, final VirtualMachine vm) { + public boolean addVMToBackupPolicy(final BackupPolicy policy, final VirtualMachine vm) { final VmwareDatacenter vmwareDatacenter = findVmwareDatacenterForVM(vm); - return getClient(zoneId).addVMToVeeamJob(policy.getExternalId(), vm.getInstanceName(), vmwareDatacenter.getVcenterHost()); + return getClient(vm.getDataCenterId()).addVMToVeeamJob(policy.getExternalId(), vm.getInstanceName(), vmwareDatacenter.getVcenterHost()); } @Override - public boolean removeVMFromBackupPolicy(final Long zoneId, final BackupPolicy policy, final VirtualMachine vm) { + public boolean removeVMFromBackupPolicy(final BackupPolicy policy, final VirtualMachine vm) { final VmwareDatacenter vmwareDatacenter = findVmwareDatacenterForVM(vm); - return getClient(zoneId).removeVMFromVeeamJob(policy.getExternalId(), vm.getInstanceName(), vmwareDatacenter.getVcenterHost()); + return getClient(vm.getDataCenterId()).removeVMFromVeeamJob(policy.getExternalId(), vm.getInstanceName(), vmwareDatacenter.getVcenterHost()); + } + + @Override + public boolean startBackup(BackupPolicy policy, VirtualMachine vm) { + return getClient(vm.getDataCenterId()).startBackupJob(policy.getExternalId()); } @Override 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 44965d955a1..16e402a2372 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 @@ -312,7 +312,7 @@ public class VeeamClient { return new ArrayList<>(); } - public boolean startAdhocBackupJob(final String jobId) { + public boolean startBackupJob(final String jobId) { LOG.debug("Trying to start ad-hoc backup for Veeam job: " + jobId); try { final HttpResponse response = post(String.format("/jobs/%s?action=start", jobId), null); @@ -357,7 +357,7 @@ public class VeeamClient { return checkTaskStatus(deleteResponse); } } - return checkTaskStatus(response); + throw new CloudRuntimeException("VM was not found to be assigned to backup policy"); } catch (final IOException e) { LOG.error("Failed to list Veeam jobs due to:", e); checkResponseTimeOut(e); 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 48b0d8de54d..1eeb7a240b2 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 @@ -17,32 +17,69 @@ package org.apache.cloudstack.backup.veeam; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +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 java.util.List; + +import org.apache.cloudstack.backup.BackupPolicy; +import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import com.github.tomakehurst.wiremock.client.BasicCredentials; +import com.github.tomakehurst.wiremock.junit.WireMockRule; + public class VeeamClientTest { + private String adminUsername = "administrator"; + private String adminPassword = "P@ssword123"; private VeeamClient client; + @Rule + public WireMockRule wireMockRule = new WireMockRule(9399); + @Before public void setUp() throws Exception { - client = new VeeamClient("http://10.2.2.89:9399/api/", "administrator", "P@ssword123", true, 60); + wireMockRule.stubFor(post(urlMatching(".*/sessionMngr/")) + .willReturn(aResponse() + .withStatus(201) + .withHeader("X-RestSvcSessionId", "some-session-auth-id") + .withBody(""))); + client = new VeeamClient("http://localhost:9399/api/", adminUsername, adminPassword, true, 60); } @Test - public void testBackups() { - client.listAllBackups(); + public void testBasicAuth() { + verify(postRequestedFor(urlMatching(".*/sessionMngr/")) + .withBasicAuth(new BasicCredentials(adminUsername, adminPassword))); } @Test - public void testPolicies() { - client.listBackupPolicies(); - } - - @Test - public void testBackupLifecycle() { - client.addVMToVeeamJob("8acac50d-3711-4c99-bf7b-76fe9c7e39c3", "i-2-9-VM", "10.2.2.52"); - client.startAdhocBackupJob("8acac50d-3711-4c99-bf7b-76fe9c7e39c3"); - client.removeVMFromVeeamJob("8acac50d-3711-4c99-bf7b-76fe9c7e39c3", "i-2-9-VM", "10.2.2.52"); + public void testVeeamJobs() { + wireMockRule.stubFor(get(urlMatching(".*/jobs")) + .willReturn(aResponse() + .withHeader("Content-Type", "application/xml") + .withStatus(200) + .withBody("\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""))); + List policies = client.listBackupPolicies(); + verify(getRequestedFor(urlMatching(".*/jobs"))); + Assert.assertEquals(policies.size(), 1); + Assert.assertEquals(policies.get(0).getName(), "ZONE1-GOLD"); } } \ No newline at end of file diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java index 81bba5ec092..623bac55d85 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -32,7 +32,7 @@ import org.apache.cloudstack.api.command.user.backup.AddVMToBackupPolicyCmd; import org.apache.cloudstack.api.command.user.backup.CreateVMBackupCmd; import org.apache.cloudstack.api.command.user.backup.DeleteVMBackupCmd; import org.apache.cloudstack.api.command.user.backup.ListBackupPoliciesCmd; -import org.apache.cloudstack.api.command.user.backup.ListBackupPoliciesVMsMappingsCmd; +import org.apache.cloudstack.api.command.user.backup.ListBackupPolicyVMMappingsCmd; import org.apache.cloudstack.api.command.user.backup.ListVMBackupsCmd; import org.apache.cloudstack.api.command.user.backup.RemoveVMFromBackupPolicyCmd; import org.apache.cloudstack.api.command.user.backup.RestoreBackupVolumeCmd; @@ -105,23 +105,24 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { } @Override - public boolean addVMToBackupPolicy(Long zoneId, Long policyId, Long virtualMachineId) { - VMInstanceVO vmInstanceVO = vmInstanceDao.findById(virtualMachineId); - if (vmInstanceVO == null) { + public boolean addVMToBackupPolicy(Long policyId, Long virtualMachineId) { + VMInstanceVO vm = vmInstanceDao.findById(virtualMachineId); + if (vm == null) { throw new CloudRuntimeException("VM " + virtualMachineId + " does not exist"); } + // FIXME: check if VM is already assigned to a policy? BackupPolicyVO policy = backupPolicyDao.findById(policyId); if (policy == null) { throw new CloudRuntimeException("Policy " + policy + " does not exist"); } - BackupProvider backupProvider = getBackupProvider(zoneId); - boolean result = backupProvider.addVMToBackupPolicy(zoneId, policy, vmInstanceVO); + BackupProvider backupProvider = getBackupProvider(vm.getDataCenterId()); + boolean result = backupProvider.addVMToBackupPolicy(policy, vm); if (result) { BackupPolicyVMMapVO map = backupPolicyVMMapDao.findByVMId(virtualMachineId); if (map != null) { backupPolicyVMMapDao.expunge(map.getId()); } - map = new BackupPolicyVMMapVO(zoneId, policy.getId(), virtualMachineId); + map = new BackupPolicyVMMapVO(vm.getDataCenterId(), policy.getId(), virtualMachineId); backupPolicyVMMapDao.persist(map); LOG.debug("Successfully assigned VM " + virtualMachineId + " to backup policy " + policy.getName()); } else { @@ -131,7 +132,7 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { } @Override - public boolean removeVMFromBackupPolicy(Long zoneId, Long policyId, Long vmId) { + public boolean removeVMFromBackupPolicy(Long policyId, Long vmId) { BackupPolicyVO policy = backupPolicyDao.findById(policyId); if (policy == null) { throw new CloudRuntimeException("Policy " + policyId + " does not exist"); @@ -140,8 +141,8 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { if (vm == null) { throw new CloudRuntimeException("VM " + vmId + " does not exist"); } - BackupProvider backupProvider = getBackupProvider(zoneId); - boolean result = backupProvider.removeVMFromBackupPolicy(zoneId, policy, vm); + BackupProvider backupProvider = getBackupProvider(vm.getDataCenterId()); + boolean result = backupProvider.removeVMFromBackupPolicy(policy, vm); if (result) { List map = backupPolicyVMMapDao.listByPolicyIdAndVMId(policyId, vmId); if (map.size() > 1) { @@ -156,10 +157,17 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { } @Override - public List listBackupPolicyVMMappings(Long zoneId, Long policyId) { - return policyId == null ? - new ArrayList<>(backupPolicyVMMapDao.listByZoneId(zoneId)) : - new ArrayList<>(backupPolicyVMMapDao.listByPolicyId(policyId)); + public List listBackupPolicyVMMappings(Long vmId, Long zoneId, Long policyId) { + if (vmId != null) { + return Collections.singletonList(backupPolicyVMMapDao.findByVMId(vmId)); + } + if (zoneId != null) { + return new ArrayList<>(backupPolicyVMMapDao.listByZoneId(zoneId)); + } + if (policyId != null) { + return new ArrayList<>(backupPolicyVMMapDao.listByPolicyId(policyId)); + } + return new ArrayList<>(backupPolicyVMMapDao.listAll()); } @Override @@ -222,8 +230,18 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { @Override public boolean createBackup(Long vmId) { - // TODO: implement me - return false; + VMInstanceVO vm = vmInstanceDao.findById(vmId); + if (vm == null) { + throw new CloudRuntimeException("VM does not exist"); + } + BackupPolicyVMMap vmMap = backupPolicyVMMapDao.findByVMId(vmId); + BackupPolicyVO policy = backupPolicyDao.findById(vmMap.getPolicyId()); + if (policy == null) { + throw new CloudRuntimeException("Policy does not exist"); + } + BackupProvider backupProvider = getBackupProvider(vm.getDataCenterId()); + // FIXME: on successfully started, add an entry in DB? + return backupProvider.startBackup(policy, vm); } @Override @@ -314,19 +332,23 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { @Override public List> getCommands() { final List> cmdList = new ArrayList>(); + + // Backup Policy APIs cmdList.add(ListBackupProvidersCmd.class); cmdList.add(ListBackupPoliciesCmd.class); cmdList.add(ImportBackupPolicyCmd.class); cmdList.add(DeleteBackupPolicyCmd.class); - cmdList.add(AddVMToBackupPolicyCmd.class); cmdList.add(RemoveVMFromBackupPolicyCmd.class); + cmdList.add(ListBackupPolicyVMMappingsCmd.class); + + // Backup and Restore APIs cmdList.add(ListVMBackupsCmd.class); cmdList.add(CreateVMBackupCmd.class); cmdList.add(DeleteVMBackupCmd.class); cmdList.add(RestoreVMBackupCmd.class); cmdList.add(RestoreBackupVolumeCmd.class); - cmdList.add(ListBackupPoliciesVMsMappingsCmd.class); + return cmdList; }