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 a2d8358443b..8c2ad24599d 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 @@ -46,7 +46,7 @@ import javax.inject.Inject; authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class RestoreBackupVolumeCmd extends BaseCmd { - public static final String APINAME = "restoreBackupVolume"; + public static final String APINAME = "restoreBackupVolumeAndAttachToVM"; @Inject BackupManager backupManager; @@ -59,14 +59,14 @@ public class RestoreBackupVolumeCmd extends BaseCmd { type = CommandType.UUID, entityType = VolumeResponse.class, required = true, - description = "id of the volume") + description = "id of the volume to restore and to be attached to the vm") private Long volumeId; @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, required = true, - description = "id of the VM") + description = "id of the VM where to attach the restored volume") private Long virtualMachineId; @Parameter(name = ApiConstants.BACKUP_ID, @@ -117,7 +117,7 @@ public class RestoreBackupVolumeCmd extends BaseCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try { - boolean result = backupManager.restoreBackupVolume(zoneId, volumeId, virtualMachineId, backupId); + boolean result = backupManager.restoreBackupVolumeAndAttachToVM(zoneId, volumeId, virtualMachineId, backupId); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); response.setResponseName(getCommandName()); 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 18e8d032ea3..3a9e06c84c1 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java @@ -37,7 +37,7 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer ConfigKey BackupProviderPlugin = new ConfigKey<>("Advanced", String.class, "backup.framework.provider.plugin", - "", + "dummy", "The backup and recovery provider plugin.", true, ConfigKey.Scope.Zone); /** @@ -71,8 +71,10 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer */ boolean restoreBackup(Long zoneId, Long vmId, Long backupId); - //TODO - boolean restoreBackupVolume(Long zoneId, Long volumeId, Long vmId, Long backupId); + /** + * Restore a backed up volume and attach it to a VM + */ + boolean restoreBackupVolumeAndAttachToVM(Long zoneId, Long volumeId, Long vmId, Long backupId); /** * Deletes a backup policy 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 e98d9269290..b9d87575c6d 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java @@ -16,6 +16,8 @@ //under the License. package org.apache.cloudstack.backup; +import com.cloud.agent.api.to.VolumeTO; + import java.util.List; public interface BackupProvider { @@ -53,4 +55,9 @@ public interface BackupProvider { * Restore VM from backup */ boolean restoreVMFromBackup(String vmUuid, String backupUuid); + + /** + * Restore a volume from a backup + */ + VolumeTO restoreVolumeFromBackup(String volumeUuid, String backupUuid); } 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 69ef7d0c60b..03217ad7d35 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,6 +16,9 @@ // under the License. package org.apache.cloudstack.backup; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.storage.Storage; +import com.cloud.storage.Volume; import com.cloud.utils.component.AdapterBase; import org.apache.log4j.Logger; @@ -61,4 +64,11 @@ public class DummyBackupProvider extends AdapterBase implements BackupProvider { s_logger.debug("Restoring vm " + vmUuid + "from backup " + backupUuid + " on the Dummy Backup Provider"); return true; } + + @Override + public VolumeTO restoreVolumeFromBackup(String volumeUuid, String backupUuid) { + s_logger.debug("Restoring volume " + volumeUuid + "from backup " + backupUuid + " on the Dummy Backup Provider"); + return new VolumeTO(0L, Volume.Type.DATADISK, Storage.StoragePoolType.NetworkFilesystem, "pool-aaaa", "volumeTest", + "/test", "volTest", 1024L, "", ""); + } } 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 546b1b55412..11e975f50fd 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 @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.cloud.agent.api.to.VolumeTO; import org.apache.cloudstack.backup.veeam.VeeamClient; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; @@ -97,6 +98,11 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider, return false; } + @Override + public VolumeTO restoreVolumeFromBackup(String volumeUuid, String backupUuid) { + return null; + } + @Override public String getConfigComponentName() { return BackupService.class.getSimpleName(); 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 0a761534fad..b51f424a5ff 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -24,7 +24,11 @@ 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; @@ -54,19 +58,25 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { private static final Logger LOG = Logger.getLogger(BackupManagerImpl.class); @Inject - BackupPolicyDao backupPolicyDao; + private BackupPolicyDao backupPolicyDao; @Inject - VMInstanceDao vmInstanceDao; + private VMInstanceDao vmInstanceDao; @Inject private AccountService accountService; @Inject - BackupPolicyVMMapDao backupPolicyVMMapDao; + private BackupPolicyVMMapDao backupPolicyVMMapDao; @Inject - BackupDao backupDao; + private BackupDao backupDao; + + @Inject + private VolumeDao volumeDao; + + @Inject + private VolumeApiService volumeApiService; private static Map backupProvidersMap = new HashMap<>(); private List backupProviders; @@ -160,11 +170,34 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { } @Override - public boolean restoreBackupVolume(Long zoneId, Long volumeId, Long vmId, Long backupId) { - //TODO + public boolean restoreBackupVolumeAndAttachToVM(Long zoneId, Long volumeId, Long vmId, Long backupId) { + BackupProvider backupProvider = getBackupProvider(zoneId); + BackupVO backup = backupDao.findById(backupId); + if (backup == null) { + throw new CloudRuntimeException("Backup " + backupId + " does not exist"); + } + VMInstanceVO vm = vmInstanceDao.findById(vmId); + if (vm == null) { + throw new CloudRuntimeException("VM " + vmId + " does not exist"); + } + VolumeVO volume = volumeDao.findByIdIncludingRemoved(volumeId); + if (volume == null) { + throw new CloudRuntimeException("Volume " + volumeId + " could not be found"); + } + LOG.debug("Asking provider to restore volume " + volumeId + " from backup " + backupId); + VolumeTO restoredVolume = backupProvider.restoreVolumeFromBackup(backup.getUuid(), volume.getUuid()); + attachVolumeToVM(restoredVolume, vm); return false; } + /** + * Attach volume to VM + */ + private void attachVolumeToVM(VolumeTO restoredVolume, VMInstanceVO vm) { + LOG.debug("Attaching the restored volume to VM " + vm.getId()); + volumeDao.attachVolume(restoredVolume.getId(), vm.getId(), restoredVolume.getDeviceId()); + } + @Override public boolean deleteBackupPolicy(Long policyId) { BackupPolicyVO policy = backupPolicyDao.findById(policyId);