Add list backups and list policy-VM mappings
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 c74dccd..8b4311d 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.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 @@ 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 @@ 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 @@ return virtualMachineId; } + public Long getZoneId() { + return zoneId; + } + @Override public String getCommandName() { return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; @@ -82,14 +91,10 @@ /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// - private void setupResponse(List<Backup> backups) { - - } - @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { try{ - List<Backup> backups = backupManager.listBackups(virtualMachineId); + List<Backup> 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 e4acf7c..77e916a 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 @@ @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 @@ 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 947bf4d..9ffbf4a 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 @@ BackingUp, BackedUp, Failed, Queued, Restoring } + Long getZoneId(); Long getAccountId(); - Long getUserId(); + String getExternalId(); String getName(); String getDescription(); Long getParentId(); - Long getVMId(); + Long getVmId(); List<Long> 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 27b5a1f..c4f77b0 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 @@ /** * List existing backups for a VM */ - List<Backup> listBackups(Long vmId); + List<Backup> 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 c6c7e1d..89285e8 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 @@ * Restore a volume from a backup */ VolumeTO restoreVolumeFromBackup(String volumeUuid, String backupUuid); + + /** + * List VM Backups + */ + List<Backup> 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 0000000..61f0b90 --- /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<Long> 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<Long> 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<Long> getVolumeIds() { + return volumeIds; + } + + public void setVolumeIds(List<Long> 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 2452676..f7b3f78 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.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 @@ @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 @@ private Status status; @Column(name = "start") - private Date start; + @Temporal(value = TemporalType.TIMESTAMP) + private Date startTime; + @Transient private List<Long> volumeIds; @Override @@ -89,13 +97,26 @@ } @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 @@ } @Override - public Long getVMId() { + public Long getVmId() { return vmId; } @@ -125,7 +146,7 @@ @Override public Date getStartTime() { - return start; + return startTime; } public void setId(long id) { @@ -140,10 +161,6 @@ this.accountId = accountId; } - public void setUserId(long userId) { - this.userId = userId; - } - public void setName(String name) { this.name = name; } @@ -164,8 +181,8 @@ 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 7911172..fb6f01b 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 @@ public interface BackupDao extends GenericDao<BackupVO, Long> { - List<Backup> listByVmId(Long vmId); - List<Backup> listByUserId(Long userId); + List<Backup> listByVmId(Long zoneId, Long vmId); + List<Backup> syncVMBackups(Long zoneId, Long vmId, List<Backup> 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 b48cf9c..1e2eb4b 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 @@ AccountDao accountDao; @Inject - UserDao userDao; + DataCenterDao dataCenterDao; @Inject VMInstanceDao vmInstanceDao; @@ -60,35 +62,79 @@ @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<Backup> listByVmId(Long vmId) { + public List<Backup> listByVmId(Long zoneId, Long vmId) { SearchCriteria<BackupVO> sc = backupSearch.create(); sc.setParameters("vm_id", vmId); + sc.setParameters("zone_id", zoneId); return new ArrayList<>(listBy(sc)); } - @Override - public List<Backup> listByUserId(Long userId) { + private Backup findByExternalId(Long zoneId, String externalId) { SearchCriteria<BackupVO> 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<BackupVO> sc = backupSearch.create(); + sc.setParameters("vm_id", vmId); + sc.setParameters("zone_id", zoneId); + expunge(sc); + } + + @Override + public List<Backup> syncVMBackups(Long zoneId, Long vmId, List<Backup> externalBackups) { + List<Backup> 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 317e711..e18f4b1 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 @@ response.setBackupPolicyId(policy.getUuid()); response.setVmId(vm.getUuid()); response.setZoneId(zone.getUuid()); + response.setObjectName("backuppolicyvmmap"); return response; } }
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 83665ab..3cf4151 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
@@ -63,7 +63,8 @@ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `uuid` varchar(40) NOT NULL, `account_id` bigint(20) unsigned NOT NULL, - `user_id` bigint(20) unsigned NOT NULL, + `zone_id` bigint(20) unsigned NOT NULL, + `external_id` varchar(40) NOT NULL COMMENT 'backup ID on provider side', `name` varchar(255) NOT NULL COMMENT 'backup name', `description` varchar(255) COMMENT 'backup description', `parent_id` bigint(20) unsigned COMMENT 'backup parent id', @@ -73,7 +74,7 @@ `start` timestamp, PRIMARY KEY (`id`), CONSTRAINT `fk_backup__account_id` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`) ON DELETE CASCADE, - CONSTRAINT `fk_backup__user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE, + 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
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 df9fea7..9818d41 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
@@ -24,6 +24,7 @@ import org.apache.log4j.Logger; import java.util.Arrays; +import java.util.Date; import java.util.List; public class DummyBackupProvider extends AdapterBase implements BackupProvider { @@ -78,4 +79,19 @@ return new VolumeTO(0L, Volume.Type.DATADISK, Storage.StoragePoolType.NetworkFilesystem, "pool-aaaa", "volumeTest", "/test", "volTest", 1024L, "", ""); } + + @Override + public List<Backup> 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 4558c58..e7bc1c3 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 @@ @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<Backup> 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 02fea99..a72e8d2 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
@@ -33,12 +33,17 @@ } @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 @@ } @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 04b58b3..daffec0 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 @@ } @Override - public List<Backup> listBackups(Long vmId) { - return backupDao.listByVmId(vmId); + public List<Backup> 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<Backup> externalBackups = backupProvider.listVMBackups(zoneId, vm); + return backupDao.syncVMBackups(zoneId, vmId, externalBackups); } /**