diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index bd845acfd5f..4d3c51e1b12 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -32,8 +32,6 @@ public class ApiConstants { public static final String APPLIED = "applied"; public static final String LIST_LB_VMIPS = "lbvmips"; public static final String AVAILABLE = "available"; - public static final String BACKUP_ID = "backupid"; - public static final String BACKUP_POLICY_ID = "backuppolicyid"; public static final String BITS = "bits"; public static final String BOOTABLE = "bootable"; public static final String BIND_DN = "binddn"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/DeleteBackupPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/DeleteBackupPolicyCmd.java index ff662646498..f3dadafe065 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/DeleteBackupPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/DeleteBackupPolicyCmd.java @@ -17,11 +17,8 @@ package org.apache.cloudstack.api.command.admin.backup; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; +import javax.inject.Inject; + import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,24 +31,27 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.context.CallContext; -import javax.inject.Inject; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; @APICommand(name = DeleteBackupPolicyCmd.APINAME, description = "Deletes a backup policy", responseObject = SuccessResponse.class, since = "4.12.0", authorized = {RoleType.Admin}) public class DeleteBackupPolicyCmd extends BaseCmd { - public static final String APINAME = "deleteBackupPolicy"; @Inject - BackupManager backupManager; + private BackupManager backupManager; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// //////////////////////////////////////////////////// - @Parameter(name = ApiConstants.BACKUP_POLICY_ID, + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = BackupPolicyResponse.class, required = true, @@ -66,6 +66,20 @@ public class DeleteBackupPolicyCmd extends BaseCmd { return id; } + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + if (backupManager.deleteBackupPolicy(getId())) { + SuccessResponse response = new SuccessResponse(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Unable to remove backup policy: " + getId()); + } + } + @Override public String getCommandName() { return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; @@ -75,18 +89,4 @@ public class DeleteBackupPolicyCmd extends BaseCmd { public long getEntityOwnerId() { return CallContext.current().getCallingAccount().getId(); } - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - - @Override - public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { - if (backupManager.deleteBackupPolicy(id)) { - SuccessResponse response = new SuccessResponse(getCommandName()); - setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Unable to remove backup policy: " + id); - } - } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ImportBackupPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ImportBackupPolicyCmd.java index 97beea3ea91..1dbe0337df6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ImportBackupPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ImportBackupPolicyCmd.java @@ -47,7 +47,7 @@ public class ImportBackupPolicyCmd extends BaseCmd { public static final String APINAME = "importBackupPolicy"; @Inject - BackupManager backupManager; + private BackupManager backupManager; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -91,16 +91,6 @@ public class ImportBackupPolicyCmd extends BaseCmd { return description; } - @Override - public String getCommandName() { - return APINAME.toLowerCase() + RESPONSE_SUFFIX; - } - - @Override - public long getEntityOwnerId() { - return CallContext.current().getCallingAccount().getId(); - } - ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -108,7 +98,7 @@ public class ImportBackupPolicyCmd extends BaseCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try { - BackupPolicy policy = backupManager.importBackupPolicy(zoneId, policyExternalId, policyName, description); + BackupPolicy policy = backupManager.importBackupPolicy(getZoneId(), getPolicyExternalId(), getPolicyName(), getDescription()); if (policy != null) { BackupPolicyResponse response = _responseGenerator.createBackupPolicyResponse(policy); response.setResponseName(getCommandName()); @@ -122,4 +112,14 @@ public class ImportBackupPolicyCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } + + @Override + public String getCommandName() { + return 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/AddVMToBackupPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/AddVMToBackupPolicyCmd.java index 487460874ef..f643cc07387 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 @@ -43,10 +43,10 @@ import com.cloud.exception.ResourceUnavailableException; responseObject = SuccessResponse.class, since = "4.12.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class AddVMToBackupPolicyCmd extends BaseCmd { - public static final String APINAME = "addVirtualMachineToBackupPolicy"; + public static final String APINAME = "addVMToBackupPolicy"; @Inject - BackupManager backupManager; + private BackupManager backupManager; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -57,9 +57,9 @@ public class AddVMToBackupPolicyCmd extends BaseCmd { entityType = UserVmResponse.class, required = true, description = "id of the VM to be assigned to the backup policy") - private Long virtualMachineId; + private Long vmId; - @Parameter(name = ApiConstants.BACKUP_POLICY_ID, + @Parameter(name = ApiConstants.POLICY_ID, type = CommandType.UUID, entityType = BackupPolicyResponse.class, required = true, @@ -74,8 +74,8 @@ public class AddVMToBackupPolicyCmd extends BaseCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public Long getVirtualMachineId() { - return virtualMachineId; + public Long getVmId() { + return vmId; } public Long getPolicyId() { @@ -103,7 +103,7 @@ public class AddVMToBackupPolicyCmd extends BaseCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try { - boolean result = backupManager.addVMToBackupPolicy(zoneId, policyId, virtualMachineId); + boolean result = backupManager.addVMToBackupPolicy(getZoneId(), getPolicyId(), getVmId()); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); response.setResponseName(getCommandName()); 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 new file mode 100644 index 00000000000..e09e0f95e31 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/CreateVMBackupCmd.java @@ -0,0 +1,100 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.user.backup; + +import javax.inject.Inject; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.backup.BackupManager; +import org.apache.cloudstack.context.CallContext; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = CreateVMBackupCmd.APINAME, + description = "Create VM backup", + responseObject = SuccessResponse.class, since = "4.12.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class CreateVMBackupCmd extends BaseCmd { + public static final String APINAME = "createVMBackup"; + + @Inject + private BackupManager backupManager; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, + type = CommandType.UUID, + entityType = UserVmResponse.class, + required = true, + description = "id of the VM") + private Long vmId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getVmId() { + return vmId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + try { + boolean result = backupManager.createBackup(vmId); + // FIXME: the response type + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new CloudRuntimeException("Error while creating backup of VM"); + } + } catch (Exception e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.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/DeleteVMBackupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/DeleteVMBackupCmd.java new file mode 100644 index 00000000000..1faa6286133 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/DeleteVMBackupCmd.java @@ -0,0 +1,100 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.user.backup; + +import javax.inject.Inject; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.backup.BackupManager; +import org.apache.cloudstack.context.CallContext; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = DeleteVMBackupCmd.APINAME, + description = "Delete VM backup", + responseObject = SuccessResponse.class, since = "4.12.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class DeleteVMBackupCmd extends BaseCmd { + public static final String APINAME = "deleteVMBackup"; + + @Inject + private BackupManager backupManager; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, + type = CommandType.UUID, + entityType = UserVmResponse.class, + required = true, + description = "id of the VM") + private Long vmId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getVmId() { + return vmId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + try { + boolean result = backupManager.deleteBackup(vmId); + // FIXME: the response type + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new CloudRuntimeException("Error while deleting backup of VM"); + } + } catch (Exception e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.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/ListBackupPoliciesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupPoliciesCmd.java index 49278d801f5..4ac21ac7158 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 @@ -32,29 +32,28 @@ import org.apache.cloudstack.api.response.BackupPolicyResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.backup.BackupPolicy; +import org.apache.commons.lang.BooleanUtils; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.utils.exception.CloudRuntimeException; -import org.apache.commons.lang.BooleanUtils; @APICommand(name = ListBackupPoliciesCmd.APINAME, description = "Lists backup policies", responseObject = BackupPolicyResponse.class, since = "4.12.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ListBackupPoliciesCmd extends BaseBackupListCmd { - public static final String APINAME = "listBackupPolicies"; @Inject - BackupManager backupManager; + private BackupManager backupManager; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = ApiConstants.BACKUP_POLICY_ID, type = BaseCmd.CommandType.UUID, entityType = BackupPolicyResponse.class, + @Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, entityType = BackupPolicyResponse.class, description = "The backup policy ID") private Long policyId; @@ -82,11 +81,6 @@ public class ListBackupPoliciesCmd extends BaseBackupListCmd { return policyId; } - @Override - public String getCommandName() { - return APINAME.toLowerCase() + RESPONSE_SUFFIX; - } - ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -95,7 +89,7 @@ public class ListBackupPoliciesCmd extends BaseBackupListCmd { public void execute() throws ResourceUnavailableException, ServerApiException, ConcurrentOperationException { validateParameters(); try { - List backupPolicies = backupManager.listBackupPolicies(zoneId, external, policyId); + final List backupPolicies = backupManager.listBackupPolicies(getZoneId(), isExternal(), getPolicyId()); setupResponseBackupPolicyList(backupPolicies); } catch (InvalidParameterValueException e) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, e.getMessage()); @@ -105,8 +99,13 @@ public class ListBackupPoliciesCmd extends BaseBackupListCmd { } private void validateParameters() { - if (zoneId == null && policyId == null) { - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please provide a zone id or a policy id"); + if (external && zoneId == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please provide the zone id when external option is specified"); } } + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + RESPONSE_SUFFIX; + } } 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/ListBackupPoliciesVMsMappingsCmd.java index e23c4eaf4b2..f7b816d7c35 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/ListBackupPoliciesVMsMappingsCmd.java @@ -16,12 +16,10 @@ // under the License. package org.apache.cloudstack.api.command.user.backup; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.utils.exception.CloudRuntimeException; +import java.util.List; + +import javax.inject.Inject; + import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,8 +33,12 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.backup.BackupPolicyVMMap; -import javax.inject.Inject; -import java.util.List; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = ListBackupPoliciesVMsMappingsCmd.APINAME, description = "Lists VMs mapped to a backup policy", @@ -46,13 +48,13 @@ public class ListBackupPoliciesVMsMappingsCmd extends BaseBackupListCmd { public static final String APINAME = "listBackupPoliciesVirtualMachineMappings"; @Inject - BackupManager backupManager; + private BackupManager backupManager; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = ApiConstants.BACKUP_POLICY_ID, type = BaseCmd.CommandType.UUID, entityType = BackupPolicyResponse.class, + @Parameter(name = ApiConstants.POLICY_ID, type = BaseCmd.CommandType.UUID, entityType = BackupPolicyResponse.class, description = "The backup policy ID") private Long policyId; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListVMBackupsCmd.java similarity index 90% rename from api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java rename to api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListVMBackupsCmd.java index 8b4311da352..d4444803b3f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListVMBackupsCmd.java @@ -17,11 +17,10 @@ package org.apache.cloudstack.api.command.user.backup; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; +import java.util.List; + +import javax.inject.Inject; + import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,22 +32,25 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.BackupResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.backup.Backup; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.backup.Backup; -import javax.inject.Inject; -import java.util.List; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; -@APICommand(name = ListBackupsCmd.APINAME, - description = "Lists backups", +@APICommand(name = ListVMBackupsCmd.APINAME, + description = "Lists VM backups", responseObject = BackupResponse.class, since = "4.12.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) -public class ListBackupsCmd extends BaseBackupListCmd { +public class ListVMBackupsCmd extends BaseBackupListCmd { public static final String APINAME = "listVMBackups"; @Inject - BackupManager backupManager; + private BackupManager backupManager; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -57,9 +59,8 @@ public class ListBackupsCmd extends BaseBackupListCmd { @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, - required = true, description = "id of the VM") - private Long virtualMachineId; + private Long vmId; @Parameter(name = ApiConstants.ZONE_ID, type = BaseCmd.CommandType.UUID, entityType = ZoneResponse.class, description = "The zone ID") @@ -69,14 +70,28 @@ public class ListBackupsCmd extends BaseBackupListCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public Long getVirtualMachineId() { - return virtualMachineId; + public Long getVmId() { + return vmId; } public Long getZoneId() { return zoneId; } + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + try{ + List backups = backupManager.listVMBackups(getZoneId(), getVmId()); + setupResponseBackupList(backups); + } catch (Exception e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } + @Override public String getCommandName() { return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; @@ -87,19 +102,4 @@ public class ListBackupsCmd extends BaseBackupListCmd { return CallContext.current().getCallingAccount().getId(); } - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - - @Override - public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { - try{ - List backups = backupManager.listVMBackups(zoneId, virtualMachineId); - setupResponseBackupList(backups); - } catch (Exception 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 d4c3ecd2dd2..c7cb6788441 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 @@ -17,11 +17,8 @@ package org.apache.cloudstack.api.command.user.backup; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; +import javax.inject.Inject; + import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,18 +33,21 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.context.CallContext; -import javax.inject.Inject; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; @APICommand(name = RemoveVMFromBackupPolicyCmd.APINAME, description = "Removes a VM from an existing backup policy", responseObject = SuccessResponse.class, since = "4.12.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class RemoveVMFromBackupPolicyCmd extends BaseCmd { - - public static final String APINAME = "removeVirtualMachineFromBackupPolicy"; + public static final String APINAME = "removeVMFromBackupPolicy"; @Inject - BackupManager backupManager; + private BackupManager backupManager; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -58,9 +58,9 @@ public class RemoveVMFromBackupPolicyCmd extends BaseCmd { entityType = UserVmResponse.class, required = true, description = "id of the VM to be removed from the backup policy") - private Long virtualMachineId; + private Long vmId; - @Parameter(name = ApiConstants.BACKUP_POLICY_ID, + @Parameter(name = ApiConstants.POLICY_ID, type = CommandType.UUID, entityType = BackupPolicyResponse.class, required = true, @@ -77,8 +77,8 @@ public class RemoveVMFromBackupPolicyCmd extends BaseCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public Long getVirtualMachineId() { - return virtualMachineId; + public Long getVmId() { + return vmId; } public Long getPolicyId() { @@ -106,7 +106,7 @@ public class RemoveVMFromBackupPolicyCmd extends BaseCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try { - boolean result = backupManager.removeVMFromBackupPolicy(zoneId, policyId, virtualMachineId); + boolean result = backupManager.removeVMFromBackupPolicy(getZoneId(), getPolicyId(), getVmId()); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); response.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreBackupVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreBackupVolumeCmd.java index 8c2ad24599d..f9cbe26b5ec 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreBackupVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreBackupVolumeCmd.java @@ -17,12 +17,8 @@ package org.apache.cloudstack.api.command.user.backup; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.utils.exception.CloudRuntimeException; +import javax.inject.Inject; + import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,23 +34,36 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.context.CallContext; -import javax.inject.Inject; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = RestoreBackupVolumeCmd.APINAME, description = "Restore and attach a backed up volume to VM", responseObject = SuccessResponse.class, since = "4.12.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class RestoreBackupVolumeCmd extends BaseCmd { - public static final String APINAME = "restoreBackupVolumeAndAttachToVM"; @Inject - BackupManager backupManager; + private BackupManager backupManager; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// + //FIXME: discuss on simplification + @Parameter(name = ApiConstants.ID, + type = CommandType.UUID, + entityType = BackupResponse.class, + required = true, + description = "id of the backup") + private Long backupId; + + //FIXME: is this necessary when backup id is known? unless we want to restore to a different volume? @Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.UUID, entityType = VolumeResponse.class, @@ -62,19 +71,13 @@ public class RestoreBackupVolumeCmd extends BaseCmd { description = "id of the volume to restore and to be attached to the vm") private Long volumeId; + //FIXME: is this necessary when backup id is known? unless we want to restore to a different VM? @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, required = true, description = "id of the VM where to attach the restored volume") - private Long virtualMachineId; - - @Parameter(name = ApiConstants.BACKUP_ID, - type = CommandType.UUID, - entityType = BackupResponse.class, - required = true, - description = "id of the backup") - private Long backupId; + private Long vmId; @Parameter(name = ApiConstants.ZONE_ID, type = BaseCmd.CommandType.UUID, entityType = ZoneResponse.class, description = "The zone ID") @@ -88,8 +91,8 @@ public class RestoreBackupVolumeCmd extends BaseCmd { return volumeId; } - public Long getVirtualMachineId() { - return virtualMachineId; + public Long getVmId() { + return vmId; } public Long getBackupId() { @@ -117,7 +120,7 @@ public class RestoreBackupVolumeCmd extends BaseCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try { - boolean result = backupManager.restoreBackupVolumeAndAttachToVM(zoneId, volumeId, virtualMachineId, backupId); + boolean result = backupManager.restoreBackupVolumeAndAttachToVM(zoneId, volumeId, vmId, backupId); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); response.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreBackupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreVMBackupCmd.java similarity index 90% rename from api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreBackupCmd.java rename to api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreVMBackupCmd.java index ae4f98f3d68..7ffc8816473 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreBackupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/RestoreVMBackupCmd.java @@ -17,12 +17,8 @@ package org.apache.cloudstack.api.command.user.backup; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.utils.exception.CloudRuntimeException; +import javax.inject.Inject; + import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,36 +33,42 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.context.CallContext; -import javax.inject.Inject; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.utils.exception.CloudRuntimeException; -@APICommand(name = RestoreBackupCmd.APINAME, - description = "Restore backup", +@APICommand(name = RestoreVMBackupCmd.APINAME, + description = "Restore VM backup", responseObject = SuccessResponse.class, since = "4.12.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) -public class RestoreBackupCmd extends BaseCmd { - public static final String APINAME = "restoreBackup"; +public class RestoreVMBackupCmd extends BaseCmd { + public static final String APINAME = "restoreVMBackup"; @Inject - BackupManager backupManager; + private BackupManager backupManager; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, - type = CommandType.UUID, - entityType = UserVmResponse.class, - required = true, - description = "id of the VM") - private Long virtualMachineId; - - @Parameter(name = ApiConstants.BACKUP_ID, + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = BackupResponse.class, required = true, description = "id of the backup") private Long backupId; + //FIXME: is this necessary when backup id is known? unless we want to restore to a different VM? + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, + type = CommandType.UUID, + entityType = UserVmResponse.class, + required = true, + description = "id of the VM") + private Long vmId; + @Parameter(name = ApiConstants.ZONE_ID, type = BaseCmd.CommandType.UUID, entityType = ZoneResponse.class, description = "The zone ID") private Long zoneId; @@ -75,8 +77,8 @@ public class RestoreBackupCmd extends BaseCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public Long getVirtualMachineId() { - return virtualMachineId; + public Long getVmId() { + return vmId; } public Long getBackupId() { @@ -87,16 +89,6 @@ public class RestoreBackupCmd extends BaseCmd { return zoneId; } - @Override - public String getCommandName() { - return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; - } - - @Override - public long getEntityOwnerId() { - return CallContext.current().getCallingAccount().getId(); - } - ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -104,7 +96,7 @@ public class RestoreBackupCmd extends BaseCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try { - boolean result = backupManager.restoreBackup(zoneId, virtualMachineId, backupId); + boolean result = backupManager.restoreBackup(zoneId, vmId, backupId); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); response.setResponseName(getCommandName()); @@ -117,5 +109,14 @@ public class RestoreBackupCmd extends BaseCmd { } } + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/BackupPolicyVMMapResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/BackupPolicyVMMapResponse.java index 909ed9d13f5..855ae51fd52 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/BackupPolicyVMMapResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/BackupPolicyVMMapResponse.java @@ -17,13 +17,14 @@ package org.apache.cloudstack.api.response; -import com.cloud.serializer.Param; -import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; import org.apache.cloudstack.backup.BackupPolicyVMMap; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + @EntityReference(value = BackupPolicyVMMap.class) public class BackupPolicyVMMapResponse extends BaseResponse { @@ -31,7 +32,7 @@ public class BackupPolicyVMMapResponse extends BaseResponse { @Param(description = "zone id") private String zoneId; - @SerializedName(ApiConstants.BACKUP_POLICY_ID) + @SerializedName(ApiConstants.POLICY_ID) @Param(description = "backup policy id") private String backupPolicyId; 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 c4f77b0d66a..bb89f126f6e 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java @@ -67,6 +67,20 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer */ List listBackupPolicies(Long zoneId, Boolean external, Long policyId); + /** + * Creates backup of a VM + * @param vmId Virtual Machine ID + * @return returns operation success + */ + boolean createBackup(Long vmId); + + /** + * Deletes backup of a VM + * @param vmId Virtual Machine ID + * @return returns operation success + */ + boolean deleteBackup(Long vmId); + /** * Restore a full backed up VM */ 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 89285e83b8b..d58457afbbf 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java @@ -16,11 +16,11 @@ //under the License. package org.apache.cloudstack.backup; +import java.util.List; + import com.cloud.agent.api.to.VolumeTO; import com.cloud.vm.VirtualMachine; -import java.util.List; - public interface BackupProvider { /** @@ -35,17 +35,6 @@ public interface BackupProvider { */ String getDescription(); - /** - * Assign VM to backup policy - * @return true if VM is successfully assigned, false if not - */ - boolean addVMToBackupPolicy(Long zoneId, String policyId, VirtualMachine vm); - - /** - * Remove a VM form a backup policy - */ - boolean removeVMFromBackupPolicy(Long zoneId, String policyId, VirtualMachine vm); - /** * Returns the list of existing backup policies on the provider * @return backup policies list @@ -55,7 +44,18 @@ public interface BackupProvider { /** * True if policy with id uuid exists on the backup provider */ - boolean isBackupPolicy(String uuid); + boolean isBackupPolicy(Long zoneId, String uuid); + + /** + * Assign VM to backup policy + * @return true if VM is successfully assigned, false if not + */ + boolean addVMToBackupPolicy(Long zoneId, BackupPolicy policy, VirtualMachine vm); + + /** + * Remove a VM form a backup policy + */ + boolean removeVMFromBackupPolicy(Long zoneId, BackupPolicy policy, VirtualMachine vm); /** * Restore VM from backup diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupPolicyVO.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupPolicyVO.java index e143a1fe4f4..a1f8d4058e1 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupPolicyVO.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupPolicyVO.java @@ -29,19 +29,6 @@ import javax.persistence.Table; @Entity @Table(name = "backup_policy") public class BackupPolicyVO implements BackupPolicy { - - public BackupPolicyVO() { - this.uuid = UUID.randomUUID().toString(); - } - - public BackupPolicyVO(final long zoneId, final String externalId, final String name, final String description) { - this(); - this.zoneId = zoneId; - this.name = name; - this.description = description; - this.externalId = externalId; - } - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") @@ -62,6 +49,19 @@ public class BackupPolicyVO implements BackupPolicy { @Column(name = "zone_id") private long zoneId; + public BackupPolicyVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public BackupPolicyVO(final long zoneId, final String externalId, final String name, final String description) { + this(); + this.zoneId = zoneId; + this.name = name; + this.description = description; + this.externalId = externalId; + } + + public String getUuid() { return uuid; } diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41110to41200.sql b/engine/schema/src/main/resources/META-INF/db/schema-41110to41200.sql index 3cf4151398a..c347f7ada76 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41110to41200.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41110to41200.sql @@ -41,7 +41,7 @@ CREATE TABLE IF NOT EXISTS `cloud`.`backup_policy` ( `uuid` varchar(40) NOT NULL, `name` varchar(255) NOT NULL COMMENT 'backup policy name', `description` varchar(255) NOT NULL COMMENT 'backup policy description', - `external_id` varchar(40) NOT NULL COMMENT 'backup policy ID on provider side', + `external_id` varchar(80) NOT NULL COMMENT 'backup policy ID on provider side', `zone_id` bigint(20) unsigned NOT NULL COMMENT 'zone id', PRIMARY KEY (`id`), UNIQUE KEY `uuid` (`uuid`), @@ -77,4 +77,4 @@ CREATE TABLE IF NOT EXISTS `cloud`.`backup` ( CONSTRAINT `fk_backup__zone_id` FOREIGN KEY (`zone_id`) REFERENCES `data_center` (`id`) ON DELETE CASCADE, CONSTRAINT `fk_backup__parent_id` FOREIGN KEY (`parent_id`) REFERENCES `backup` (`id`) ON DELETE CASCADE, CONSTRAINT `fk_backup__vm_id` FOREIGN KEY (`vm_id`) REFERENCES `vm_instance` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file +) ENGINE=InnoDB DEFAULT CHARSET=utf8; 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 9818d416909..e3090f3c7a5 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 @@ -16,16 +16,17 @@ // under the License. package org.apache.cloudstack.backup; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; + import com.cloud.agent.api.to.VolumeTO; import com.cloud.storage.Storage; import com.cloud.storage.Volume; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.VirtualMachine; -import org.apache.log4j.Logger; - -import java.util.Arrays; -import java.util.Date; -import java.util.List; public class DummyBackupProvider extends AdapterBase implements BackupProvider { @@ -41,18 +42,6 @@ public class DummyBackupProvider extends AdapterBase implements BackupProvider { return "Dummy B&R Plugin"; } - @Override - public boolean addVMToBackupPolicy(Long zoneId, String policyId, VirtualMachine vm) { - s_logger.debug("Assigning VM " + vm.getInstanceName() + " to backup policy " + policyId); - return true; - } - - @Override - public boolean removeVMFromBackupPolicy(Long zoneId, String policyId, VirtualMachine vm) { - s_logger.debug("Removing VM " + vm.getInstanceName() + " from backup policy " + policyId); - return true; - } - @Override public List listBackupPolicies(Long zoneId) { s_logger.debug("Listing backup policies on Dummy B&R Plugin"); @@ -62,11 +51,23 @@ public class DummyBackupProvider extends AdapterBase implements BackupProvider { } @Override - public boolean isBackupPolicy(String uuid) { + public boolean isBackupPolicy(Long zoneId, String uuid) { s_logger.debug("Checking if backup policy exists on the Dummy Backup Provider"); return true; } + @Override + public boolean addVMToBackupPolicy(Long zoneId, 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) { + s_logger.debug("Removing VM " + vm.getInstanceName() + " from backup policy " + policy.getName()); + 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 4a6769ea28b..88f31ac1988 100644 --- a/plugins/backup/veeam/pom.xml +++ b/plugins/backup/veeam/pom.xml @@ -43,6 +43,11 @@ commons-lang3 ${cs.commons-lang3.version} + + org.apache.cloudstack + cloud-plugin-hypervisor-vmware + ${project.version} + 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 14cf6c35b14..fdf0fa8360f 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 @@ -22,32 +22,28 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.List; -import com.cloud.hypervisor.vmware.VmwareDatacenterVO; -import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMapVO; -import com.cloud.hypervisor.vmware.dao.VmwareDatacenterDao; -import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao; +import javax.inject.Inject; + import org.apache.cloudstack.backup.veeam.VeeamClient; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; +import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; import com.cloud.agent.api.to.VolumeTO; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.hypervisor.vmware.VmwareDatacenter; +import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMap; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VirtualMachine; -import javax.inject.Inject; - public class VeeamBackupProvider extends AdapterBase implements BackupProvider, Configurable { private static final Logger LOG = Logger.getLogger(VeeamBackupProvider.class); - @Inject - VmwareDatacenterZoneMapDao vmwareDatacenterZoneMapDao; - - @Inject - VmwareDatacenterDao vmwareDatacenterDao; - private ConfigKey VeeamUrl = new ConfigKey<>("Advanced", String.class, "backup.plugin.veeam.url", "http://localhost:9399/api/", @@ -66,10 +62,14 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider, private ConfigKey VeeamValidateSSLSecurity = new ConfigKey<>("Advanced", Boolean.class, "backup.plugin.veeam.validate.ssl", "true", "When set to true, this will validate the SSL certificate when connecting to https/ssl enabled Veeam API service.", true, ConfigKey.Scope.Zone); - private ConfigKey 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); + @Inject + private VmwareDatacenterZoneMapDao vmwareDatacenterZoneMapDao; + @Inject + private VmwareDatacenterDao vmwareDatacenterDao; + private VeeamClient getClient(final Long zoneId) { try { return new VeeamClient(VeeamUrl.valueIn(zoneId), VeeamUsername.valueIn(zoneId), VeeamPassword.valueIn(zoneId), @@ -82,39 +82,49 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider, throw new CloudRuntimeException("Failed to build Veeam API client"); } - private String getVCenterIp(Long zoneId) { - VmwareDatacenterZoneMapVO map = vmwareDatacenterZoneMapDao.findByZoneId(zoneId); - if (map == null) { - throw new CloudRuntimeException("No vCenter associated to zone " + zoneId); - } - long vmwareDcId = map.getVmwareDcId(); - VmwareDatacenterVO dataCenterVO = vmwareDatacenterDao.findById(vmwareDcId); - return dataCenterVO.getVcenterHost(); - } - - @Override - public boolean addVMToBackupPolicy(Long zoneId, String policyId, VirtualMachine vm) { - String instanceName = vm.getInstanceName(); - String vCenterIp = getVCenterIp(zoneId); - return getClient(zoneId).addVMToVeeamJob(policyId, instanceName, vCenterIp); - } - - @Override - public boolean removeVMFromBackupPolicy(Long zoneId, String policyId, VirtualMachine vm) { - String instanceName = vm.getInstanceName(); - String vCenterIp = getVCenterIp(zoneId); - return getClient(zoneId).removeVMFromVeeamJob(policyId, instanceName, vCenterIp); - } - - @Override - public List listBackupPolicies(Long zoneId) { + public List listBackupPolicies(final Long zoneId) { return getClient(zoneId).listBackupPolicies(); } @Override - public boolean isBackupPolicy(String uuid) { - //TODO - return true; + public boolean isBackupPolicy(final Long zoneId, final String uuid) { + List policies = listBackupPolicies(zoneId); + if (CollectionUtils.isEmpty(policies)) { + return false; + } + for (final BackupPolicy policy : policies) { + if (policy.getExternalId().equals(uuid)) { + return true; + } + } + return false; + } + + private VmwareDatacenter findVmwareDatacenterForVM(final VirtualMachine vm) { + if (vm == null || vm.getHypervisorType() != Hypervisor.HypervisorType.VMware) { + throw new CloudRuntimeException("The Veeam backup provider is only applicable for VMware VMs"); + } + final VmwareDatacenterZoneMap zoneMap = vmwareDatacenterZoneMapDao.findByZoneId(vm.getDataCenterId()); + if (zoneMap == null) { + throw new CloudRuntimeException("Failed to find a mapped VMware datacenter for zone id:" + vm.getDataCenterId()); + } + final VmwareDatacenter vmwareDatacenter = vmwareDatacenterDao.findById(zoneMap.getVmwareDcId()); + if (vmwareDatacenter == null) { + throw new CloudRuntimeException("Failed to find a valid VMware datacenter mapped for zone id:" + vm.getDataCenterId()); + } + return vmwareDatacenter; + } + + @Override + public boolean addVMToBackupPolicy(final Long zoneId, final BackupPolicy policy, final VirtualMachine vm) { + final VmwareDatacenter vmwareDatacenter = findVmwareDatacenterForVM(vm); + return getClient(zoneId).addVMToVeeamJob(policy.getExternalId(), vm.getInstanceName(), vmwareDatacenter.getVcenterHost()); + } + + @Override + public boolean removeVMFromBackupPolicy(final Long zoneId, final BackupPolicy policy, final VirtualMachine vm) { + final VmwareDatacenter vmwareDatacenter = findVmwareDatacenterForVM(vm); + return getClient(zoneId).removeVMFromVeeamJob(policy.getExternalId(), vm.getInstanceName(), vmwareDatacenter.getVcenterHost()); } @Override 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 31db797b178..81bba5ec092 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -25,25 +25,18 @@ import java.util.Map; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.agent.api.to.VolumeTO; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.storage.VolumeApiService; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.user.Account; -import com.cloud.user.AccountService; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.dao.VMInstanceDao; import org.apache.cloudstack.api.command.admin.backup.DeleteBackupPolicyCmd; -import org.apache.cloudstack.api.command.user.backup.AddVMToBackupPolicyCmd; import org.apache.cloudstack.api.command.admin.backup.ImportBackupPolicyCmd; -import org.apache.cloudstack.api.command.user.backup.ListBackupPoliciesCmd; import org.apache.cloudstack.api.command.admin.backup.ListBackupProvidersCmd; +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.ListBackupsCmd; +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.RestoreBackupCmd; import org.apache.cloudstack.api.command.user.backup.RestoreBackupVolumeCmd; +import org.apache.cloudstack.api.command.user.backup.RestoreVMBackupCmd; import org.apache.cloudstack.backup.dao.BackupDao; import org.apache.cloudstack.backup.dao.BackupPolicyDao; import org.apache.cloudstack.backup.dao.BackupPolicyVMMapDao; @@ -54,8 +47,18 @@ import org.apache.commons.lang.BooleanUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.storage.VolumeApiService; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.user.Account; +import com.cloud.user.AccountService; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.dao.VMInstanceDao; +import com.google.common.base.Strings; @Component public class BackupManagerImpl extends ManagerBase implements BackupManager { @@ -87,18 +90,18 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { @Override public BackupPolicy importBackupPolicy(Long zoneId, String policyExternalId, String policyName, String policyDescription) { - BackupProvider provider = getBackupProvider(zoneId); - if (!provider.isBackupPolicy(policyExternalId)) { + final BackupProvider provider = getBackupProvider(zoneId); + if (!provider.isBackupPolicy(zoneId, policyExternalId)) { throw new CloudRuntimeException("Policy " + policyExternalId + " does not exist on provider " + provider.getName() + " on zone " + zoneId); } - BackupPolicyVO policy = new BackupPolicyVO(zoneId, policyExternalId, policyName, policyDescription); - BackupPolicyVO vo = backupPolicyDao.persist(policy); - if (vo == null) { + final BackupPolicyVO policy = new BackupPolicyVO(zoneId, policyExternalId, policyName, policyDescription); + final BackupPolicyVO savedPolicy = backupPolicyDao.persist(policy); + if (savedPolicy == null) { throw new CloudRuntimeException("Unable to create backup policy: " + policyExternalId + ", name: " + policyName); } LOG.debug("Successfully created backup policy " + policyName + " mapped to backup provider policy " + policyExternalId); - return vo; + return savedPolicy; } @Override @@ -112,7 +115,7 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { throw new CloudRuntimeException("Policy " + policy + " does not exist"); } BackupProvider backupProvider = getBackupProvider(zoneId); - boolean result = backupProvider.addVMToBackupPolicy(zoneId, policy.getExternalId(), vmInstanceVO); + boolean result = backupProvider.addVMToBackupPolicy(zoneId, policy, vmInstanceVO); if (result) { BackupPolicyVMMapVO map = backupPolicyVMMapDao.findByVMId(virtualMachineId); if (map != null) { @@ -138,7 +141,7 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { throw new CloudRuntimeException("VM " + vmId + " does not exist"); } BackupProvider backupProvider = getBackupProvider(zoneId); - boolean result = backupProvider.removeVMFromBackupPolicy(zoneId, policy.getExternalId(), vm); + boolean result = backupProvider.removeVMFromBackupPolicy(zoneId, policy, vm); if (result) { List map = backupPolicyVMMapDao.listByPolicyIdAndVMId(policyId, vmId); if (map.size() > 1) { @@ -217,6 +220,18 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { } } + @Override + public boolean createBackup(Long vmId) { + // TODO: implement me + return false; + } + + @Override + public boolean deleteBackup(Long vmId) { + // TODO: implement me + return false; + } + @Override public boolean restoreBackup(Long zoneId, Long vmId, Long backupId) { BackupProvider backupProvider = getBackupProvider(zoneId); @@ -286,9 +301,12 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { @Override public BackupProvider getBackupProvider(final Long zoneId) { - String name = BackupProviderPlugin.valueIn(zoneId); + final String name = BackupProviderPlugin.valueIn(zoneId); + if (Strings.isNullOrEmpty(name)) { + throw new CloudRuntimeException("Invalid backup provider name configured in zone id: " + zoneId); + } if (!backupProvidersMap.containsKey(name)) { - throw new CloudRuntimeException("Could not find a backup provider on zone " + zoneId); + throw new CloudRuntimeException("Failed to find backup provider for zone id:" + zoneId); } return backupProvidersMap.get(name); } @@ -299,11 +317,14 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { 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(DeleteBackupPolicyCmd.class); - cmdList.add(ListBackupsCmd.class); - cmdList.add(RestoreBackupCmd.class); + 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;