From 5ed0cf5bdda169d16564b758f0b2ddfeaeaa617e Mon Sep 17 00:00:00 2001 From: nvazquez Date: Fri, 1 Jun 2018 14:01:41 -0300 Subject: [PATCH] Add list backups and list policy-VM mappings --- .../command/user/backup/ListBackupsCmd.java | 17 +- .../api/response/BackupResponse.java | 26 ++- .../org/apache/cloudstack/backup/Backup.java | 5 +- .../cloudstack/backup/BackupManager.java | 2 +- .../cloudstack/backup/BackupProvider.java | 5 + .../apache/cloudstack/backup/BackupTO.java | 171 ++++++++++++++++++ .../apache/cloudstack/backup/BackupVO.java | 47 +++-- .../cloudstack/backup/dao/BackupDao.java | 4 +- .../cloudstack/backup/dao/BackupDaoImpl.java | 72 ++++++-- .../backup/dao/BackupPolicyVMMapDaoImpl.java | 1 + .../META-INF/db/schema-41110to41200.sql | 5 +- .../backup/DummyBackupProvider.java | 16 ++ .../backup/VeeamBackupProvider.java | 9 + .../cloudstack/backup/veeam/VeeamBackup.java | 9 +- .../cloudstack/backup/BackupManagerImpl.java | 10 +- 15 files changed, 347 insertions(+), 52 deletions(-) create mode 100644 engine/schema/src/main/java/org/apache/cloudstack/backup/BackupTO.java 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/ListBackupsCmd.java index c74dccd3036..8b4311da352 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/ListBackupsCmd.java @@ -32,6 +32,7 @@ import org.apache.cloudstack.api.Parameter; 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.BackupManager; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.backup.Backup; @@ -44,7 +45,7 @@ import java.util.List; responseObject = BackupResponse.class, since = "4.12.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ListBackupsCmd extends BaseBackupListCmd { - public static final String APINAME = "listBackups"; + public static final String APINAME = "listVMBackups"; @Inject BackupManager backupManager; @@ -60,6 +61,10 @@ public class ListBackupsCmd extends BaseBackupListCmd { description = "id of the VM") private Long virtualMachineId; + @Parameter(name = ApiConstants.ZONE_ID, type = BaseCmd.CommandType.UUID, entityType = ZoneResponse.class, + description = "The zone ID") + private Long zoneId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -68,6 +73,10 @@ public class ListBackupsCmd extends BaseBackupListCmd { return virtualMachineId; } + public Long getZoneId() { + return zoneId; + } + @Override public String getCommandName() { return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; @@ -82,14 +91,10 @@ public class ListBackupsCmd extends BaseBackupListCmd { /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// - private void setupResponse(List backups) { - - } - @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try{ - List backups = backupManager.listBackups(virtualMachineId); + 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/response/BackupResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/BackupResponse.java index e4acf7c0629..77e916a8775 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/BackupResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/BackupResponse.java @@ -33,13 +33,17 @@ public class BackupResponse extends BaseResponse { @Param(description = "internal id of the backup") private String id; + @SerializedName(ApiConstants.ZONE_ID) + @Param(description = "zone id") + private String zoneId; + @SerializedName(ApiConstants.ACCOUNT_ID) @Param(description = "account id") private String accountId; - @SerializedName(ApiConstants.USER_ID) - @Param(description = "user id") - private String userId; + @SerializedName(ApiConstants.EXTERNAL_ID) + @Param(description = "external backup id") + private String externalId; @SerializedName(ApiConstants.NAME) @Param(description = "backup name") @@ -81,12 +85,20 @@ public class BackupResponse extends BaseResponse { this.accountId = accountId; } - public String getUserId() { - return userId; + public String getZoneId() { + return zoneId; } - public void setUserId(String userId) { - this.userId = userId; + public void setZoneId(String zoneId) { + this.zoneId = zoneId; + } + + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; } public String getName() { diff --git a/api/src/main/java/org/apache/cloudstack/backup/Backup.java b/api/src/main/java/org/apache/cloudstack/backup/Backup.java index 947bf4d2ed5..9ffbf4a758c 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/Backup.java +++ b/api/src/main/java/org/apache/cloudstack/backup/Backup.java @@ -29,12 +29,13 @@ public interface Backup extends InternalIdentity, Identity { BackingUp, BackedUp, Failed, Queued, Restoring } + Long getZoneId(); Long getAccountId(); - Long getUserId(); + String getExternalId(); String getName(); String getDescription(); Long getParentId(); - Long getVMId(); + Long getVmId(); List getVolumeIds(); Status getStatus(); Date getStartTime(); 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 27b5a1f41fd..c4f77b0d66a 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java @@ -57,7 +57,7 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer /** * List existing backups for a VM */ - List listBackups(Long vmId); + List listVMBackups(Long zoneId, Long vmId); /** * List backup policies 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 c6c7e1d6a59..89285e83b8b 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java +++ b/api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java @@ -66,4 +66,9 @@ public interface BackupProvider { * Restore a volume from a backup */ VolumeTO restoreVolumeFromBackup(String volumeUuid, String backupUuid); + + /** + * List VM Backups + */ + List listVMBackups(Long zoneId, VirtualMachine vm); } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupTO.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupTO.java new file mode 100644 index 00000000000..61f0b90bcb2 --- /dev/null +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupTO.java @@ -0,0 +1,171 @@ +// 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.backup; + +import java.util.Date; +import java.util.List; + +public class BackupTO implements Backup { + + private long id; + private String uuid; + private Long accountId; + private String name; + private String description; + private Long parentId; + private Long vmId; + private List volumeIds; + private Status status; + private Date startTime; + private Long zoneId; + private String externalId; + private String parentExternalId; + + public BackupTO() { + } + + public BackupTO(final Long zoneId, final Long accountId, final String externalId, final String name, final String description, + final String parentExternalId, final Long vmId, final List volumeIds, final Status status, final Date startTime) { + this.zoneId = zoneId; + this.accountId = accountId; + this.externalId = externalId; + this.name = name; + this.description = description; + this.parentExternalId = parentExternalId; + this.vmId = vmId; + this.volumeIds = volumeIds; + this.status = status; + this.startTime = startTime; + } + + @Override + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + @Override + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + @Override + public Long getAccountId() { + return accountId; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + @Override + public Long getZoneId() { + return zoneId; + } + + public void setZoneId(Long zoneId) { + this.zoneId = zoneId; + } + + public String getParentExternalId() { + return parentExternalId; + } + + public void setParentExternalId(String parentExternalId) { + this.parentExternalId = parentExternalId; + } + + @Override + + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public Long getParentId() { + return parentId; + } + + public void setParentId(Long parentId) { + this.parentId = parentId; + } + + public Long getVmId() { + return vmId; + } + + public void setVmId(Long vmId) { + this.vmId = vmId; + } + + @Override + public List getVolumeIds() { + return volumeIds; + } + + public void setVolumeIds(List volumeIds) { + this.volumeIds = volumeIds; + } + + @Override + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + @Override + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } +} diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java index 24526766803..f7b3f781f0d 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java @@ -26,6 +26,9 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Transient; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -52,8 +55,11 @@ public class BackupVO implements Backup { @Column(name = "account_id") private long accountId; - @Column(name = "user_id") - private long userId; + @Column(name = "zone_id") + private Long zoneId; + + @Column(name = "external_id") + private String externalId; @Column(name = "name") private String name; @@ -74,8 +80,10 @@ public class BackupVO implements Backup { private Status status; @Column(name = "start") - private Date start; + @Temporal(value = TemporalType.TIMESTAMP) + private Date startTime; + @Transient private List volumeIds; @Override @@ -89,13 +97,26 @@ public class BackupVO implements Backup { } @Override - public Long getAccountId() { - return accountId; + public Long getZoneId() { + return zoneId; + } + + public void setZoneId(Long zoneId) { + this.zoneId = zoneId; } @Override - public Long getUserId() { - return userId; + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } + + @Override + public Long getAccountId() { + return accountId; } @Override @@ -114,7 +135,7 @@ public class BackupVO implements Backup { } @Override - public Long getVMId() { + public Long getVmId() { return vmId; } @@ -125,7 +146,7 @@ public class BackupVO implements Backup { @Override public Date getStartTime() { - return start; + return startTime; } public void setId(long id) { @@ -140,10 +161,6 @@ public class BackupVO implements Backup { this.accountId = accountId; } - public void setUserId(long userId) { - this.userId = userId; - } - public void setName(String name) { this.name = name; } @@ -164,8 +181,8 @@ public class BackupVO implements Backup { this.status = status; } - public void setStart(Date start) { - this.start = start; + public void setStartTime(Date start) { + this.startTime = start; } protected void convertVolumeStringToList() { diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDao.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDao.java index 7911172061e..fb6f01b0ef0 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDao.java @@ -26,8 +26,8 @@ import java.util.List; public interface BackupDao extends GenericDao { - List listByVmId(Long vmId); - List listByUserId(Long userId); + List listByVmId(Long zoneId, Long vmId); + List syncVMBackups(Long zoneId, Long vmId, List externalBackups); BackupResponse newBackupResponse(Backup backup); } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java index b48cf9c9276..1e2eb4b6f2c 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java @@ -17,21 +17,23 @@ package org.apache.cloudstack.backup.dao; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.DataCenterDao; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; import com.cloud.user.AccountVO; -import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; -import com.cloud.user.dao.UserDao; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.dao.VMInstanceDao; import org.apache.cloudstack.api.response.BackupResponse; +import org.apache.cloudstack.backup.BackupTO; import org.apache.cloudstack.backup.BackupVO; import org.apache.cloudstack.backup.Backup; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; import javax.annotation.PostConstruct; import javax.inject.Inject; @@ -44,7 +46,7 @@ public class BackupDaoImpl extends GenericDaoBase implements Bac AccountDao accountDao; @Inject - UserDao userDao; + DataCenterDao dataCenterDao; @Inject VMInstanceDao vmInstanceDao; @@ -60,35 +62,79 @@ public class BackupDaoImpl extends GenericDaoBase implements Bac @PostConstruct protected void init() { backupSearch = createSearchBuilder(); - backupSearch.and("vm_id", backupSearch.entity().getVMId(), SearchCriteria.Op.EQ); - backupSearch.and("user_id", backupSearch.entity().getUserId(), SearchCriteria.Op.EQ); + backupSearch.and("vm_id", backupSearch.entity().getVmId(), SearchCriteria.Op.EQ); + backupSearch.and("zone_id", backupSearch.entity().getZoneId(), SearchCriteria.Op.EQ); + backupSearch.and("external_id", backupSearch.entity().getExternalId(), SearchCriteria.Op.EQ); backupSearch.done(); } @Override - public List listByVmId(Long vmId) { + public List listByVmId(Long zoneId, Long vmId) { SearchCriteria sc = backupSearch.create(); sc.setParameters("vm_id", vmId); + sc.setParameters("zone_id", zoneId); return new ArrayList<>(listBy(sc)); } - @Override - public List listByUserId(Long userId) { + private Backup findByExternalId(Long zoneId, String externalId) { SearchCriteria sc = backupSearch.create(); - sc.setParameters("user_id", userId); - return new ArrayList<>(listBy(sc)); + sc.setParameters("external_id", externalId); + sc.setParameters("zone_id", zoneId); + return findOneBy(sc); + } + + private BackupVO getBackupVO(Backup backup) { + BackupVO backupVO = new BackupVO(); + backupVO.setZoneId(backup.getZoneId()); + backupVO.setAccountId(backup.getAccountId()); + backupVO.setExternalId(backup.getExternalId()); + backupVO.setName(backup.getName()); + backupVO.setDescription(backup.getDescription()); + if (backup instanceof BackupTO) { + String parentExternalId = ((BackupTO) backup).getParentExternalId(); + if (StringUtils.isNotBlank(parentExternalId)) { + Backup parent = findByExternalId(backup.getZoneId(), parentExternalId); + backupVO.setParentId(parent.getId()); + } + } + backupVO.setVmId(backup.getVmId()); + backupVO.setVolumeIds(backup.getVolumeIds()); + backupVO.setStatus(backup.getStatus()); + backupVO.setStartTime(backup.getStartTime()); + return backupVO; + } + + public void removeExistingVMBackups(Long zoneId, Long vmId) { + SearchCriteria sc = backupSearch.create(); + sc.setParameters("vm_id", vmId); + sc.setParameters("zone_id", zoneId); + expunge(sc); + } + + @Override + public List syncVMBackups(Long zoneId, Long vmId, List externalBackups) { + List existingVMBackups = listByVmId(zoneId, vmId); + if (CollectionUtils.isNotEmpty(existingVMBackups)) { + removeExistingVMBackups(zoneId, vmId); + } + for (Backup backup : externalBackups) { + BackupVO backupVO = getBackupVO(backup); + persist(backupVO); + } + return listByVmId(zoneId, vmId); } @Override public BackupResponse newBackupResponse(Backup backup) { AccountVO account = accountDao.findById(backup.getAccountId()); - UserVO user = userDao.findById(backup.getUserId()); BackupVO parent = findById(backup.getParentId()); - VMInstanceVO vm = vmInstanceDao.findById(backup.getVMId()); + VMInstanceVO vm = vmInstanceDao.findById(backup.getVmId()); + DataCenterVO zone = dataCenterDao.findById(backup.getZoneId()); BackupResponse backupResponse = new BackupResponse(); + backupResponse.setZoneId(zone.getUuid()); backupResponse.setId(backup.getUuid()); backupResponse.setAccountId(account.getUuid()); - backupResponse.setUserId(user.getUuid()); + backupResponse.setExternalId(backup.getExternalId()); backupResponse.setName(backup.getName()); backupResponse.setDescription(backup.getDescription()); if (parent != null) { 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 317e7117bbf..e18f4b15590 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 @@ -118,6 +118,7 @@ public class BackupPolicyVMMapDaoImpl extends GenericDaoBase listVMBackups(Long zoneId, VirtualMachine vm) { + s_logger.debug("Listing VM " + vm.getInstanceName() + "backups on the Dummy Backup Provider"); + + BackupTO backup1 = new BackupTO(zoneId, vm.getAccountId(), + "xxxx-xxxx", "Backup-1", "VM-" + vm.getInstanceName() + "-backup-1", + null, vm.getId(), null, Backup.Status.BackedUp, new Date()); + + BackupTO backup2 = new BackupTO(zoneId, vm.getAccountId(), "yyyy-yyyy", + "Backup-2", "VM-" + vm.getInstanceName() + "-backup-2", + backup1.getExternalId(), vm.getId(), null, Backup.Status.BackedUp, new Date()); + + return Arrays.asList(backup1, backup2); + } } 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 4558c581238..e7bc1c31f3c 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 @@ -89,16 +89,25 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider, @Override public boolean isBackupPolicy(String uuid) { + //TODO return true; } @Override public boolean restoreVMFromBackup(String vmUuid, String backupUuid) { + //TODO return false; } @Override public VolumeTO restoreVolumeFromBackup(String volumeUuid, String backupUuid) { + //TODO + return null; + } + + @Override + public List listVMBackups(Long zoneId, VirtualMachine vm) { + //TODO return null; } diff --git a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamBackup.java b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamBackup.java index 02fea9906d3..a72e8d2f691 100644 --- a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamBackup.java +++ b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/veeam/VeeamBackup.java @@ -32,13 +32,18 @@ public class VeeamBackup implements Backup { this.uid = uid; } + @Override + public Long getZoneId() { + return null; + } + @Override public Long getAccountId() { return null; } @Override - public Long getUserId() { + public String getExternalId() { return null; } @@ -58,7 +63,7 @@ public class VeeamBackup implements Backup { } @Override - public Long getVMId() { + public Long getVmId() { return null; } 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 04b58b3c4cb..daffec08399 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -159,8 +159,14 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { } @Override - public List listBackups(Long vmId) { - return backupDao.listByVmId(vmId); + public List listVMBackups(Long zoneId, Long vmId) { + BackupProvider backupProvider = getBackupProvider(zoneId); + VMInstanceVO vm = vmInstanceDao.findById(vmId); + if (vm == null) { + throw new CloudRuntimeException("VM " + vmId + " does not exist"); + } + List externalBackups = backupProvider.listVMBackups(zoneId, vm); + return backupDao.syncVMBackups(zoneId, vmId, externalBackups); } /**