diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartBackupCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartBackupCommandWrapper.java index 4ed39f1ae89..2e7c8c5ae98 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartBackupCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartBackupCommandWrapper.java @@ -171,7 +171,6 @@ public class LibvirtStartBackupCommandWrapper extends CommandWrapper hosts = null; - if (storagePoolVO.getScope().equals(ScopeType.CLUSTER)) { - hosts = hostDao.findByClusterId(storagePoolVO.getClusterId()); - - } else if (storagePoolVO.getScope().equals(ScopeType.ZONE)) { - hosts = hostDao.findByDataCenterId(storagePoolVO.getDataCenterId()); + private HostVO getRandomHostFromStoragePool(StoragePoolVO storagePool) { + List hosts; + switch (storagePool.getScope()) { + case CLUSTER: + hosts = hostDao.findByClusterId(storagePool.getClusterId()); + Collections.shuffle(hosts); + return hosts.get(0); + case ZONE: + hosts = hostDao.findByDataCenterId(storagePool.getDataCenterId()); + Collections.shuffle(hosts); + return hosts.get(0); + case HOST: + List storagePoolHostVOs = storagePoolHostDao.listByPoolId(storagePool.getId()); + Collections.shuffle(storagePoolHostVOs); + return hostDao.findById(storagePoolHostVOs.get(0).getHostId()); + default: + throw new CloudRuntimeException("Unsupported storage pool scope: " + storagePool.getScope()); } - return hosts.get(0); } private void startNBDServer(String transferId, String direction, Long hostId, String exportName, String volumePath, String checkpointId) { @@ -396,12 +411,24 @@ public class KVMBackupExportServiceImpl extends ManagerBase implements KVMBackup } } + private String getVolumePathPrefix(StoragePoolVO storagePool) { + if (ScopeType.HOST.equals(storagePool.getScope())) { + return storagePool.getPath(); + } + switch (storagePool.getPoolType()) { + case NetworkFilesystem: + return String.format("/mnt/%s", storagePool.getUuid()); + case SharedMountPoint: + return storagePool.getPath(); + default: + throw new CloudRuntimeException("Unsupported storage pool type for file based image transfer: " + storagePool.getPoolType()); + } + } + private String getVolumePathForFileBasedBackend(Volume volume) { - Long poolId = volume.getPoolId(); - StoragePoolVO storagePoolVO = primaryDataStoreDao.findById(poolId); - // todo: This only works with file based storage (not ceph, linbit) - String volumePath = String.format("/mnt/%s/%s", storagePoolVO.getUuid(), volume.getPath()); - return volumePath; + StoragePoolVO storagePool = primaryDataStoreDao.findById(volume.getPoolId()); + String volumePathPrefix = getVolumePathPrefix(storagePool); + return volumePathPrefix + "/" + volume.getPath(); } private ImageTransferVO createUploadImageTransfer(VolumeVO volume, ImageTransfer.Backend backend) { @@ -409,8 +436,12 @@ public class KVMBackupExportServiceImpl extends ManagerBase implements KVMBackup String transferId = UUID.randomUUID().toString(); Long poolId = volume.getPoolId(); - StoragePoolVO storagePoolVO = primaryDataStoreDao.findById(poolId); - Host host = getFirstHostFromStoragePool(storagePoolVO); + StoragePoolVO storagePool = poolId == null ? null : primaryDataStoreDao.findById(poolId); + if (storagePool == null) { + throw new CloudRuntimeException("Storage pool cannot be determined for volume: " + volume.getUuid()); + } + + Host host = getRandomHostFromStoragePool(storagePool); String volumePath = getVolumePathForFileBasedBackend(volume); ImageTransferVO imageTransfer;