Github user mike-tutkowski commented on a diff in the pull request: https://github.com/apache/cloudstack/pull/1403#discussion_r63086019 --- Diff: engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java --- @@ -347,38 +395,87 @@ private String getProperty(long snapshotId, String property) { return null; } - private HostVO getHost(Long hostId, VolumeVO volumeVO) { - HostVO hostVO = _hostDao.findById(hostId); + private HostVO getHost(long volumeId) { + VolumeVO volumeVO = _volumeDao.findById(volumeId); + + Long vmInstanceId = volumeVO.getInstanceId(); + VMInstanceVO vmInstanceVO = _vmInstanceDao.findById(vmInstanceId); + + Long hostId = null; + + // if the volume to snapshot is associated with a VM + if (vmInstanceVO != null) { + hostId = vmInstanceVO.getHostId(); + + // if the VM is not associated with a host + if (hostId == null) { + hostId = vmInstanceVO.getLastHostId(); + } + } + + return getHost(volumeVO.getDataCenterId(), hostId); + } + + private HostVO getHost(long zoneId, Long hostId) { + HostVO hostVO = getHost(zoneId, true); if (hostVO != null) { return hostVO; } - // pick a host in any XenServer cluster that's in the applicable zone + hostVO = _hostDao.findById(hostId); - long zoneId = volumeVO.getDataCenterId(); + if (hostVO != null) { + return hostVO; + } + + hostVO = getHost(zoneId, false); - List<? extends Cluster> clusters = _mgr.searchForClusters(zoneId, new Long(0), Long.MAX_VALUE, HypervisorType.XenServer.toString()); + if (hostVO != null) { + return hostVO; + } + + throw new CloudRuntimeException("Unable to locate an applicable host"); + } + + private HostVO getHost(long zoneId, boolean computeClusterMustSupportResign) { + List<? extends Cluster> clusters = _mgr.searchForClusters(zoneId, 0L, Long.MAX_VALUE, HypervisorType.XenServer.toString()); if (clusters == null) { - throw new CloudRuntimeException("Unable to locate an applicable cluster"); + clusters = new ArrayList<>(); } + Collections.shuffle(clusters, new Random(System.nanoTime())); + + clusters: for (Cluster cluster : clusters) { if (cluster.getAllocationState() == AllocationState.Enabled) { List<HostVO> hosts = _hostDao.findByClusterId(cluster.getId()); if (hosts != null) { + Collections.shuffle(hosts, new Random(System.nanoTime())); + for (HostVO host : hosts) { if (host.getResourceState() == ResourceState.Enabled) { - return host; + if (computeClusterMustSupportResign) { + if (_clusterDao.computeClusterSupportsResign(cluster.getId())) { + return host; + } + else { + // no other host in the cluster in question should be able to satisfy our requirements here, so move on to the next cluster + continue clusters; + } + } + else { + return host; + } } } } } } - throw new CloudRuntimeException("Unable to locate an applicable cluster"); + return null; --- End diff -- @DaanHoogland I changed this to make use of Guava's Optional class.
--- If your project is set up for it, you can reply to this email and have your reply appear on GitHub as well. If your project does not have this feature enabled and wishes so, or if the feature is enabled but not working, please contact infrastructure at infrastruct...@apache.org or file a JIRA ticket with INFRA. ---